diff --git a/.gitmodules b/.gitmodules index e3b5c7b3e..db52c2b66 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "specifications"] +[submodule "testdata/specifications"] path = testdata/specifications - url = https://github.com/mongodb/specifications + url = https://github.com/matthewdale/specifications.git diff --git a/internal/integration/unified/database_operation_execution.go b/internal/integration/unified/database_operation_execution.go index 940bf3733..2bf8d391f 100644 --- a/internal/integration/unified/database_operation_execution.go +++ b/internal/integration/unified/database_operation_execution.go @@ -185,6 +185,33 @@ func executeDropCollection(ctx context.Context, operation *operation) (*operatio return newErrorResult(err), nil } +func executeDropDatabase(ctx context.Context, operation *operation) (*operationResult, error) { + client, err := entities(ctx).client(operation.Object) + if err != nil { + return nil, err + } + + var dbName string + elems, _ := operation.Arguments.Elements() + for _, elem := range elems { + key := elem.Key() + val := elem.Value() + + switch key { + case "database": + dbName = val.StringValue() + default: + return nil, fmt.Errorf("unrecognized dropDatabase option %q", key) + } + } + if dbName == "" { + return nil, newMissingArgumentError("database") + } + + err = client.Database(dbName).Drop(ctx) + return newErrorResult(err), nil +} + func executeListCollections(ctx context.Context, operation *operation) (*operationResult, error) { db, err := entities(ctx).database(operation.Object) if err != nil { diff --git a/internal/integration/unified/operation.go b/internal/integration/unified/operation.go index 41df0430c..d90ec4aad 100644 --- a/internal/integration/unified/operation.go +++ b/internal/integration/unified/operation.go @@ -150,6 +150,8 @@ func (op *operation) run(ctx context.Context, loopDone <-chan struct{}) (*operat return executeCreateCollection(ctx, op) case "dropCollection": return executeDropCollection(ctx, op) + case "dropDatabase": + return executeDropDatabase(ctx, op) case "listCollections": return executeListCollections(ctx, op) case "listCollectionNames": diff --git a/internal/integration/unified/unified_spec_test.go b/internal/integration/unified/unified_spec_test.go index f92a05386..293fb4a5f 100644 --- a/internal/integration/unified/unified_spec_test.go +++ b/internal/integration/unified/unified_spec_test.go @@ -39,6 +39,7 @@ var ( "mongodb-handshake/tests/unified", "client-backpressure/tests", "transactions/tests/unified", + "causal-consistency/tests", } failDirectories = []string{ "unified-test-format/tests/valid-fail", diff --git a/testdata/specifications b/testdata/specifications index b519824da..8ab62d639 160000 --- a/testdata/specifications +++ b/testdata/specifications @@ -1 +1 @@ -Subproject commit b519824da64005cdf99ca680fc49c4e278af0ef3 +Subproject commit 8ab62d639054396bd0d784791bd3683f16af0747 diff --git a/x/mongo/driver/operation.go b/x/mongo/driver/operation.go index b8be12ebb..a0014befc 100644 --- a/x/mongo/driver/operation.go +++ b/x/mongo/driver/operation.go @@ -1583,6 +1583,27 @@ func (op Operation) addReadConcern(dst []byte, desc description.SelectedServer) rc = &readconcern.ReadConcern{} } + // If this is a write operation, then we add an empty read concern so the + // following code can set "afterClusterTime". That avoids a data correctness + // problem that can happen when there is a network partition in a sharded + // cluster. See DRIVERS-3274 for more details. + isWrite := op.Name == driverutil.InsertOp || + op.Name == driverutil.UpdateOp || + op.Name == driverutil.FindAndModifyOp || + op.Name == driverutil.DeleteOp || + op.Name == driverutil.BulkWriteOp || + op.Name == driverutil.CreateOp || + op.Name == driverutil.CreateIndexesOp || + op.Name == driverutil.DropOp || + op.Name == driverutil.DropDatabaseOp || + op.Name == driverutil.DropIndexesOp + isNotInTxn := client != nil && (client.TransactionState == session.None || + client.TransactionState == session.Committed || + client.TransactionState == session.Aborted) + if rc == nil && client != nil && client.Consistent && client.OperationTime != nil && isWrite && isNotInTxn { + rc = &readconcern.ReadConcern{} + } + if client != nil && client.Snapshot { if desc.WireVersion.Max < readSnapshotMinWireVersion { return dst, errors.New("snapshot reads require MongoDB 5.0 or later") diff --git a/x/mongo/driver/operation/create.go b/x/mongo/driver/operation/create.go index f9a406dbc..c1d4f8479 100644 --- a/x/mongo/driver/operation/create.go +++ b/x/mongo/driver/operation/create.go @@ -80,6 +80,7 @@ func (c *Create) Execute(ctx context.Context) error { WriteConcern: c.writeConcern, ServerAPI: c.serverAPI, Authenticator: c.authenticator, + Name: driverutil.CreateOp, }.Execute(ctx) }