Skip to content

Commit 3b10cff

Browse files
h3n4lclaude
andauthored
fix: return JSON objects from SHOW COLLECTIONS/DATABASES commands (#21)
SHOW COLLECTIONS, SHOW DATABASES, and db.getCollectionNames() returned plain strings which couldn't be parsed by the frontend's lossless-json. Now returns JSON objects with a "name" field: {"name": "collection_name"} Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c296164 commit 3b10cff

File tree

4 files changed

+66
-17
lines changed

4 files changed

+66
-17
lines changed

admin_test.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package gomongo_test
33
import (
44
"context"
55
"fmt"
6-
"slices"
76
"strings"
87
"testing"
98

@@ -13,6 +12,24 @@ import (
1312
"go.mongodb.org/mongo-driver/v2/bson"
1413
)
1514

15+
// containsCollectionName checks if the rows contain a JSON object with the given collection name.
16+
func containsCollectionName(rows []string, name string) bool {
17+
for _, row := range rows {
18+
var doc bson.M
19+
if err := bson.UnmarshalExtJSON([]byte(row), false, &doc); err == nil {
20+
if doc["name"] == name {
21+
return true
22+
}
23+
}
24+
}
25+
return false
26+
}
27+
28+
// containsDatabaseName checks if the rows contain a JSON object with the given database name.
29+
func containsDatabaseName(rows []string, name string) bool {
30+
return containsCollectionName(rows, name) // Same logic
31+
}
32+
1633
func TestCreateIndex(t *testing.T) {
1734
testutil.RunOnAllDBs(t, func(t *testing.T, db testutil.TestDB) {
1835
dbName := fmt.Sprintf("testdb_create_idx_%s", db.Name)
@@ -163,7 +180,7 @@ func TestCreateCollection(t *testing.T) {
163180
collResult, err := gc.Execute(ctx, dbName, `show collections`)
164181
require.NoError(t, err)
165182
require.Equal(t, 1, collResult.RowCount)
166-
require.Equal(t, "newcollection", collResult.Rows[0])
183+
require.True(t, containsCollectionName(collResult.Rows, "newcollection"), "expected 'newcollection' in result")
167184
})
168185
}
169186

@@ -183,7 +200,7 @@ func TestDropDatabase(t *testing.T) {
183200
// Verify database exists
184201
result, err := gc.Execute(ctx, dbName, `show dbs`)
185202
require.NoError(t, err)
186-
require.True(t, slices.Contains(result.Rows, dbName), "database should exist before drop")
203+
require.True(t, containsDatabaseName(result.Rows, dbName), "database should exist before drop")
187204

188205
// Drop the database
189206
result, err = gc.Execute(ctx, dbName, `db.dropDatabase()`)
@@ -216,7 +233,7 @@ func TestRenameCollection(t *testing.T) {
216233
collResult, err := gc.Execute(ctx, dbName, `show collections`)
217234
require.NoError(t, err)
218235
require.Equal(t, 1, collResult.RowCount)
219-
require.Equal(t, "newname", collResult.Rows[0])
236+
require.True(t, containsCollectionName(collResult.Rows, "newname"), "expected 'newname' in result")
220237

221238
// Verify data is preserved
222239
findResult, err := gc.Execute(ctx, dbName, `db.newname.find()`)
@@ -252,7 +269,7 @@ func TestRenameCollectionWithDropTarget(t *testing.T) {
252269
collResult, err := gc.Execute(ctx, dbName, `show collections`)
253270
require.NoError(t, err)
254271
require.Equal(t, 1, collResult.RowCount)
255-
require.Equal(t, "target", collResult.Rows[0])
272+
require.True(t, containsCollectionName(collResult.Rows, "target"), "expected 'target' in result")
256273

257274
// Verify it has source data, not old target data
258275
findResult, err := gc.Execute(ctx, dbName, `db.target.find()`)
@@ -280,7 +297,7 @@ func TestCreateCollectionWithOptions(t *testing.T) {
280297
collResult, err := gc.Execute(ctx, dbName, `show collections`)
281298
require.NoError(t, err)
282299
require.Equal(t, 1, collResult.RowCount)
283-
require.Equal(t, "cappedcoll", collResult.Rows[0])
300+
require.True(t, containsCollectionName(collResult.Rows, "cappedcoll"), "expected 'cappedcoll' in result")
284301
})
285302
}
286303

database_test.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package gomongo_test
33
import (
44
"context"
55
"fmt"
6-
"slices"
76
"testing"
87

98
"github.com/bytebase/gomongo"
@@ -40,8 +39,17 @@ func TestShowDatabases(t *testing.T) {
4039
require.NotNil(t, result)
4140
require.GreaterOrEqual(t, result.RowCount, 1)
4241

43-
// Check that dbName is in the result
44-
require.True(t, slices.Contains(result.Rows, dbName), "expected '%s' in database list, got: %v", dbName, result.Rows)
42+
// Check that dbName is in the result (as JSON object with "name" field)
43+
found := false
44+
for _, row := range result.Rows {
45+
var doc bson.M
46+
err := bson.UnmarshalExtJSON([]byte(row), false, &doc)
47+
if err == nil && doc["name"] == dbName {
48+
found = true
49+
break
50+
}
51+
}
52+
require.True(t, found, "expected database '%s' in result, got: %v", dbName, result.Rows)
4553
})
4654
}
4755
})
@@ -67,10 +75,15 @@ func TestShowCollections(t *testing.T) {
6775
require.NotNil(t, result)
6876
require.Equal(t, 2, result.RowCount)
6977

70-
// Check that both collections are in the result
78+
// Check that both collections are in the result (as JSON objects with "name" field)
7179
collectionSet := make(map[string]bool)
7280
for _, row := range result.Rows {
73-
collectionSet[row] = true
81+
var doc bson.M
82+
err := bson.UnmarshalExtJSON([]byte(row), false, &doc)
83+
require.NoError(t, err, "row should be valid JSON: %s", row)
84+
if name, ok := doc["name"].(string); ok {
85+
collectionSet[name] = true
86+
}
7487
}
7588
require.True(t, collectionSet["users"], "expected 'users' collection")
7689
require.True(t, collectionSet["orders"], "expected 'orders' collection")
@@ -97,10 +110,15 @@ func TestGetCollectionNames(t *testing.T) {
97110
require.NotNil(t, result)
98111
require.Equal(t, 2, result.RowCount)
99112

100-
// Check that both collections are in the result
113+
// Check that both collections are in the result (as JSON objects with "name" field)
101114
collectionSet := make(map[string]bool)
102115
for _, row := range result.Rows {
103-
collectionSet[row] = true
116+
var doc bson.M
117+
err := bson.UnmarshalExtJSON([]byte(row), false, &doc)
118+
require.NoError(t, err, "row should be valid JSON: %s", row)
119+
if name, ok := doc["name"].(string); ok {
120+
collectionSet[name] = true
121+
}
104122
}
105123
require.True(t, collectionSet["products"], "expected 'products' collection")
106124
require.True(t, collectionSet["categories"], "expected 'categories' collection")

internal/executor/database.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,15 @@ func executeShowCollections(ctx context.Context, client *mongo.Client, database
1717
return nil, fmt.Errorf("list collections failed: %w", err)
1818
}
1919

20-
rows := make([]string, len(names))
21-
copy(rows, names)
20+
rows := make([]string, 0, len(names))
21+
for _, name := range names {
22+
doc := bson.M{"name": name}
23+
jsonBytes, err := bson.MarshalExtJSONIndent(doc, false, false, "", " ")
24+
if err != nil {
25+
return nil, fmt.Errorf("marshal failed: %w", err)
26+
}
27+
rows = append(rows, string(jsonBytes))
28+
}
2229

2330
return &Result{
2431
Rows: rows,

internal/executor/server.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,15 @@ func executeShowDatabases(ctx context.Context, client *mongo.Client) (*Result, e
1515
return nil, fmt.Errorf("list databases failed: %w", err)
1616
}
1717

18-
rows := make([]string, len(names))
19-
copy(rows, names)
18+
rows := make([]string, 0, len(names))
19+
for _, name := range names {
20+
doc := bson.M{"name": name}
21+
jsonBytes, err := bson.MarshalExtJSONIndent(doc, false, false, "", " ")
22+
if err != nil {
23+
return nil, fmt.Errorf("marshal failed: %w", err)
24+
}
25+
rows = append(rows, string(jsonBytes))
26+
}
2027

2128
return &Result{
2229
Rows: rows,

0 commit comments

Comments
 (0)