From 118eb1c0fd2486d52467d6d615409f2fc6a8893d Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Fri, 13 Oct 2023 09:21:33 -0600 Subject: [PATCH 1/2] GODRIVER-961 Change IndexView.DropAll to not return bson.Raw (#1419) --- mongo/index_view.go | 18 ++++++++++-------- mongo/integration/index_view_test.go | 2 +- .../unified/collection_operation_execution.go | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/mongo/index_view.go b/mongo/index_view.go index 41a93a2145..9f9509b8e7 100644 --- a/mongo/index_view.go +++ b/mongo/index_view.go @@ -425,16 +425,18 @@ func (iv IndexView) DropOne(ctx context.Context, name string, opts ...*options.D return iv.drop(ctx, name, opts...) } -// DropAll executes a dropIndexes operation to drop all indexes on the collection. If the operation succeeds, this -// returns a BSON document in the form {nIndexesWas: }. The "nIndexesWas" field in the response contains the -// number of indexes that existed prior to the drop. +// DropAll executes a dropIndexes operation to drop all indexes on the +// collection. // -// The opts parameter can be used to specify options for this operation (see the options.DropIndexesOptions -// documentation). +// The opts parameter can be used to specify options for this operation (see the +// options.DropIndexesOptions documentation). // -// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/dropIndexes/. -func (iv IndexView) DropAll(ctx context.Context, opts ...*options.DropIndexesOptions) (bson.Raw, error) { - return iv.drop(ctx, "*", opts...) +// For more information about the command, see +// https://www.mongodb.com/docs/manual/reference/command/dropIndexes/. +func (iv IndexView) DropAll(ctx context.Context, opts ...*options.DropIndexesOptions) error { + _, err := iv.drop(ctx, "*", opts...) + + return err } func getOrGenerateIndexName(keySpecDocument bsoncore.Document, model IndexModel) (string, error) { diff --git a/mongo/integration/index_view_test.go b/mongo/integration/index_view_test.go index e0cc6e2f87..eaa8f0fa2a 100644 --- a/mongo/integration/index_view_test.go +++ b/mongo/integration/index_view_test.go @@ -618,7 +618,7 @@ func TestIndexView(t *testing.T) { }) assert.Nil(mt, err, "CreateMany error: %v", err) assert.Equal(mt, 2, len(names), "expected 2 index names, got %v", len(names)) - _, err = iv.DropAll(context.Background()) + err = iv.DropAll(context.Background()) assert.Nil(mt, err, "DropAll error: %v", err) cursor, err := iv.List(context.Background()) diff --git a/mongo/integration/unified/collection_operation_execution.go b/mongo/integration/unified/collection_operation_execution.go index 0d4930b335..d8554ab706 100644 --- a/mongo/integration/unified/collection_operation_execution.go +++ b/mongo/integration/unified/collection_operation_execution.go @@ -607,8 +607,8 @@ func executeDropIndexes(ctx context.Context, operation *operation) (*operationRe } } - res, err := coll.Indexes().DropAll(ctx, dropIndexOpts) - return newDocumentResult(res, err), nil + err = coll.Indexes().DropAll(ctx, dropIndexOpts) + return newDocumentResult(nil, err), nil } func executeDropSearchIndex(ctx context.Context, operation *operation) (*operationResult, error) { From 71f65e3a0ae906f5ddcba6bc9fb0c314194636ad Mon Sep 17 00:00:00 2001 From: Qingyang Hu <103950869+qingyang-hu@users.noreply.github.com> Date: Fri, 13 Oct 2023 18:12:50 -0400 Subject: [PATCH 2/2] GODRIVER-2617 Remove deprecated code (#1398) --- benchmark/canary.go | 27 -- benchmark/operation_test.go | 21 +- benchmark/single.go | 5 +- event/monitoring.go | 44 +- examples/documentation_examples/examples.go | 18 +- mongo/change_stream.go | 51 +- mongo/change_stream_test.go | 63 +++ mongo/client.go | 74 ++- mongo/client_encryption.go | 76 ++- mongo/client_test.go | 22 +- mongo/collection.go | 453 ++++++++++++++++-- mongo/collection_test.go | 6 +- mongo/database.go | 130 ++++- mongo/database_test.go | 8 +- mongo/description/server.go | 65 ++- mongo/description/server_test.go | 3 +- mongo/description/topology.go | 12 +- mongo/gridfs/bucket.go | 78 ++- mongo/gridfs/gridfs_test.go | 2 +- mongo/index_options_builder.go | 176 ------- mongo/index_view.go | 44 +- mongo/integration/client_options_test.go | 4 +- .../client_side_encryption_prose_test.go | 6 +- mongo/integration/client_test.go | 8 - .../cmd_monitoring_helpers_test.go | 2 + mongo/integration/collection_test.go | 13 +- mongo/integration/index_view_test.go | 5 +- mongo/integration/json_helpers_test.go | 23 +- mongo/integration/mtest/mongotest.go | 14 +- mongo/integration/mtest/opmsg_deployment.go | 24 +- mongo/integration/mtest/setup.go | 12 +- mongo/integration/mtest/setup_options.go | 17 - mongo/integration/sessions_test.go | 2 +- mongo/integration/unified/client_entity.go | 2 +- .../unified/collection_operation_execution.go | 6 - mongo/integration/unified/common_options.go | 14 +- mongo/integration/unified/options.go | 18 - .../unified/unified_spec_runner.go | 11 +- mongo/mongo.go | 24 - mongo/mongocryptd.go | 6 +- mongo/options/aggregateoptions.go | 46 -- mongo/options/autoencryptionoptions.go | 46 -- mongo/options/bulkwriteoptions.go | 28 -- mongo/options/changestreamoptions.go | 52 -- mongo/options/changestreamoptions_test.go | 70 --- mongo/options/clientencryptionoptions.go | 28 -- mongo/options/clientoptions.go | 25 +- mongo/options/clientoptions_test.go | 10 +- mongo/options/collectionoptions.go | 29 -- mongo/options/countoptions.go | 33 -- mongo/options/createcollectionoptions.go | 81 ---- mongo/options/datakeyoptions.go | 25 - mongo/options/dboptions.go | 29 -- mongo/options/deleteoptions.go | 27 -- mongo/options/distinctoptions.go | 25 - mongo/options/encryptoptions.go | 34 -- mongo/options/estimatedcountoptions.go | 22 - mongo/options/findoptions.go | 393 --------------- mongo/options/gridfsoptions.go | 113 ----- mongo/options/indexoptions.go | 153 ------ mongo/options/insertoptions.go | 47 -- mongo/options/listcollectionsoptions.go | 25 - mongo/options/listdatabasesoptions.go | 22 - mongo/options/mongooptions.go | 18 - mongo/options/replaceoptions.go | 34 -- mongo/options/rewrapdatakeyoptions.go | 21 - mongo/options/runcmdoptions.go | 18 - mongo/options/sessionoptions.go | 37 -- mongo/options/transactionoptions.go | 28 -- mongo/options/updateoptions.go | 36 -- mongo/read_write_concern_spec_test.go | 30 +- mongo/readconcern/readconcern.go | 50 +- mongo/readconcern/readconcern_test.go | 2 +- mongo/search_index_view.go | 7 +- mongo/session.go | 19 +- mongo/with_transactions_test.go | 2 +- mongo/writeconcern/writeconcern.go | 214 --------- mongo/writeconcern/writeconcern_test.go | 38 -- x/mongo/driver/integration/aggregate_test.go | 4 +- x/mongo/driver/integration/compressor_test.go | 2 +- x/mongo/driver/integration/scram_test.go | 2 +- .../options/mongocrypt_context_options.go | 21 - x/mongo/driver/operation.go | 34 +- x/mongo/driver/operation_test.go | 78 +-- x/mongo/driver/session/client_session.go | 15 +- x/mongo/driver/session/session_pool.go | 2 +- x/mongo/driver/topology/fsm.go | 18 +- x/mongo/driver/topology/fsm_test.go | 28 +- .../topology/polling_srv_records_test.go | 8 +- x/mongo/driver/topology/sdam_spec_test.go | 2 +- x/mongo/driver/topology/server.go | 18 +- x/mongo/driver/topology/topology.go | 16 +- x/mongo/driver/topology/topology_options.go | 7 - x/mongo/driver/topology/topology_test.go | 143 +++--- 94 files changed, 1228 insertions(+), 2676 deletions(-) delete mode 100644 benchmark/canary.go delete mode 100644 mongo/index_options_builder.go delete mode 100644 mongo/options/changestreamoptions_test.go diff --git a/benchmark/canary.go b/benchmark/canary.go deleted file mode 100644 index 8742c79a9c..0000000000 --- a/benchmark/canary.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2017-present. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -package benchmark - -import ( - "context" -) - -// CanaryIncCase is a no-op. -// -// Deprecated: CanaryIncCase has no observable effect, so recent versions of the Go compiler may -// bypass calls to it in the compiled binary. It should not be used in benchmarks. -func CanaryIncCase(context.Context, TimerManager, int) error { - return nil -} - -// GlobalCanaryIncCase is a no-op. -// -// Deprecated: GlobalCanaryIncCase has no observable effect, so recent versions of the Go compiler -// may bypass calls to it in the compiled binary. It should not be used in benchmarks. -func GlobalCanaryIncCase(context.Context, TimerManager, int) error { - return nil -} diff --git a/benchmark/operation_test.go b/benchmark/operation_test.go index 147934273f..d53f75c994 100644 --- a/benchmark/operation_test.go +++ b/benchmark/operation_test.go @@ -32,15 +32,10 @@ func BenchmarkClientWrite(b *testing.B) { } for _, bm := range benchmarks { b.Run(bm.name, func(b *testing.B) { - client, err := mongo.NewClient(bm.opt) + client, err := mongo.Connect(context.Background(), bm.opt) if err != nil { b.Fatalf("error creating client: %v", err) } - ctx := context.Background() - err = client.Connect(ctx) - if err != nil { - b.Fatalf("error connecting: %v", err) - } defer func() { _ = client.Disconnect(context.Background()) }() coll := client.Database("test").Collection("test") _, err = coll.DeleteMany(context.Background(), bson.D{}) @@ -76,15 +71,10 @@ func BenchmarkClientBulkWrite(b *testing.B) { } for _, bm := range benchmarks { b.Run(bm.name, func(b *testing.B) { - client, err := mongo.NewClient(bm.opt) + client, err := mongo.Connect(context.Background(), bm.opt) if err != nil { b.Fatalf("error creating client: %v", err) } - ctx := context.Background() - err = client.Connect(ctx) - if err != nil { - b.Fatalf("error connecting: %v", err) - } defer func() { _ = client.Disconnect(context.Background()) }() coll := client.Database("test").Collection("test") _, err = coll.DeleteMany(context.Background(), bson.D{}) @@ -125,15 +115,10 @@ func BenchmarkClientRead(b *testing.B) { } for _, bm := range benchmarks { b.Run(bm.name, func(b *testing.B) { - client, err := mongo.NewClient(bm.opt) + client, err := mongo.Connect(context.Background(), bm.opt) if err != nil { b.Fatalf("error creating client: %v", err) } - ctx := context.Background() - err = client.Connect(ctx) - if err != nil { - b.Fatalf("error connecting: %v", err) - } defer func() { _ = client.Disconnect(context.Background()) }() coll := client.Database("test").Collection("test") _, err = coll.DeleteMany(context.Background(), bson.D{}) diff --git a/benchmark/single.go b/benchmark/single.go index da286c7e02..d8366e34f6 100644 --- a/benchmark/single.go +++ b/benchmark/single.go @@ -29,13 +29,10 @@ func getClientDB(ctx context.Context) (*mongo.Database, error) { if err != nil { return nil, err } - client, err := mongo.NewClient(options.Client().ApplyURI(cs.String())) + client, err := mongo.Connect(ctx, options.Client().ApplyURI(cs.String())) if err != nil { return nil, err } - if err = client.Connect(ctx); err != nil { - return nil, err - } db := client.Database(integtest.GetDBName(cs)) return db, nil diff --git a/event/monitoring.go b/event/monitoring.go index 53d1caf2e3..edfca3fa68 100644 --- a/event/monitoring.go +++ b/event/monitoring.go @@ -23,12 +23,6 @@ type CommandStartedEvent struct { CommandName string RequestID int64 ConnectionID string - // ServerConnectionID contains the connection ID from the server of the operation. If the server does not return - // this value (e.g. on MDB < 4.2), it is unset. If the server connection ID would cause an int32 overflow, then - // then this field will be nil. - // - // Deprecated: Use ServerConnectionID64. - ServerConnectionID *int32 // ServerConnectionID64 contains the connection ID from the server of the operation. If the server does not // return this value (e.g. on MDB < 4.2), it is unset. ServerConnectionID64 *int64 @@ -39,19 +33,11 @@ type CommandStartedEvent struct { // CommandFinishedEvent represents a generic command finishing. type CommandFinishedEvent struct { - // Deprecated: Use Duration instead. - DurationNanos int64 - Duration time.Duration - CommandName string - DatabaseName string - RequestID int64 - ConnectionID string - // ServerConnectionID contains the connection ID from the server of the operation. If the server does not return - // this value (e.g. on MDB < 4.2), it is unset.If the server connection ID would cause an int32 overflow, then - // this field will be nil. - // - // Deprecated: Use ServerConnectionID64. - ServerConnectionID *int32 + Duration time.Duration + CommandName string + DatabaseName string + RequestID int64 + ConnectionID string // ServerConnectionID64 contains the connection ID from the server of the operation. If the server does not // return this value (e.g. on MDB < 4.2), it is unset. ServerConnectionID64 *int64 @@ -174,22 +160,18 @@ type ServerHeartbeatStartedEvent struct { // ServerHeartbeatSucceededEvent is an event generated when the heartbeat succeeds. type ServerHeartbeatSucceededEvent struct { - // Deprecated: Use Duration instead. - DurationNanos int64 - Duration time.Duration - Reply description.Server - ConnectionID string // The address this heartbeat was sent to with a unique identifier - Awaited bool // If this heartbeat was awaitable + Duration time.Duration + Reply description.Server + ConnectionID string // The address this heartbeat was sent to with a unique identifier + Awaited bool // If this heartbeat was awaitable } // ServerHeartbeatFailedEvent is an event generated when the heartbeat fails. type ServerHeartbeatFailedEvent struct { - // Deprecated: Use Duration instead. - DurationNanos int64 - Duration time.Duration - Failure error - ConnectionID string // The address this heartbeat was sent to with a unique identifier - Awaited bool // If this heartbeat was awaitable + Duration time.Duration + Failure error + ConnectionID string // The address this heartbeat was sent to with a unique identifier + Awaited bool // If this heartbeat was awaitable } // ServerMonitor represents a monitor that is triggered for different server events. The client diff --git a/examples/documentation_examples/examples.go b/examples/documentation_examples/examples.go index b188448a02..fdae3e357e 100644 --- a/examples/documentation_examples/examples.go +++ b/examples/documentation_examples/examples.go @@ -1763,7 +1763,7 @@ func UpdateEmployeeInfo(ctx context.Context, client *mongo.Client) error { return client.UseSession(ctx, func(sctx mongo.SessionContext) error { err := sctx.StartTransaction(options.Transaction(). SetReadConcern(readconcern.Snapshot()). - SetWriteConcern(writeconcern.New(writeconcern.WMajority())), + SetWriteConcern(writeconcern.Majority()), ) if err != nil { return err @@ -1921,7 +1921,7 @@ func TransactionsExamples(ctx context.Context, client *mongo.Client) error { err := sctx.StartTransaction(options.Transaction(). SetReadConcern(readconcern.Snapshot()). - SetWriteConcern(writeconcern.New(writeconcern.WMajority())), + SetWriteConcern(writeconcern.Majority()), ) if err != nil { return err @@ -1971,7 +1971,8 @@ func WithTransactionExample(ctx context.Context) error { defer func() { _ = client.Disconnect(ctx) }() // Prereq: Create collections. - wcMajority := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second)) + wcMajority := writeconcern.Majority() + wcMajority.WTimeout = 1 * time.Second wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority) fooColl := client.Database("mydb1").Collection("foo", wcMajorityCollectionOpts) barColl := client.Database("mydb1").Collection("bar", wcMajorityCollectionOpts) @@ -2550,9 +2551,11 @@ func CausalConsistencyExamples(client *mongo.Client) error { // Start Causal Consistency Example 1 + rc := readconcern.Majority() + wc := writeconcern.Majority() + wc.WTimeout = 1000 // Use a causally-consistent session to run some operations - opts := options.Session().SetDefaultReadConcern(readconcern.Majority()).SetDefaultWriteConcern( - writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1000))) + opts := options.Session().SetDefaultReadConcern(rc).SetDefaultWriteConcern(wc) session1, err := client.StartSession(opts) if err != nil { return err @@ -2584,9 +2587,8 @@ func CausalConsistencyExamples(client *mongo.Client) error { // Start Causal Consistency Example 2 // Make a new session that is causally consistent with session1 so session2 reads what session1 writes - opts = options.Session().SetDefaultReadPreference(readpref.Secondary()).SetDefaultReadConcern( - readconcern.Majority()).SetDefaultWriteConcern(writeconcern.New(writeconcern.WMajority(), - writeconcern.WTimeout(1000))) + opts = options.Session().SetDefaultReadPreference(readpref.Secondary()). + SetDefaultReadConcern(rc).SetDefaultWriteConcern(wc) session2, err := client.StartSession(opts) if err != nil { return err diff --git a/mongo/change_stream.go b/mongo/change_stream.go index 773cbb0e5d..b7e16f99aa 100644 --- a/mongo/change_stream.go +++ b/mongo/change_stream.go @@ -101,6 +101,55 @@ type changeStreamConfig struct { crypt driver.Crypt } +// mergeChangeStreamOptions combines the given ChangeStreamOptions instances into a single ChangeStreamOptions in a +// last-property-wins fashion. +func mergeChangeStreamOptions(opts ...*options.ChangeStreamOptions) *options.ChangeStreamOptions { + csOpts := options.ChangeStream() + for _, cso := range opts { + if cso == nil { + continue + } + if cso.BatchSize != nil { + csOpts.BatchSize = cso.BatchSize + } + if cso.Collation != nil { + csOpts.Collation = cso.Collation + } + if cso.Comment != nil { + csOpts.Comment = cso.Comment + } + if cso.FullDocument != nil { + csOpts.FullDocument = cso.FullDocument + } + if cso.FullDocumentBeforeChange != nil { + csOpts.FullDocumentBeforeChange = cso.FullDocumentBeforeChange + } + if cso.MaxAwaitTime != nil { + csOpts.MaxAwaitTime = cso.MaxAwaitTime + } + if cso.ResumeAfter != nil { + csOpts.ResumeAfter = cso.ResumeAfter + } + if cso.ShowExpandedEvents != nil { + csOpts.ShowExpandedEvents = cso.ShowExpandedEvents + } + if cso.StartAtOperationTime != nil { + csOpts.StartAtOperationTime = cso.StartAtOperationTime + } + if cso.StartAfter != nil { + csOpts.StartAfter = cso.StartAfter + } + if cso.Custom != nil { + csOpts.Custom = cso.Custom + } + if cso.CustomPipeline != nil { + csOpts.CustomPipeline = cso.CustomPipeline + } + } + + return csOpts +} + func newChangeStream(ctx context.Context, config changeStreamConfig, pipeline interface{}, opts ...*options.ChangeStreamOptions) (*ChangeStream, error) { if ctx == nil { @@ -116,7 +165,7 @@ func newChangeStream(ctx context.Context, config changeStreamConfig, pipeline in bsonOpts: config.bsonOpts, registry: config.registry, streamType: config.streamType, - options: options.MergeChangeStreamOptions(opts...), + options: mergeChangeStreamOptions(opts...), selector: description.CompositeSelector([]description.ServerSelector{ description.ReadPrefSelector(config.readPreference), description.LatencySelector(config.client.localThreshold), diff --git a/mongo/change_stream_test.go b/mongo/change_stream_test.go index 31066a8c06..fa44713593 100644 --- a/mongo/change_stream_test.go +++ b/mongo/change_stream_test.go @@ -10,6 +10,7 @@ import ( "testing" "go.mongodb.org/mongo-driver/internal/assert" + "go.mongodb.org/mongo-driver/mongo/options" ) func TestChangeStream(t *testing.T) { @@ -27,3 +28,65 @@ func TestChangeStream(t *testing.T) { assert.Nil(t, err, "Close error: %v", err) }) } + +func TestMergeChangeStreamOptions(t *testing.T) { + t.Parallel() + + fullDocumentP := func(x options.FullDocument) *options.FullDocument { return &x } + int32P := func(x int32) *int32 { return &x } + + testCases := []struct { + description string + input []*options.ChangeStreamOptions + want *options.ChangeStreamOptions + }{ + { + description: "nil", + input: nil, + want: &options.ChangeStreamOptions{}, + }, + { + description: "empty", + input: []*options.ChangeStreamOptions{}, + want: &options.ChangeStreamOptions{}, + }, + { + description: "many ChangeStreamOptions with one configuration each", + input: []*options.ChangeStreamOptions{ + options.ChangeStream().SetFullDocumentBeforeChange(options.Required), + options.ChangeStream().SetFullDocument(options.Required), + options.ChangeStream().SetBatchSize(10), + }, + want: &options.ChangeStreamOptions{ + FullDocument: fullDocumentP(options.Required), + FullDocumentBeforeChange: fullDocumentP(options.Required), + BatchSize: int32P(10), + }, + }, + { + description: "single ChangeStreamOptions with many configurations", + input: []*options.ChangeStreamOptions{ + options.ChangeStream(). + SetFullDocumentBeforeChange(options.Required). + SetFullDocument(options.Required). + SetBatchSize(10), + }, + want: &options.ChangeStreamOptions{ + FullDocument: fullDocumentP(options.Required), + FullDocumentBeforeChange: fullDocumentP(options.Required), + BatchSize: int32P(10), + }, + }, + } + + for _, tc := range testCases { + tc := tc // Capture range variable. + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + got := mergeChangeStreamOptions(tc.input...) + assert.Equal(t, tc.want, got, "expected and actual ChangeStreamOptions are different") + }) + } +} diff --git a/mongo/client.go b/mongo/client.go index 5929274831..56641179d0 100644 --- a/mongo/client.go +++ b/mongo/client.go @@ -41,7 +41,7 @@ const ( var ( // keyVaultCollOpts specifies options used to communicate with the key vault collection keyVaultCollOpts = options.Collection().SetReadConcern(readconcern.Majority()). - SetWriteConcern(writeconcern.New(writeconcern.WMajority())) + SetWriteConcern(writeconcern.Majority()) endSessionsBatchSize = 10000 ) @@ -81,8 +81,7 @@ type Client struct { encryptedFieldsMap map[string]interface{} } -// Connect creates a new Client and then initializes it using the Connect method. This is equivalent to calling -// NewClient followed by Client.Connect. +// Connect creates a new Client and then initializes it using the Connect method. // // When creating an options.ClientOptions, the order the methods are called matters. Later Set* // methods will overwrite the values from previous Set* method invocations. This includes the @@ -104,18 +103,18 @@ type Client struct { // The Client.Ping method can be used to verify that the deployment is successfully connected and the // Client was correctly configured. func Connect(ctx context.Context, opts ...*options.ClientOptions) (*Client, error) { - c, err := NewClient(opts...) + c, err := newClient(opts...) if err != nil { return nil, err } - err = c.Connect(ctx) + err = c.connect(ctx) if err != nil { return nil, err } return c, nil } -// NewClient creates a new client to connect to a deployment specified by the uri. +// newClient creates a new client to connect to a deployment specified by the uri. // // When creating an options.ClientOptions, the order the methods are called matters. Later Set* // methods will overwrite the values from previous Set* method invocations. This includes the @@ -128,9 +127,7 @@ func Connect(ctx context.Context, opts ...*options.ClientOptions) (*Client, erro // option fields of previous options, there is no partial overwriting. For example, if Username is // set in the Auth field for the first option, and Password is set for the second but with no // Username, after the merge the Username field will be empty. -// -// Deprecated: Use [Connect] instead. -func NewClient(opts ...*options.ClientOptions) (*Client, error) { +func newClient(opts ...*options.ClientOptions) (*Client, error) { clientOpt := options.MergeClientOptions(opts...) id, err := uuid.New() @@ -156,7 +153,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 } @@ -235,14 +232,12 @@ func NewClient(opts ...*options.ClientOptions) (*Client, error) { return client, nil } -// Connect initializes the Client by starting background monitoring goroutines. +// connect initializes the Client by starting background monitoring goroutines. // If the Client was created using the NewClient function, this method must be called before a Client can be used. // // Connect starts background goroutines to monitor the state of the deployment and does not do any I/O in the main // goroutine. The Client.Ping method can be used to verify that the connection was created successfully. -// -// Deprecated: Use [mongo.Connect] instead. -func (c *Client) Connect(ctx context.Context) error { +func (c *Client) connect(ctx context.Context) error { if connector, ok := c.deployment.(driver.Connector); ok { err := connector.Connect() if err != nil { @@ -257,19 +252,19 @@ func (c *Client) Connect(ctx context.Context) error { } if c.internalClientFLE != nil { - if err := c.internalClientFLE.Connect(ctx); err != nil { + if err := c.internalClientFLE.connect(ctx); err != nil { return err } } if c.keyVaultClientFLE != nil && c.keyVaultClientFLE != c.internalClientFLE && c.keyVaultClientFLE != c { - if err := c.keyVaultClientFLE.Connect(ctx); err != nil { + if err := c.keyVaultClientFLE.connect(ctx); err != nil { return err } } if c.metadataClientFLE != nil && c.metadataClientFLE != c.internalClientFLE && c.metadataClientFLE != c { - if err := c.metadataClientFLE.Connect(ctx); err != nil { + if err := c.metadataClientFLE.connect(ctx); err != nil { return err } } @@ -384,7 +379,33 @@ func (c *Client) StartSession(opts ...*options.SessionOptions) (Session, error) return nil, ErrClientDisconnected } - sopts := options.MergeSessionOptions(opts...) + sopts := options.Session() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.CausalConsistency != nil { + sopts.CausalConsistency = opt.CausalConsistency + } + if opt.DefaultReadConcern != nil { + sopts.DefaultReadConcern = opt.DefaultReadConcern + } + if opt.DefaultReadPreference != nil { + sopts.DefaultReadPreference = opt.DefaultReadPreference + } + if opt.DefaultWriteConcern != nil { + sopts.DefaultWriteConcern = opt.DefaultWriteConcern + } + if opt.DefaultMaxCommitTime != nil { + sopts.DefaultMaxCommitTime = opt.DefaultMaxCommitTime + } + if opt.Snapshot != nil { + sopts.Snapshot = opt.Snapshot + } + } + if sopts.CausalConsistency == nil && (sopts.Snapshot == nil || !*sopts.Snapshot) { + sopts.CausalConsistency = &options.DefaultCausalConsistency + } coreOpts := &session.ClientOptions{ DefaultReadConcern: c.readConcern, DefaultReadPreference: c.readPreference, @@ -489,7 +510,7 @@ func (c *Client) getOrCreateInternalClient(clientOpts *options.ClientOptions) (* internalClientOpts.AutoEncryptionOptions = nil internalClientOpts.SetMinPoolSize(0) var err error - c.internalClientFLE, err = NewClient(internalClientOpts) + c.internalClientFLE, err = newClient(internalClientOpts) return c.internalClientFLE, err } @@ -499,7 +520,7 @@ func (c *Client) configureKeyVaultClientFLE(clientOpts *options.ClientOptions) e aeOpts := clientOpts.AutoEncryptionOptions switch { case aeOpts.KeyVaultClientOptions != nil: - c.keyVaultClientFLE, err = NewClient(aeOpts.KeyVaultClientOptions) + c.keyVaultClientFLE, err = newClient(aeOpts.KeyVaultClientOptions) case clientOpts.MaxPoolSize != nil && *clientOpts.MaxPoolSize == 0: c.keyVaultClientFLE = c default: @@ -690,7 +711,18 @@ func (c *Client) ListDatabases(ctx context.Context, filter interface{}, opts ... }) selector = makeReadPrefSelector(sess, selector, c.localThreshold) - ldo := options.MergeListDatabasesOptions(opts...) + ldo := options.ListDatabases() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.NameOnly != nil { + ldo.NameOnly = opt.NameOnly + } + if opt.AuthorizedDatabases != nil { + ldo.AuthorizedDatabases = opt.AuthorizedDatabases + } + } op := operation.NewListDatabases(filterDoc). Session(sess).ReadPreference(c.readPreference).CommandMonitor(c.monitor). ServerSelector(selector).ClusterClock(c.clock).Database("admin").Deployment(c.deployment).Crypt(c.cryptFLE). diff --git a/mongo/client_encryption.go b/mongo/client_encryption.go index 01c2ec3193..c03afc8e67 100644 --- a/mongo/client_encryption.go +++ b/mongo/client_encryption.go @@ -38,7 +38,25 @@ func NewClientEncryption(keyVaultClient *Client, opts ...*options.ClientEncrypti ce := &ClientEncryption{ keyVaultClient: keyVaultClient, } - ceo := options.MergeClientEncryptionOptions(opts...) + ceo := options.ClientEncryption() + for _, opt := range opts { + if opt == nil { + continue + } + + if opt.KeyVaultNamespace != "" { + ceo.KeyVaultNamespace = opt.KeyVaultNamespace + } + if opt.KmsProviders != nil { + ceo.KmsProviders = opt.KmsProviders + } + if opt.TLSConfig != nil { + ceo.TLSConfig = opt.TLSConfig + } + if opt.HTTPClient != nil { + ceo.HTTPClient = opt.HTTPClient + } + } // create keyVaultColl db, coll := splitNamespace(ceo.KeyVaultNamespace) @@ -144,7 +162,22 @@ func (ce *ClientEncryption) CreateDataKey(ctx context.Context, kmsProvider strin opts ...*options.DataKeyOptions) (primitive.Binary, error) { // translate opts to mcopts.DataKeyOptions - dko := options.MergeDataKeyOptions(opts...) + dko := options.DataKey() + for _, opt := range opts { + if opt == nil { + continue + } + + if opt.MasterKey != nil { + dko.MasterKey = opt.MasterKey + } + if opt.KeyAltNames != nil { + dko.KeyAltNames = opt.KeyAltNames + } + if opt.KeyMaterial != nil { + dko.KeyMaterial = opt.KeyMaterial + } + } co := mcopts.DataKey().SetKeyAltNames(dko.KeyAltNames) if dko.MasterKey != nil { keyDoc, err := marshal( @@ -178,7 +211,31 @@ func (ce *ClientEncryption) CreateDataKey(ctx context.Context, kmsProvider strin // transformExplicitEncryptionOptions creates explicit encryption options to be passed to libmongocrypt. func transformExplicitEncryptionOptions(opts ...*options.EncryptOptions) *mcopts.ExplicitEncryptionOptions { - eo := options.MergeEncryptOptions(opts...) + eo := options.Encrypt() + for _, opt := range opts { + if opt == nil { + continue + } + + if opt.KeyID != nil { + eo.KeyID = opt.KeyID + } + if opt.KeyAltName != nil { + eo.KeyAltName = opt.KeyAltName + } + if opt.Algorithm != "" { + eo.Algorithm = opt.Algorithm + } + if opt.QueryType != "" { + eo.QueryType = opt.QueryType + } + if opt.ContentionFactor != nil { + eo.ContentionFactor = opt.ContentionFactor + } + if opt.RangeOptions != nil { + eo.RangeOptions = opt.RangeOptions + } + } transformed := mcopts.ExplicitEncryption() if eo.KeyID != nil { transformed.SetKeyID(*eo.KeyID) @@ -375,7 +432,18 @@ func (ce *ClientEncryption) RewrapManyDataKey(ctx context.Context, filter interf return nil, fmt.Errorf("RewrapManyDataKey requires libmongocrypt 1.5.2 or newer. Detected version: %v", libmongocryptVersion) } - rmdko := options.MergeRewrapManyDataKeyOptions(opts...) + rmdko := options.RewrapManyDataKey() + for _, opt := range opts { + if opt == nil { + continue + } + if provider := opt.Provider; provider != nil { + rmdko.Provider = provider + } + if masterKey := opt.MasterKey; masterKey != nil { + rmdko.MasterKey = masterKey + } + } if ctx == nil { ctx = context.Background() } diff --git a/mongo/client_test.go b/mongo/client_test.go index e1e8f322a8..5ba4cb4a2e 100644 --- a/mongo/client_test.go +++ b/mongo/client_test.go @@ -35,7 +35,7 @@ func setupClient(opts ...*options.ClientOptions) *Client { integtest.AddTestServerAPIVersion(clientOpts) opts = append(opts, clientOpts) } - client, _ := NewClient(opts...) + client, _ := newClient(opts...) return client } @@ -183,7 +183,7 @@ func TestClient(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - _, err := NewClient(tc.opts) + _, err := newClient(tc.opts) assert.Equal(t, tc.err, err, "expected error %v, got %v", tc.err, err) }) } @@ -227,7 +227,7 @@ func TestClient(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - _, err := NewClient(tc.opts) + _, err := newClient(tc.opts) assert.Equal(t, tc.err, err, "expected error %v, got %v", tc.err, err) }) } @@ -249,7 +249,7 @@ func TestClient(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - client, err := NewClient(tc.opts) + client, err := newClient(tc.opts) if tc.expectErr { assert.NotNil(t, err, "expected error, got nil") return @@ -277,7 +277,7 @@ func TestClient(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - client, err := NewClient(tc.opts) + client, err := newClient(tc.opts) if tc.expectErr { assert.NotNil(t, err, "expected error, got nil") return @@ -289,7 +289,7 @@ func TestClient(t *testing.T) { } }) t.Run("write concern", func(t *testing.T) { - wc := writeconcern.New(writeconcern.WMajority()) + wc := writeconcern.Majority() client := setupClient(options.Client().SetWriteConcern(wc)) assert.Equal(t, wc, client.writeConcern, "mismatch; expected write concern %v, got %v", wc, client.writeConcern) }) @@ -354,7 +354,7 @@ func TestClient(t *testing.T) { }, } clientOpts := options.Client().ApplyURI(cs.Original).SetReadPreference(readpref.Primary()). - SetWriteConcern(writeconcern.New(writeconcern.WMajority())).SetMonitor(cmdMonitor) + SetWriteConcern(writeconcern.Majority()).SetMonitor(cmdMonitor) integtest.AddTestServerAPIVersion(clientOpts) client, err := Connect(bgCtx, clientOpts) assert.Nil(t, err, "Connect error: %v", err) @@ -412,7 +412,7 @@ func TestClient(t *testing.T) { t.Run("success with all options", func(t *testing.T) { serverAPIOptions := getServerAPIOptions() - client, err := NewClient(options.Client().SetServerAPIOptions(serverAPIOptions)) + client, err := newClient(options.Client().SetServerAPIOptions(serverAPIOptions)) assert.Nil(t, err, "unexpected error from NewClient: %v", err) convertedAPIOptions := topology.ConvertToDriverAPIOptions(serverAPIOptions) assert.Equal(t, convertedAPIOptions, client.serverAPI, @@ -420,14 +420,14 @@ func TestClient(t *testing.T) { }) t.Run("failure with unsupported version", func(t *testing.T) { serverAPIOptions := options.ServerAPI("badVersion") - _, err := NewClient(options.Client().SetServerAPIOptions(serverAPIOptions)) + _, err := newClient(options.Client().SetServerAPIOptions(serverAPIOptions)) assert.NotNil(t, err, "expected error from NewClient, got nil") errmsg := `api version "badVersion" not supported; this driver version only supports API version "1"` assert.Equal(t, errmsg, err.Error(), "expected error %v, got %v", errmsg, err.Error()) }) t.Run("cannot modify options after client creation", func(t *testing.T) { serverAPIOptions := getServerAPIOptions() - client, err := NewClient(options.Client().SetServerAPIOptions(serverAPIOptions)) + client, err := newClient(options.Client().SetServerAPIOptions(serverAPIOptions)) assert.Nil(t, err, "unexpected error from NewClient: %v", err) expectedServerAPIOptions := getServerAPIOptions() @@ -476,7 +476,7 @@ func TestClient(t *testing.T) { extraOptions["__cryptSharedLibDisabledForTestOnly"] = true } - _, err := NewClient(options.Client(). + _, err := newClient(options.Client(). SetAutoEncryptionOptions(options.AutoEncryption(). SetKmsProviders(map[string]map[string]interface{}{ "local": {"key": make([]byte, 96)}, diff --git a/mongo/collection.go b/mongo/collection.go index 6699a6d4c0..129df8ff57 100644 --- a/mongo/collection.go +++ b/mongo/collection.go @@ -68,8 +68,34 @@ func closeImplicitSession(sess *session.Client) { } } +// mergeCollectionOptions combines the given CollectionOptions instances into a single *CollectionOptions in a +// last-property-wins fashion. +func mergeCollectionOptions(opts ...*options.CollectionOptions) *options.CollectionOptions { + c := options.Collection() + + for _, opt := range opts { + if opt == nil { + continue + } + if opt.ReadConcern != nil { + c.ReadConcern = opt.ReadConcern + } + if opt.WriteConcern != nil { + c.WriteConcern = opt.WriteConcern + } + if opt.ReadPreference != nil { + c.ReadPreference = opt.ReadPreference + } + if opt.Registry != nil { + c.Registry = opt.Registry + } + } + + return c +} + func newCollection(db *Database, name string, opts ...*options.CollectionOptions) *Collection { - collOpt := options.MergeCollectionOptions(opts...) + collOpt := mergeCollectionOptions(opts...) rc := db.readConcern if collOpt.ReadConcern != nil { @@ -141,7 +167,7 @@ func (coll *Collection) copy() *Collection { // precedence. func (coll *Collection) Clone(opts ...*options.CollectionOptions) (*Collection, error) { copyColl := coll.copy() - optsColl := options.MergeCollectionOptions(opts...) + optsColl := mergeCollectionOptions(opts...) if optsColl.ReadConcern != nil { copyColl.readConcern = optsColl.ReadConcern @@ -210,7 +236,7 @@ func (coll *Collection) BulkWrite(ctx context.Context, models []WriteModel, if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } @@ -222,7 +248,24 @@ func (coll *Collection) BulkWrite(ctx context.Context, models []WriteModel, } } - bwo := options.MergeBulkWriteOptions(opts...) + bwo := options.BulkWrite() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.Comment != nil { + bwo.Comment = opt.Comment + } + if opt.Ordered != nil { + bwo.Ordered = opt.Ordered + } + if opt.BypassDocumentValidation != nil { + bwo.BypassDocumentValidation = opt.BypassDocumentValidation + } + if opt.Let != nil { + bwo.Let = opt.Let + } + } op := bulkWrite{ comment: bwo.Comment, @@ -280,7 +323,7 @@ func (coll *Collection) insert(ctx context.Context, documents []interface{}, if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } @@ -292,7 +335,21 @@ func (coll *Collection) insert(ctx context.Context, documents []interface{}, Database(coll.db.name).Collection(coll.name). Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Ordered(true). ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout).Logger(coll.client.logger) - imo := options.MergeInsertManyOptions(opts...) + imo := options.InsertMany() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.BypassDocumentValidation != nil { + imo.BypassDocumentValidation = opt.BypassDocumentValidation + } + if opt.Comment != nil { + imo.Comment = opt.Comment + } + if opt.Ordered != nil { + imo.Ordered = opt.Ordered + } + } if imo.BypassDocumentValidation != nil && *imo.BypassDocumentValidation { op = op.BypassDocumentValidation(*imo.BypassDocumentValidation) } @@ -345,7 +402,18 @@ func (coll *Collection) insert(ctx context.Context, documents []interface{}, func (coll *Collection) InsertOne(ctx context.Context, document interface{}, opts ...*options.InsertOneOptions) (*InsertOneResult, error) { - ioOpts := options.MergeInsertOneOptions(opts...) + ioOpts := options.InsertOne() + for _, ioo := range opts { + if ioo == nil { + continue + } + if ioo.BypassDocumentValidation != nil { + ioOpts.BypassDocumentValidation = ioo.BypassDocumentValidation + } + if ioo.Comment != nil { + ioOpts.Comment = ioo.Comment + } + } imOpts := options.InsertMany() if ioOpts.BypassDocumentValidation != nil && *ioOpts.BypassDocumentValidation { @@ -436,7 +504,7 @@ func (coll *Collection) delete(ctx context.Context, filter interface{}, deleteOn if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } @@ -446,7 +514,26 @@ func (coll *Collection) delete(ctx context.Context, filter interface{}, deleteOn if deleteOne { limit = 1 } - do := options.MergeDeleteOptions(opts...) + + do := options.Delete() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.Collation != nil { + do.Collation = opt.Collation + } + if opt.Comment != nil { + do.Comment = opt.Comment + } + if opt.Hint != nil { + do.Hint = opt.Hint + } + if opt.Let != nil { + do.Let = opt.Let + } + } + didx, doc := bsoncore.AppendDocumentStart(nil) doc = bsoncore.AppendDocumentElement(doc, "q", f) doc = bsoncore.AppendInt32Element(doc, "limit", limit) @@ -542,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 @@ -576,7 +689,7 @@ func (coll *Collection) updateOrReplace(ctx context.Context, filter bsoncore.Doc if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } @@ -796,6 +909,49 @@ func (coll *Collection) Aggregate(ctx context.Context, pipeline interface{}, return aggregate(a) } +// mergeAggregateOptions combines the given AggregateOptions instances into a single AggregateOptions in a last-property-wins +// fashion. +func mergeAggregateOptions(opts ...*options.AggregateOptions) *options.AggregateOptions { + aggOpts := options.Aggregate() + for _, ao := range opts { + if ao == nil { + continue + } + if ao.AllowDiskUse != nil { + aggOpts.AllowDiskUse = ao.AllowDiskUse + } + if ao.BatchSize != nil { + aggOpts.BatchSize = ao.BatchSize + } + if ao.BypassDocumentValidation != nil { + aggOpts.BypassDocumentValidation = ao.BypassDocumentValidation + } + if ao.Collation != nil { + aggOpts.Collation = ao.Collation + } + if ao.MaxTime != nil { + aggOpts.MaxTime = ao.MaxTime + } + if ao.MaxAwaitTime != nil { + aggOpts.MaxAwaitTime = ao.MaxAwaitTime + } + if ao.Comment != nil { + aggOpts.Comment = ao.Comment + } + if ao.Hint != nil { + aggOpts.Hint = ao.Hint + } + if ao.Let != nil { + aggOpts.Let = ao.Let + } + if ao.Custom != nil { + aggOpts.Custom = ao.Custom + } + } + + return aggOpts +} + // aggregate is the helper method for Aggregate func aggregate(a aggregateParams) (cur *Cursor, err error) { if a.ctx == nil { @@ -830,7 +986,7 @@ func aggregate(a aggregateParams) (cur *Cursor, err error) { wc = nil rc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { closeImplicitSession(sess) sess = nil } @@ -840,7 +996,7 @@ func aggregate(a aggregateParams) (cur *Cursor, err error) { selector = makeOutputAggregateSelector(sess, a.readPreference, a.client.localThreshold) } - ao := options.MergeAggregateOptions(a.opts...) + ao := mergeAggregateOptions(a.opts...) cursorOpts := a.client.createBaseCursorOptions() @@ -958,7 +1114,30 @@ func (coll *Collection) CountDocuments(ctx context.Context, filter interface{}, ctx = context.Background() } - countOpts := options.MergeCountOptions(opts...) + countOpts := options.Count() + for _, co := range opts { + if co == nil { + continue + } + if co.Collation != nil { + countOpts.Collation = co.Collation + } + if co.Comment != nil { + countOpts.Comment = co.Comment + } + if co.Hint != nil { + countOpts.Hint = co.Hint + } + if co.Limit != nil { + countOpts.Limit = co.Limit + } + if co.MaxTime != nil { + countOpts.MaxTime = co.MaxTime + } + if co.Skip != nil { + countOpts.Skip = co.Skip + } + } pipelineArr, err := countDocumentsAggregatePipeline(filter, coll.bsonOpts, coll.registry, countOpts) if err != nil { @@ -1061,8 +1240,18 @@ func (coll *Collection) EstimatedDocumentCount(ctx context.Context, rc = nil } - co := options.MergeEstimatedDocumentCountOptions(opts...) - + co := options.EstimatedDocumentCount() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.Comment != nil { + co.Comment = opt.Comment + } + if opt.MaxTime != nil { + co.MaxTime = opt.MaxTime + } + } selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold) op := operation.NewCount().Session(sess).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name).CommandMonitor(coll.client.monitor). @@ -1128,7 +1317,21 @@ func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter i } selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold) - option := options.MergeDistinctOptions(opts...) + option := options.Distinct() + for _, do := range opts { + if do == nil { + continue + } + if do.Collation != nil { + option.Collation = do.Collation + } + if do.Comment != nil { + option.Comment = do.Comment + } + if do.MaxTime != nil { + option.MaxTime = do.MaxTime + } + } op := operation.NewDistinct(fieldName, f). Session(sess).ClusterClock(coll.client.clock). @@ -1181,6 +1384,75 @@ func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter i return retArray, replaceErrors(err) } +// mergeFindOptions combines the given FindOptions instances into a single FindOptions in a last-property-wins fashion. +func mergeFindOptions(opts ...*options.FindOptions) *options.FindOptions { + fo := options.Find() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.AllowDiskUse != nil { + fo.AllowDiskUse = opt.AllowDiskUse + } + if opt.AllowPartialResults != nil { + fo.AllowPartialResults = opt.AllowPartialResults + } + if opt.BatchSize != nil { + fo.BatchSize = opt.BatchSize + } + if opt.Collation != nil { + fo.Collation = opt.Collation + } + if opt.Comment != nil { + fo.Comment = opt.Comment + } + if opt.CursorType != nil { + fo.CursorType = opt.CursorType + } + if opt.Hint != nil { + fo.Hint = opt.Hint + } + if opt.Let != nil { + fo.Let = opt.Let + } + if opt.Limit != nil { + fo.Limit = opt.Limit + } + if opt.Max != nil { + fo.Max = opt.Max + } + if opt.MaxAwaitTime != nil { + fo.MaxAwaitTime = opt.MaxAwaitTime + } + if opt.MaxTime != nil { + fo.MaxTime = opt.MaxTime + } + if opt.Min != nil { + fo.Min = opt.Min + } + if opt.NoCursorTimeout != nil { + fo.NoCursorTimeout = opt.NoCursorTimeout + } + if opt.Projection != nil { + fo.Projection = opt.Projection + } + if opt.ReturnKey != nil { + fo.ReturnKey = opt.ReturnKey + } + if opt.ShowRecordID != nil { + fo.ShowRecordID = opt.ShowRecordID + } + if opt.Skip != nil { + fo.Skip = opt.Skip + } + if opt.Sort != nil { + fo.Sort = opt.Sort + } + } + + return fo +} + // Find executes a find command and returns a Cursor over the matching documents in the collection. // // The filter parameter must be a document containing query operators and can be used to select which documents are @@ -1222,7 +1494,7 @@ func (coll *Collection) Find(ctx context.Context, filter interface{}, rc = nil } - fo := options.MergeFindOptions(opts...) + fo := mergeFindOptions(opts...) selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold) op := operation.NewFind(f). @@ -1313,9 +1585,6 @@ func (coll *Collection) Find(ctx context.Context, filter interface{}, if fo.NoCursorTimeout != nil { op.NoCursorTimeout(*fo.NoCursorTimeout) } - if fo.OplogReplay != nil { - op.OplogReplay(*fo.OplogReplay) - } if fo.Projection != nil { proj, err := marshal(fo.Projection, coll.bsonOpts, coll.registry) if err != nil { @@ -1332,9 +1601,6 @@ func (coll *Collection) Find(ctx context.Context, filter interface{}, if fo.Skip != nil { op.Skip(*fo.Skip) } - if fo.Snapshot != nil { - op.Snapshot(*fo.Snapshot) - } if fo.Sort != nil { if isUnorderedMap(fo.Sort) { return nil, ErrMapForOrderedArgument{"sort"} @@ -1385,22 +1651,16 @@ func (coll *Collection) FindOne(ctx context.Context, filter interface{}, } findOpts = append(findOpts, &options.FindOptions{ AllowPartialResults: opt.AllowPartialResults, - BatchSize: opt.BatchSize, Collation: opt.Collation, Comment: opt.Comment, - CursorType: opt.CursorType, Hint: opt.Hint, Max: opt.Max, - MaxAwaitTime: opt.MaxAwaitTime, MaxTime: opt.MaxTime, Min: opt.Min, - NoCursorTimeout: opt.NoCursorTimeout, - OplogReplay: opt.OplogReplay, Projection: opt.Projection, ReturnKey: opt.ReturnKey, ShowRecordID: opt.ShowRecordID, Skip: opt.Skip, - Snapshot: opt.Snapshot, Sort: opt.Sort, }) } @@ -1439,7 +1699,7 @@ func (coll *Collection) findAndModify(ctx context.Context, op *operation.FindAnd if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } @@ -1474,6 +1734,40 @@ func (coll *Collection) findAndModify(ctx context.Context, op *operation.FindAnd } } +// mergeFindOneAndDeleteOptions combines the given FindOneAndDeleteOptions instances into a single +// FindOneAndDeleteOptions in a last-property-wins fashion. +func mergeFindOneAndDeleteOptions(opts ...*options.FindOneAndDeleteOptions) *options.FindOneAndDeleteOptions { + fo := options.FindOneAndDelete() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.Collation != nil { + fo.Collation = opt.Collation + } + if opt.Comment != nil { + fo.Comment = opt.Comment + } + if opt.MaxTime != nil { + fo.MaxTime = opt.MaxTime + } + if opt.Projection != nil { + fo.Projection = opt.Projection + } + if opt.Sort != nil { + fo.Sort = opt.Sort + } + if opt.Hint != nil { + fo.Hint = opt.Hint + } + if opt.Let != nil { + fo.Let = opt.Let + } + } + + return fo +} + // FindOneAndDelete executes a findAndModify command to delete at most one document in the collection. and returns the // document as it appeared before deletion. // @@ -1492,7 +1786,7 @@ func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{} if err != nil { return &SingleResult{err: err} } - fod := options.MergeFindOneAndDeleteOptions(opts...) + fod := mergeFindOneAndDeleteOptions(opts...) op := operation.NewFindAndModify(f).Remove(true).ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout). MaxTime(fod.MaxTime) if fod.Collation != nil { @@ -1543,6 +1837,49 @@ func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{} return coll.findAndModify(ctx, op) } +// mergeFindOneAndReplaceOptions combines the given FindOneAndReplaceOptions instances into a single +// FindOneAndReplaceOptions in a last-property-wins fashion. +func mergeFindOneAndReplaceOptions(opts ...*options.FindOneAndReplaceOptions) *options.FindOneAndReplaceOptions { + fo := options.FindOneAndReplace() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.BypassDocumentValidation != nil { + fo.BypassDocumentValidation = opt.BypassDocumentValidation + } + if opt.Collation != nil { + fo.Collation = opt.Collation + } + if opt.Comment != nil { + fo.Comment = opt.Comment + } + if opt.MaxTime != nil { + fo.MaxTime = opt.MaxTime + } + if opt.Projection != nil { + fo.Projection = opt.Projection + } + if opt.ReturnDocument != nil { + fo.ReturnDocument = opt.ReturnDocument + } + if opt.Sort != nil { + fo.Sort = opt.Sort + } + if opt.Upsert != nil { + fo.Upsert = opt.Upsert + } + if opt.Hint != nil { + fo.Hint = opt.Hint + } + if opt.Let != nil { + fo.Let = opt.Let + } + } + + return fo +} + // FindOneAndReplace executes a findAndModify command to replace at most one document in the collection // and returns the document as it appeared before replacement. // @@ -1572,7 +1909,7 @@ func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{ return &SingleResult{err: errors.New("replacement document cannot contain keys beginning with '$'")} } - fo := options.MergeFindOneAndReplaceOptions(opts...) + fo := mergeFindOneAndReplaceOptions(opts...) op := operation.NewFindAndModify(f).Update(bsoncore.Value{Type: bsontype.EmbeddedDocument, Data: r}). ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout).MaxTime(fo.MaxTime) if fo.BypassDocumentValidation != nil && *fo.BypassDocumentValidation { @@ -1632,6 +1969,52 @@ func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{ return coll.findAndModify(ctx, op) } +// mergeFindOneAndUpdateOptions combines the given FindOneAndUpdateOptions instances into a single +// FindOneAndUpdateOptions in a last-property-wins fashion. +func mergeFindOneAndUpdateOptions(opts ...*options.FindOneAndUpdateOptions) *options.FindOneAndUpdateOptions { + fo := options.FindOneAndUpdate() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.ArrayFilters != nil { + fo.ArrayFilters = opt.ArrayFilters + } + if opt.BypassDocumentValidation != nil { + fo.BypassDocumentValidation = opt.BypassDocumentValidation + } + if opt.Collation != nil { + fo.Collation = opt.Collation + } + if opt.Comment != nil { + fo.Comment = opt.Comment + } + if opt.MaxTime != nil { + fo.MaxTime = opt.MaxTime + } + if opt.Projection != nil { + fo.Projection = opt.Projection + } + if opt.ReturnDocument != nil { + fo.ReturnDocument = opt.ReturnDocument + } + if opt.Sort != nil { + fo.Sort = opt.Sort + } + if opt.Upsert != nil { + fo.Upsert = opt.Upsert + } + if opt.Hint != nil { + fo.Hint = opt.Hint + } + if opt.Let != nil { + fo.Let = opt.Let + } + } + + return fo +} + // FindOneAndUpdate executes a findAndModify command to update at most one document in the collection and returns the // document as it appeared before updating. // @@ -1659,7 +2042,7 @@ func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{} return &SingleResult{err: err} } - fo := options.MergeFindOneAndUpdateOptions(opts...) + fo := mergeFindOneAndUpdateOptions(opts...) op := operation.NewFindAndModify(f).ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout). MaxTime(fo.MaxTime) @@ -1853,7 +2236,7 @@ func (coll *Collection) drop(ctx context.Context) error { if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } diff --git a/mongo/collection_test.go b/mongo/collection_test.go index f17e6dfda7..6e2d9e9f1c 100644 --- a/mongo/collection_test.go +++ b/mongo/collection_test.go @@ -46,8 +46,8 @@ func TestCollection(t *testing.T) { t.Run("specified options", func(t *testing.T) { rpPrimary := readpref.Primary() rpSecondary := readpref.Secondary() - wc1 := writeconcern.New(writeconcern.W(5)) - wc2 := writeconcern.New(writeconcern.W(10)) + wc1 := &writeconcern.WriteConcern{W: 5} + wc2 := &writeconcern.WriteConcern{W: 10} rcLocal := readconcern.Local() rcMajority := readconcern.Majority() @@ -64,7 +64,7 @@ func TestCollection(t *testing.T) { t.Run("inherit options", func(t *testing.T) { rpPrimary := readpref.Primary() rcLocal := readconcern.Local() - wc1 := writeconcern.New(writeconcern.W(10)) + wc1 := &writeconcern.WriteConcern{W: 10} db := setupDb("foo", options.Database().SetReadPreference(rpPrimary).SetReadConcern(rcLocal)) coll := db.Collection("bar", options.Collection().SetWriteConcern(wc1)) diff --git a/mongo/database.go b/mongo/database.go index f5d5ad379b..65026ce0fb 100644 --- a/mongo/database.go +++ b/mongo/database.go @@ -44,7 +44,24 @@ type Database struct { } func newDatabase(client *Client, name string, opts ...*options.DatabaseOptions) *Database { - dbOpt := options.MergeDatabaseOptions(opts...) + dbOpt := options.Database() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.ReadConcern != nil { + dbOpt.ReadConcern = opt.ReadConcern + } + if opt.WriteConcern != nil { + dbOpt.WriteConcern = opt.WriteConcern + } + if opt.ReadPreference != nil { + dbOpt.ReadPreference = opt.ReadPreference + } + if opt.Registry != nil { + dbOpt.Registry = opt.Registry + } + } rc := client.readConcern if dbOpt.ReadConcern != nil { @@ -152,7 +169,15 @@ func (db *Database) processRunCommand(ctx context.Context, cmd interface{}, return nil, sess, err } - ro := options.MergeRunCmdOptions(append(defaultRunCmdOpts, opts...)...) + ro := options.RunCmd() + for _, opt := range append(defaultRunCmdOpts, opts...) { + if opt == nil { + continue + } + if opt.ReadPreference != nil { + ro.ReadPreference = opt.ReadPreference + } + } if sess != nil && sess.TransactionRunning() && ro.ReadPreference != nil && ro.ReadPreference.Mode() != readpref.PrimaryMode { return nil, sess, errors.New("read preference in a transaction must be primary") } @@ -295,7 +320,7 @@ func (db *Database) Drop(ctx context.Context) error { if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } @@ -394,7 +419,21 @@ func (db *Database) ListCollections(ctx context.Context, filter interface{}, opt }) selector = makeReadPrefSelector(sess, selector, db.client.localThreshold) - lco := options.MergeListCollectionsOptions(opts...) + lco := options.ListCollections() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.NameOnly != nil { + lco.NameOnly = opt.NameOnly + } + if opt.BatchSize != nil { + lco.BatchSize = opt.BatchSize + } + if opt.AuthorizedCollections != nil { + lco.AuthorizedCollections = opt.AuthorizedCollections + } + } op := operation.NewListCollections(filterDoc). Session(sess).ReadPreference(db.readPreference).CommandMonitor(db.client.monitor). ServerSelector(selector).ClusterClock(db.client.clock). @@ -523,6 +562,63 @@ func (db *Database) Watch(ctx context.Context, pipeline interface{}, return newChangeStream(ctx, csConfig, pipeline, opts...) } +// mergeCreateCollectionOptions combines the given CreateCollectionOptions instances into a single +// CreateCollectionOptions in a last-property-wins fashion. +func mergeCreateCollectionOptions(opts ...*options.CreateCollectionOptions) *options.CreateCollectionOptions { + cc := options.CreateCollection() + + for _, opt := range opts { + if opt == nil { + continue + } + + if opt.Capped != nil { + cc.Capped = opt.Capped + } + if opt.Collation != nil { + cc.Collation = opt.Collation + } + if opt.ChangeStreamPreAndPostImages != nil { + cc.ChangeStreamPreAndPostImages = opt.ChangeStreamPreAndPostImages + } + if opt.DefaultIndexOptions != nil { + cc.DefaultIndexOptions = opt.DefaultIndexOptions + } + if opt.MaxDocuments != nil { + cc.MaxDocuments = opt.MaxDocuments + } + if opt.SizeInBytes != nil { + cc.SizeInBytes = opt.SizeInBytes + } + if opt.StorageEngine != nil { + cc.StorageEngine = opt.StorageEngine + } + if opt.ValidationAction != nil { + cc.ValidationAction = opt.ValidationAction + } + if opt.ValidationLevel != nil { + cc.ValidationLevel = opt.ValidationLevel + } + if opt.Validator != nil { + cc.Validator = opt.Validator + } + if opt.ExpireAfterSeconds != nil { + cc.ExpireAfterSeconds = opt.ExpireAfterSeconds + } + if opt.TimeSeriesOptions != nil { + cc.TimeSeriesOptions = opt.TimeSeriesOptions + } + if opt.EncryptedFields != nil { + cc.EncryptedFields = opt.EncryptedFields + } + if opt.ClusteredIndex != nil { + cc.ClusteredIndex = opt.ClusteredIndex + } + } + + return cc +} + // CreateCollection executes a create command to explicitly create a new collection with the specified name on the // server. If the collection being created already exists, this method will return a mongo.CommandError. This method // requires driver version 1.4.0 or higher. @@ -532,7 +628,7 @@ func (db *Database) Watch(ctx context.Context, pipeline interface{}, // // For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/create/. func (db *Database) CreateCollection(ctx context.Context, name string, opts ...*options.CreateCollectionOptions) error { - cco := options.MergeCreateCollectionOptions(opts...) + cco := mergeCreateCollectionOptions(opts...) // Follow Client-Side Encryption specification to check for encryptedFields. // Check for encryptedFields from create options. ef := cco.EncryptedFields @@ -675,7 +771,7 @@ func (db *Database) createCollection(ctx context.Context, name string, opts ...* } func (db *Database) createCollectionOperation(name string, opts ...*options.CreateCollectionOptions) (*operation.Create, error) { - cco := options.MergeCreateCollectionOptions(opts...) + cco := mergeCreateCollectionOptions(opts...) op := operation.NewCreate(name).ServerAPI(db.client.serverAPI) if cco.Capped != nil { @@ -778,6 +874,24 @@ func (db *Database) createCollectionOperation(name string, opts ...*options.Crea return op, nil } +// mergeCreateViewOptions combines the given CreateViewOptions instances into a single CreateViewOptions in a +// last-property-wins fashion. +func mergeCreateViewOptions(opts ...*options.CreateViewOptions) *options.CreateViewOptions { + cv := options.CreateView() + + for _, opt := range opts { + if opt == nil { + continue + } + + if opt.Collation != nil { + cv.Collation = opt.Collation + } + } + + return cv +} + // CreateView executes a create command to explicitly create a view on the server. See // https://www.mongodb.com/docs/manual/core/views/ for more information about views. This method requires driver version >= // 1.4.0 and MongoDB version >= 3.4. @@ -803,7 +917,7 @@ func (db *Database) CreateView(ctx context.Context, viewName, viewOn string, pip ViewOn(viewOn). Pipeline(pipelineArray). ServerAPI(db.client.serverAPI) - cvo := options.MergeCreateViewOptions(opts...) + cvo := mergeCreateViewOptions(opts...) if cvo.Collation != nil { op.Collation(bsoncore.Document(cvo.Collation.ToDocument())) } @@ -827,7 +941,7 @@ func (db *Database) executeCreateOperation(ctx context.Context, op *operation.Cr if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } diff --git a/mongo/database_test.go b/mongo/database_test.go index 61905e9c56..745f533b73 100644 --- a/mongo/database_test.go +++ b/mongo/database_test.go @@ -50,8 +50,8 @@ func TestDatabase(t *testing.T) { t.Run("custom", func(t *testing.T) { rpPrimary := readpref.Primary() rpSecondary := readpref.Secondary() - wc1 := writeconcern.New(writeconcern.W(5)) - wc2 := writeconcern.New(writeconcern.W(10)) + wc1 := &writeconcern.WriteConcern{W: 5} + wc2 := &writeconcern.WriteConcern{W: 10} rcLocal := readconcern.Local() rcMajority := readconcern.Majority() reg := bsoncodec.NewRegistryBuilder().Build() @@ -70,7 +70,7 @@ func TestDatabase(t *testing.T) { t.Run("inherit", func(t *testing.T) { rpPrimary := readpref.Primary() rcLocal := readconcern.Local() - wc1 := writeconcern.New(writeconcern.W(10)) + wc1 := &writeconcern.WriteConcern{W: 10} reg := bsoncodec.NewRegistryBuilder().Build() client := setupClient(options.Client().SetReadPreference(rpPrimary).SetReadConcern(rcLocal).SetRegistry(reg)) @@ -97,7 +97,7 @@ func TestDatabase(t *testing.T) { }) t.Run("TransientTransactionError label", func(t *testing.T) { client := setupClient(options.Client().ApplyURI("mongodb://nonexistent").SetServerSelectionTimeout(3 * time.Second)) - err := client.Connect(bgCtx) + err := client.connect(bgCtx) defer func() { _ = client.Disconnect(bgCtx) }() assert.Nil(t, err, "expected nil, got %v", err) diff --git a/mongo/description/server.go b/mongo/description/server.go index cf39423839..e73c819ca9 100644 --- a/mongo/description/server.go +++ b/mongo/description/server.go @@ -33,37 +33,35 @@ type SelectedServer struct { type Server struct { Addr address.Address - Arbiters []string - AverageRTT time.Duration - AverageRTTSet bool - Compression []string // compression methods returned by server - CanonicalAddr address.Address - ElectionID primitive.ObjectID - HeartbeatInterval time.Duration - HelloOK bool - Hosts []string - IsCryptd bool - LastError error - LastUpdateTime time.Time - LastWriteTime time.Time - MaxBatchCount uint32 - MaxDocumentSize uint32 - MaxMessageSize uint32 - Members []address.Address - Passives []string - Passive bool - Primary address.Address - ReadOnly bool - ServiceID *primitive.ObjectID // Only set for servers that are deployed behind a load balancer. - // Deprecated: Use SessionTimeoutMinutesPtr instead. - SessionTimeoutMinutes uint32 - SessionTimeoutMinutesPtr *int64 - SetName string - SetVersion uint32 - Tags tag.Set - TopologyVersion *TopologyVersion - Kind ServerKind - WireVersion *VersionRange + Arbiters []string + AverageRTT time.Duration + AverageRTTSet bool + Compression []string // compression methods returned by server + CanonicalAddr address.Address + ElectionID primitive.ObjectID + HeartbeatInterval time.Duration + HelloOK bool + Hosts []string + IsCryptd bool + LastError error + LastUpdateTime time.Time + LastWriteTime time.Time + MaxBatchCount uint32 + MaxDocumentSize uint32 + MaxMessageSize uint32 + Members []address.Address + Passives []string + Passive bool + Primary address.Address + ReadOnly bool + ServiceID *primitive.ObjectID // Only set for servers that are deployed behind a load balancer. + SessionTimeoutMinutes *int64 + SetName string + SetVersion uint32 + Tags tag.Set + TopologyVersion *TopologyVersion + Kind ServerKind + WireVersion *VersionRange } // NewServer creates a new server description from the given hello command response. @@ -171,8 +169,7 @@ func NewServer(addr address.Address, response bson.Raw) Server { return desc } - desc.SessionTimeoutMinutes = uint32(i64) - desc.SessionTimeoutMinutesPtr = &i64 + desc.SessionTimeoutMinutes = &i64 case "maxBsonObjectSize": i64, ok := element.Value().AsInt64OK() if !ok { @@ -468,7 +465,7 @@ func (s Server) Equal(other Server) bool { return false } - if ptrutil.CompareInt64(s.SessionTimeoutMinutesPtr, other.SessionTimeoutMinutesPtr) != 0 { + if ptrutil.CompareInt64(s.SessionTimeoutMinutes, other.SessionTimeoutMinutes) != 0 { return false } diff --git a/mongo/description/server_test.go b/mongo/description/server_test.go index 027cd21700..74f02b6cd1 100644 --- a/mongo/description/server_test.go +++ b/mongo/description/server_test.go @@ -51,8 +51,7 @@ func TestServer(t *testing.T) { { "sessionTimeoutMinutes", Server{ - SessionTimeoutMinutesPtr: int64ToPtr(1), - SessionTimeoutMinutes: 1, + SessionTimeoutMinutes: int64ToPtr(1), }, false, }, diff --git a/mongo/description/topology.go b/mongo/description/topology.go index b082515e53..b0a52931fe 100644 --- a/mongo/description/topology.go +++ b/mongo/description/topology.go @@ -14,13 +14,11 @@ import ( // Topology contains information about a MongoDB cluster. type Topology struct { - Servers []Server - SetName string - Kind TopologyKind - // Deprecated: Use SessionTimeoutMinutesPtr instead. - SessionTimeoutMinutes uint32 - SessionTimeoutMinutesPtr *int64 - CompatibilityErr error + Servers []Server + SetName string + Kind TopologyKind + SessionTimeoutMinutes *int64 + CompatibilityErr error } // String implements the Stringer interface. diff --git a/mongo/gridfs/bucket.go b/mongo/gridfs/bucket.go index 61e2cb9e74..0d93fc72d7 100644 --- a/mongo/gridfs/bucket.go +++ b/mongo/gridfs/bucket.go @@ -73,7 +73,27 @@ func NewBucket(db *mongo.Database, opts ...*options.BucketOptions) (*Bucket, err rp: db.ReadPreference(), } - bo := options.MergeBucketOptions(opts...) + bo := options.GridFSBucket() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.Name != nil { + bo.Name = opt.Name + } + if opt.ChunkSizeBytes != nil { + bo.ChunkSizeBytes = opt.ChunkSizeBytes + } + if opt.WriteConcern != nil { + bo.WriteConcern = opt.WriteConcern + } + if opt.ReadConcern != nil { + bo.ReadConcern = opt.ReadConcern + } + if opt.ReadPreference != nil { + bo.ReadPreference = opt.ReadPreference + } + } if bo.Name != nil { b.name = *bo.Name } @@ -210,7 +230,17 @@ func (b *Bucket) OpenDownloadStreamByName(filename string, opts ...*options.Name var numSkip int32 = -1 var sortOrder int32 = 1 - nameOpts := options.MergeNameOptions(opts...) + nameOpts := options.GridFSName() + nameOpts.Revision = &options.DefaultRevision + + for _, opt := range opts { + if opt == nil { + continue + } + if opt.Revision != nil { + nameOpts.Revision = opt.Revision + } + } if nameOpts.Revision != nil { numSkip = *nameOpts.Revision } @@ -302,7 +332,33 @@ func (b *Bucket) Find(filter interface{}, opts ...*options.GridFSFindOptions) (* // Use the context parameter to time-out or cancel the find operation. The deadline set by SetReadDeadline // is ignored. func (b *Bucket) FindContext(ctx context.Context, filter interface{}, opts ...*options.GridFSFindOptions) (*mongo.Cursor, error) { - gfsOpts := options.MergeGridFSFindOptions(opts...) + gfsOpts := options.GridFSFind() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.AllowDiskUse != nil { + gfsOpts.AllowDiskUse = opt.AllowDiskUse + } + if opt.BatchSize != nil { + gfsOpts.BatchSize = opt.BatchSize + } + if opt.Limit != nil { + gfsOpts.Limit = opt.Limit + } + if opt.MaxTime != nil { + gfsOpts.MaxTime = opt.MaxTime + } + if opt.NoCursorTimeout != nil { + gfsOpts.NoCursorTimeout = opt.NoCursorTimeout + } + if opt.Skip != nil { + gfsOpts.Skip = opt.Skip + } + if opt.Sort != nil { + gfsOpts.Sort = opt.Sort + } + } find := options.Find() if gfsOpts.AllowDiskUse != nil { find.SetAllowDiskUse(*gfsOpts.AllowDiskUse) @@ -642,7 +698,21 @@ func (b *Bucket) parseUploadOptions(opts ...*options.UploadOptions) (*Upload, er chunkSize: b.chunkSize, // upload chunk size defaults to bucket's value } - uo := options.MergeUploadOptions(opts...) + uo := options.GridFSUpload() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.ChunkSizeBytes != nil { + uo.ChunkSizeBytes = opt.ChunkSizeBytes + } + if opt.Metadata != nil { + uo.Metadata = opt.Metadata + } + if opt.Registry != nil { + uo.Registry = opt.Registry + } + } if uo.ChunkSizeBytes != nil { upload.chunkSize = *uo.ChunkSizeBytes } diff --git a/mongo/gridfs/gridfs_test.go b/mongo/gridfs/gridfs_test.go index c95cf1f8d6..f4c1d08e60 100644 --- a/mongo/gridfs/gridfs_test.go +++ b/mongo/gridfs/gridfs_test.go @@ -42,7 +42,7 @@ func TestGridFS(t *testing.T) { clientOpts := options.Client(). ApplyURI(cs.Original). SetReadPreference(readpref.Primary()). - SetWriteConcern(writeconcern.New(writeconcern.WMajority())). + SetWriteConcern(writeconcern.Majority()). SetPoolMonitor(poolMonitor). // Connect to a single host. For sharded clusters, this will pin to a single mongos, which avoids // non-deterministic versioning errors in the server. This has no effect for replica sets because the driver diff --git a/mongo/index_options_builder.go b/mongo/index_options_builder.go deleted file mode 100644 index d12deaee28..0000000000 --- a/mongo/index_options_builder.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2017-present. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -package mongo - -import ( - "go.mongodb.org/mongo-driver/bson" -) - -// IndexOptionsBuilder specifies options for a new index. -// -// Deprecated: Use the IndexOptions type in the mongo/options package instead. -type IndexOptionsBuilder struct { - document bson.D -} - -// NewIndexOptionsBuilder creates a new IndexOptionsBuilder. -// -// Deprecated: Use the Index function in mongo/options instead. -func NewIndexOptionsBuilder() *IndexOptionsBuilder { - return &IndexOptionsBuilder{} -} - -// Background specifies a value for the background option. -// -// Deprecated: Use the IndexOptions.SetBackground function in mongo/options instead. -func (iob *IndexOptionsBuilder) Background(background bool) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"background", background}) - return iob -} - -// ExpireAfterSeconds specifies a value for the expireAfterSeconds option. -// -// Deprecated: Use the IndexOptions.SetExpireAfterSeconds function in mongo/options instead. -func (iob *IndexOptionsBuilder) ExpireAfterSeconds(expireAfterSeconds int32) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"expireAfterSeconds", expireAfterSeconds}) - return iob -} - -// Name specifies a value for the name option. -// -// Deprecated: Use the IndexOptions.SetName function in mongo/options instead. -func (iob *IndexOptionsBuilder) Name(name string) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"name", name}) - return iob -} - -// Sparse specifies a value for the sparse option. -// -// Deprecated: Use the IndexOptions.SetSparse function in mongo/options instead. -func (iob *IndexOptionsBuilder) Sparse(sparse bool) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"sparse", sparse}) - return iob -} - -// StorageEngine specifies a value for the storageEngine option. -// -// Deprecated: Use the IndexOptions.SetStorageEngine function in mongo/options instead. -func (iob *IndexOptionsBuilder) StorageEngine(storageEngine interface{}) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"storageEngine", storageEngine}) - return iob -} - -// Unique specifies a value for the unique option. -// -// Deprecated: Use the IndexOptions.SetUnique function in mongo/options instead. -func (iob *IndexOptionsBuilder) Unique(unique bool) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"unique", unique}) - return iob -} - -// Version specifies a value for the version option. -// -// Deprecated: Use the IndexOptions.SetVersion function in mongo/options instead. -func (iob *IndexOptionsBuilder) Version(version int32) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"v", version}) - return iob -} - -// DefaultLanguage specifies a value for the default_language option. -// -// Deprecated: Use the IndexOptions.SetDefaultLanguage function in mongo/options instead. -func (iob *IndexOptionsBuilder) DefaultLanguage(defaultLanguage string) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"default_language", defaultLanguage}) - return iob -} - -// LanguageOverride specifies a value for the language_override option. -// -// Deprecated: Use the IndexOptions.SetLanguageOverride function in mongo/options instead. -func (iob *IndexOptionsBuilder) LanguageOverride(languageOverride string) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"language_override", languageOverride}) - return iob -} - -// TextVersion specifies a value for the textIndexVersion option. -// -// Deprecated: Use the IndexOptions.SetTextVersion function in mongo/options instead. -func (iob *IndexOptionsBuilder) TextVersion(textVersion int32) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"textIndexVersion", textVersion}) - return iob -} - -// Weights specifies a value for the weights option. -// -// Deprecated: Use the IndexOptions.SetWeights function in mongo/options instead. -func (iob *IndexOptionsBuilder) Weights(weights interface{}) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"weights", weights}) - return iob -} - -// SphereVersion specifies a value for the 2dsphereIndexVersion option. -// -// Deprecated: Use the IndexOptions.SetSphereVersion function in mongo/options instead. -func (iob *IndexOptionsBuilder) SphereVersion(sphereVersion int32) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"2dsphereIndexVersion", sphereVersion}) - return iob -} - -// Bits specifies a value for the bits option. -// -// Deprecated: Use the IndexOptions.SetBits function in mongo/options instead. -func (iob *IndexOptionsBuilder) Bits(bits int32) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"bits", bits}) - return iob -} - -// Max specifies a value for the max option. -// -// Deprecated: Use the IndexOptions.SetMax function in mongo/options instead. -func (iob *IndexOptionsBuilder) Max(max float64) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"max", max}) - return iob -} - -// Min specifies a value for the min option. -// -// Deprecated: Use the IndexOptions.SetMin function in mongo/options instead. -func (iob *IndexOptionsBuilder) Min(min float64) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"min", min}) - return iob -} - -// BucketSize specifies a value for the bucketSize option. -// -// Deprecated: Use the IndexOptions.SetBucketSize function in mongo/options instead. -func (iob *IndexOptionsBuilder) BucketSize(bucketSize int32) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"bucketSize", bucketSize}) - return iob -} - -// PartialFilterExpression specifies a value for the partialFilterExpression option. -// -// Deprecated: Use the IndexOptions.SetPartialFilterExpression function in mongo/options instead. -func (iob *IndexOptionsBuilder) PartialFilterExpression(partialFilterExpression interface{}) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"partialFilterExpression", partialFilterExpression}) - return iob -} - -// Collation specifies a value for the collation option. -// -// Deprecated: Use the IndexOptions.SetCollation function in mongo/options instead. -func (iob *IndexOptionsBuilder) Collation(collation interface{}) *IndexOptionsBuilder { - iob.document = append(iob.document, bson.E{"collation", collation}) - return iob -} - -// Build finishes constructing an the builder. -// -// Deprecated: Use the IndexOptions type in the mongo/options package instead. -func (iob *IndexOptionsBuilder) Build() bson.D { - return iob.document -} diff --git a/mongo/index_view.go b/mongo/index_view.go index 9f9509b8e7..97d63edbf9 100644 --- a/mongo/index_view.go +++ b/mongo/index_view.go @@ -18,7 +18,6 @@ import ( "go.mongodb.org/mongo-driver/mongo/description" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readpref" - "go.mongodb.org/mongo-driver/mongo/writeconcern" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" "go.mongodb.org/mongo-driver/x/mongo/driver" "go.mongodb.org/mongo-driver/x/mongo/driver/operation" @@ -97,7 +96,18 @@ func (iv IndexView) List(ctx context.Context, opts ...*options.ListIndexesOption cursorOpts.MarshalValueEncoderFn = newEncoderFn(iv.coll.bsonOpts, iv.coll.registry) - lio := options.MergeListIndexesOptions(opts...) + lio := options.ListIndexes() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.BatchSize != nil { + lio.BatchSize = opt.BatchSize + } + if opt.MaxTime != nil { + lio.MaxTime = opt.MaxTime + } + } if lio.BatchSize != nil { op = op.BatchSize(*lio.BatchSize) cursorOpts.BatchSize = *lio.BatchSize @@ -243,13 +253,24 @@ func (iv IndexView) CreateMany(ctx context.Context, models []IndexModel, opts .. if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } selector := makePinnedSelector(sess, iv.coll.writeSelector) - option := options.MergeCreateIndexesOptions(opts...) + option := options.CreateIndexes() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.MaxTime != nil { + option.MaxTime = opt.MaxTime + } + if opt.CommitQuorum != nil { + option.CommitQuorum = opt.CommitQuorum + } + } op := operation.NewCreateIndexes(indexes). Session(sess).WriteConcern(wc).ClusterClock(iv.coll.client.clock). @@ -276,9 +297,6 @@ func (iv IndexView) CreateMany(ctx context.Context, models []IndexModel, opts .. func (iv IndexView) createOptionsDoc(opts *options.IndexOptions) (bsoncore.Document, error) { optsDoc := bsoncore.Document{} - if opts.Background != nil { - optsDoc = bsoncore.AppendBooleanElement(optsDoc, "background", *opts.Background) - } if opts.ExpireAfterSeconds != nil { optsDoc = bsoncore.AppendInt32Element(optsDoc, "expireAfterSeconds", *opts.ExpireAfterSeconds) } @@ -380,13 +398,21 @@ func (iv IndexView) drop(ctx context.Context, name string, opts ...*options.Drop if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } selector := makePinnedSelector(sess, iv.coll.writeSelector) - dio := options.MergeDropIndexesOptions(opts...) + dio := options.DropIndexes() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.MaxTime != nil { + dio.MaxTime = opt.MaxTime + } + } op := operation.NewDropIndexes(name). Session(sess).WriteConcern(wc).CommandMonitor(iv.coll.client.monitor). ServerSelector(selector).ClusterClock(iv.coll.client.clock). diff --git a/mongo/integration/client_options_test.go b/mongo/integration/client_options_test.go index 0fb068bc5e..43703d5e33 100644 --- a/mongo/integration/client_options_test.go +++ b/mongo/integration/client_options_test.go @@ -24,9 +24,7 @@ func TestClientOptions_CustomDialer(t *testing.T) { cs := integtest.ConnString(t) opts := options.Client().ApplyURI(cs.String()).SetDialer(td) integtest.AddTestServerAPIVersion(opts) - client, err := mongo.NewClient(opts) - require.NoError(t, err) - err = client.Connect(context.Background()) + client, err := mongo.Connect(context.Background(), opts) require.NoError(t, err) _, err = client.ListDatabases(context.Background(), bson.D{}) require.NoError(t, err) diff --git a/mongo/integration/client_side_encryption_prose_test.go b/mongo/integration/client_side_encryption_prose_test.go index b157767d2d..22dde7c896 100644 --- a/mongo/integration/client_side_encryption_prose_test.go +++ b/mongo/integration/client_side_encryption_prose_test.go @@ -150,7 +150,8 @@ func TestClientSideEncryptionProse(t *testing.T) { alteredKeydoc, _ = bsoncore.AppendDocumentEnd(alteredKeydoc, cidx) // Insert the copied key document into keyvault.datakeys with majority write concern. - wcMajority := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second)) + wcMajority := writeconcern.Majority() + wcMajority.WTimeout = 1 * time.Second wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority) wcmColl := cse.kvClient.Database(kvDatabase).Collection(dkCollection, wcMajorityCollectionOpts) _, err = wcmColl.InsertOne(context.Background(), alteredKeydoc) @@ -1883,7 +1884,8 @@ func TestClientSideEncryptionProse(t *testing.T) { }), } - wcMajority := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second)) + wcMajority := writeconcern.Majority() + wcMajority.WTimeout = 1 * time.Second wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority) wcmColl := cse.kvClient.Database(kvDatabase).Collection(dkCollection, wcMajorityCollectionOpts) _, err = wcmColl.Indexes().CreateOne(context.Background(), keyVaultIndex) diff --git a/mongo/integration/client_test.go b/mongo/integration/client_test.go index e3a5b26241..af90b6b45e 100644 --- a/mongo/integration/client_test.go +++ b/mongo/integration/client_test.go @@ -339,14 +339,6 @@ func TestClient(t *testing.T) { assert.Nil(mt, err, "Disconnect error: %v", err) }) }) - mt.RunOpts("watch", noClientOpts, func(mt *mtest.T) { - mt.Run("disconnected", func(mt *mtest.T) { - c, err := mongo.NewClient(options.Client().ApplyURI(mtest.ClusterURI())) - assert.Nil(mt, err, "NewClient error: %v", err) - _, err = c.Watch(context.Background(), mongo.Pipeline{}) - assert.Equal(mt, mongo.ErrClientDisconnected, err, "expected error %v, got %v", mongo.ErrClientDisconnected, err) - }) - }) mt.RunOpts("end sessions", mtest.NewOptions().MinServerVersion("3.6"), func(mt *mtest.T) { _, err := mt.Client.ListDatabases(context.Background(), bson.D{}) assert.Nil(mt, err, "ListDatabases error: %v", err) diff --git a/mongo/integration/cmd_monitoring_helpers_test.go b/mongo/integration/cmd_monitoring_helpers_test.go index 6c4931d26c..16218816c2 100644 --- a/mongo/integration/cmd_monitoring_helpers_test.go +++ b/mongo/integration/cmd_monitoring_helpers_test.go @@ -41,6 +41,8 @@ func numberFromValue(mt *mtest.T, val bson.RawValue) int64 { } func compareNumberValues(mt *mtest.T, key string, expected, actual bson.RawValue) error { + mt.Helper() + eInt := numberFromValue(mt, expected) if eInt == 42 { if actual.Type == bson.TypeNull { diff --git a/mongo/integration/collection_test.go b/mongo/integration/collection_test.go index da03258738..ba5b87c5ca 100644 --- a/mongo/integration/collection_test.go +++ b/mongo/integration/collection_test.go @@ -35,7 +35,10 @@ var ( // impossibleWc is a write concern that can't be satisfied and is used to test write concern errors // for various operations. It includes a timeout because legacy servers will wait for all W nodes to respond, // causing tests to hang. - impossibleWc = writeconcern.New(writeconcern.W(30), writeconcern.WTimeout(time.Second)) + impossibleWc = &writeconcern.WriteConcern{ + W: 30, + WTimeout: time.Second, + } ) func TestCollection(t *testing.T) { @@ -1136,15 +1139,12 @@ func TestCollection(t *testing.T) { // SetCursorTime and setMaxAwaitTime will be deprecated in GODRIVER-1775 opts := options.FindOne(). SetAllowPartialResults(true). - SetBatchSize(2). SetCollation(&options.Collation{Locale: "en_US"}). SetComment(expectedComment). SetHint(indexName). SetMax(bson.D{{"x", int32(5)}}). SetMaxTime(1 * time.Second). SetMin(bson.D{{"x", int32(0)}}). - SetNoCursorTimeout(false). - SetOplogReplay(false). SetProjection(bson.D{{"x", int32(1)}}). SetReturnKey(false). SetShowRecordID(false). @@ -1161,15 +1161,12 @@ func TestCollection(t *testing.T) { optionsDoc := bsoncore.NewDocumentBuilder(). AppendBoolean("allowPartialResults", true). - AppendInt32("batchSize", 2). StartDocument("collation").AppendString("locale", "en_US").FinishDocument(). AppendString("comment", expectedComment). AppendString("hint", indexName). StartDocument("max").AppendInt32("x", 5).FinishDocument(). AppendInt32("maxTimeMS", 1000). StartDocument("min").AppendInt32("x", 0).FinishDocument(). - AppendBoolean("noCursorTimeout", false). - AppendBoolean("oplogReplay", false). StartDocument("projection").AppendInt32("x", 1).FinishDocument(). AppendBoolean("returnKey", false). AppendBoolean("showRecordId", false). @@ -1688,7 +1685,7 @@ func TestCollection(t *testing.T) { assert.Equal(mt, res.UpsertedIDs[3].(string), id3, "expected UpsertedIDs[3] to be %v, got %v", id3, res.UpsertedIDs[3]) }) unackClientOpts := options.Client(). - SetWriteConcern(writeconcern.New(writeconcern.W(0))) + SetWriteConcern(writeconcern.Unacknowledged()) unackMtOpts := mtest.NewOptions(). ClientOptions(unackClientOpts). MinServerVersion("3.6") diff --git a/mongo/integration/index_view_test.go b/mongo/integration/index_view_test.go index eaa8f0fa2a..cc5680056b 100644 --- a/mongo/integration/index_view_test.go +++ b/mongo/integration/index_view_test.go @@ -112,7 +112,6 @@ func TestIndexView(t *testing.T) { }) mt.Run("all options", func(mt *mtest.T) { opts := options.Index(). - SetBackground(false). SetExpireAfterSeconds(10). SetName("a"). SetSparse(false). @@ -264,7 +263,7 @@ func TestIndexView(t *testing.T) { } }) unackClientOpts := options.Client(). - SetWriteConcern(writeconcern.New(writeconcern.W(0))) + SetWriteConcern(writeconcern.Unacknowledged()) unackMtOpts := mtest.NewOptions(). ClientOptions(unackClientOpts). MinServerVersion("3.6") @@ -345,7 +344,7 @@ func TestIndexView(t *testing.T) { Name: indexNames[1], }) }) - wc := writeconcern.New(writeconcern.W(1)) + wc := writeconcern.W1() wcMtOpts := mtest.NewOptions().CollectionOptions(options.Collection().SetWriteConcern(wc)) mt.RunOpts("uses writeconcern", wcMtOpts, func(mt *mtest.T) { iv := mt.Coll.Indexes() diff --git a/mongo/integration/json_helpers_test.go b/mongo/integration/json_helpers_test.go index 749de6a5b1..c6d171b6a6 100644 --- a/mongo/integration/json_helpers_test.go +++ b/mongo/integration/json_helpers_test.go @@ -82,17 +82,17 @@ func createClientOptions(t testing.TB, opts bson.Raw) *options.ClientOptions { switch opt.Type { case bson.TypeInt32: w := int(opt.Int32()) - clientOpts.SetWriteConcern(writeconcern.New(writeconcern.W(w))) + clientOpts.SetWriteConcern(&writeconcern.WriteConcern{W: w}) case bson.TypeDouble: w := int(opt.Double()) - clientOpts.SetWriteConcern(writeconcern.New(writeconcern.W(w))) + clientOpts.SetWriteConcern(&writeconcern.WriteConcern{W: w}) case bson.TypeString: - clientOpts.SetWriteConcern(writeconcern.New(writeconcern.WMajority())) + clientOpts.SetWriteConcern(writeconcern.Majority()) default: 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 @@ -398,7 +398,7 @@ func createWriteConcern(t testing.TB, opt bson.RawValue) *writeconcern.WriteConc return nil } - var opts []writeconcern.Option + wc := &writeconcern.WriteConcern{} elems, _ := wcDoc.Elements() for _, elem := range elems { key := elem.Key() @@ -407,19 +407,20 @@ func createWriteConcern(t testing.TB, opt bson.RawValue) *writeconcern.WriteConc switch key { case "wtimeout": wtimeout := convertValueToMilliseconds(t, val) - opts = append(opts, writeconcern.WTimeout(wtimeout)) + wc.WTimeout = wtimeout case "j": - opts = append(opts, writeconcern.J(val.Boolean())) + j := val.Boolean() + wc.Journal = &j case "w": switch val.Type { case bson.TypeString: if val.StringValue() != "majority" { break } - opts = append(opts, writeconcern.WMajority()) + wc.W = "majority" case bson.TypeInt32: w := int(val.Int32()) - opts = append(opts, writeconcern.W(w)) + wc.W = w default: t.Fatalf("unrecognized type for w: %v", val.Type) } @@ -427,7 +428,7 @@ func createWriteConcern(t testing.TB, opt bson.RawValue) *writeconcern.WriteConc t.Fatalf("unrecognized write concern option: %v", key) } } - return writeconcern.New(opts...) + return wc } // create a read preference from a string. diff --git a/mongo/integration/mtest/mongotest.go b/mongo/integration/mtest/mongotest.go index e16ab262ad..2924c06e79 100644 --- a/mongo/integration/mtest/mongotest.go +++ b/mongo/integration/mtest/mongotest.go @@ -30,7 +30,7 @@ import ( var ( // MajorityWc is the majority write concern. - MajorityWc = writeconcern.New(writeconcern.WMajority()) + MajorityWc = writeconcern.Majority() // PrimaryRp is the primary read preference. PrimaryRp = readpref.Primary() // SecondaryRp is the secondary read preference. @@ -520,7 +520,8 @@ func (t *T) ClearCollections() { // could prevent it from being dropped for sharded clusters. We can resolve this by // re-instantiating the collection with a majority write concern before dropping. collname := coll.created.Name() - wcm := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second)) + wcm := writeconcern.Majority() + wcm.WTimeout = 1 * time.Second wccoll := t.DB.Collection(collname, options.Collection().SetWriteConcern(wcm)) _ = wccoll.Drop(context.Background()) @@ -683,13 +684,13 @@ func (t *T) createTestClient() { // pin to first mongos pinnedHostList := []string{testContext.connString.Hosts[0]} uriOpts := options.Client().ApplyURI(testContext.connString.Original).SetHosts(pinnedHostList) - t.Client, err = mongo.NewClient(uriOpts, clientOpts) + t.Client, err = mongo.Connect(context.Background(), uriOpts, clientOpts) case Mock: // clear pool monitor to avoid configuration error clientOpts.PoolMonitor = nil t.mockDeployment = newMockDeployment() clientOpts.Deployment = t.mockDeployment - t.Client, err = mongo.NewClient(clientOpts) + t.Client, err = mongo.Connect(context.Background(), clientOpts) case Proxy: t.proxyDialer = newProxyDialer() clientOpts.SetDialer(t.proxyDialer) @@ -707,14 +708,11 @@ func (t *T) createTestClient() { } // Pass in uriOpts first so clientOpts wins if there are any conflicting settings. - t.Client, err = mongo.NewClient(uriOpts, clientOpts) + t.Client, err = mongo.Connect(context.Background(), uriOpts, clientOpts) } if err != nil { t.Fatalf("error creating client: %v", err) } - if err := t.Client.Connect(context.Background()); err != nil { - t.Fatalf("error connecting client: %v", err) - } } func (t *T) createTestCollection() { diff --git a/mongo/integration/mtest/opmsg_deployment.go b/mongo/integration/mtest/opmsg_deployment.go index ae4e359380..63947d3919 100644 --- a/mongo/integration/mtest/opmsg_deployment.go +++ b/mongo/integration/mtest/opmsg_deployment.go @@ -28,21 +28,17 @@ const ( ) var ( - sessionTimeoutMinutes uint32 = 30 - sessionTimeoutMinutesInt64 = int64(sessionTimeoutMinutes) + sessionTimeoutMinutes int64 = 30 // MockDescription is the server description used for the mock deployment. Each mocked connection returns this // value from its Description method. MockDescription = description.Server{ - CanonicalAddr: serverAddress, - MaxDocumentSize: maxDocumentSize, - MaxMessageSize: maxMessageSize, - MaxBatchCount: maxBatchCount, - // TODO(GODRIVER-2885): This can be removed once legacy - // SessionTimeoutMinutes is removed. - SessionTimeoutMinutes: sessionTimeoutMinutes, - SessionTimeoutMinutesPtr: &sessionTimeoutMinutesInt64, - Kind: description.RSPrimary, + CanonicalAddr: serverAddress, + MaxDocumentSize: maxDocumentSize, + MaxMessageSize: maxMessageSize, + MaxBatchCount: maxBatchCount, + SessionTimeoutMinutes: &sessionTimeoutMinutes, + Kind: description.RSPrimary, WireVersion: &description.VersionRange{ Max: topology.SupportedWireVersions.Max, }, @@ -169,11 +165,7 @@ func (md *mockDeployment) Subscribe() (*driver.Subscription, error) { md.updates = make(chan description.Topology, 1) md.updates <- description.Topology{ - SessionTimeoutMinutesPtr: &sessionTimeoutMinutesInt64, - - // TODO(GODRIVER-2885): This can be removed once legacy - // SessionTimeoutMinutes is removed. - SessionTimeoutMinutes: sessionTimeoutMinutes, + SessionTimeoutMinutes: &sessionTimeoutMinutes, } } diff --git a/mongo/integration/mtest/setup.go b/mongo/integration/mtest/setup.go index 303b7afdc2..de5525f2dc 100644 --- a/mongo/integration/mtest/setup.go +++ b/mongo/integration/mtest/setup.go @@ -58,7 +58,7 @@ var testContext struct { } func setupClient(opts *options.ClientOptions) (*mongo.Client, error) { - wcMajority := writeconcern.New(writeconcern.WMajority()) + wcMajority := writeconcern.Majority() // set ServerAPIOptions to latest version if required if opts.ServerAPIOptions == nil && testContext.requireAPIVersion { opts.SetServerAPIOptions(options.ServerAPI(driver.TestServerAPIVersion)) @@ -71,7 +71,15 @@ func setupClient(opts *options.ClientOptions) (*mongo.Client, error) { // Setup initializes the current testing context. // This function must only be called one time and must be called before any tests run. func Setup(setupOpts ...*SetupOptions) error { - opts := MergeSetupOptions(setupOpts...) + opts := NewSetupOptions() + for _, opt := range setupOpts { + if opt == nil { + continue + } + if opt.URI != nil { + opts.URI = opt.URI + } + } var uri string var err error diff --git a/mongo/integration/mtest/setup_options.go b/mongo/integration/mtest/setup_options.go index bd403a7311..76a3c27457 100644 --- a/mongo/integration/mtest/setup_options.go +++ b/mongo/integration/mtest/setup_options.go @@ -23,20 +23,3 @@ func (so *SetupOptions) SetURI(uri string) *SetupOptions { so.URI = &uri return so } - -// MergeSetupOptions combines the given *SetupOptions into a single *Options 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 MergeSetupOptions(opts ...*SetupOptions) *SetupOptions { - op := NewSetupOptions() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.URI != nil { - op.URI = opt.URI - } - } - return op -} diff --git a/mongo/integration/sessions_test.go b/mongo/integration/sessions_test.go index dfd3e2d260..799d22e9d1 100644 --- a/mongo/integration/sessions_test.go +++ b/mongo/integration/sessions_test.go @@ -107,7 +107,7 @@ func TestSessions(t *testing.T) { }) }) - unackWcOpts := options.Collection().SetWriteConcern(writeconcern.New(writeconcern.W(0))) + unackWcOpts := options.Collection().SetWriteConcern(writeconcern.Unacknowledged()) mt.RunOpts("unacknowledged write", mtest.NewOptions().CollectionOptions(unackWcOpts), func(mt *mtest.T) { // unacknowledged write during a session should result in an error sess, err := mt.Client.StartSession() 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/collection_operation_execution.go b/mongo/integration/unified/collection_operation_execution.go index d8554ab706..fc5c884791 100644 --- a/mongo/integration/unified/collection_operation_execution.go +++ b/mongo/integration/unified/collection_operation_execution.go @@ -244,8 +244,6 @@ func executeCreateIndex(ctx context.Context, operation *operation) (*operationRe switch key { case "2dsphereIndexVersion": indexOpts.SetSphereVersion(val.Int32()) - case "background": - indexOpts.SetBackground(val.Boolean()) case "bits": indexOpts.SetBits(val.Int32()) case "bucketSize": @@ -1422,8 +1420,6 @@ func createFindCursor(ctx context.Context, operation *operation) (*cursorResult, opts.SetMin(val.Document()) case "noCursorTimeout": opts.SetNoCursorTimeout(val.Boolean()) - case "oplogReplay": - opts.SetOplogReplay(val.Boolean()) case "projection": opts.SetProjection(val.Document()) case "returnKey": @@ -1432,8 +1428,6 @@ func createFindCursor(ctx context.Context, operation *operation) (*cursorResult, opts.SetShowRecordID(val.Boolean()) case "skip": opts.SetSkip(int64(val.Int32())) - case "snapshot": - opts.SetSnapshot(val.Boolean()) case "sort": opts.SetSort(val.Document()) default: diff --git a/mongo/integration/unified/common_options.go b/mongo/integration/unified/common_options.go index 04a462d7b6..7c34586325 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 { @@ -34,9 +34,9 @@ type writeConcern struct { } func (wc *writeConcern) toWriteConcernOption() (*writeconcern.WriteConcern, error) { - var wcOptions []writeconcern.Option + c := &writeconcern.WriteConcern{} if wc.Journal != nil { - wcOptions = append(wcOptions, writeconcern.J(*wc.Journal)) + c.Journal = wc.Journal } if wc.W != nil { switch converted := wc.W.(type) { @@ -44,19 +44,19 @@ func (wc *writeConcern) toWriteConcernOption() (*writeconcern.WriteConcern, erro if converted != "majority" { return nil, fmt.Errorf("invalid write concern 'w' string value %q", converted) } - wcOptions = append(wcOptions, writeconcern.WMajority()) + c.W = "majority" case int32: - wcOptions = append(wcOptions, writeconcern.W(int(converted))) + c.W = int(converted) default: return nil, fmt.Errorf("invalid type for write concern 'w' field %T", wc.W) } } if wc.WTimeoutMS != nil { wTimeout := time.Duration(*wc.WTimeoutMS) * time.Millisecond - wcOptions = append(wcOptions, writeconcern.WTimeout(wTimeout)) + c.WTimeout = wTimeout } - return writeconcern.New(wcOptions...), nil + return c, nil } // ReadPreference is a representation of BSON readPreference objects in tests. diff --git a/mongo/integration/unified/options.go b/mongo/integration/unified/options.go index b66dd7a12b..430f751010 100644 --- a/mongo/integration/unified/options.go +++ b/mongo/integration/unified/options.go @@ -25,21 +25,3 @@ func (op *Options) SetRunKillAllSessions(killAllSessions bool) *Options { op.RunKillAllSessions = &killAllSessions return op } - -// MergeOptions combines the given *Options into a single *Options 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 MergeOptions(opts ...*Options) *Options { - op := NewOptions() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.RunKillAllSessions != nil { - op.RunKillAllSessions = opt.RunKillAllSessions - } - } - - return op -} diff --git a/mongo/integration/unified/unified_spec_runner.go b/mongo/integration/unified/unified_spec_runner.go index 7b92d07204..40fbff4fa1 100644 --- a/mongo/integration/unified/unified_spec_runner.go +++ b/mongo/integration/unified/unified_spec_runner.go @@ -144,7 +144,16 @@ func parseTestFile(testJSON []byte, opts ...*Options) ([]mtest.RunOnBlock, []*Te return nil, nil, err } - op := MergeOptions(opts...) + op := NewOptions() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.RunKillAllSessions != nil { + op.RunKillAllSessions = opt.RunKillAllSessions + } + } + for _, testCase := range testFile.TestCases { testCase.initialData = testFile.InitialData testCase.createEntities = testFile.CreateEntities diff --git a/mongo/mongo.go b/mongo/mongo.go index 393c5b7713..4fd4c1548a 100644 --- a/mongo/mongo.go +++ b/mongo/mongo.go @@ -33,30 +33,6 @@ type Dialer interface { DialContext(ctx context.Context, network, address string) (net.Conn, error) } -// BSONAppender is an interface implemented by types that can marshal a -// provided type into BSON bytes and append those bytes to the provided []byte. -// The AppendBSON can return a non-nil error and non-nil []byte. The AppendBSON -// method may also write incomplete BSON to the []byte. -// -// Deprecated: BSONAppender is unused and will be removed in Go Driver 2.0. -type BSONAppender interface { - AppendBSON([]byte, interface{}) ([]byte, error) -} - -// BSONAppenderFunc is an adapter function that allows any function that -// satisfies the AppendBSON method signature to be used where a BSONAppender is -// used. -// -// Deprecated: BSONAppenderFunc is unused and will be removed in Go Driver 2.0. -type BSONAppenderFunc func([]byte, interface{}) ([]byte, error) - -// AppendBSON implements the BSONAppender interface -// -// Deprecated: BSONAppenderFunc is unused and will be removed in Go Driver 2.0. -func (baf BSONAppenderFunc) AppendBSON(dst []byte, val interface{}) ([]byte, error) { - return baf(dst, val) -} - // MarshalError is returned when attempting to marshal a value into a document // results in an error. type MarshalError struct { diff --git a/mongo/mongocryptd.go b/mongo/mongocryptd.go index 2603a3918d..7af7f3a8f0 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 @@ -74,7 +74,7 @@ func newMongocryptdClient(opts *options.AutoEncryptionOptions) (*mongocryptdClie } // create client - client, err := NewClient(options.Client().ApplyURI(uri).SetServerSelectionTimeout(defaultServerSelectionTimeout)) + client, err := newClient(options.Client().ApplyURI(uri).SetServerSelectionTimeout(defaultServerSelectionTimeout)) if err != nil { return nil, err } @@ -114,7 +114,7 @@ func (mc *mongocryptdClient) markCommand(ctx context.Context, dbName string, cmd // connect connects the underlying Client instance. This must be called before performing any mark operations. func (mc *mongocryptdClient) connect(ctx context.Context) error { - return mc.client.Connect(ctx) + return mc.client.connect(ctx) } // disconnect disconnects the underlying Client instance. This should be called after all operations have completed. diff --git a/mongo/options/aggregateoptions.go b/mongo/options/aggregateoptions.go index 20e1c70439..9fcafcaf73 100644 --- a/mongo/options/aggregateoptions.go +++ b/mongo/options/aggregateoptions.go @@ -136,49 +136,3 @@ func (ao *AggregateOptions) SetCustom(c bson.M) *AggregateOptions { ao.Custom = c return ao } - -// MergeAggregateOptions combines the given AggregateOptions instances into a single AggregateOptions 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 MergeAggregateOptions(opts ...*AggregateOptions) *AggregateOptions { - aggOpts := Aggregate() - for _, ao := range opts { - if ao == nil { - continue - } - if ao.AllowDiskUse != nil { - aggOpts.AllowDiskUse = ao.AllowDiskUse - } - if ao.BatchSize != nil { - aggOpts.BatchSize = ao.BatchSize - } - if ao.BypassDocumentValidation != nil { - aggOpts.BypassDocumentValidation = ao.BypassDocumentValidation - } - if ao.Collation != nil { - aggOpts.Collation = ao.Collation - } - if ao.MaxTime != nil { - aggOpts.MaxTime = ao.MaxTime - } - if ao.MaxAwaitTime != nil { - aggOpts.MaxAwaitTime = ao.MaxAwaitTime - } - if ao.Comment != nil { - aggOpts.Comment = ao.Comment - } - if ao.Hint != nil { - aggOpts.Hint = ao.Hint - } - if ao.Let != nil { - aggOpts.Let = ao.Let - } - if ao.Custom != nil { - aggOpts.Custom = ao.Custom - } - } - - return aggOpts -} diff --git a/mongo/options/autoencryptionoptions.go b/mongo/options/autoencryptionoptions.go index 15d513862d..1c79dde611 100644 --- a/mongo/options/autoencryptionoptions.go +++ b/mongo/options/autoencryptionoptions.go @@ -162,49 +162,3 @@ func (a *AutoEncryptionOptions) SetBypassQueryAnalysis(bypass bool) *AutoEncrypt a.BypassQueryAnalysis = &bypass return a } - -// MergeAutoEncryptionOptions combines the argued AutoEncryptionOptions 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 MergeAutoEncryptionOptions(opts ...*AutoEncryptionOptions) *AutoEncryptionOptions { - aeo := AutoEncryption() - for _, opt := range opts { - if opt == nil { - continue - } - - if opt.KeyVaultClientOptions != nil { - aeo.KeyVaultClientOptions = opt.KeyVaultClientOptions - } - if opt.KeyVaultNamespace != "" { - aeo.KeyVaultNamespace = opt.KeyVaultNamespace - } - if opt.KmsProviders != nil { - aeo.KmsProviders = opt.KmsProviders - } - if opt.SchemaMap != nil { - aeo.SchemaMap = opt.SchemaMap - } - if opt.BypassAutoEncryption != nil { - aeo.BypassAutoEncryption = opt.BypassAutoEncryption - } - if opt.ExtraOptions != nil { - aeo.ExtraOptions = opt.ExtraOptions - } - if opt.TLSConfig != nil { - aeo.TLSConfig = opt.TLSConfig - } - if opt.EncryptedFieldsMap != nil { - aeo.EncryptedFieldsMap = opt.EncryptedFieldsMap - } - if opt.BypassQueryAnalysis != nil { - aeo.BypassQueryAnalysis = opt.BypassQueryAnalysis - } - if opt.HTTPClient != nil { - aeo.HTTPClient = opt.HTTPClient - } - } - - return aeo -} diff --git a/mongo/options/bulkwriteoptions.go b/mongo/options/bulkwriteoptions.go index 153de0c735..2cf4a61822 100644 --- a/mongo/options/bulkwriteoptions.go +++ b/mongo/options/bulkwriteoptions.go @@ -64,31 +64,3 @@ func (b *BulkWriteOptions) SetLet(let interface{}) *BulkWriteOptions { b.Let = &let return b } - -// MergeBulkWriteOptions combines the given BulkWriteOptions instances into a single BulkWriteOptions 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 MergeBulkWriteOptions(opts ...*BulkWriteOptions) *BulkWriteOptions { - b := BulkWrite() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.Comment != nil { - b.Comment = opt.Comment - } - if opt.Ordered != nil { - b.Ordered = opt.Ordered - } - if opt.BypassDocumentValidation != nil { - b.BypassDocumentValidation = opt.BypassDocumentValidation - } - if opt.Let != nil { - b.Let = opt.Let - } - } - - return b -} diff --git a/mongo/options/changestreamoptions.go b/mongo/options/changestreamoptions.go index 3d06a668e5..3c84b83458 100644 --- a/mongo/options/changestreamoptions.go +++ b/mongo/options/changestreamoptions.go @@ -153,55 +153,3 @@ func (cso *ChangeStreamOptions) SetCustomPipeline(cp bson.M) *ChangeStreamOption cso.CustomPipeline = cp return cso } - -// MergeChangeStreamOptions combines the given ChangeStreamOptions instances into a single ChangeStreamOptions 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 MergeChangeStreamOptions(opts ...*ChangeStreamOptions) *ChangeStreamOptions { - csOpts := ChangeStream() - for _, cso := range opts { - if cso == nil { - continue - } - if cso.BatchSize != nil { - csOpts.BatchSize = cso.BatchSize - } - if cso.Collation != nil { - csOpts.Collation = cso.Collation - } - if cso.Comment != nil { - csOpts.Comment = cso.Comment - } - if cso.FullDocument != nil { - csOpts.FullDocument = cso.FullDocument - } - if cso.FullDocumentBeforeChange != nil { - csOpts.FullDocumentBeforeChange = cso.FullDocumentBeforeChange - } - if cso.MaxAwaitTime != nil { - csOpts.MaxAwaitTime = cso.MaxAwaitTime - } - if cso.ResumeAfter != nil { - csOpts.ResumeAfter = cso.ResumeAfter - } - if cso.ShowExpandedEvents != nil { - csOpts.ShowExpandedEvents = cso.ShowExpandedEvents - } - if cso.StartAtOperationTime != nil { - csOpts.StartAtOperationTime = cso.StartAtOperationTime - } - if cso.StartAfter != nil { - csOpts.StartAfter = cso.StartAfter - } - if cso.Custom != nil { - csOpts.Custom = cso.Custom - } - if cso.CustomPipeline != nil { - csOpts.CustomPipeline = cso.CustomPipeline - } - } - - return csOpts -} diff --git a/mongo/options/changestreamoptions_test.go b/mongo/options/changestreamoptions_test.go deleted file mode 100644 index 7b9179c2ff..0000000000 --- a/mongo/options/changestreamoptions_test.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2023-present. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -package options - -import ( - "testing" - - "go.mongodb.org/mongo-driver/internal/assert" -) - -func TestMergeChangeStreamOptions(t *testing.T) { - t.Parallel() - - fullDocumentP := func(x FullDocument) *FullDocument { return &x } - int32P := func(x int32) *int32 { return &x } - - testCases := []struct { - description string - input []*ChangeStreamOptions - want *ChangeStreamOptions - }{ - { - description: "empty", - input: []*ChangeStreamOptions{}, - want: &ChangeStreamOptions{}, - }, - { - description: "many ChangeStreamOptions with one configuration each", - input: []*ChangeStreamOptions{ - ChangeStream().SetFullDocumentBeforeChange(Required), - ChangeStream().SetFullDocument(Required), - ChangeStream().SetBatchSize(10), - }, - want: &ChangeStreamOptions{ - FullDocument: fullDocumentP(Required), - FullDocumentBeforeChange: fullDocumentP(Required), - BatchSize: int32P(10), - }, - }, - { - description: "single ChangeStreamOptions with many configurations", - input: []*ChangeStreamOptions{ - ChangeStream(). - SetFullDocumentBeforeChange(Required). - SetFullDocument(Required). - SetBatchSize(10), - }, - want: &ChangeStreamOptions{ - FullDocument: fullDocumentP(Required), - FullDocumentBeforeChange: fullDocumentP(Required), - BatchSize: int32P(10), - }, - }, - } - - for _, tc := range testCases { - tc := tc // Capture range variable. - - t.Run(tc.description, func(t *testing.T) { - t.Parallel() - - got := MergeChangeStreamOptions(tc.input...) - assert.Equal(t, tc.want, got, "expected and actual ChangeStreamOptions are different") - }) - } -} diff --git a/mongo/options/clientencryptionoptions.go b/mongo/options/clientencryptionoptions.go index 2457f682ba..24eb9a600b 100644 --- a/mongo/options/clientencryptionoptions.go +++ b/mongo/options/clientencryptionoptions.go @@ -120,31 +120,3 @@ func BuildTLSConfig(tlsOpts map[string]interface{}) (*tls.Config, error) { return cfg, nil } - -// MergeClientEncryptionOptions combines the argued ClientEncryptionOptions 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 MergeClientEncryptionOptions(opts ...*ClientEncryptionOptions) *ClientEncryptionOptions { - ceo := ClientEncryption() - for _, opt := range opts { - if opt == nil { - continue - } - - if opt.KeyVaultNamespace != "" { - ceo.KeyVaultNamespace = opt.KeyVaultNamespace - } - if opt.KmsProviders != nil { - ceo.KmsProviders = opt.KmsProviders - } - if opt.TLSConfig != nil { - ceo.TLSConfig = opt.TLSConfig - } - if opt.HTTPClient != nil { - ceo.HTTPClient = opt.HTTPClient - } - } - - return ceo -} diff --git a/mongo/options/clientoptions.go b/mongo/options/clientoptions.go index fe9178cc49..4572d331cf 100644 --- a/mongo/options/clientoptions.go +++ b/mongo/options/clientoptions.go @@ -219,12 +219,6 @@ type ClientOptions struct { uri string cs *connstring.ConnString - // AuthenticateToAnything skips server type checks when deciding if authentication is possible. - // - // Deprecated: This option is for internal use only and should not be set. It may be changed or removed in any - // release. - AuthenticateToAnything *bool - // Crypt specifies a custom driver.Crypt to be used to encrypt and decrypt documents. The default is no // encryption. // @@ -414,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 { @@ -511,23 +505,21 @@ func (c *ClientOptions) ApplyURI(uri string) *ClientOptions { } if cs.JSet || cs.WString != "" || cs.WNumberSet || cs.WTimeoutSet { - opts := make([]writeconcern.Option, 0, 1) + c.WriteConcern = &writeconcern.WriteConcern{} if len(cs.WString) > 0 { - opts = append(opts, writeconcern.WTagSet(cs.WString)) + c.WriteConcern.W = cs.WString } else if cs.WNumberSet { - opts = append(opts, writeconcern.W(cs.WNumber)) + c.WriteConcern.W = cs.WNumber } if cs.JSet { - opts = append(opts, writeconcern.J(cs.J)) + c.WriteConcern.Journal = &cs.J } if cs.WTimeoutSet { - opts = append(opts, writeconcern.WTimeout(cs.WTimeout)) + c.WriteConcern.WTimeout = cs.WTimeout } - - c.WriteConcern = writeconcern.New(opts...) } if cs.ZlibLevelSet { @@ -961,7 +953,7 @@ func (c *ClientOptions) SetSRVServiceName(srvName string) *ClientOptions { return c } -// MergeClientOptions combines the given *ClientOptions into a single *ClientOptions in a last one wins fashion. +// MergeClientOptions combines the given *ClientOptions into a single *ClientOptions in a last property wins fashion. // The specified options are merged with the existing options on the client, with the specified options taking // precedence. // @@ -984,9 +976,6 @@ func MergeClientOptions(opts ...*ClientOptions) *ClientOptions { if opt.Auth != nil { c.Auth = opt.Auth } - if opt.AuthenticateToAnything != nil { - c.AuthenticateToAnything = opt.AuthenticateToAnything - } if opt.Compressors != nil { c.Compressors = opt.Compressors } diff --git a/mongo/options/clientoptions_test.go b/mongo/options/clientoptions_test.go index 7c148ca0bd..9db9b6b82f 100644 --- a/mongo/options/clientoptions_test.go +++ b/mongo/options/clientoptions_test.go @@ -88,7 +88,7 @@ func TestClientOptions(t *testing.T) { {"Direct", (*ClientOptions).SetDirect, true, "Direct", true}, {"SocketTimeout", (*ClientOptions).SetSocketTimeout, 5 * time.Second, "SocketTimeout", true}, {"TLSConfig", (*ClientOptions).SetTLSConfig, &tls.Config{}, "TLSConfig", false}, - {"WriteConcern", (*ClientOptions).SetWriteConcern, writeconcern.New(writeconcern.WMajority()), "WriteConcern", false}, + {"WriteConcern", (*ClientOptions).SetWriteConcern, writeconcern.Majority(), "WriteConcern", false}, {"ZlibLevel", (*ClientOptions).SetZlibLevel, 6, "ZlibLevel", true}, {"DisableOCSPEndpointCheck", (*ClientOptions).SetDisableOCSPEndpointCheck, true, "DisableOCSPEndpointCheck", true}, {"LoadBalanced", (*ClientOptions).SetLoadBalanced, true, "LoadBalanced", true}, @@ -439,22 +439,22 @@ func TestClientOptions(t *testing.T) { { "WriteConcern J", "mongodb://localhost/?journal=true", - baseClient().SetWriteConcern(writeconcern.New(writeconcern.J(true))), + baseClient().SetWriteConcern(writeconcern.Journaled()), }, { "WriteConcern WString", "mongodb://localhost/?w=majority", - baseClient().SetWriteConcern(writeconcern.New(writeconcern.WMajority())), + baseClient().SetWriteConcern(writeconcern.Majority()), }, { "WriteConcern W", "mongodb://localhost/?w=3", - baseClient().SetWriteConcern(writeconcern.New(writeconcern.W(3))), + baseClient().SetWriteConcern(&writeconcern.WriteConcern{W: 3}), }, { "WriteConcern WTimeout", "mongodb://localhost/?wTimeoutMS=45000", - baseClient().SetWriteConcern(writeconcern.New(writeconcern.WTimeout(45 * time.Second))), + baseClient().SetWriteConcern(&writeconcern.WriteConcern{WTimeout: 45 * time.Second}), }, { "ZLibLevel", diff --git a/mongo/options/collectionoptions.go b/mongo/options/collectionoptions.go index 04fda6d779..14e93f8fac 100644 --- a/mongo/options/collectionoptions.go +++ b/mongo/options/collectionoptions.go @@ -70,32 +70,3 @@ func (c *CollectionOptions) SetRegistry(r *bsoncodec.Registry) *CollectionOption c.Registry = r return c } - -// MergeCollectionOptions combines the given CollectionOptions instances into a single *CollectionOptions 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 MergeCollectionOptions(opts ...*CollectionOptions) *CollectionOptions { - c := Collection() - - for _, opt := range opts { - if opt == nil { - continue - } - if opt.ReadConcern != nil { - c.ReadConcern = opt.ReadConcern - } - if opt.WriteConcern != nil { - c.WriteConcern = opt.WriteConcern - } - if opt.ReadPreference != nil { - c.ReadPreference = opt.ReadPreference - } - if opt.Registry != nil { - c.Registry = opt.Registry - } - } - - return c -} diff --git a/mongo/options/countoptions.go b/mongo/options/countoptions.go index bb765d950d..677d3e4e2a 100644 --- a/mongo/options/countoptions.go +++ b/mongo/options/countoptions.go @@ -87,36 +87,3 @@ func (co *CountOptions) SetSkip(i int64) *CountOptions { co.Skip = &i return co } - -// MergeCountOptions combines the given CountOptions instances into a single CountOptions 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 MergeCountOptions(opts ...*CountOptions) *CountOptions { - countOpts := Count() - for _, co := range opts { - if co == nil { - continue - } - if co.Collation != nil { - countOpts.Collation = co.Collation - } - if co.Comment != nil { - countOpts.Comment = co.Comment - } - if co.Hint != nil { - countOpts.Hint = co.Hint - } - if co.Limit != nil { - countOpts.Limit = co.Limit - } - if co.MaxTime != nil { - countOpts.MaxTime = co.MaxTime - } - if co.Skip != nil { - countOpts.Skip = co.Skip - } - } - - return countOpts -} diff --git a/mongo/options/createcollectionoptions.go b/mongo/options/createcollectionoptions.go index d8ffaaf337..08447e6e84 100644 --- a/mongo/options/createcollectionoptions.go +++ b/mongo/options/createcollectionoptions.go @@ -260,66 +260,6 @@ func (c *CreateCollectionOptions) SetClusteredIndex(clusteredIndex interface{}) return c } -// MergeCreateCollectionOptions combines the given CreateCollectionOptions instances into a single -// CreateCollectionOptions 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 MergeCreateCollectionOptions(opts ...*CreateCollectionOptions) *CreateCollectionOptions { - cc := CreateCollection() - - for _, opt := range opts { - if opt == nil { - continue - } - - if opt.Capped != nil { - cc.Capped = opt.Capped - } - if opt.Collation != nil { - cc.Collation = opt.Collation - } - if opt.ChangeStreamPreAndPostImages != nil { - cc.ChangeStreamPreAndPostImages = opt.ChangeStreamPreAndPostImages - } - if opt.DefaultIndexOptions != nil { - cc.DefaultIndexOptions = opt.DefaultIndexOptions - } - if opt.MaxDocuments != nil { - cc.MaxDocuments = opt.MaxDocuments - } - if opt.SizeInBytes != nil { - cc.SizeInBytes = opt.SizeInBytes - } - if opt.StorageEngine != nil { - cc.StorageEngine = opt.StorageEngine - } - if opt.ValidationAction != nil { - cc.ValidationAction = opt.ValidationAction - } - if opt.ValidationLevel != nil { - cc.ValidationLevel = opt.ValidationLevel - } - if opt.Validator != nil { - cc.Validator = opt.Validator - } - if opt.ExpireAfterSeconds != nil { - cc.ExpireAfterSeconds = opt.ExpireAfterSeconds - } - if opt.TimeSeriesOptions != nil { - cc.TimeSeriesOptions = opt.TimeSeriesOptions - } - if opt.EncryptedFields != nil { - cc.EncryptedFields = opt.EncryptedFields - } - if opt.ClusteredIndex != nil { - cc.ClusteredIndex = opt.ClusteredIndex - } - } - - return cc -} - // CreateViewOptions represents options that can be used to configure a CreateView operation. type CreateViewOptions struct { // Specifies the default collation for the new collection. This option is only valid for MongoDB versions >= 3.4. @@ -337,24 +277,3 @@ func (c *CreateViewOptions) SetCollation(collation *Collation) *CreateViewOption c.Collation = collation return c } - -// MergeCreateViewOptions combines the given CreateViewOptions instances into a single CreateViewOptions 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 MergeCreateViewOptions(opts ...*CreateViewOptions) *CreateViewOptions { - cv := CreateView() - - for _, opt := range opts { - if opt == nil { - continue - } - - if opt.Collation != nil { - cv.Collation = opt.Collation - } - } - - return cv -} diff --git a/mongo/options/datakeyoptions.go b/mongo/options/datakeyoptions.go index 5afe8a2480..15cc01f9ef 100644 --- a/mongo/options/datakeyoptions.go +++ b/mongo/options/datakeyoptions.go @@ -77,28 +77,3 @@ func (dk *DataKeyOptions) SetKeyMaterial(keyMaterial []byte) *DataKeyOptions { dk.KeyMaterial = keyMaterial return dk } - -// MergeDataKeyOptions combines the argued DataKeyOptions 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 MergeDataKeyOptions(opts ...*DataKeyOptions) *DataKeyOptions { - dko := DataKey() - for _, opt := range opts { - if opt == nil { - continue - } - - if opt.MasterKey != nil { - dko.MasterKey = opt.MasterKey - } - if opt.KeyAltNames != nil { - dko.KeyAltNames = opt.KeyAltNames - } - if opt.KeyMaterial != nil { - dko.KeyMaterial = opt.KeyMaterial - } - } - - return dko -} diff --git a/mongo/options/dboptions.go b/mongo/options/dboptions.go index 8a380d2168..99c2d8fff2 100644 --- a/mongo/options/dboptions.go +++ b/mongo/options/dboptions.go @@ -70,32 +70,3 @@ func (d *DatabaseOptions) SetRegistry(r *bsoncodec.Registry) *DatabaseOptions { d.Registry = r return d } - -// MergeDatabaseOptions combines the given DatabaseOptions instances into a single DatabaseOptions 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 MergeDatabaseOptions(opts ...*DatabaseOptions) *DatabaseOptions { - d := Database() - - for _, opt := range opts { - if opt == nil { - continue - } - if opt.ReadConcern != nil { - d.ReadConcern = opt.ReadConcern - } - if opt.WriteConcern != nil { - d.WriteConcern = opt.WriteConcern - } - if opt.ReadPreference != nil { - d.ReadPreference = opt.ReadPreference - } - if opt.Registry != nil { - d.Registry = opt.Registry - } - } - - return d -} diff --git a/mongo/options/deleteoptions.go b/mongo/options/deleteoptions.go index 59aaef9153..f155b2a6c7 100644 --- a/mongo/options/deleteoptions.go +++ b/mongo/options/deleteoptions.go @@ -60,30 +60,3 @@ func (do *DeleteOptions) SetLet(let interface{}) *DeleteOptions { do.Let = let return do } - -// MergeDeleteOptions combines the given DeleteOptions instances into a single DeleteOptions 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 MergeDeleteOptions(opts ...*DeleteOptions) *DeleteOptions { - dOpts := Delete() - for _, do := range opts { - if do == nil { - continue - } - if do.Collation != nil { - dOpts.Collation = do.Collation - } - if do.Comment != nil { - dOpts.Comment = do.Comment - } - if do.Hint != nil { - dOpts.Hint = do.Hint - } - if do.Let != nil { - dOpts.Let = do.Let - } - } - - return dOpts -} diff --git a/mongo/options/distinctoptions.go b/mongo/options/distinctoptions.go index 819f2a9a8f..4cfcb98526 100644 --- a/mongo/options/distinctoptions.go +++ b/mongo/options/distinctoptions.go @@ -54,28 +54,3 @@ func (do *DistinctOptions) SetMaxTime(d time.Duration) *DistinctOptions { do.MaxTime = &d return do } - -// MergeDistinctOptions combines the given DistinctOptions instances into a single DistinctOptions 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 MergeDistinctOptions(opts ...*DistinctOptions) *DistinctOptions { - distinctOpts := Distinct() - for _, do := range opts { - if do == nil { - continue - } - if do.Collation != nil { - distinctOpts.Collation = do.Collation - } - if do.Comment != nil { - distinctOpts.Comment = do.Comment - } - if do.MaxTime != nil { - distinctOpts.MaxTime = do.MaxTime - } - } - - return distinctOpts -} diff --git a/mongo/options/encryptoptions.go b/mongo/options/encryptoptions.go index 88517d0c8d..c11a541916 100644 --- a/mongo/options/encryptoptions.go +++ b/mongo/options/encryptoptions.go @@ -115,37 +115,3 @@ func (ro *RangeOptions) SetPrecision(precision int32) *RangeOptions { ro.Precision = &precision return ro } - -// MergeEncryptOptions combines the argued EncryptOptions 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 MergeEncryptOptions(opts ...*EncryptOptions) *EncryptOptions { - eo := Encrypt() - for _, opt := range opts { - if opt == nil { - continue - } - - if opt.KeyID != nil { - eo.KeyID = opt.KeyID - } - if opt.KeyAltName != nil { - eo.KeyAltName = opt.KeyAltName - } - if opt.Algorithm != "" { - eo.Algorithm = opt.Algorithm - } - if opt.QueryType != "" { - eo.QueryType = opt.QueryType - } - if opt.ContentionFactor != nil { - eo.ContentionFactor = opt.ContentionFactor - } - if opt.RangeOptions != nil { - eo.RangeOptions = opt.RangeOptions - } - } - - return eo -} diff --git a/mongo/options/estimatedcountoptions.go b/mongo/options/estimatedcountoptions.go index d088af9c9a..b7d52bef6d 100644 --- a/mongo/options/estimatedcountoptions.go +++ b/mongo/options/estimatedcountoptions.go @@ -43,25 +43,3 @@ func (eco *EstimatedDocumentCountOptions) SetMaxTime(d time.Duration) *Estimated eco.MaxTime = &d return eco } - -// MergeEstimatedDocumentCountOptions combines the given EstimatedDocumentCountOptions instances into a single -// EstimatedDocumentCountOptions 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 MergeEstimatedDocumentCountOptions(opts ...*EstimatedDocumentCountOptions) *EstimatedDocumentCountOptions { - e := EstimatedDocumentCount() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.Comment != nil { - e.Comment = opt.Comment - } - if opt.MaxTime != nil { - e.MaxTime = opt.MaxTime - } - } - - return e -} diff --git a/mongo/options/findoptions.go b/mongo/options/findoptions.go index fa3bf1197a..93c4787e98 100644 --- a/mongo/options/findoptions.go +++ b/mongo/options/findoptions.go @@ -73,12 +73,6 @@ type FindOptions struct { // The default value is false. NoCursorTimeout *bool - // OplogReplay is for internal replication use only and should not be set. - // - // Deprecated: This option has been deprecated in MongoDB version 4.4 and will be ignored by the server if it is - // set. - OplogReplay *bool - // Project is a document describing which fields will be included in the documents returned by the Find operation. The // default value is nil, which means all fields will be included. Projection interface{} @@ -94,12 +88,6 @@ type FindOptions struct { // Skip is the number of documents to skip before adding documents to the result. The default value is 0. Skip *int64 - // Snapshot specifies whether the cursor will not return a document more than once because of an intervening write operation. - // The default value is false. - // - // Deprecated: This option has been deprecated in MongoDB version 3.6 and removed in MongoDB version 4.0. - Snapshot *bool - // Sort is a document specifying the order in which documents should be returned. The driver will return an error if the // sort parameter is a multi-key map. Sort interface{} @@ -204,14 +192,6 @@ func (f *FindOptions) SetNoCursorTimeout(b bool) *FindOptions { return f } -// SetOplogReplay sets the value for the OplogReplay field. -// -// Deprecated: This option has been deprecated in MongoDB version 4.4 and will be ignored by the server if it is set. -func (f *FindOptions) SetOplogReplay(b bool) *FindOptions { - f.OplogReplay = &b - return f -} - // SetProjection sets the value for the Projection field. func (f *FindOptions) SetProjection(projection interface{}) *FindOptions { f.Projection = projection @@ -236,109 +216,18 @@ func (f *FindOptions) SetSkip(i int64) *FindOptions { return f } -// SetSnapshot sets the value for the Snapshot field. -// -// Deprecated: This option has been deprecated in MongoDB version 3.6 and removed in MongoDB version 4.0. -func (f *FindOptions) SetSnapshot(b bool) *FindOptions { - f.Snapshot = &b - return f -} - // SetSort sets the value for the Sort field. func (f *FindOptions) SetSort(sort interface{}) *FindOptions { f.Sort = sort return f } -// MergeFindOptions combines the given FindOptions instances into a single FindOptions 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 MergeFindOptions(opts ...*FindOptions) *FindOptions { - fo := Find() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.AllowDiskUse != nil { - fo.AllowDiskUse = opt.AllowDiskUse - } - if opt.AllowPartialResults != nil { - fo.AllowPartialResults = opt.AllowPartialResults - } - if opt.BatchSize != nil { - fo.BatchSize = opt.BatchSize - } - if opt.Collation != nil { - fo.Collation = opt.Collation - } - if opt.Comment != nil { - fo.Comment = opt.Comment - } - if opt.CursorType != nil { - fo.CursorType = opt.CursorType - } - if opt.Hint != nil { - fo.Hint = opt.Hint - } - if opt.Let != nil { - fo.Let = opt.Let - } - if opt.Limit != nil { - fo.Limit = opt.Limit - } - if opt.Max != nil { - fo.Max = opt.Max - } - if opt.MaxAwaitTime != nil { - fo.MaxAwaitTime = opt.MaxAwaitTime - } - if opt.MaxTime != nil { - fo.MaxTime = opt.MaxTime - } - if opt.Min != nil { - fo.Min = opt.Min - } - if opt.NoCursorTimeout != nil { - fo.NoCursorTimeout = opt.NoCursorTimeout - } - if opt.OplogReplay != nil { - fo.OplogReplay = opt.OplogReplay - } - if opt.Projection != nil { - fo.Projection = opt.Projection - } - if opt.ReturnKey != nil { - fo.ReturnKey = opt.ReturnKey - } - if opt.ShowRecordID != nil { - fo.ShowRecordID = opt.ShowRecordID - } - if opt.Skip != nil { - fo.Skip = opt.Skip - } - if opt.Snapshot != nil { - fo.Snapshot = opt.Snapshot - } - if opt.Sort != nil { - fo.Sort = opt.Sort - } - } - - return fo -} - // FindOneOptions represents options that can be used to configure a FindOne operation. type FindOneOptions struct { // If true, an operation on a sharded cluster can return partial results if some shards are down rather than // returning an error. The default value is false. AllowPartialResults *bool - // The maximum number of documents to be included in each batch returned by the server. - // - // Deprecated: This option is not valid for a findOne operation, as no cursor is actually created. - BatchSize *int32 - // Specifies a collation to use for string comparisons during the operation. This option is only valid for MongoDB // versions >= 3.4. For previous server versions, the driver will return an error if this option is used. The // default value is nil, which means the default collation of the collection will be used. @@ -348,12 +237,6 @@ type FindOneOptions struct { // The default is nil, which means that no comment will be included in the logs. Comment *string - // Specifies the type of cursor that should be created for the operation. The default is NonTailable, which means - // that the cursor will be closed by the server when the last batch of documents is retrieved. - // - // Deprecated: This option is not valid for a findOne operation, as no cursor is actually created. - CursorType *CursorType - // The index to use for the aggregation. This should either be the index name as a string or the index specification // as a document. The driver will return an error if the hint parameter is a multi-key map. The default value is nil, // which means that no hint will be sent. @@ -363,13 +246,6 @@ type FindOneOptions struct { // there is no maximum value. Max interface{} - // The maximum amount of time that the server should wait for new documents to satisfy a tailable cursor query. - // This option is only valid for tailable await cursors (see the CursorType option for more information) and - // MongoDB versions >= 3.2. For other cursor types or previous server versions, this option is ignored. - // - // Deprecated: This option is not valid for a findOne operation, as no cursor is actually created. - MaxAwaitTime *time.Duration - // The maximum amount of time that the query can run on the server. The default value is nil, meaning that there // is no time limit for query execution. // @@ -382,18 +258,6 @@ type FindOneOptions struct { // there is no minimum value. Min interface{} - // If true, the cursor created by the operation will not timeout after a period of inactivity. The default value - // is false. - // - // Deprecated: This option is not valid for a findOne operation, as no cursor is actually created. - NoCursorTimeout *bool - - // This option is for internal replication use only and should not be set. - // - // Deprecated: This option has been deprecated in MongoDB version 4.4 and will be ignored by the server if it is - // set. - OplogReplay *bool - // A document describing which fields will be included in the document returned by the operation. The default value // is nil, which means all fields will be included. Projection interface{} @@ -409,12 +273,6 @@ type FindOneOptions struct { // The number of documents to skip before selecting the document to be returned. The default value is 0. Skip *int64 - // If true, the cursor will not return a document more than once because of an intervening write operation. The - // default value is false. - // - // Deprecated: This option has been deprecated in MongoDB version 3.6 and removed in MongoDB version 4.0. - Snapshot *bool - // A document specifying the sort order to apply to the query. The first document in the sorted order will be // returned. The driver will return an error if the sort parameter is a multi-key map. Sort interface{} @@ -431,14 +289,6 @@ func (f *FindOneOptions) SetAllowPartialResults(b bool) *FindOneOptions { return f } -// SetBatchSize sets the value for the BatchSize field. -// -// Deprecated: This option is not valid for a findOne operation, as no cursor is actually created. -func (f *FindOneOptions) SetBatchSize(i int32) *FindOneOptions { - f.BatchSize = &i - return f -} - // SetCollation sets the value for the Collation field. func (f *FindOneOptions) SetCollation(collation *Collation) *FindOneOptions { f.Collation = collation @@ -451,14 +301,6 @@ func (f *FindOneOptions) SetComment(comment string) *FindOneOptions { return f } -// SetCursorType sets the value for the CursorType field. -// -// Deprecated: This option is not valid for a findOne operation, as no cursor is actually created. -func (f *FindOneOptions) SetCursorType(ct CursorType) *FindOneOptions { - f.CursorType = &ct - return f -} - // SetHint sets the value for the Hint field. func (f *FindOneOptions) SetHint(hint interface{}) *FindOneOptions { f.Hint = hint @@ -471,14 +313,6 @@ func (f *FindOneOptions) SetMax(max interface{}) *FindOneOptions { return f } -// SetMaxAwaitTime sets the value for the MaxAwaitTime field. -// -// Deprecated: This option is not valid for a findOne operation, as no cursor is actually created. -func (f *FindOneOptions) SetMaxAwaitTime(d time.Duration) *FindOneOptions { - f.MaxAwaitTime = &d - return f -} - // SetMaxTime sets the value for the MaxTime field. // // NOTE(benjirewis): MaxTime will be deprecated in a future release. The more general Timeout @@ -495,23 +329,6 @@ func (f *FindOneOptions) SetMin(min interface{}) *FindOneOptions { return f } -// SetNoCursorTimeout sets the value for the NoCursorTimeout field. -// -// Deprecated: This option is not valid for a findOne operation, as no cursor is actually created. -func (f *FindOneOptions) SetNoCursorTimeout(b bool) *FindOneOptions { - f.NoCursorTimeout = &b - return f -} - -// SetOplogReplay sets the value for the OplogReplay field. -// -// Deprecated: This option has been deprecated in MongoDB version 4.4 and will be ignored by the server if it is -// set. -func (f *FindOneOptions) SetOplogReplay(b bool) *FindOneOptions { - f.OplogReplay = &b - return f -} - // SetProjection sets the value for the Projection field. func (f *FindOneOptions) SetProjection(projection interface{}) *FindOneOptions { f.Projection = projection @@ -536,90 +353,12 @@ func (f *FindOneOptions) SetSkip(i int64) *FindOneOptions { return f } -// SetSnapshot sets the value for the Snapshot field. -// -// Deprecated: This option has been deprecated in MongoDB version 3.6 and removed in MongoDB version 4.0. -func (f *FindOneOptions) SetSnapshot(b bool) *FindOneOptions { - f.Snapshot = &b - return f -} - // SetSort sets the value for the Sort field. func (f *FindOneOptions) SetSort(sort interface{}) *FindOneOptions { f.Sort = sort return f } -// MergeFindOneOptions combines the given FindOneOptions instances into a single FindOneOptions 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 MergeFindOneOptions(opts ...*FindOneOptions) *FindOneOptions { - fo := FindOne() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.AllowPartialResults != nil { - fo.AllowPartialResults = opt.AllowPartialResults - } - if opt.BatchSize != nil { - fo.BatchSize = opt.BatchSize - } - if opt.Collation != nil { - fo.Collation = opt.Collation - } - if opt.Comment != nil { - fo.Comment = opt.Comment - } - if opt.CursorType != nil { - fo.CursorType = opt.CursorType - } - if opt.Hint != nil { - fo.Hint = opt.Hint - } - if opt.Max != nil { - fo.Max = opt.Max - } - if opt.MaxAwaitTime != nil { - fo.MaxAwaitTime = opt.MaxAwaitTime - } - if opt.MaxTime != nil { - fo.MaxTime = opt.MaxTime - } - if opt.Min != nil { - fo.Min = opt.Min - } - if opt.NoCursorTimeout != nil { - fo.NoCursorTimeout = opt.NoCursorTimeout - } - if opt.OplogReplay != nil { - fo.OplogReplay = opt.OplogReplay - } - if opt.Projection != nil { - fo.Projection = opt.Projection - } - if opt.ReturnKey != nil { - fo.ReturnKey = opt.ReturnKey - } - if opt.ShowRecordID != nil { - fo.ShowRecordID = opt.ShowRecordID - } - if opt.Skip != nil { - fo.Skip = opt.Skip - } - if opt.Snapshot != nil { - fo.Snapshot = opt.Snapshot - } - if opt.Sort != nil { - fo.Sort = opt.Sort - } - } - - return fo -} - // FindOneAndReplaceOptions represents options that can be used to configure a FindOneAndReplace instance. type FindOneAndReplaceOptions struct { // If true, writes executed as part of the operation will opt out of document-level validation on the server. This @@ -746,52 +485,6 @@ func (f *FindOneAndReplaceOptions) SetLet(let interface{}) *FindOneAndReplaceOpt return f } -// MergeFindOneAndReplaceOptions combines the given FindOneAndReplaceOptions instances into a single -// FindOneAndReplaceOptions 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 MergeFindOneAndReplaceOptions(opts ...*FindOneAndReplaceOptions) *FindOneAndReplaceOptions { - fo := FindOneAndReplace() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.BypassDocumentValidation != nil { - fo.BypassDocumentValidation = opt.BypassDocumentValidation - } - if opt.Collation != nil { - fo.Collation = opt.Collation - } - if opt.Comment != nil { - fo.Comment = opt.Comment - } - if opt.MaxTime != nil { - fo.MaxTime = opt.MaxTime - } - if opt.Projection != nil { - fo.Projection = opt.Projection - } - if opt.ReturnDocument != nil { - fo.ReturnDocument = opt.ReturnDocument - } - if opt.Sort != nil { - fo.Sort = opt.Sort - } - if opt.Upsert != nil { - fo.Upsert = opt.Upsert - } - if opt.Hint != nil { - fo.Hint = opt.Hint - } - if opt.Let != nil { - fo.Let = opt.Let - } - } - - return fo -} - // FindOneAndUpdateOptions represents options that can be used to configure a FindOneAndUpdate options. type FindOneAndUpdateOptions struct { // A set of filters specifying to which array elements an update should apply. This option is only valid for MongoDB @@ -929,55 +622,6 @@ func (f *FindOneAndUpdateOptions) SetLet(let interface{}) *FindOneAndUpdateOptio return f } -// MergeFindOneAndUpdateOptions combines the given FindOneAndUpdateOptions instances into a single -// FindOneAndUpdateOptions 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 MergeFindOneAndUpdateOptions(opts ...*FindOneAndUpdateOptions) *FindOneAndUpdateOptions { - fo := FindOneAndUpdate() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.ArrayFilters != nil { - fo.ArrayFilters = opt.ArrayFilters - } - if opt.BypassDocumentValidation != nil { - fo.BypassDocumentValidation = opt.BypassDocumentValidation - } - if opt.Collation != nil { - fo.Collation = opt.Collation - } - if opt.Comment != nil { - fo.Comment = opt.Comment - } - if opt.MaxTime != nil { - fo.MaxTime = opt.MaxTime - } - if opt.Projection != nil { - fo.Projection = opt.Projection - } - if opt.ReturnDocument != nil { - fo.ReturnDocument = opt.ReturnDocument - } - if opt.Sort != nil { - fo.Sort = opt.Sort - } - if opt.Upsert != nil { - fo.Upsert = opt.Upsert - } - if opt.Hint != nil { - fo.Hint = opt.Hint - } - if opt.Let != nil { - fo.Let = opt.Let - } - } - - return fo -} - // FindOneAndDeleteOptions represents options that can be used to configure a FindOneAndDelete operation. type FindOneAndDeleteOptions struct { // Specifies a collation to use for string comparisons during the operation. This option is only valid for MongoDB @@ -1071,40 +715,3 @@ func (f *FindOneAndDeleteOptions) SetLet(let interface{}) *FindOneAndDeleteOptio f.Let = let return f } - -// MergeFindOneAndDeleteOptions combines the given FindOneAndDeleteOptions instances into a single -// FindOneAndDeleteOptions 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 MergeFindOneAndDeleteOptions(opts ...*FindOneAndDeleteOptions) *FindOneAndDeleteOptions { - fo := FindOneAndDelete() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.Collation != nil { - fo.Collation = opt.Collation - } - if opt.Comment != nil { - fo.Comment = opt.Comment - } - if opt.MaxTime != nil { - fo.MaxTime = opt.MaxTime - } - if opt.Projection != nil { - fo.Projection = opt.Projection - } - if opt.Sort != nil { - fo.Sort = opt.Sort - } - if opt.Hint != nil { - fo.Hint = opt.Hint - } - if opt.Let != nil { - fo.Let = opt.Let - } - } - - return fo -} diff --git a/mongo/options/gridfsoptions.go b/mongo/options/gridfsoptions.go index c8d347f4e7..ed525b34f4 100644 --- a/mongo/options/gridfsoptions.go +++ b/mongo/options/gridfsoptions.go @@ -84,37 +84,6 @@ func (b *BucketOptions) SetReadPreference(rp *readpref.ReadPref) *BucketOptions return b } -// MergeBucketOptions combines the given BucketOptions instances into a single BucketOptions 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 MergeBucketOptions(opts ...*BucketOptions) *BucketOptions { - b := GridFSBucket() - - for _, opt := range opts { - if opt == nil { - continue - } - if opt.Name != nil { - b.Name = opt.Name - } - if opt.ChunkSizeBytes != nil { - b.ChunkSizeBytes = opt.ChunkSizeBytes - } - if opt.WriteConcern != nil { - b.WriteConcern = opt.WriteConcern - } - if opt.ReadConcern != nil { - b.ReadConcern = opt.ReadConcern - } - if opt.ReadPreference != nil { - b.ReadPreference = opt.ReadPreference - } - } - - return b -} - // UploadOptions represents options that can be used to configure a GridFS upload operation. type UploadOptions struct { // The number of bytes in each chunk in the bucket. The default value is DefaultChunkSize (255 KiB). @@ -146,31 +115,6 @@ func (u *UploadOptions) SetMetadata(doc interface{}) *UploadOptions { return u } -// MergeUploadOptions combines the given UploadOptions instances into a single UploadOptions 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 MergeUploadOptions(opts ...*UploadOptions) *UploadOptions { - u := GridFSUpload() - - for _, opt := range opts { - if opt == nil { - continue - } - if opt.ChunkSizeBytes != nil { - u.ChunkSizeBytes = opt.ChunkSizeBytes - } - if opt.Metadata != nil { - u.Metadata = opt.Metadata - } - if opt.Registry != nil { - u.Registry = opt.Registry - } - } - - return u -} - // NameOptions represents options that can be used to configure a GridFS DownloadByName operation. type NameOptions struct { // Specifies the revision of the file to retrieve. Revision numbers are defined as follows: @@ -197,26 +141,6 @@ func (n *NameOptions) SetRevision(r int32) *NameOptions { return n } -// MergeNameOptions combines the given NameOptions instances into a single *NameOptions 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 MergeNameOptions(opts ...*NameOptions) *NameOptions { - n := GridFSName() - n.Revision = &DefaultRevision - - for _, opt := range opts { - if opt == nil { - continue - } - if opt.Revision != nil { - n.Revision = opt.Revision - } - } - - return n -} - // GridFSFindOptions represents options that can be used to configure a GridFS Find operation. type GridFSFindOptions struct { // If true, the server can write temporary data to disk while executing the find operation. The default value @@ -302,40 +226,3 @@ func (f *GridFSFindOptions) SetSort(sort interface{}) *GridFSFindOptions { f.Sort = sort return f } - -// MergeGridFSFindOptions combines the given GridFSFindOptions instances into a single GridFSFindOptions 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 MergeGridFSFindOptions(opts ...*GridFSFindOptions) *GridFSFindOptions { - fo := GridFSFind() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.AllowDiskUse != nil { - fo.AllowDiskUse = opt.AllowDiskUse - } - if opt.BatchSize != nil { - fo.BatchSize = opt.BatchSize - } - if opt.Limit != nil { - fo.Limit = opt.Limit - } - if opt.MaxTime != nil { - fo.MaxTime = opt.MaxTime - } - if opt.NoCursorTimeout != nil { - fo.NoCursorTimeout = opt.NoCursorTimeout - } - if opt.Skip != nil { - fo.Skip = opt.Skip - } - if opt.Sort != nil { - fo.Sort = opt.Sort - } - } - - return fo -} diff --git a/mongo/options/indexoptions.go b/mongo/options/indexoptions.go index ab7e2b3f6b..1837b1037a 100644 --- a/mongo/options/indexoptions.go +++ b/mongo/options/indexoptions.go @@ -75,28 +75,6 @@ func (c *CreateIndexesOptions) SetCommitQuorumVotingMembers() *CreateIndexesOpti return c } -// MergeCreateIndexesOptions combines the given CreateIndexesOptions into a single CreateIndexesOptions 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 MergeCreateIndexesOptions(opts ...*CreateIndexesOptions) *CreateIndexesOptions { - c := CreateIndexes() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.MaxTime != nil { - c.MaxTime = opt.MaxTime - } - if opt.CommitQuorum != nil { - c.CommitQuorum = opt.CommitQuorum - } - } - - return c -} - // DropIndexesOptions represents options that can be used to configure IndexView.DropOne and IndexView.DropAll // operations. type DropIndexesOptions struct { @@ -124,25 +102,6 @@ func (d *DropIndexesOptions) SetMaxTime(duration time.Duration) *DropIndexesOpti return d } -// MergeDropIndexesOptions combines the given DropIndexesOptions into a single DropIndexesOptions 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 MergeDropIndexesOptions(opts ...*DropIndexesOptions) *DropIndexesOptions { - c := DropIndexes() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.MaxTime != nil { - c.MaxTime = opt.MaxTime - } - } - - return c -} - // ListIndexesOptions represents options that can be used to configure an IndexView.List operation. type ListIndexesOptions struct { // The maximum number of documents to be included in each batch returned by the server. @@ -178,37 +137,9 @@ func (l *ListIndexesOptions) SetMaxTime(d time.Duration) *ListIndexesOptions { return l } -// MergeListIndexesOptions combines the given ListIndexesOptions instances into a single *ListIndexesOptions 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 MergeListIndexesOptions(opts ...*ListIndexesOptions) *ListIndexesOptions { - c := ListIndexes() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.BatchSize != nil { - c.BatchSize = opt.BatchSize - } - if opt.MaxTime != nil { - c.MaxTime = opt.MaxTime - } - } - - return c -} - // IndexOptions represents options that can be used to configure a new index created through the IndexView.CreateOne // or IndexView.CreateMany operations. type IndexOptions struct { - // If true, the index will be built in the background on the server and will not block other tasks. The default - // value is false. - // - // Deprecated: This option has been deprecated in MongoDB version 4.2. - Background *bool - // The length of time, in seconds, for documents to remain in the collection. The default value is 0, which means // that documents will remain in the collection until they're explicitly deleted or the collection is dropped. ExpireAfterSeconds *int32 @@ -295,14 +226,6 @@ func Index() *IndexOptions { return &IndexOptions{} } -// SetBackground sets value for the Background field. -// -// Deprecated: This option has been deprecated in MongoDB version 4.2. -func (i *IndexOptions) SetBackground(background bool) *IndexOptions { - i.Background = &background - return i -} - // SetExpireAfterSeconds sets value for the ExpireAfterSeconds field. func (i *IndexOptions) SetExpireAfterSeconds(seconds int32) *IndexOptions { i.ExpireAfterSeconds = &seconds @@ -416,79 +339,3 @@ func (i *IndexOptions) SetHidden(hidden bool) *IndexOptions { i.Hidden = &hidden return i } - -// MergeIndexOptions combines the given IndexOptions into a single IndexOptions 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 MergeIndexOptions(opts ...*IndexOptions) *IndexOptions { - i := Index() - - for _, opt := range opts { - if opt == nil { - continue - } - if opt.Background != nil { - i.Background = opt.Background - } - if opt.ExpireAfterSeconds != nil { - i.ExpireAfterSeconds = opt.ExpireAfterSeconds - } - if opt.Name != nil { - i.Name = opt.Name - } - if opt.Sparse != nil { - i.Sparse = opt.Sparse - } - if opt.StorageEngine != nil { - i.StorageEngine = opt.StorageEngine - } - if opt.Unique != nil { - i.Unique = opt.Unique - } - if opt.Version != nil { - i.Version = opt.Version - } - if opt.DefaultLanguage != nil { - i.DefaultLanguage = opt.DefaultLanguage - } - if opt.LanguageOverride != nil { - i.LanguageOverride = opt.LanguageOverride - } - if opt.TextVersion != nil { - i.TextVersion = opt.TextVersion - } - if opt.Weights != nil { - i.Weights = opt.Weights - } - if opt.SphereVersion != nil { - i.SphereVersion = opt.SphereVersion - } - if opt.Bits != nil { - i.Bits = opt.Bits - } - if opt.Max != nil { - i.Max = opt.Max - } - if opt.Min != nil { - i.Min = opt.Min - } - if opt.BucketSize != nil { - i.BucketSize = opt.BucketSize - } - if opt.PartialFilterExpression != nil { - i.PartialFilterExpression = opt.PartialFilterExpression - } - if opt.Collation != nil { - i.Collation = opt.Collation - } - if opt.WildcardProjection != nil { - i.WildcardProjection = opt.WildcardProjection - } - if opt.Hidden != nil { - i.Hidden = opt.Hidden - } - } - - return i -} diff --git a/mongo/options/insertoptions.go b/mongo/options/insertoptions.go index 82137c60a3..7ef612db9c 100644 --- a/mongo/options/insertoptions.go +++ b/mongo/options/insertoptions.go @@ -36,28 +36,6 @@ func (ioo *InsertOneOptions) SetComment(comment interface{}) *InsertOneOptions { return ioo } -// MergeInsertOneOptions combines the given InsertOneOptions instances into a single InsertOneOptions 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 MergeInsertOneOptions(opts ...*InsertOneOptions) *InsertOneOptions { - ioOpts := InsertOne() - for _, ioo := range opts { - if ioo == nil { - continue - } - if ioo.BypassDocumentValidation != nil { - ioOpts.BypassDocumentValidation = ioo.BypassDocumentValidation - } - if ioo.Comment != nil { - ioOpts.Comment = ioo.Comment - } - } - - return ioOpts -} - // InsertManyOptions represents options that can be used to configure an InsertMany operation. type InsertManyOptions struct { // If true, writes executed as part of the operation will opt out of document-level validation on the server. This @@ -98,28 +76,3 @@ func (imo *InsertManyOptions) SetOrdered(b bool) *InsertManyOptions { imo.Ordered = &b return imo } - -// MergeInsertManyOptions combines the given InsertManyOptions instances into a single InsertManyOptions 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 MergeInsertManyOptions(opts ...*InsertManyOptions) *InsertManyOptions { - imOpts := InsertMany() - for _, imo := range opts { - if imo == nil { - continue - } - if imo.BypassDocumentValidation != nil { - imOpts.BypassDocumentValidation = imo.BypassDocumentValidation - } - if imo.Comment != nil { - imOpts.Comment = imo.Comment - } - if imo.Ordered != nil { - imOpts.Ordered = imo.Ordered - } - } - - return imOpts -} diff --git a/mongo/options/listcollectionsoptions.go b/mongo/options/listcollectionsoptions.go index 69b8c997e9..a4e6454682 100644 --- a/mongo/options/listcollectionsoptions.go +++ b/mongo/options/listcollectionsoptions.go @@ -42,28 +42,3 @@ func (lc *ListCollectionsOptions) SetAuthorizedCollections(b bool) *ListCollecti lc.AuthorizedCollections = &b return lc } - -// MergeListCollectionsOptions combines the given ListCollectionsOptions instances into a single *ListCollectionsOptions -// 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 MergeListCollectionsOptions(opts ...*ListCollectionsOptions) *ListCollectionsOptions { - lc := ListCollections() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.NameOnly != nil { - lc.NameOnly = opt.NameOnly - } - if opt.BatchSize != nil { - lc.BatchSize = opt.BatchSize - } - if opt.AuthorizedCollections != nil { - lc.AuthorizedCollections = opt.AuthorizedCollections - } - } - - return lc -} diff --git a/mongo/options/listdatabasesoptions.go b/mongo/options/listdatabasesoptions.go index fbd3df60d8..7f1c0bd99b 100644 --- a/mongo/options/listdatabasesoptions.go +++ b/mongo/options/listdatabasesoptions.go @@ -34,25 +34,3 @@ func (ld *ListDatabasesOptions) SetAuthorizedDatabases(b bool) *ListDatabasesOpt ld.AuthorizedDatabases = &b return ld } - -// MergeListDatabasesOptions combines the given ListDatabasesOptions instances into a single *ListDatabasesOptions 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 MergeListDatabasesOptions(opts ...*ListDatabasesOptions) *ListDatabasesOptions { - ld := ListDatabases() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.NameOnly != nil { - ld.NameOnly = opt.NameOnly - } - if opt.AuthorizedDatabases != nil { - ld.AuthorizedDatabases = opt.AuthorizedDatabases - } - } - - return ld -} diff --git a/mongo/options/mongooptions.go b/mongo/options/mongooptions.go index fd17ce44e1..931d0a0479 100644 --- a/mongo/options/mongooptions.go +++ b/mongo/options/mongooptions.go @@ -7,8 +7,6 @@ package options import ( - "fmt" - "reflect" "strconv" "go.mongodb.org/mongo-driver/bson" @@ -165,19 +163,3 @@ func (af *ArrayFilters) ToArrayDocument() (bson.Raw, error) { arr, _ = bsoncore.AppendArrayEnd(arr, idx) return arr, nil } - -// MarshalError is returned when attempting to transform a value into a document -// results in an error. -// -// Deprecated: MarshalError is unused and will be removed in Go Driver 2.0. -type MarshalError struct { - Value interface{} - Err error -} - -// Error implements the error interface. -// -// Deprecated: MarshalError is unused and will be removed in Go Driver 2.0. -func (me MarshalError) Error() string { - return fmt.Sprintf("cannot transform type %s to a bson.Raw", reflect.TypeOf(me.Value)) -} diff --git a/mongo/options/replaceoptions.go b/mongo/options/replaceoptions.go index f7d3960194..20c20fb108 100644 --- a/mongo/options/replaceoptions.go +++ b/mongo/options/replaceoptions.go @@ -82,37 +82,3 @@ func (ro *ReplaceOptions) SetLet(l interface{}) *ReplaceOptions { ro.Let = l return ro } - -// MergeReplaceOptions combines the given ReplaceOptions instances into a single ReplaceOptions 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 MergeReplaceOptions(opts ...*ReplaceOptions) *ReplaceOptions { - rOpts := Replace() - for _, ro := range opts { - if ro == nil { - continue - } - if ro.BypassDocumentValidation != nil { - rOpts.BypassDocumentValidation = ro.BypassDocumentValidation - } - if ro.Collation != nil { - rOpts.Collation = ro.Collation - } - if ro.Comment != nil { - rOpts.Comment = ro.Comment - } - if ro.Hint != nil { - rOpts.Hint = ro.Hint - } - if ro.Upsert != nil { - rOpts.Upsert = ro.Upsert - } - if ro.Let != nil { - rOpts.Let = ro.Let - } - } - - return rOpts -} diff --git a/mongo/options/rewrapdatakeyoptions.go b/mongo/options/rewrapdatakeyoptions.go index 22ba586042..1bd486956a 100644 --- a/mongo/options/rewrapdatakeyoptions.go +++ b/mongo/options/rewrapdatakeyoptions.go @@ -32,24 +32,3 @@ func (rmdko *RewrapManyDataKeyOptions) SetMasterKey(masterKey interface{}) *Rewr rmdko.MasterKey = masterKey return rmdko } - -// MergeRewrapManyDataKeyOptions combines the given RewrapManyDataKeyOptions instances into a single -// RewrapManyDataKeyOptions 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 MergeRewrapManyDataKeyOptions(opts ...*RewrapManyDataKeyOptions) *RewrapManyDataKeyOptions { - rmdkOpts := RewrapManyDataKey() - for _, rmdko := range opts { - if rmdko == nil { - continue - } - if provider := rmdko.Provider; provider != nil { - rmdkOpts.Provider = provider - } - if masterKey := rmdko.MasterKey; masterKey != nil { - rmdkOpts.MasterKey = masterKey - } - } - return rmdkOpts -} diff --git a/mongo/options/runcmdoptions.go b/mongo/options/runcmdoptions.go index b0cdec32ce..c1b79a1ac1 100644 --- a/mongo/options/runcmdoptions.go +++ b/mongo/options/runcmdoptions.go @@ -27,21 +27,3 @@ func (rc *RunCmdOptions) SetReadPreference(rp *readpref.ReadPref) *RunCmdOptions rc.ReadPreference = rp return rc } - -// MergeRunCmdOptions combines the given RunCmdOptions instances into one *RunCmdOptions 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 MergeRunCmdOptions(opts ...*RunCmdOptions) *RunCmdOptions { - rc := RunCmd() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.ReadPreference != nil { - rc.ReadPreference = opt.ReadPreference - } - } - - return rc -} diff --git a/mongo/options/sessionoptions.go b/mongo/options/sessionoptions.go index e1eab098be..4e1fdb1114 100644 --- a/mongo/options/sessionoptions.go +++ b/mongo/options/sessionoptions.go @@ -95,40 +95,3 @@ func (s *SessionOptions) SetSnapshot(b bool) *SessionOptions { s.Snapshot = &b return s } - -// MergeSessionOptions combines the given SessionOptions instances into a single SessionOptions 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 MergeSessionOptions(opts ...*SessionOptions) *SessionOptions { - s := Session() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.CausalConsistency != nil { - s.CausalConsistency = opt.CausalConsistency - } - if opt.DefaultReadConcern != nil { - s.DefaultReadConcern = opt.DefaultReadConcern - } - if opt.DefaultReadPreference != nil { - s.DefaultReadPreference = opt.DefaultReadPreference - } - if opt.DefaultWriteConcern != nil { - s.DefaultWriteConcern = opt.DefaultWriteConcern - } - if opt.DefaultMaxCommitTime != nil { - s.DefaultMaxCommitTime = opt.DefaultMaxCommitTime - } - if opt.Snapshot != nil { - s.Snapshot = opt.Snapshot - } - } - if s.CausalConsistency == nil && (s.Snapshot == nil || !*s.Snapshot) { - s.CausalConsistency = &DefaultCausalConsistency - } - - return s -} 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..dfbe14e3f4 100644 --- a/mongo/read_write_concern_spec_test.go +++ b/mongo/read_write_concern_spec_test.go @@ -104,13 +104,13 @@ 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) if expectedWc.wSet { - expected := expectedWc.GetW() + expected := expectedWc.W if _, ok := expected.(int); ok { assert.True(t, cs.WNumberSet, "expected WNumberSet, got false") assert.Equal(t, expected, cs.WNumber, "expected w value %v, got %v", expected, cs.WNumber) @@ -121,12 +121,12 @@ func runConnectionStringTest(t *testing.T, test connectionStringTest) { } if expectedWc.timeoutSet { assert.True(t, cs.WTimeoutSet, "expected WTimeoutSet, got false") - assert.Equal(t, expectedWc.GetWTimeout(), cs.WTimeout, - "expected timeout value %v, got %v", expectedWc.GetWTimeout(), cs.WTimeout) + assert.Equal(t, expectedWc.WTimeout, cs.WTimeout, + "expected timeout value %v, got %v", expectedWc.WTimeout, cs.WTimeout) } if expectedWc.jSet { assert.True(t, cs.JSet, "expected JSet, got false") - assert.Equal(t, expectedWc.GetJ(), cs.J, "expected j value %v, got %v", expectedWc.GetJ(), cs.J) + assert.Equal(t, *expectedWc.Journal, cs.J, "expected j value %v, got %v", *expectedWc.Journal, cs.J) } } } @@ -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 { @@ -225,7 +225,7 @@ type writeConcern struct { func writeConcernFromRaw(t *testing.T, wcRaw bson.Raw) writeConcern { var wc writeConcern - var opts []writeconcern.Option + wc.WriteConcern = &writeconcern.WriteConcern{} elems, _ := wcRaw.Elements() for _, elem := range elems { @@ -238,26 +238,24 @@ func writeConcernFromRaw(t *testing.T, wcRaw bson.Raw) writeConcern { switch val.Type { case bsontype.Int32: w := int(val.Int32()) - opts = append(opts, writeconcern.W(w)) + wc.WriteConcern.W = w case bsontype.String: - opts = append(opts, writeconcern.WTagSet(val.StringValue())) + wc.WriteConcern.W = val.StringValue() default: t.Fatalf("unexpected type for w: %v", val.Type) } case "wtimeoutMS": wc.timeoutSet = true timeout := time.Duration(val.Int32()) * time.Millisecond - opts = append(opts, writeconcern.WTimeout(timeout)) + wc.WriteConcern.WTimeout = timeout case "journal": wc.jSet = true j := val.Boolean() - opts = append(opts, writeconcern.J(j)) + wc.WriteConcern.Journal = &j default: t.Fatalf("unrecognized write concern field: %v", key) } } - - wc.WriteConcern = writeconcern.New(opts...) return wc } 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/search_index_view.go b/mongo/search_index_view.go index 6a7871531e..4eb7416d0d 100644 --- a/mongo/search_index_view.go +++ b/mongo/search_index_view.go @@ -13,7 +13,6 @@ import ( "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/mongo/writeconcern" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" "go.mongodb.org/mongo-driver/x/mongo/driver" "go.mongodb.org/mongo-driver/x/mongo/driver/operation" @@ -138,7 +137,7 @@ func (siv SearchIndexView) CreateMany( if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } @@ -200,7 +199,7 @@ func (siv SearchIndexView) DropOne( if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } @@ -262,7 +261,7 @@ func (siv SearchIndexView) UpdateOne( if sess.TransactionRunning() { wc = nil } - if !writeconcern.AckWrite(wc) { + if !wc.Acknowledged() { sess = nil } diff --git a/mongo/session.go b/mongo/session.go index 8f1e029b95..dcd83f650c 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/mongo/with_transactions_test.go b/mongo/with_transactions_test.go index de9893fdef..2be4e4ced3 100644 --- a/mongo/with_transactions_test.go +++ b/mongo/with_transactions_test.go @@ -581,7 +581,7 @@ func setupConvenientTransactions(t *testing.T, extraClientOpts ...*options.Clien baseClientOpts := options.Client(). ApplyURI(cs.Original). SetReadPreference(readpref.Primary()). - SetWriteConcern(writeconcern.New(writeconcern.WMajority())). + SetWriteConcern(writeconcern.Majority()). SetPoolMonitor(poolMonitor) integtest.AddTestServerAPIVersion(baseClientOpts) fullClientOpts := []*options.ClientOptions{baseClientOpts} diff --git a/mongo/writeconcern/writeconcern.go b/mongo/writeconcern/writeconcern.go index 8e288d10b7..41ecee275f 100644 --- a/mongo/writeconcern/writeconcern.go +++ b/mongo/writeconcern/writeconcern.go @@ -144,138 +144,6 @@ func Custom(tag string) *WriteConcern { return &WriteConcern{W: tag} } -// Option is an option to provide when creating a WriteConcern. -// -// Deprecated: Use the WriteConcern convenience functions or define a struct literal instead. -// For example: -// -// writeconcern.Majority() -// -// or -// -// journal := true -// &writeconcern.WriteConcern{ -// W: 2, -// Journal: &journal, -// } -type Option func(concern *WriteConcern) - -// New constructs a new WriteConcern. -// -// Deprecated: Use the WriteConcern convenience functions or define a struct literal instead. -// For example: -// -// writeconcern.Majority() -// -// or -// -// journal := true -// &writeconcern.WriteConcern{ -// W: 2, -// Journal: &journal, -// } -func New(options ...Option) *WriteConcern { - concern := &WriteConcern{} - - for _, option := range options { - option(concern) - } - - return concern -} - -// W requests acknowledgement that write operations propagate to the specified number of mongod -// instances. -// -// Deprecated: Use the Unacknowledged or W1 functions or define a struct literal instead. -// For example: -// -// writeconcern.Unacknowledged() -// -// or -// -// journal := true -// &writeconcern.WriteConcern{ -// W: 2, -// Journal: &journal, -// } -func W(w int) Option { - return func(concern *WriteConcern) { - concern.W = w - } -} - -// WMajority requests acknowledgement that write operations propagate to the majority of mongod -// instances. -// -// Deprecated: Use [Majority] instead. -func WMajority() Option { - return func(concern *WriteConcern) { - concern.W = majority - } -} - -// WTagSet requests acknowledgement that write operations propagate to the specified mongod -// instance. -// -// Deprecated: Use [Custom] instead. -func WTagSet(tag string) Option { - return func(concern *WriteConcern) { - concern.W = tag - } -} - -// J requests acknowledgement from MongoDB that write operations are written to -// the journal. -// -// Deprecated: Use the Journaled function or define a struct literal instead. -// For example: -// -// writeconcern.Journaled() -// -// or -// -// journal := true -// &writeconcern.WriteConcern{ -// W: 2, -// Journal: &journal, -// } -func J(j bool) Option { - return func(concern *WriteConcern) { - // To maintain backward compatible behavior (now that the J field is a - // bool pointer), only set a value for J if the input is true. If the - // input is false, do not set a value, which omits "j" from the - // marshaled write concern. - if j { - concern.Journal = &j - } - } -} - -// WTimeout specifies a time limit for the write concern. -// -// It is only applicable for "w" values greater than 1. Using a WTimeout and setting Timeout on the -// Client at the same time will result in undefined behavior. -// -// Deprecated: Use the WriteConcern convenience functions or define a struct literal instead. -// For example: -// -// wc := writeconcern.W1() -// wc.WTimeout = 30 * time.Second -// -// or -// -// journal := true -// &writeconcern.WriteConcern{ -// W: "majority", -// WTimeout: 30 * time.Second, -// } -func WTimeout(d time.Duration) Option { - return func(concern *WriteConcern) { - concern.WTimeout = d - } -} - // MarshalBSONValue implements the bson.ValueMarshaler interface. // // Deprecated: Marshaling a WriteConcern to BSON will not be supported in Go @@ -329,29 +197,6 @@ func (wc *WriteConcern) MarshalBSONValue() (bsontype.Type, []byte, error) { return bson.TypeEmbeddedDocument, bsoncore.BuildDocument(nil, elems), nil } -// AcknowledgedValue returns true if a BSON RawValue for a write concern represents an acknowledged write concern. -// The element's value must be a document representing a write concern. -// -// Deprecated: AcknowledgedValue will not be supported in Go Driver 2.0. -func AcknowledgedValue(rawv bson.RawValue) bool { - doc, ok := bsoncore.Value{Type: rawv.Type, Data: rawv.Value}.DocumentOK() - if !ok { - return false - } - - val, err := doc.LookupErr("w") - if err != nil { - // key w not found --> acknowledged - return true - } - - i32, ok := val.Int32OK() - if !ok { - return false - } - return i32 != 0 -} - // Acknowledged indicates whether or not a write with the given write concern will be acknowledged. func (wc *WriteConcern) Acknowledged() bool { // Only {w: 0} or {w: 0, j: false} are an unacknowledged write concerns. All other values are @@ -378,62 +223,3 @@ func (wc *WriteConcern) IsValid() bool { return false } } - -// GetW returns the write concern w level. -// -// Deprecated: Use the WriteConcern.W field instead. -func (wc *WriteConcern) GetW() interface{} { - return wc.W -} - -// GetJ returns the write concern journaling level. -// -// Deprecated: Use the WriteConcern.Journal field instead. -func (wc *WriteConcern) GetJ() bool { - // Treat a nil Journal as false. That maintains backward compatibility with the existing - // behavior of GetJ where unset is false. If users want the real value of Journal, they can - // access the Journal field. - return wc.Journal != nil && *wc.Journal -} - -// GetWTimeout returns the write concern timeout. -// -// Deprecated: Use the WriteConcern.WTimeout field instead. -func (wc *WriteConcern) GetWTimeout() time.Duration { - return wc.WTimeout -} - -// WithOptions returns a copy of this WriteConcern with the options set. -// -// Deprecated: Use the WriteConcern convenience functions or define a struct literal instead. -// For example: -// -// writeconcern.Majority() -// -// or -// -// journal := true -// &writeconcern.WriteConcern{ -// W: 2, -// Journal: &journal, -// } -func (wc *WriteConcern) WithOptions(options ...Option) *WriteConcern { - if wc == nil { - return New(options...) - } - newWC := &WriteConcern{} - *newWC = *wc - - for _, option := range options { - option(newWC) - } - - return newWC -} - -// AckWrite returns true if a write concern represents an acknowledged write -// -// Deprecated: Use [WriteConcern.Acknowledged] instead. -func AckWrite(wc *WriteConcern) bool { - return wc == nil || wc.Acknowledged() -} diff --git a/mongo/writeconcern/writeconcern_test.go b/mongo/writeconcern/writeconcern_test.go index 459e0eabe3..8f1da38499 100644 --- a/mongo/writeconcern/writeconcern_test.go +++ b/mongo/writeconcern/writeconcern_test.go @@ -18,44 +18,6 @@ import ( "go.mongodb.org/mongo-driver/mongo/writeconcern" ) -func TestWriteConcernWithOptions(t *testing.T) { - t.Parallel() - - t.Run("on nil WriteConcern", func(t *testing.T) { - t.Parallel() - - var wc *writeconcern.WriteConcern - - wc = wc.WithOptions(writeconcern.WMajority()) - assert.Equal(t, "majority", wc.GetW().(string)) - assert.False(t, wc.GetJ()) - }) - t.Run("on existing WriteConcern", func(t *testing.T) { - t.Parallel() - - wc := writeconcern.New(writeconcern.W(1), writeconcern.J(true)) - assert.Equal(t, 1, wc.GetW().(int)) - assert.True(t, wc.GetJ()) - - wc = wc.WithOptions(writeconcern.WMajority()) - assert.Equal(t, "majority", wc.GetW().(string)) - assert.True(t, wc.GetJ()) - }) - t.Run("with multiple options", func(t *testing.T) { - t.Parallel() - - wc := writeconcern.New(writeconcern.W(1), writeconcern.J(true)) - assert.Equal(t, 1, wc.GetW().(int)) - assert.True(t, wc.GetJ()) - assert.Equal(t, time.Duration(0), wc.GetWTimeout()) - - wc = wc.WithOptions(writeconcern.WMajority(), writeconcern.WTimeout(time.Second)) - assert.Equal(t, "majority", wc.GetW().(string)) - assert.True(t, wc.GetJ()) - assert.Equal(t, time.Second, wc.GetWTimeout()) - }) -} - func TestWriteConcern_MarshalBSONValue(t *testing.T) { t.Parallel() diff --git a/x/mongo/driver/integration/aggregate_test.go b/x/mongo/driver/integration/aggregate_test.go index 95a9b821ae..1dae4fec3a 100644 --- a/x/mongo/driver/integration/aggregate_test.go +++ b/x/mongo/driver/integration/aggregate_test.go @@ -121,7 +121,7 @@ func TestAggregate(t *testing.T) { bsoncore.BuildDocument(nil, bsoncore.AppendInt32Element(nil, "_id", 4)), bsoncore.BuildDocument(nil, bsoncore.AppendInt32Element(nil, "_id", 5)), } - wc := writeconcern.New(writeconcern.WMajority()) + wc := writeconcern.Majority() autoInsertDocs(t, wc, ds...) op := operation.NewAggregate(bsoncore.BuildArray(nil, @@ -169,7 +169,7 @@ func TestAggregate(t *testing.T) { bsoncore.BuildDocument(nil, bsoncore.AppendInt32Element(nil, "_id", 1)), bsoncore.BuildDocument(nil, bsoncore.AppendInt32Element(nil, "_id", 2)), } - wc := writeconcern.New(writeconcern.WMajority()) + wc := writeconcern.Majority() autoInsertDocs(t, wc, ds...) op := operation.NewAggregate(bsoncore.BuildArray(nil)).Collection(integtest.ColName(t)).Database(dbName). diff --git a/x/mongo/driver/integration/compressor_test.go b/x/mongo/driver/integration/compressor_test.go index 16f809cb80..5fca9baf80 100644 --- a/x/mongo/driver/integration/compressor_test.go +++ b/x/mongo/driver/integration/compressor_test.go @@ -25,7 +25,7 @@ func TestCompression(t *testing.T) { t.Skip("Skipping because no compressor specified") } - wc := writeconcern.New(writeconcern.WMajority()) + wc := writeconcern.Majority() collOne := integtest.ColName(t) dropCollection(t, integtest.DBName(t), collOne) diff --git a/x/mongo/driver/integration/scram_test.go b/x/mongo/driver/integration/scram_test.go index 18d99a5c40..cd473cae0b 100644 --- a/x/mongo/driver/integration/scram_test.go +++ b/x/mongo/driver/integration/scram_test.go @@ -59,7 +59,7 @@ func TestSCRAM(t *testing.T) { // Verify that test (root) user is authenticated. If this fails, the // rest of the test can't succeed. - wc := writeconcern.New(writeconcern.WMajority()) + wc := writeconcern.Majority() collOne := integtest.ColName(t) dropCollection(t, integtest.DBName(t), collOne) insertDocs(t, integtest.DBName(t), diff --git a/x/mongo/driver/mongocrypt/options/mongocrypt_context_options.go b/x/mongo/driver/mongocrypt/options/mongocrypt_context_options.go index 325777eb2b..2874416a19 100644 --- a/x/mongo/driver/mongocrypt/options/mongocrypt_context_options.go +++ b/x/mongo/driver/mongocrypt/options/mongocrypt_context_options.go @@ -134,24 +134,3 @@ func (rmdko *RewrapManyDataKeyOptions) SetMasterKey(masterKey bsoncore.Document) rmdko.MasterKey = masterKey return rmdko } - -// MergeRewrapManyDataKeyOptions combines the given RewrapManyDataKeyOptions instances into a single -// RewrapManyDataKeyOptions 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 MergeRewrapManyDataKeyOptions(opts ...*RewrapManyDataKeyOptions) *RewrapManyDataKeyOptions { - rmdkOpts := RewrapManyDataKey() - for _, rmdko := range opts { - if rmdko == nil { - continue - } - if provider := rmdko.Provider; provider != nil { - rmdkOpts.Provider = provider - } - if masterKey := rmdko.MasterKey; masterKey != nil { - rmdkOpts.MasterKey = masterKey - } - } - return rmdkOpts -} diff --git a/x/mongo/driver/operation.go b/x/mongo/driver/operation.go index 6b56191a01..d7b24e90e2 100644 --- a/x/mongo/driver/operation.go +++ b/x/mongo/driver/operation.go @@ -11,7 +11,6 @@ import ( "context" "errors" "fmt" - "math" "net" "strconv" "strings" @@ -119,22 +118,6 @@ type finishedInformation struct { duration time.Duration } -// convertInt64PtrToInt32Ptr will convert an int64 pointer reference to an int32 pointer -// reference. If the int64 value cannot be converted to int32 without causing -// an overflow, then this function will return nil. -func convertInt64PtrToInt32Ptr(i64 *int64) *int32 { - if i64 == nil { - return nil - } - - if *i64 > math.MaxInt32 || *i64 < math.MinInt32 { - return nil - } - - i32 := int32(*i64) - return &i32 -} - // success returns true if there was no command error or the command error is a // "WriteCommandError". Commands that executed on the server and return a status // of { ok: 1.0 } are considered successful commands and MUST generate a @@ -477,7 +460,7 @@ func (op Operation) Validate() error { if op.Database == "" { return errDatabaseNameEmpty } - if op.Client != nil && !writeconcern.AckWrite(op.WriteConcern) { + if op.Client != nil && !op.WriteConcern.Acknowledged() { return errors.New("session provided for an unacknowledged write") } return nil @@ -1039,7 +1022,7 @@ func (op Operation) retryable(desc description.Server) bool { } if retryWritesSupported(desc) && op.Client != nil && !(op.Client.TransactionInProgress() || op.Client.TransactionStarting()) && - writeconcern.AckWrite(op.WriteConcern) { + op.WriteConcern.Acknowledged() { return true } case Read: @@ -1282,7 +1265,7 @@ func (op Operation) createMsgWireMessage( var wmindex int32 // We set the MoreToCome bit if we have a write concern, it's unacknowledged, and we either // aren't batching or we are encoding the last batch. - if op.WriteConcern != nil && !writeconcern.AckWrite(op.WriteConcern) && (op.Batches == nil || len(op.Batches.Documents) == 0) { + if op.WriteConcern != nil && !op.WriteConcern.Acknowledged() && (op.Batches == nil || len(op.Batches.Documents) == 0) { flags = wiremessage.MoreToCome } // Set the ExhaustAllowed flag if the connection supports streaming. This will tell the server that it can @@ -1444,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 { @@ -1507,11 +1490,11 @@ func (op Operation) addSession(dst []byte, desc description.SelectedServer) ([]b // If the operation is defined for an explicit session but the server // does not support sessions, then throw an error. - if client != nil && !client.IsImplicit && desc.SessionTimeoutMinutesPtr == nil { + if client != nil && !client.IsImplicit && desc.SessionTimeoutMinutes == nil { return nil, fmt.Errorf("current topology does not support sessions") } - if client == nil || !sessionsSupported(desc.WireVersion) || desc.SessionTimeoutMinutesPtr == nil { + if client == nil || !sessionsSupported(desc.WireVersion) || desc.SessionTimeoutMinutes == nil { return dst, nil } if err := client.UpdateUseTime(); err != nil { @@ -1955,7 +1938,6 @@ func (op Operation) publishStartedEvent(ctx context.Context, info startedInforma CommandName: info.cmdName, RequestID: int64(info.requestID), ConnectionID: info.connID, - ServerConnectionID: convertInt64PtrToInt32Ptr(info.serverConnID), ServerConnectionID64: info.serverConnID, ServiceID: info.serviceID, } @@ -2035,8 +2017,6 @@ func (op Operation) publishFinishedEvent(ctx context.Context, info finishedInfor RequestID: int64(info.requestID), ConnectionID: info.connID, Duration: info.duration, - DurationNanos: info.duration.Nanoseconds(), - ServerConnectionID: convertInt64PtrToInt32Ptr(info.serverConnID), ServerConnectionID64: info.serverConnID, ServiceID: info.serviceID, } @@ -2065,5 +2045,5 @@ func sessionsSupported(wireVersion *description.VersionRange) bool { // retryWritesSupported returns true if this description represents a server that supports retryable writes. func retryWritesSupported(s description.Server) bool { - return s.SessionTimeoutMinutesPtr != nil && s.Kind != description.Standalone + return s.SessionTimeoutMinutes != nil && s.Kind != description.Standalone } diff --git a/x/mongo/driver/operation_test.go b/x/mongo/driver/operation_test.go index e6c9d4cf95..6e28ab90bc 100644 --- a/x/mongo/driver/operation_test.go +++ b/x/mongo/driver/operation_test.go @@ -10,7 +10,6 @@ import ( "bytes" "context" "errors" - "math" "testing" "time" @@ -149,26 +148,23 @@ func TestOperation(t *testing.T) { err = sessInProgressTransaction.ApplyCommand(description.Server{}) noerr(t, err) - wcAck := writeconcern.New(writeconcern.WMajority()) - wcUnack := writeconcern.New(writeconcern.W(0)) + wcAck := writeconcern.Majority() + wcUnack := writeconcern.Unacknowledged() descRetryable := description.Server{ - WireVersion: &description.VersionRange{Min: 6, Max: 21}, - SessionTimeoutMinutes: 1, - SessionTimeoutMinutesPtr: int64ToPtr(1), + WireVersion: &description.VersionRange{Min: 6, Max: 21}, + SessionTimeoutMinutes: int64ToPtr(1), } descNotRetryableWireVersion := description.Server{ - WireVersion: &description.VersionRange{Min: 6, Max: 21}, - SessionTimeoutMinutes: 1, - SessionTimeoutMinutesPtr: int64ToPtr(1), + WireVersion: &description.VersionRange{Min: 6, Max: 21}, + SessionTimeoutMinutes: int64ToPtr(1), } descNotRetryableStandalone := description.Server{ - WireVersion: &description.VersionRange{Min: 6, Max: 21}, - SessionTimeoutMinutes: 1, - SessionTimeoutMinutesPtr: int64ToPtr(1), - Kind: description.Standalone, + WireVersion: &description.VersionRange{Min: 6, Max: 21}, + SessionTimeoutMinutes: int64ToPtr(1), + Kind: description.Standalone, } testCases := []struct { @@ -218,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}, } @@ -234,7 +230,7 @@ func TestOperation(t *testing.T) { want := bsoncore.AppendDocumentElement(nil, "writeConcern", bsoncore.BuildDocumentFromElements( nil, bsoncore.AppendStringElement(nil, "w", "majority"), )) - got, err := Operation{WriteConcern: writeconcern.New(writeconcern.WMajority())}.addWriteConcern(nil, description.SelectedServer{}) + got, err := Operation{WriteConcern: writeconcern.Majority()}.addWriteConcern(nil, description.SelectedServer{}) noerr(t, err) if !bytes.Equal(got, want) { t.Errorf("WriteConcern elements do not match. got %v; want %v", got, want) @@ -816,58 +812,6 @@ func TestRetry(t *testing.T) { }) } -func TestConvertI64PtrToI32Ptr(t *testing.T) { - t.Parallel() - - newI64 := func(i64 int64) *int64 { return &i64 } - newI32 := func(i32 int32) *int32 { return &i32 } - - tests := []struct { - name string - i64 *int64 - want *int32 - }{ - { - name: "empty", - want: nil, - }, - { - name: "in bounds", - i64: newI64(1), - want: newI32(1), - }, - { - name: "out of bounds negative", - i64: newI64(math.MinInt32 - 1), - }, - { - name: "out of bounds positive", - i64: newI64(math.MaxInt32 + 1), - }, - { - name: "exact min int32", - i64: newI64(math.MinInt32), - want: newI32(math.MinInt32), - }, - { - name: "exact max int32", - i64: newI64(math.MaxInt32), - want: newI32(math.MaxInt32), - }, - } - - for _, test := range tests { - test := test - - t.Run(test.name, func(t *testing.T) { - t.Parallel() - - got := convertInt64PtrToInt32Ptr(test.i64) - assert.Equal(t, test.want, got) - }) - } -} - func TestDecodeOpReply(t *testing.T) { t.Parallel() diff --git a/x/mongo/driver/session/client_session.go b/x/mongo/driver/session/client_session.go index 8dac0932de..4181b6d3de 100644 --- a/x/mongo/driver/session/client_session.go +++ b/x/mongo/driver/session/client_session.go @@ -430,7 +430,7 @@ func (c *Client) StartTransaction(opts *TransactionOptions) error { c.CurrentMct = c.transactionMaxCommitTime } - if !writeconcern.AckWrite(c.CurrentWc) { + if !c.CurrentWc.Acknowledged() { _ = c.clearTransactionOpts() return ErrUnackWCUnsupported } @@ -465,12 +465,17 @@ func (c *Client) CommitTransaction() error { // w timeout of 10 seconds. This should be called after a commit transaction operation fails with a // retryable error or after a successful commit transaction operation. func (c *Client) UpdateCommitTransactionWriteConcern() { - wc := c.CurrentWc + wc := &writeconcern.WriteConcern{} timeout := 10 * time.Second - if wc != nil && wc.GetWTimeout() != 0 { - timeout = wc.GetWTimeout() + if c.CurrentWc != nil { + *wc = *c.CurrentWc + if c.CurrentWc.WTimeout != 0 { + timeout = c.CurrentWc.WTimeout + } } - c.CurrentWc = wc.WithOptions(writeconcern.WMajority(), writeconcern.WTimeout(timeout)) + wc.W = "majority" + wc.WTimeout = timeout + c.CurrentWc = wc } // CheckAbortTransaction checks to see if allowed to abort transaction and returns diff --git a/x/mongo/driver/session/session_pool.go b/x/mongo/driver/session/session_pool.go index 7336f54513..8b3cb8bebd 100644 --- a/x/mongo/driver/session/session_pool.go +++ b/x/mongo/driver/session/session_pool.go @@ -65,7 +65,7 @@ func (p *Pool) updateTimeout() { case newDesc := <-p.descChan: p.latestTopology = topologyDescription{ kind: newDesc.Kind, - timeoutMinutes: newDesc.SessionTimeoutMinutesPtr, + timeoutMinutes: newDesc.SessionTimeoutMinutes, } default: // no new description waiting diff --git a/x/mongo/driver/topology/fsm.go b/x/mongo/driver/topology/fsm.go index 1494ae7807..4a941eefe5 100644 --- a/x/mongo/driver/topology/fsm.go +++ b/x/mongo/driver/topology/fsm.go @@ -54,8 +54,8 @@ func newFSM() *fsm { // still do not have a timeout. This function chooses the lowest of the existing // timeouts. func selectFSMSessionTimeout(f *fsm, s description.Server) *int64 { - oldMinutes := f.SessionTimeoutMinutesPtr - comp := ptrutil.CompareInt64(oldMinutes, s.SessionTimeoutMinutesPtr) + oldMinutes := f.SessionTimeoutMinutes + comp := ptrutil.CompareInt64(oldMinutes, s.SessionTimeoutMinutes) // If the server is data-bearing and the current timeout exists and is // either: @@ -65,7 +65,7 @@ func selectFSMSessionTimeout(f *fsm, s description.Server) *int64 { // // then return the server timeout. if s.DataBearing() && (comp == 1 || comp == 2) { - return s.SessionTimeoutMinutesPtr + return s.SessionTimeoutMinutes } // If the current timeout exists and the server is not data-bearing OR @@ -75,7 +75,7 @@ func selectFSMSessionTimeout(f *fsm, s description.Server) *int64 { return oldMinutes } - timeout := s.SessionTimeoutMinutesPtr + timeout := s.SessionTimeoutMinutes for _, server := range f.Servers { // If the server is not data-bearing, then we do not consider // it's timeout whether set or not. @@ -83,14 +83,14 @@ func selectFSMSessionTimeout(f *fsm, s description.Server) *int64 { continue } - srvTimeout := server.SessionTimeoutMinutesPtr + srvTimeout := server.SessionTimeoutMinutes comp := ptrutil.CompareInt64(timeout, srvTimeout) if comp <= 0 { // timeout <= srvTimout continue } - timeout = server.SessionTimeoutMinutesPtr + timeout = server.SessionTimeoutMinutes } return timeout @@ -116,11 +116,7 @@ func (f *fsm) apply(s description.Server) (description.Topology, description.Ser SetName: f.SetName, } - f.Topology.SessionTimeoutMinutesPtr = serverTimeoutMinutes - - if serverTimeoutMinutes != nil { - f.SessionTimeoutMinutes = uint32(*serverTimeoutMinutes) - } + f.Topology.SessionTimeoutMinutes = serverTimeoutMinutes if _, ok := f.findServer(s.Addr); !ok { return f.Topology, s diff --git a/x/mongo/driver/topology/fsm_test.go b/x/mongo/driver/topology/fsm_test.go index 07fc5b8104..390ffebc32 100644 --- a/x/mongo/driver/topology/fsm_test.go +++ b/x/mongo/driver/topology/fsm_test.go @@ -35,7 +35,7 @@ func TestFSMSessionTimeout(t *testing.T) { name: "no session support on data-bearing server with session support on fsm", f: &fsm{ Topology: description.Topology{ - SessionTimeoutMinutesPtr: int64ToPtr(1), + SessionTimeoutMinutes: int64ToPtr(1), }, }, s: description.Server{ @@ -47,12 +47,12 @@ func TestFSMSessionTimeout(t *testing.T) { name: "lower timeout on data-bearing server with session support on fsm", f: &fsm{ Topology: description.Topology{ - SessionTimeoutMinutesPtr: int64ToPtr(2), + SessionTimeoutMinutes: int64ToPtr(2), }, }, s: description.Server{ - Kind: description.RSPrimary, - SessionTimeoutMinutesPtr: int64ToPtr(1), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(1), }, want: int64ToPtr(1), }, @@ -60,8 +60,8 @@ func TestFSMSessionTimeout(t *testing.T) { name: "session support on data-bearing server with no session support on fsm with no servers", f: &fsm{Topology: description.Topology{}}, s: description.Server{ - Kind: description.RSPrimary, - SessionTimeoutMinutesPtr: int64ToPtr(1), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(1), }, want: int64ToPtr(1), }, @@ -70,14 +70,14 @@ func TestFSMSessionTimeout(t *testing.T) { f: &fsm{Topology: description.Topology{ Servers: []description.Server{ { - Kind: description.RSPrimary, - SessionTimeoutMinutesPtr: int64ToPtr(1), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(1), }, }, }}, s: description.Server{ - Kind: description.RSPrimary, - SessionTimeoutMinutesPtr: int64ToPtr(2), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(2), }, want: int64ToPtr(1), }, @@ -86,14 +86,14 @@ func TestFSMSessionTimeout(t *testing.T) { f: &fsm{Topology: description.Topology{ Servers: []description.Server{ { - Kind: description.RSPrimary, - SessionTimeoutMinutesPtr: int64ToPtr(3), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(3), }, }, }}, s: description.Server{ - Kind: description.RSPrimary, - SessionTimeoutMinutesPtr: int64ToPtr(2), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(2), }, want: int64ToPtr(2), }, diff --git a/x/mongo/driver/topology/polling_srv_records_test.go b/x/mongo/driver/topology/polling_srv_records_test.go index 7484109d4e..99161f0ce0 100644 --- a/x/mongo/driver/topology/polling_srv_records_test.go +++ b/x/mongo/driver/topology/polling_srv_records_test.go @@ -183,12 +183,8 @@ func TestPollSRVRecords(t *testing.T) { topo.serversLock.Lock() topo.fsm.Kind = description.Single topo.desc.Store(description.Topology{ - Kind: topo.fsm.Kind, - Servers: topo.fsm.Servers, - SessionTimeoutMinutesPtr: topo.fsm.SessionTimeoutMinutesPtr, - - // TODO(GODRIVER-2885): This field can be removed once - // legacy SessionTimeoutMinutes is removed. + Kind: topo.fsm.Kind, + Servers: topo.fsm.Servers, SessionTimeoutMinutes: topo.fsm.SessionTimeoutMinutes, }) topo.serversLock.Unlock() diff --git a/x/mongo/driver/topology/sdam_spec_test.go b/x/mongo/driver/topology/sdam_spec_test.go index 3548d69b3e..e282133608 100644 --- a/x/mongo/driver/topology/sdam_spec_test.go +++ b/x/mongo/driver/topology/sdam_spec_test.go @@ -504,7 +504,7 @@ func runTest(t *testing.T, directory string, filename string) { assert.Equal(t, phase.Outcome.LogicalSessionTimeoutMinutes, - desc.SessionTimeoutMinutesPtr, + desc.SessionTimeoutMinutes, "expected and actual logical session timeout minutes are different") assert.Equal(t, phase.Outcome.MaxSetVersion, topo.fsm.maxSetVersion, diff --git a/x/mongo/driver/topology/server.go b/x/mongo/driver/topology/server.go index dff87407c0..29c96e9a72 100644 --- a/x/mongo/driver/topology/server.go +++ b/x/mongo/driver/topology/server.go @@ -1015,11 +1015,10 @@ func (s *Server) publishServerHeartbeatSucceededEvent(connectionID string, await bool, ) { serverHeartbeatSucceeded := &event.ServerHeartbeatSucceededEvent{ - DurationNanos: duration.Nanoseconds(), - Duration: duration, - Reply: desc, - ConnectionID: connectionID, - Awaited: await, + Duration: duration, + Reply: desc, + ConnectionID: connectionID, + Awaited: await, } if s != nil && s.cfg.serverMonitor != nil && s.cfg.serverMonitor.ServerHeartbeatSucceeded != nil { @@ -1041,11 +1040,10 @@ func (s *Server) publishServerHeartbeatFailedEvent(connectionID string, await bool, ) { serverHeartbeatFailed := &event.ServerHeartbeatFailedEvent{ - DurationNanos: duration.Nanoseconds(), - Duration: duration, - Failure: err, - ConnectionID: connectionID, - Awaited: await, + Duration: duration, + Failure: err, + ConnectionID: connectionID, + Awaited: await, } if s != nil && s.cfg.serverMonitor != nil && s.cfg.serverMonitor.ServerHeartbeatFailed != nil { diff --git a/x/mongo/driver/topology/topology.go b/x/mongo/driver/topology/topology.go index 6c8d445e3f..5794ebcb80 100644 --- a/x/mongo/driver/topology/topology.go +++ b/x/mongo/driver/topology/topology.go @@ -330,12 +330,8 @@ func (t *Topology) Connect() error { // server monitoring goroutines. newDesc := description.Topology{ - Kind: t.fsm.Kind, - Servers: t.fsm.Servers, - SessionTimeoutMinutesPtr: t.fsm.SessionTimeoutMinutesPtr, - - // TODO(GODRIVER-2885): This field can be removed once - // legacy SessionTimeoutMinutes is removed. + Kind: t.fsm.Kind, + Servers: t.fsm.Servers, SessionTimeoutMinutes: t.fsm.SessionTimeoutMinutes, } t.desc.Store(newDesc) @@ -862,12 +858,8 @@ func (t *Topology) processSRVResults(parsedHosts []string) bool { // store new description newDesc := description.Topology{ - Kind: t.fsm.Kind, - Servers: t.fsm.Servers, - SessionTimeoutMinutesPtr: t.fsm.SessionTimeoutMinutesPtr, - - // TODO(GODRIVER-2885): This field can be removed once legacy - // SessionTimeoutMinutes is removed. + Kind: t.fsm.Kind, + Servers: t.fsm.Servers, SessionTimeoutMinutes: t.fsm.SessionTimeoutMinutes, } t.desc.Store(newDesc) diff --git a/x/mongo/driver/topology/topology_options.go b/x/mongo/driver/topology/topology_options.go index 8deb614815..460b82e406 100644 --- a/x/mongo/driver/topology/topology_options.go +++ b/x/mongo/driver/topology/topology_options.go @@ -15,7 +15,6 @@ import ( "go.mongodb.org/mongo-driver/event" "go.mongodb.org/mongo-driver/internal/logger" - "go.mongodb.org/mongo-driver/mongo/description" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/x/mongo/driver" "go.mongodb.org/mongo-driver/x/mongo/driver/auth" @@ -199,12 +198,6 @@ func NewConfig(co *options.ClientOptions, clock *session.ClusterClock) (*Config, // Required for SASL mechanism negotiation during handshake handshakeOpts.DBUser = cred.Source + "." + cred.Username } - if co.AuthenticateToAnything != nil && *co.AuthenticateToAnything { - // Authenticate arbiters - handshakeOpts.PerformAuthentication = func(serv description.Server) bool { - return true - } - } handshaker = func(driver.Handshaker) driver.Handshaker { return auth.Handshaker(nil, handshakeOpts) diff --git a/x/mongo/driver/topology/topology_test.go b/x/mongo/driver/topology/topology_test.go index 6cf540a95e..2a9e2aff8f 100644 --- a/x/mongo/driver/topology/topology_test.go +++ b/x/mongo/driver/topology/topology_test.go @@ -421,10 +421,9 @@ func TestSessionTimeout(t *testing.T) { topo.servers["foo"] = nil topo.fsm.Servers = []description.Server{ { - Addr: address.Address("foo").Canonicalize(), - Kind: description.RSPrimary, - SessionTimeoutMinutes: 60, - SessionTimeoutMinutesPtr: int64ToPtr(60), + Addr: address.Address("foo").Canonicalize(), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(60), }, } @@ -432,16 +431,15 @@ func TestSessionTimeout(t *testing.T) { defer cancel() desc := description.Server{ - Addr: "foo", - Kind: description.RSPrimary, - SessionTimeoutMinutes: 30, - SessionTimeoutMinutesPtr: int64ToPtr(30), + Addr: "foo", + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(30), } topo.apply(ctx, desc) currDesc := topo.desc.Load().(description.Topology) want := int64(30) - require.Equal(t, &want, currDesc.SessionTimeoutMinutesPtr, + require.Equal(t, &want, currDesc.SessionTimeoutMinutes, "session timeout minutes mismatch") }) t.Run("MultipleUpdates", func(t *testing.T) { @@ -452,16 +450,14 @@ func TestSessionTimeout(t *testing.T) { topo.servers["bar"] = nil topo.fsm.Servers = []description.Server{ { - Addr: address.Address("foo").Canonicalize(), - Kind: description.RSPrimary, - SessionTimeoutMinutes: 60, - SessionTimeoutMinutesPtr: int64ToPtr(60), + Addr: address.Address("foo").Canonicalize(), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(60), }, { - Addr: address.Address("bar").Canonicalize(), - Kind: description.RSSecondary, - SessionTimeoutMinutes: 60, - SessionTimeoutMinutesPtr: int64ToPtr(60), + Addr: address.Address("bar").Canonicalize(), + Kind: description.RSSecondary, + SessionTimeoutMinutes: int64ToPtr(60), }, } @@ -469,26 +465,24 @@ func TestSessionTimeout(t *testing.T) { defer cancel() desc1 := description.Server{ - Addr: "foo", - Kind: description.RSPrimary, - SessionTimeoutMinutes: 30, - SessionTimeoutMinutesPtr: int64ToPtr(30), - Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, + Addr: "foo", + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(30), + Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, } // should update because new timeout is lower desc2 := description.Server{ - Addr: "bar", - Kind: description.RSPrimary, - SessionTimeoutMinutes: 20, - SessionTimeoutMinutesPtr: int64ToPtr(20), - Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, + Addr: "bar", + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(20), + Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, } topo.apply(ctx, desc1) topo.apply(ctx, desc2) currDesc := topo.Description() want := int64(20) - require.Equal(t, &want, currDesc.SessionTimeoutMinutesPtr, + require.Equal(t, &want, currDesc.SessionTimeoutMinutes, "session timeout minutes mismatch") }) t.Run("NoUpdate", func(t *testing.T) { @@ -498,16 +492,14 @@ func TestSessionTimeout(t *testing.T) { topo.servers["bar"] = nil topo.fsm.Servers = []description.Server{ { - Addr: address.Address("foo").Canonicalize(), - Kind: description.RSPrimary, - SessionTimeoutMinutes: 60, - SessionTimeoutMinutesPtr: int64ToPtr(60), + Addr: address.Address("foo").Canonicalize(), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(60), }, { - Addr: address.Address("bar").Canonicalize(), - Kind: description.RSSecondary, - SessionTimeoutMinutes: 60, - SessionTimeoutMinutesPtr: int64ToPtr(60), + Addr: address.Address("bar").Canonicalize(), + Kind: description.RSSecondary, + SessionTimeoutMinutes: int64ToPtr(60), }, } @@ -515,26 +507,24 @@ func TestSessionTimeout(t *testing.T) { defer cancel() desc1 := description.Server{ - Addr: "foo", - Kind: description.RSPrimary, - SessionTimeoutMinutes: 20, - SessionTimeoutMinutesPtr: int64ToPtr(20), - Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, + Addr: "foo", + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(20), + Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, } // should not update because new timeout is higher desc2 := description.Server{ - Addr: "bar", - Kind: description.RSPrimary, - SessionTimeoutMinutes: 30, - SessionTimeoutMinutesPtr: int64ToPtr(30), - Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, + Addr: "bar", + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(30), + Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, } topo.apply(ctx, desc1) topo.apply(ctx, desc2) currDesc := topo.desc.Load().(description.Topology) want := int64(20) - require.Equal(t, &want, currDesc.SessionTimeoutMinutesPtr, + require.Equal(t, &want, currDesc.SessionTimeoutMinutes, "session timeout minutes mismatch") }) t.Run("TimeoutDataBearing", func(t *testing.T) { @@ -544,16 +534,14 @@ func TestSessionTimeout(t *testing.T) { topo.servers["bar"] = nil topo.fsm.Servers = []description.Server{ { - Addr: address.Address("foo").Canonicalize(), - Kind: description.RSPrimary, - SessionTimeoutMinutes: 60, - SessionTimeoutMinutesPtr: int64ToPtr(60), + Addr: address.Address("foo").Canonicalize(), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(60), }, { - Addr: address.Address("bar").Canonicalize(), - Kind: description.RSSecondary, - SessionTimeoutMinutes: 60, - SessionTimeoutMinutesPtr: int64ToPtr(60), + Addr: address.Address("bar").Canonicalize(), + Kind: description.RSSecondary, + SessionTimeoutMinutes: int64ToPtr(60), }, } @@ -561,26 +549,24 @@ func TestSessionTimeout(t *testing.T) { defer cancel() desc1 := description.Server{ - Addr: "foo", - Kind: description.RSPrimary, - SessionTimeoutMinutes: 20, - SessionTimeoutMinutesPtr: int64ToPtr(20), - Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, + Addr: "foo", + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(20), + Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, } // should not update because not a data bearing server desc2 := description.Server{ - Addr: "bar", - Kind: description.Unknown, - SessionTimeoutMinutes: 10, - SessionTimeoutMinutesPtr: int64ToPtr(10), - Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, + Addr: "bar", + Kind: description.Unknown, + SessionTimeoutMinutes: int64ToPtr(10), + Members: []address.Address{address.Address("foo").Canonicalize(), address.Address("bar").Canonicalize()}, } topo.apply(ctx, desc1) topo.apply(ctx, desc2) currDesc := topo.desc.Load().(description.Topology) want := int64(20) - assert.Equal(t, &want, currDesc.SessionTimeoutMinutesPtr, + assert.Equal(t, &want, currDesc.SessionTimeoutMinutes, "session timeout minutes mismatch") }) t.Run("MixedSessionSupport", func(t *testing.T) { @@ -592,10 +578,9 @@ func TestSessionTimeout(t *testing.T) { topo.servers["three"] = nil topo.fsm.Servers = []description.Server{ { - Addr: address.Address("one").Canonicalize(), - Kind: description.RSPrimary, - SessionTimeoutMinutes: 20, - SessionTimeoutMinutesPtr: int64ToPtr(20), + Addr: address.Address("one").Canonicalize(), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(20), }, { // does not support sessions @@ -603,10 +588,9 @@ func TestSessionTimeout(t *testing.T) { Kind: description.RSSecondary, }, { - Addr: address.Address("three").Canonicalize(), - Kind: description.RSPrimary, - SessionTimeoutMinutes: 60, - SessionTimeoutMinutesPtr: int64ToPtr(60), + Addr: address.Address("three").Canonicalize(), + Kind: description.RSPrimary, + SessionTimeoutMinutes: int64ToPtr(60), }, } @@ -614,17 +598,16 @@ func TestSessionTimeout(t *testing.T) { defer cancel() desc := description.Server{ - Addr: address.Address("three"), - Kind: description.RSSecondary, - SessionTimeoutMinutes: 30, - SessionTimeoutMinutesPtr: int64ToPtr(30), + Addr: address.Address("three"), + Kind: description.RSSecondary, + SessionTimeoutMinutes: int64ToPtr(30), } topo.apply(ctx, desc) currDesc := topo.desc.Load().(description.Topology) - require.Nil(t, currDesc.SessionTimeoutMinutesPtr, - "session timeout minutes mismatch. got: %d. expected: nil", currDesc.SessionTimeoutMinutes) + require.Nil(t, currDesc.SessionTimeoutMinutes, + "session timeout minutes mismatch. expected: nil") }) }