diff --git a/mongo/client.go b/mongo/client.go index c163c79392..df2fd17f09 100644 --- a/mongo/client.go +++ b/mongo/client.go @@ -156,7 +156,7 @@ func NewClient(opts ...*options.ClientOptions) (*Client, error) { client.serverMonitor = clientOpt.ServerMonitor } // ReadConcern - client.readConcern = readconcern.New() + client.readConcern = &readconcern.ReadConcern{} if clientOpt.ReadConcern != nil { client.readConcern = clientOpt.ReadConcern } diff --git a/mongo/collection.go b/mongo/collection.go index 545ad12cd7..02537dc777 100644 --- a/mongo/collection.go +++ b/mongo/collection.go @@ -629,7 +629,33 @@ func (coll *Collection) updateOrReplace(ctx context.Context, filter bsoncore.Doc ctx = context.Background() } - uo := options.MergeUpdateOptions(opts...) + uo := options.Update() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.ArrayFilters != nil { + uo.ArrayFilters = opt.ArrayFilters + } + if opt.BypassDocumentValidation != nil { + uo.BypassDocumentValidation = opt.BypassDocumentValidation + } + if opt.Collation != nil { + uo.Collation = opt.Collation + } + if opt.Comment != nil { + uo.Comment = opt.Comment + } + if opt.Hint != nil { + uo.Hint = opt.Hint + } + if opt.Upsert != nil { + uo.Upsert = opt.Upsert + } + if opt.Let != nil { + uo.Let = opt.Let + } + } // collation, arrayFilters, upsert, and hint are included on the individual update documents rather than as part of the // command diff --git a/mongo/integration/json_helpers_test.go b/mongo/integration/json_helpers_test.go index 749de6a5b1..1a1a53189c 100644 --- a/mongo/integration/json_helpers_test.go +++ b/mongo/integration/json_helpers_test.go @@ -92,7 +92,7 @@ func createClientOptions(t testing.TB, opts bson.Raw) *options.ClientOptions { t.Fatalf("unrecognized type for w client option: %v", opt.Type) } case "readConcernLevel": - clientOpts.SetReadConcern(readconcern.New(readconcern.Level(opt.StringValue()))) + clientOpts.SetReadConcern(&readconcern.ReadConcern{Level: opt.StringValue()}) case "readPreference": clientOpts.SetReadPreference(readPrefFromString(opt.StringValue())) case "heartbeatFrequencyMS": @@ -388,7 +388,7 @@ func createTransactionOptions(t testing.TB, opts bson.Raw) *options.TransactionO // create a read concern from a map func createReadConcern(opt bson.RawValue) *readconcern.ReadConcern { - return readconcern.New(readconcern.Level(opt.Document().Lookup("level").StringValue())) + return &readconcern.ReadConcern{Level: opt.Document().Lookup("level").StringValue()} } // create a read concern from a map diff --git a/mongo/integration/unified/client_entity.go b/mongo/integration/unified/client_entity.go index ff7d9d5fc3..bd131799a3 100644 --- a/mongo/integration/unified/client_entity.go +++ b/mongo/integration/unified/client_entity.go @@ -581,7 +581,7 @@ func setClientOptionsFromURIOptions(clientOpts *options.ClientOptions, uriOpts b case "maxconnecting": clientOpts.SetMaxConnecting(uint64(value.(int32))) case "readconcernlevel": - clientOpts.SetReadConcern(readconcern.New(readconcern.Level(value.(string)))) + clientOpts.SetReadConcern(&readconcern.ReadConcern{Level: value.(string)}) case "retryreads": clientOpts.SetRetryReads(value.(bool)) case "retrywrites": diff --git a/mongo/integration/unified/common_options.go b/mongo/integration/unified/common_options.go index 04a462d7b6..67999e686c 100644 --- a/mongo/integration/unified/common_options.go +++ b/mongo/integration/unified/common_options.go @@ -24,7 +24,7 @@ type readConcern struct { } func (rc *readConcern) toReadConcernOption() *readconcern.ReadConcern { - return readconcern.New(readconcern.Level(rc.Level)) + return &readconcern.ReadConcern{Level: rc.Level} } type writeConcern struct { diff --git a/mongo/mongocryptd.go b/mongo/mongocryptd.go index 41aebc76c1..e77a392419 100644 --- a/mongo/mongocryptd.go +++ b/mongo/mongocryptd.go @@ -26,7 +26,7 @@ const ( ) var defaultTimeoutArgs = []string{"--idleShutdownTimeoutSecs=60"} -var databaseOpts = options.Database().SetReadConcern(readconcern.New()).SetReadPreference(readpref.Primary()) +var databaseOpts = options.Database().SetReadConcern(&readconcern.ReadConcern{}).SetReadPreference(readpref.Primary()) type mongocryptdClient struct { bypassSpawn bool diff --git a/mongo/options/clientoptions.go b/mongo/options/clientoptions.go index 287164341f..d08bbf6992 100644 --- a/mongo/options/clientoptions.go +++ b/mongo/options/clientoptions.go @@ -408,7 +408,7 @@ func (c *ClientOptions) ApplyURI(uri string) *ClientOptions { } if cs.ReadConcernLevel != "" { - c.ReadConcern = readconcern.New(readconcern.Level(cs.ReadConcernLevel)) + c.ReadConcern = &readconcern.ReadConcern{Level: cs.ReadConcernLevel} } if cs.ReadPreference != "" || len(cs.ReadPreferenceTagSets) > 0 || cs.MaxStalenessSet { diff --git a/mongo/options/transactionoptions.go b/mongo/options/transactionoptions.go index 9270cd20d4..2bc4c2166c 100644 --- a/mongo/options/transactionoptions.go +++ b/mongo/options/transactionoptions.go @@ -73,31 +73,3 @@ func (t *TransactionOptions) SetMaxCommitTime(mct *time.Duration) *TransactionOp t.MaxCommitTime = mct return t } - -// MergeTransactionOptions combines the given TransactionOptions instances into a single TransactionOptions in a -// last-one-wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeTransactionOptions(opts ...*TransactionOptions) *TransactionOptions { - t := Transaction() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.ReadConcern != nil { - t.ReadConcern = opt.ReadConcern - } - if opt.ReadPreference != nil { - t.ReadPreference = opt.ReadPreference - } - if opt.WriteConcern != nil { - t.WriteConcern = opt.WriteConcern - } - if opt.MaxCommitTime != nil { - t.MaxCommitTime = opt.MaxCommitTime - } - } - - return t -} diff --git a/mongo/options/updateoptions.go b/mongo/options/updateoptions.go index 5206f9f01b..a47fb20592 100644 --- a/mongo/options/updateoptions.go +++ b/mongo/options/updateoptions.go @@ -93,39 +93,3 @@ func (uo *UpdateOptions) SetLet(l interface{}) *UpdateOptions { uo.Let = l return uo } - -// MergeUpdateOptions combines the given UpdateOptions instances into a single UpdateOptions in a last-one-wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeUpdateOptions(opts ...*UpdateOptions) *UpdateOptions { - uOpts := Update() - for _, uo := range opts { - if uo == nil { - continue - } - if uo.ArrayFilters != nil { - uOpts.ArrayFilters = uo.ArrayFilters - } - if uo.BypassDocumentValidation != nil { - uOpts.BypassDocumentValidation = uo.BypassDocumentValidation - } - if uo.Collation != nil { - uOpts.Collation = uo.Collation - } - if uo.Comment != nil { - uOpts.Comment = uo.Comment - } - if uo.Hint != nil { - uOpts.Hint = uo.Hint - } - if uo.Upsert != nil { - uOpts.Upsert = uo.Upsert - } - if uo.Let != nil { - uOpts.Let = uo.Let - } - } - - return uOpts -} diff --git a/mongo/read_write_concern_spec_test.go b/mongo/read_write_concern_spec_test.go index 51d46b4c2a..8dcab1274a 100644 --- a/mongo/read_write_concern_spec_test.go +++ b/mongo/read_write_concern_spec_test.go @@ -104,8 +104,8 @@ func runConnectionStringTest(t *testing.T, test connectionStringTest) { if test.ReadConcern != nil { expected := readConcernFromRaw(t, test.ReadConcern) - assert.Equal(t, expected.GetLevel(), cs.ReadConcernLevel, - "expected level %v, got %v", expected.GetLevel(), cs.ReadConcernLevel) + assert.Equal(t, expected.Level, cs.ReadConcernLevel, + "expected level %v, got %v", expected.Level, cs.ReadConcernLevel) } if test.WriteConcern != nil { expectedWc := writeConcernFromRaw(t, test.WriteConcern) @@ -200,7 +200,7 @@ func runDocumentTest(t *testing.T, test documentTest) { func readConcernFromRaw(t *testing.T, rc bson.Raw) *readconcern.ReadConcern { t.Helper() - var opts []readconcern.Option + concern := &readconcern.ReadConcern{} elems, _ := rc.Elements() for _, elem := range elems { key := elem.Key() @@ -208,12 +208,12 @@ func readConcernFromRaw(t *testing.T, rc bson.Raw) *readconcern.ReadConcern { switch key { case "level": - opts = append(opts, readconcern.Level(val.StringValue())) + concern.Level = val.StringValue() default: t.Fatalf("unrecognized read concern field %v", key) } } - return readconcern.New(opts...) + return concern } type writeConcern struct { diff --git a/mongo/readconcern/readconcern.go b/mongo/readconcern/readconcern.go index 51408e142d..8b387c3fd8 100644 --- a/mongo/readconcern/readconcern.go +++ b/mongo/readconcern/readconcern.go @@ -26,31 +26,13 @@ type ReadConcern struct { Level string } -// Option is an option to provide when creating a ReadConcern. -// -// Deprecated: Use the ReadConcern literal declaration instead. For example: -// -// &readconcern.ReadConcern{Level: "local"} -type Option func(concern *ReadConcern) - -// Level creates an option that sets the level of a ReadConcern. -// -// Deprecated: Use the ReadConcern literal declaration instead. For example: -// -// &readconcern.ReadConcern{Level: "local"} -func Level(level string) Option { - return func(concern *ReadConcern) { - concern.Level = level - } -} - // Local returns a ReadConcern that requests data from the instance with no guarantee that the data // has been written to a majority of the replica set members (i.e. may be rolled back). // // For more information about read concern "local", see // https://www.mongodb.com/docs/manual/reference/read-concern-local/ func Local() *ReadConcern { - return New(Level("local")) + return &ReadConcern{Level: "local"} } // Majority returns a ReadConcern that requests data that has been acknowledged by a majority of the @@ -59,7 +41,7 @@ func Local() *ReadConcern { // For more information about read concern "majority", see // https://www.mongodb.com/docs/manual/reference/read-concern-majority/ func Majority() *ReadConcern { - return New(Level("majority")) + return &ReadConcern{Level: "majority"} } // Linearizable returns a ReadConcern that requests data that reflects all successful @@ -68,7 +50,7 @@ func Majority() *ReadConcern { // For more information about read concern "linearizable", see // https://www.mongodb.com/docs/manual/reference/read-concern-linearizable/ func Linearizable() *ReadConcern { - return New(Level("linearizable")) + return &ReadConcern{Level: "linearizable"} } // Available returns a ReadConcern that requests data from an instance with no guarantee that the @@ -77,7 +59,7 @@ func Linearizable() *ReadConcern { // For more information about read concern "available", see // https://www.mongodb.com/docs/manual/reference/read-concern-available/ func Available() *ReadConcern { - return New(Level("available")) + return &ReadConcern{Level: "available"} } // Snapshot returns a ReadConcern that requests majority-committed data as it appears across shards @@ -86,22 +68,7 @@ func Available() *ReadConcern { // For more information about read concern "snapshot", see // https://www.mongodb.com/docs/manual/reference/read-concern-snapshot/ func Snapshot() *ReadConcern { - return New(Level("snapshot")) -} - -// New constructs a new read concern from the given string. -// -// Deprecated: Use the ReadConcern literal declaration instead. For example: -// -// &readconcern.ReadConcern{Level: "local"} -func New(options ...Option) *ReadConcern { - concern := &ReadConcern{} - - for _, option := range options { - option(concern) - } - - return concern + return &ReadConcern{Level: "snapshot"} } // MarshalBSONValue implements the bson.ValueMarshaler interface. @@ -120,10 +87,3 @@ func (rc *ReadConcern) MarshalBSONValue() (bsontype.Type, []byte, error) { return bsontype.EmbeddedDocument, bsoncore.BuildDocument(nil, elems), nil } - -// GetLevel returns the read concern level. -// -// Deprecated: Use the ReadConcern.Level field instead. -func (rc *ReadConcern) GetLevel() string { - return rc.Level -} diff --git a/mongo/readconcern/readconcern_test.go b/mongo/readconcern/readconcern_test.go index 2f6ea79f3e..cecd0e90fe 100644 --- a/mongo/readconcern/readconcern_test.go +++ b/mongo/readconcern/readconcern_test.go @@ -31,7 +31,7 @@ func TestReadConcern_MarshalBSONValue(t *testing.T) { }, { name: "empty", - rc: readconcern.New(), + rc: &readconcern.ReadConcern{}, bytes: bsoncore.BuildDocument(nil, nil), wantErrorMsg: nil, }, diff --git a/mongo/session.go b/mongo/session.go index 22aa026c9e..4e687fc276 100644 --- a/mongo/session.go +++ b/mongo/session.go @@ -267,7 +267,24 @@ func (s *sessionImpl) StartTransaction(opts ...*options.TransactionOptions) erro s.didCommitAfterStart = false - topts := options.MergeTransactionOptions(opts...) + topts := options.Transaction() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.ReadConcern != nil { + topts.ReadConcern = opt.ReadConcern + } + if opt.ReadPreference != nil { + topts.ReadPreference = opt.ReadPreference + } + if opt.WriteConcern != nil { + topts.WriteConcern = opt.WriteConcern + } + if opt.MaxCommitTime != nil { + topts.MaxCommitTime = opt.MaxCommitTime + } + } coreOpts := &session.TransactionOptions{ ReadConcern: topts.ReadConcern, ReadPreference: topts.ReadPreference, diff --git a/x/mongo/driver/operation.go b/x/mongo/driver/operation.go index b84071e383..58090ce3dd 100644 --- a/x/mongo/driver/operation.go +++ b/x/mongo/driver/operation.go @@ -1427,7 +1427,7 @@ func (op Operation) addReadConcern(dst []byte, desc description.SelectedServer) // start transaction must append afterclustertime IF causally consistent and operation time exists if rc == nil && client != nil && client.TransactionStarting() && client.Consistent && client.OperationTime != nil { - rc = readconcern.New() + rc = &readconcern.ReadConcern{} } if client != nil && client.Snapshot { diff --git a/x/mongo/driver/operation_test.go b/x/mongo/driver/operation_test.go index b0ae14aad5..0377e1077f 100644 --- a/x/mongo/driver/operation_test.go +++ b/x/mongo/driver/operation_test.go @@ -214,7 +214,7 @@ func TestOperation(t *testing.T) { want bsoncore.Document }{ {"nil", nil, nil}, - {"empty", readconcern.New(), nil}, + {"empty", &readconcern.ReadConcern{}, nil}, {"non-empty", readconcern.Majority(), majorityRc}, }