Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ func executeOperation(ctx context.Context, client *mongo.Client, database string
return executeGetCollectionNames(ctx, client, database)
case opGetCollectionInfos:
return executeGetCollectionInfos(ctx, client, database, op)
case opGetIndexes:
return executeGetIndexes(ctx, client, database, op)
default:
return nil, &UnsupportedOperationError{
Operation: statement,
Expand Down Expand Up @@ -290,3 +292,37 @@ func executeGetCollectionInfos(ctx context.Context, client *mongo.Client, databa
RowCount: len(rows),
}, nil
}

// executeGetIndexes executes a db.collection.getIndexes() command.
func executeGetIndexes(ctx context.Context, client *mongo.Client, database string, op *mongoOperation) (*Result, error) {
collection := client.Database(database).Collection(op.collection)

cursor, err := collection.Indexes().List(ctx)
if err != nil {
return nil, fmt.Errorf("list indexes failed: %w", err)
}
defer func() { _ = cursor.Close(ctx) }()

var rows []string
for cursor.Next(ctx) {
var doc bson.M
if err := cursor.Decode(&doc); err != nil {
return nil, fmt.Errorf("decode failed: %w", err)
}

jsonBytes, err := bson.MarshalExtJSONIndent(doc, false, false, "", " ")
if err != nil {
return nil, fmt.Errorf("marshal failed: %w", err)
}
rows = append(rows, string(jsonBytes))
}

if err := cursor.Err(); err != nil {
return nil, fmt.Errorf("cursor error: %w", err)
}

return &Result{
Rows: rows,
RowCount: len(rows),
}, nil
}
93 changes: 93 additions & 0 deletions executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gomongo_test

import (
"context"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -1434,3 +1435,95 @@ func TestGetCollectionInfosEmptyResult(t *testing.T) {
require.Equal(t, 0, result.RowCount)
require.Empty(t, result.Rows)
}

func TestGetIndexes(t *testing.T) {
client, cleanup := setupTestContainer(t)
defer cleanup()

ctx := context.Background()

// Create a collection with a document (this creates the default _id index)
collection := client.Database("testdb").Collection("users")
_, err := collection.InsertOne(ctx, bson.M{"name": "alice", "email": "alice@example.com"})
require.NoError(t, err)

gc := gomongo.NewClient(client)

// Test getIndexes - should return at least the _id index
result, err := gc.Execute(ctx, "testdb", "db.users.getIndexes()")
require.NoError(t, err)
require.NotNil(t, result)
require.GreaterOrEqual(t, result.RowCount, 1)

// Verify the _id index exists
found := false
for _, row := range result.Rows {
if strings.Contains(row, `"name": "_id_"`) {
found = true
break
}
}
require.True(t, found, "expected _id_ index")
}

func TestGetIndexesWithCustomIndex(t *testing.T) {
client, cleanup := setupTestContainer(t)
defer cleanup()

ctx := context.Background()

// Create a collection and add a custom index
collection := client.Database("testdb").Collection("users")
_, err := collection.InsertOne(ctx, bson.M{"name": "alice", "email": "alice@example.com"})
require.NoError(t, err)

// Create an index on the email field
_, err = collection.Indexes().CreateOne(ctx, mongo.IndexModel{
Keys: bson.D{{Key: "email", Value: 1}},
})
require.NoError(t, err)

gc := gomongo.NewClient(client)

result, err := gc.Execute(ctx, "testdb", "db.users.getIndexes()")
require.NoError(t, err)
require.NotNil(t, result)
require.Equal(t, 2, result.RowCount) // _id index + email index

// Verify both indexes exist
hasIdIndex := false
hasEmailIndex := false
for _, row := range result.Rows {
if strings.Contains(row, `"name": "_id_"`) {
hasIdIndex = true
}
if strings.Contains(row, `"email"`) {
hasEmailIndex = true
}
}
require.True(t, hasIdIndex, "expected _id_ index")
require.True(t, hasEmailIndex, "expected email index")
}

func TestGetIndexesBracketNotation(t *testing.T) {
client, cleanup := setupTestContainer(t)
defer cleanup()

ctx := context.Background()

// Create a collection with hyphenated name
collection := client.Database("testdb").Collection("user-logs")
_, err := collection.InsertOne(ctx, bson.M{"message": "test"})
require.NoError(t, err)

gc := gomongo.NewClient(client)

// Test with bracket notation
result, err := gc.Execute(ctx, "testdb", `db["user-logs"].getIndexes()`)
require.NoError(t, err)
require.NotNil(t, result)
require.GreaterOrEqual(t, result.RowCount, 1)

// Verify the _id index exists
require.Contains(t, result.Rows[0], `"name": "_id_"`)
}
8 changes: 6 additions & 2 deletions translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (
opShowCollections
opGetCollectionNames
opGetCollectionInfos
opGetIndexes
)

// mongoOperation represents a parsed MongoDB operation.
Expand Down Expand Up @@ -421,10 +422,13 @@ func (v *mongoShellVisitor) visitMethodCall(ctx mongodb.IMethodCallContext) {
return
}
methodName := gmCtx.Identifier().GetText()
if methodName == "aggregate" {
switch methodName {
case "aggregate":
v.operation.opType = opAggregate
v.extractAggregationPipeline(gmCtx)
} else {
case "getIndexes":
v.operation.opType = opGetIndexes
default:
v.err = &UnsupportedOperationError{
Operation: methodName,
Hint: "unknown method",
Expand Down
Loading