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
19 changes: 8 additions & 11 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,21 @@ func (e *ParseError) Error() string {
}

// UnsupportedOperationError represents an unsupported operation.
// This is returned for operations that are not planned for implementation.
type UnsupportedOperationError struct {
Operation string
Hint string
}

func (e *UnsupportedOperationError) Error() string {
if e.Hint != "" {
return fmt.Sprintf("unsupported operation %q: %s", e.Operation, e.Hint)
}
return fmt.Sprintf("unsupported operation %q", e.Operation)
return fmt.Sprintf("unsupported operation: %s", e.Operation)
}

// DeprecatedOperationError represents a deprecated operation with alternatives.
type DeprecatedOperationError struct {
Operation string
Alternative string
// PlannedOperationError represents an operation that is planned but not yet implemented.
// When the caller receives this error, it should fallback to mongosh.
type PlannedOperationError struct {
Operation string
}

func (e *DeprecatedOperationError) Error() string {
return fmt.Sprintf("%s is deprecated. Use %s instead", e.Operation, e.Alternative)
func (e *PlannedOperationError) Error() string {
return fmt.Sprintf("operation %s is not yet implemented", e.Operation)
}
1 change: 0 additions & 1 deletion executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ func executeOperation(ctx context.Context, client *mongo.Client, database string
default:
return nil, &UnsupportedOperationError{
Operation: statement,
Hint: "could not determine operation type",
}
}
}
Expand Down
35 changes: 17 additions & 18 deletions executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,48 +284,46 @@ func TestParseError(t *testing.T) {
require.ErrorAs(t, err, &parseErr)
}

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

gc := gomongo.NewClient(client)
ctx := context.Background()

// insertOne is a planned M2 operation - should return PlannedOperationError
_, err := gc.Execute(ctx, "testdb", "db.users.insertOne({ name: 'test' })")
require.Error(t, err)

var unsupportedErr *gomongo.UnsupportedOperationError
require.ErrorAs(t, err, &unsupportedErr)
require.Equal(t, "insertOne()", unsupportedErr.Operation)
var plannedErr *gomongo.PlannedOperationError
require.ErrorAs(t, err, &plannedErr)
require.Equal(t, "insertOne()", plannedErr.Operation)
}

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

gc := gomongo.NewClient(client)
ctx := context.Background()

// Test createSearchIndex
// createSearchIndex is NOT in the registry - should return UnsupportedOperationError
_, err := gc.Execute(ctx, "testdb", `db.movies.createSearchIndex({ name: "default", definition: { mappings: { dynamic: true } } })`)
require.Error(t, err)

var unsupportedErr *gomongo.UnsupportedOperationError
require.ErrorAs(t, err, &unsupportedErr)
require.Equal(t, "createSearchIndex()", unsupportedErr.Operation)
require.Contains(t, unsupportedErr.Hint, "Atlas Search Index")
}

func TestMethodRegistryStats(t *testing.T) {
total, deprecated, unsupported := gomongo.MethodRegistryStats()
total := gomongo.MethodRegistryStats()

// Verify we have a reasonable number of methods registered
require.GreaterOrEqual(t, total, 100, "expected at least 100 methods in registry")
require.GreaterOrEqual(t, deprecated, 20, "expected at least 20 deprecated methods")
require.GreaterOrEqual(t, unsupported, 80, "expected at least 80 unsupported methods")
// Registry should contain M2 (10) + M3 (22) = 32 planned methods
require.Equal(t, 32, total, "expected 32 planned methods in registry (M2: 10, M3: 22)")

// Log stats for visibility
t.Logf("Method Registry Stats: total=%d, deprecated=%d, unsupported=%d", total, deprecated, unsupported)
t.Logf("Method Registry Stats: total=%d planned methods", total)
}

func TestFindWithFilter(t *testing.T) {
Expand Down Expand Up @@ -1914,18 +1912,19 @@ func TestDistinctNumericValues(t *testing.T) {
require.Equal(t, 3, result.RowCount) // 100, 85, 90
}

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

ctx := context.Background()

gc := gomongo.NewClient(client)

// cursor.count() is deprecated and should return an error
// cursor.count() is not in the planned registry, should return UnsupportedOperationError
_, err := gc.Execute(ctx, "testdb", "db.users.find().count()")
require.Error(t, err)
require.Contains(t, err.Error(), "count()")
require.Contains(t, err.Error(), "countDocuments()")
require.Contains(t, err.Error(), "estimatedDocumentCount()")

var unsupportedErr *gomongo.UnsupportedOperationError
require.ErrorAs(t, err, &unsupportedErr)
require.Equal(t, "count()", unsupportedErr.Operation)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.24.5

require (
github.com/antlr4-go/antlr/v4 v4.13.1
github.com/bytebase/parser v0.0.0-20260120080341-a57d4b68030c
github.com/bytebase/parser v0.0.0-20260121030202-698704919f24
github.com/google/uuid v1.6.0
github.com/stretchr/testify v1.11.1
github.com/testcontainers/testcontainers-go/modules/mongodb v0.40.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/bytebase/antlr/v4 v4.0.0-20240827034948-8c385f108920 h1:IfmPt5o5R70NKtOrs+QHOoCgViYZelZysGxVBvV4ybA=
github.com/bytebase/antlr/v4 v4.0.0-20240827034948-8c385f108920/go.mod h1:ykhjIPiv0IWpu3OGXCHdz2eUSe8UNGGD6baqjs8jSuU=
github.com/bytebase/parser v0.0.0-20260120080341-a57d4b68030c h1:owIVaPTU4DrzzajK0BsuyRtScB/8JNQco7bzg4ZduLA=
github.com/bytebase/parser v0.0.0-20260120080341-a57d4b68030c/go.mod h1:jeak/EfutSOAuWKvrFIT2IZunhWprM7oTFBRgZ9RCxo=
github.com/bytebase/parser v0.0.0-20260121030202-698704919f24 h1:oonTO26orUa4bYk/hQjALiYO1zII+Kzpjg75OnC3VtU=
github.com/bytebase/parser v0.0.0-20260121030202-698704919f24/go.mod h1:jeak/EfutSOAuWKvrFIT2IZunhWprM7oTFBRgZ9RCxo=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
Expand Down
Loading