diff --git a/mongo/change_stream.go b/mongo/change_stream.go index 773cbb0e5d..2582eb4ade 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-one-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..68070cc7ef 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,60 @@ 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: "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/collection.go b/mongo/collection.go index 6abbea9792..c925f69f13 100644 --- a/mongo/collection.go +++ b/mongo/collection.go @@ -222,7 +222,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, @@ -796,6 +813,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-one-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 { @@ -840,7 +900,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() diff --git a/mongo/integration/mtest/setup.go b/mongo/integration/mtest/setup.go index be2dae93b8..31a0672104 100644 --- a/mongo/integration/mtest/setup.go +++ b/mongo/integration/mtest/setup.go @@ -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/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/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") - }) - } -}