From 15da8a17f1b72853edad5762f49001915fdded95 Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Tue, 8 Jul 2025 10:12:49 -0400 Subject: [PATCH 1/4] add client bulkWrite --- .../unified/client_operation_execution.go | 2 ++ mongo/client.go | 1 + mongo/client_bulk_write.go | 5 +++++ mongo/options/clientbulkwriteoptions.go | 13 +++++++++++++ 4 files changed, 21 insertions(+) diff --git a/internal/integration/unified/client_operation_execution.go b/internal/integration/unified/client_operation_execution.go index 75948ff8a0..9e7ab88e5f 100644 --- a/internal/integration/unified/client_operation_execution.go +++ b/internal/integration/unified/client_operation_execution.go @@ -235,6 +235,8 @@ func executeClientBulkWrite(ctx context.Context, operation *operation) (*operati return nil, err } opts.SetWriteConcern(c) + case "rawData": + opts.SetRawData(val.Boolean()) default: return nil, fmt.Errorf("unrecognized bulkWrite option %q", key) } diff --git a/mongo/client.go b/mongo/client.go index 885246a211..e6ae721e84 100644 --- a/mongo/client.go +++ b/mongo/client.go @@ -956,6 +956,7 @@ func (c *Client) BulkWrite(ctx context.Context, writes []ClientBulkWrite, client: c, selector: selector, writeConcern: wc, + rawData: bwo.RawData, } if bwo.VerboseResults == nil || !(*bwo.VerboseResults) { op.errorsOnly = true diff --git a/mongo/client_bulk_write.go b/mongo/client_bulk_write.go index ca6ecf5240..7a0d557881 100644 --- a/mongo/client_bulk_write.go +++ b/mongo/client_bulk_write.go @@ -44,6 +44,7 @@ type clientBulkWrite struct { client *Client selector description.ServerSelector writeConcern *writeconcern.WriteConcern + rawData *bool result ClientBulkWriteResult } @@ -143,6 +144,10 @@ func (bw *clientBulkWrite) newCommand() func([]byte, description.SelectedServer) } dst = bsoncore.AppendDocumentElement(dst, "let", let) } + // Set rawData for 8.2+ servers. + if bw.rawData != nil && desc.WireVersion != nil && driverutil.VersionRangeIncludes(*desc.WireVersion, 27) { + dst = bsoncore.AppendBooleanElement(dst, "rawData", *bw.rawData) + } return dst, nil } } diff --git a/mongo/options/clientbulkwriteoptions.go b/mongo/options/clientbulkwriteoptions.go index a55ac27f05..d79b41d482 100644 --- a/mongo/options/clientbulkwriteoptions.go +++ b/mongo/options/clientbulkwriteoptions.go @@ -19,6 +19,7 @@ type ClientBulkWriteOptions struct { Ordered *bool Let interface{} WriteConcern *writeconcern.WriteConcern + RawData *bool VerboseResults *bool } @@ -108,6 +109,18 @@ func (b *ClientBulkWriteOptionsBuilder) SetWriteConcern(wc *writeconcern.WriteCo return b } +// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries +// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. +func (b *ClientBulkWriteOptionsBuilder) SetRawData(rawData bool) *ClientBulkWriteOptionsBuilder { + b.Opts = append(b.Opts, func(opts *ClientBulkWriteOptions) error { + opts.RawData = &rawData + + return nil + }) + + return b +} + // SetVerboseResults sets the value for the VerboseResults field. Specifies whether detailed // results for each successful operation should be included in the returned BulkWriteResult. // The defaults value is false. From 3be2dbb5f9fb6982fdb639b7afaf1017952eab76 Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Tue, 8 Jul 2025 10:21:04 -0400 Subject: [PATCH 2/4] add listCollections --- internal/integration/unified/crud_helpers.go | 2 ++ mongo/database.go | 3 +++ mongo/options/listcollectionsoptions.go | 13 +++++++++++++ x/mongo/driver/operation/list_collections.go | 18 +++++++++++++++++- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/internal/integration/unified/crud_helpers.go b/internal/integration/unified/crud_helpers.go index 98719224c4..a94b696996 100644 --- a/internal/integration/unified/crud_helpers.go +++ b/internal/integration/unified/crud_helpers.go @@ -173,6 +173,8 @@ func createListCollectionsArguments(args bson.Raw) (*listCollectionsArguments, e lca.filter = val.Document() case "nameOnly": lca.opts.SetNameOnly(val.Boolean()) + case "rawData": + lca.opts.SetRawData(val.Boolean()) default: return nil, fmt.Errorf("unrecognized listCollections option %q", key) } diff --git a/mongo/database.go b/mongo/database.go index a3269ddf16..f90d9027df 100644 --- a/mongo/database.go +++ b/mongo/database.go @@ -487,6 +487,9 @@ func (db *Database) ListCollections( if args.AuthorizedCollections != nil { op = op.AuthorizedCollections(*args.AuthorizedCollections) } + if args.RawData != nil { + op = op.RawData(*args.RawData) + } retry := driver.RetryNone if db.client.retryReads { diff --git a/mongo/options/listcollectionsoptions.go b/mongo/options/listcollectionsoptions.go index 2106b2f906..d307a31bff 100644 --- a/mongo/options/listcollectionsoptions.go +++ b/mongo/options/listcollectionsoptions.go @@ -14,6 +14,7 @@ type ListCollectionsOptions struct { NameOnly *bool BatchSize *int32 AuthorizedCollections *bool + RawData *bool } // ListCollectionsOptionsBuilder contains options to configure list collection @@ -70,3 +71,15 @@ func (lc *ListCollectionsOptionsBuilder) SetAuthorizedCollections(b bool) *ListC return lc } + +// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries +// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. +func (lc *ListCollectionsOptionsBuilder) SetRawData(rawData bool) *ListCollectionsOptionsBuilder { + lc.Opts = append(lc.Opts, func(opts *ListCollectionsOptions) error { + opts.RawData = &rawData + + return nil + }) + + return lc +} diff --git a/x/mongo/driver/operation/list_collections.go b/x/mongo/driver/operation/list_collections.go index 3f9b55a6c3..672404cb0b 100644 --- a/x/mongo/driver/operation/list_collections.go +++ b/x/mongo/driver/operation/list_collections.go @@ -39,6 +39,7 @@ type ListCollections struct { batchSize *int32 serverAPI *driver.ServerAPIOptions timeout *time.Duration + rawData *bool } // NewListCollections constructs and returns a new ListCollections. @@ -92,7 +93,7 @@ func (lc *ListCollections) Execute(ctx context.Context) error { } -func (lc *ListCollections) command(dst []byte, _ description.SelectedServer) ([]byte, error) { +func (lc *ListCollections) command(dst []byte, desc description.SelectedServer) ([]byte, error) { dst = bsoncore.AppendInt32Element(dst, "listCollections", 1) if lc.filter != nil { dst = bsoncore.AppendDocumentElement(dst, "filter", lc.filter) @@ -110,6 +111,11 @@ func (lc *ListCollections) command(dst []byte, _ description.SelectedServer) ([] } dst = bsoncore.AppendDocumentElement(dst, "cursor", cursorDoc.Build()) + // Set rawData for 8.2+ servers. + if lc.rawData != nil && desc.WireVersion != nil && driverutil.VersionRangeIncludes(*desc.WireVersion, 27) { + dst = bsoncore.AppendBooleanElement(dst, "rawData", *lc.rawData) + } + return dst, nil } @@ -274,3 +280,13 @@ func (lc *ListCollections) Authenticator(authenticator driver.Authenticator) *Li lc.authenticator = authenticator return lc } + +// RawData sets the rawData to access timeseries data in the compressed format. +func (lc *ListCollections) RawData(rawData bool) *ListCollections { + if lc == nil { + lc = new(ListCollections) + } + + lc.rawData = &rawData + return lc +} From 3c8bb39b97badefe1de9c22ff20013d4117f970a Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Tue, 8 Jul 2025 11:17:00 -0400 Subject: [PATCH 3/4] add index operations --- .../unified/collection_operation_execution.go | 10 ++++- mongo/index_view.go | 19 ++++++++- mongo/options/indexoptions.go | 42 ++++++++++++++++++- x/mongo/driver/operation/create_indexes.go | 15 +++++++ x/mongo/driver/operation/drop_indexes.go | 17 +++++++- x/mongo/driver/operation/list_indexes.go | 18 +++++++- 6 files changed, 114 insertions(+), 7 deletions(-) diff --git a/internal/integration/unified/collection_operation_execution.go b/internal/integration/unified/collection_operation_execution.go index be9afe0cd7..67582049f4 100644 --- a/internal/integration/unified/collection_operation_execution.go +++ b/internal/integration/unified/collection_operation_execution.go @@ -241,6 +241,7 @@ func executeCreateIndex(ctx context.Context, operation *operation) (*operationRe var keys bson.Raw indexOpts := options.Index() + opts := options.CreateIndexes() elems, err := operation.Arguments.Elements() if err != nil { @@ -295,6 +296,8 @@ func executeCreateIndex(ctx context.Context, operation *operation) (*operationRe indexOpts.SetWeights(val.Document()) case "wildcardProjection": indexOpts.SetWildcardProjection(val.Document()) + case "rawData": + opts.SetRawData(val.Boolean()) default: return nil, fmt.Errorf("unrecognized createIndex option %q", key) } @@ -307,7 +310,8 @@ func executeCreateIndex(ctx context.Context, operation *operation) (*operationRe Keys: keys, Options: indexOpts, } - name, err := coll.Indexes().CreateOne(ctx, model) + + name, err := coll.Indexes().CreateOne(ctx, model, opts) return newValueResult(bson.TypeString, bsoncore.AppendString(nil, name), err), nil } @@ -624,6 +628,8 @@ func executeDropIndex(ctx context.Context, operation *operation) (*operationResu // ensured an analogue exists, extend "skippedTestDescriptions" to avoid // this error. return nil, fmt.Errorf("the maxTimeMS collection option is not supported") + case "rawData": + dropIndexOpts.SetRawData(val.Boolean()) default: return nil, fmt.Errorf("unrecognized dropIndex option %q", key) } @@ -1217,6 +1223,8 @@ func executeListIndexes(ctx context.Context, operation *operation) (*operationRe switch key { case "batchSize": opts.SetBatchSize(val.Int32()) + case "rawData": + opts.SetRawData(val.Boolean()) default: return nil, fmt.Errorf("unrecognized listIndexes option: %q", key) } diff --git a/mongo/index_view.go b/mongo/index_view.go index a0734ebf16..e0926f5e4d 100644 --- a/mongo/index_view.go +++ b/mongo/index_view.go @@ -101,6 +101,9 @@ func (iv IndexView) List(ctx context.Context, opts ...options.Lister[options.Lis op = op.BatchSize(*args.BatchSize) cursorOpts.BatchSize = *args.BatchSize } + if args.RawData != nil { + op = op.RawData(*args.RawData) + } retry := driver.RetryNone if iv.coll.client.retryReads { @@ -279,6 +282,9 @@ func (iv IndexView) CreateMany( op.CommitQuorum(commitQuorum) } + if args.RawData != nil { + op = op.RawData(*args.RawData) + } _, err = processWriteError(op.Execute(ctx)) if err != nil { @@ -376,7 +382,12 @@ func (iv IndexView) createOptionsDoc(opts options.Lister[options.IndexOptions]) return optsDoc, nil } -func (iv IndexView) drop(ctx context.Context, index any, _ ...options.Lister[options.DropIndexesOptions]) error { +func (iv IndexView) drop(ctx context.Context, index any, opts ...options.Lister[options.DropIndexesOptions]) error { + args, err := mongoutil.NewOptions[options.DropIndexesOptions](opts...) + if err != nil { + return fmt.Errorf("failed to construct options from builder: %w", err) + } + if ctx == nil { ctx = context.Background() } @@ -387,7 +398,7 @@ func (iv IndexView) drop(ctx context.Context, index any, _ ...options.Lister[opt defer sess.EndSession() } - err := iv.coll.client.validSession(sess) + err = iv.coll.client.validSession(sess) if err != nil { return err } @@ -408,6 +419,10 @@ func (iv IndexView) drop(ctx context.Context, index any, _ ...options.Lister[opt Deployment(iv.coll.client.deployment).ServerAPI(iv.coll.client.serverAPI). Timeout(iv.coll.client.timeout).Crypt(iv.coll.client.cryptFLE).Authenticator(iv.coll.client.authenticator) + if args.RawData != nil { + op = op.RawData(*args.RawData) + } + err = op.Execute(ctx) if err != nil { return wrapErrors(err) diff --git a/mongo/options/indexoptions.go b/mongo/options/indexoptions.go index b7b61c2edf..9030d2b530 100644 --- a/mongo/options/indexoptions.go +++ b/mongo/options/indexoptions.go @@ -12,6 +12,7 @@ package options // See corresponding setter methods for documentation. type CreateIndexesOptions struct { CommitQuorum interface{} + RawData *bool } // CreateIndexesOptionsBuilder contains options to create indexes. Each option @@ -119,9 +120,23 @@ func (c *CreateIndexesOptionsBuilder) SetCommitQuorumVotingMembers() *CreateInde return c } +// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries +// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. +func (c *CreateIndexesOptionsBuilder) SetRawData(rawData bool) *CreateIndexesOptionsBuilder { + c.Opts = append(c.Opts, func(opts *CreateIndexesOptions) error { + opts.RawData = &rawData + + return nil + }) + + return c +} + // DropIndexesOptions represents arguments that can be used to configure // IndexView.DropOne and IndexView.DropAll operations. -type DropIndexesOptions struct{} +type DropIndexesOptions struct { + RawData *bool +} // DropIndexesOptionsBuilder contains options to configure dropping indexes. // Each option can be set through setter functions. See documentation for each @@ -140,12 +155,25 @@ func (d *DropIndexesOptionsBuilder) List() []func(*DropIndexesOptions) error { return d.Opts } +// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries +// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. +func (d *DropIndexesOptionsBuilder) SetRawData(rawData bool) *DropIndexesOptionsBuilder { + d.Opts = append(d.Opts, func(opts *DropIndexesOptions) error { + opts.RawData = &rawData + + return nil + }) + + return d +} + // ListIndexesOptions represents arguments that can be used to configure an // IndexView.List operation. // // See corresponding setter methods for documentation. type ListIndexesOptions struct { BatchSize *int32 + RawData *bool } // ListIndexesOptionsBuilder contains options to configure count operations. Each @@ -177,6 +205,18 @@ func (l *ListIndexesOptionsBuilder) SetBatchSize(i int32) *ListIndexesOptionsBui return l } +// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries +// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. +func (l *ListIndexesOptionsBuilder) SetRawData(rawData bool) *ListIndexesOptionsBuilder { + l.Opts = append(l.Opts, func(opts *ListIndexesOptions) error { + opts.RawData = &rawData + + return nil + }) + + return l +} + // IndexOptions represents arguments that can be used to configure a new index // created through the IndexView.CreateOne or IndexView.CreateMany operations. // diff --git a/x/mongo/driver/operation/create_indexes.go b/x/mongo/driver/operation/create_indexes.go index 0380a55a26..17e88ba8c8 100644 --- a/x/mongo/driver/operation/create_indexes.go +++ b/x/mongo/driver/operation/create_indexes.go @@ -38,6 +38,7 @@ type CreateIndexes struct { result CreateIndexesResult serverAPI *driver.ServerAPIOptions timeout *time.Duration + rawData *bool } // CreateIndexesResult represents a createIndexes result returned by the server. @@ -133,6 +134,10 @@ func (ci *CreateIndexes) command(dst []byte, desc description.SelectedServer) ([ if ci.indexes != nil { dst = bsoncore.AppendArrayElement(dst, "indexes", ci.indexes) } + // Set rawData for 8.2+ servers. + if ci.rawData != nil && desc.WireVersion != nil && driverutil.VersionRangeIncludes(*desc.WireVersion, 27) { + dst = bsoncore.AppendBooleanElement(dst, "rawData", *ci.rawData) + } return dst, nil } @@ -277,3 +282,13 @@ func (ci *CreateIndexes) Authenticator(authenticator driver.Authenticator) *Crea ci.authenticator = authenticator return ci } + +// RawData sets the rawData to access timeseries data in the compressed format. +func (ci *CreateIndexes) RawData(rawData bool) *CreateIndexes { + if ci == nil { + ci = new(CreateIndexes) + } + + ci.rawData = &rawData + return ci +} diff --git a/x/mongo/driver/operation/drop_indexes.go b/x/mongo/driver/operation/drop_indexes.go index e57cff72ee..14ecbdc1a9 100644 --- a/x/mongo/driver/operation/drop_indexes.go +++ b/x/mongo/driver/operation/drop_indexes.go @@ -37,6 +37,7 @@ type DropIndexes struct { result DropIndexesResult serverAPI *driver.ServerAPIOptions timeout *time.Duration + rawData *bool } // DropIndexesResult represents a dropIndexes result returned by the server. @@ -104,7 +105,7 @@ func (di *DropIndexes) Execute(ctx context.Context) error { } -func (di *DropIndexes) command(dst []byte, _ description.SelectedServer) ([]byte, error) { +func (di *DropIndexes) command(dst []byte, desc description.SelectedServer) ([]byte, error) { dst = bsoncore.AppendStringElement(dst, "dropIndexes", di.collection) switch t := di.index.(type) { @@ -115,6 +116,10 @@ func (di *DropIndexes) command(dst []byte, _ description.SelectedServer) ([]byte dst = bsoncore.AppendDocumentElement(dst, "index", t) } } + // Set rawData for 8.2+ servers. + if di.rawData != nil && desc.WireVersion != nil && driverutil.VersionRangeIncludes(*desc.WireVersion, 27) { + dst = bsoncore.AppendBooleanElement(dst, "rawData", *di.rawData) + } return dst, nil } @@ -248,3 +253,13 @@ func (di *DropIndexes) Authenticator(authenticator driver.Authenticator) *DropIn di.authenticator = authenticator return di } + +// RawData sets the rawData to access timeseries data in the compressed format. +func (di *DropIndexes) RawData(rawData bool) *DropIndexes { + if di == nil { + di = new(DropIndexes) + } + + di.rawData = &rawData + return di +} diff --git a/x/mongo/driver/operation/list_indexes.go b/x/mongo/driver/operation/list_indexes.go index d7642a19e1..21b138a40c 100644 --- a/x/mongo/driver/operation/list_indexes.go +++ b/x/mongo/driver/operation/list_indexes.go @@ -34,6 +34,7 @@ type ListIndexes struct { crypt driver.Crypt serverAPI *driver.ServerAPIOptions timeout *time.Duration + rawData *bool result driver.CursorResponse } @@ -91,16 +92,19 @@ func (li *ListIndexes) Execute(ctx context.Context) error { } -func (li *ListIndexes) command(dst []byte, _ description.SelectedServer) ([]byte, error) { +func (li *ListIndexes) command(dst []byte, desc description.SelectedServer) ([]byte, error) { dst = bsoncore.AppendStringElement(dst, "listIndexes", li.collection) cursorIdx, cursorDoc := bsoncore.AppendDocumentStart(nil) if li.batchSize != nil { - cursorDoc = bsoncore.AppendInt32Element(cursorDoc, "batchSize", *li.batchSize) } cursorDoc, _ = bsoncore.AppendDocumentEnd(cursorDoc, cursorIdx) dst = bsoncore.AppendDocumentElement(dst, "cursor", cursorDoc) + // Set rawData for 8.2+ servers. + if li.rawData != nil && desc.WireVersion != nil && driverutil.VersionRangeIncludes(*desc.WireVersion, 27) { + dst = bsoncore.AppendBooleanElement(dst, "rawData", *li.rawData) + } return dst, nil } @@ -235,3 +239,13 @@ func (li *ListIndexes) Authenticator(authenticator driver.Authenticator) *ListIn li.authenticator = authenticator return li } + +// RawData sets the rawData to access timeseries data in the compressed format. +func (li *ListIndexes) RawData(rawData bool) *ListIndexes { + if li == nil { + li = new(ListIndexes) + } + + li.rawData = &rawData + return li +} From 0ca203e90a2eaa1b6345eca9aa49708bf5435f92 Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Mon, 4 Aug 2025 18:59:19 -0400 Subject: [PATCH 4/4] make rawDate internal --- .../unified/client_operation_execution.go | 6 +- .../unified/collection_operation_execution.go | 15 ++- internal/integration/unified/crud_helpers.go | 5 +- mongo/client.go | 7 +- mongo/database.go | 7 +- mongo/index_view.go | 19 +++- mongo/options/clientbulkwriteoptions.go | 18 +-- mongo/options/indexoptions.go | 52 +++------ mongo/options/listcollectionsoptions.go | 19 +--- x/mongo/driver/xoptions/options.go | 105 ++++++++++++++++++ 10 files changed, 174 insertions(+), 79 deletions(-) diff --git a/internal/integration/unified/client_operation_execution.go b/internal/integration/unified/client_operation_execution.go index 9e7ab88e5f..432852dd71 100644 --- a/internal/integration/unified/client_operation_execution.go +++ b/internal/integration/unified/client_operation_execution.go @@ -19,6 +19,7 @@ import ( "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" "go.mongodb.org/mongo-driver/v2/x/bsonx/bsoncore" + "go.mongodb.org/mongo-driver/v2/x/mongo/driver/xoptions" ) // This file contains helpers to execute client operations. @@ -236,7 +237,10 @@ func executeClientBulkWrite(ctx context.Context, operation *operation) (*operati } opts.SetWriteConcern(c) case "rawData": - opts.SetRawData(val.Boolean()) + err = xoptions.SetInternalClientBulkWriteOptions(opts, key, val.Boolean()) + if err != nil { + return nil, err + } default: return nil, fmt.Errorf("unrecognized bulkWrite option %q", key) } diff --git a/internal/integration/unified/collection_operation_execution.go b/internal/integration/unified/collection_operation_execution.go index 67582049f4..26537bce7e 100644 --- a/internal/integration/unified/collection_operation_execution.go +++ b/internal/integration/unified/collection_operation_execution.go @@ -297,7 +297,10 @@ func executeCreateIndex(ctx context.Context, operation *operation) (*operationRe case "wildcardProjection": indexOpts.SetWildcardProjection(val.Document()) case "rawData": - opts.SetRawData(val.Boolean()) + err = xoptions.SetInternalCreateIndexesOptions(opts, key, val.Boolean()) + if err != nil { + return nil, err + } default: return nil, fmt.Errorf("unrecognized createIndex option %q", key) } @@ -629,7 +632,10 @@ func executeDropIndex(ctx context.Context, operation *operation) (*operationResu // this error. return nil, fmt.Errorf("the maxTimeMS collection option is not supported") case "rawData": - dropIndexOpts.SetRawData(val.Boolean()) + err = xoptions.SetInternalDropIndexesOptions(dropIndexOpts, key, val.Boolean()) + if err != nil { + return nil, err + } default: return nil, fmt.Errorf("unrecognized dropIndex option %q", key) } @@ -1224,7 +1230,10 @@ func executeListIndexes(ctx context.Context, operation *operation) (*operationRe case "batchSize": opts.SetBatchSize(val.Int32()) case "rawData": - opts.SetRawData(val.Boolean()) + err = xoptions.SetInternalListIndexesOptions(opts, key, val.Boolean()) + if err != nil { + return nil, err + } default: return nil, fmt.Errorf("unrecognized listIndexes option: %q", key) } diff --git a/internal/integration/unified/crud_helpers.go b/internal/integration/unified/crud_helpers.go index a94b696996..f24e1f9be7 100644 --- a/internal/integration/unified/crud_helpers.go +++ b/internal/integration/unified/crud_helpers.go @@ -174,7 +174,10 @@ func createListCollectionsArguments(args bson.Raw) (*listCollectionsArguments, e case "nameOnly": lca.opts.SetNameOnly(val.Boolean()) case "rawData": - lca.opts.SetRawData(val.Boolean()) + err := xoptions.SetInternalListCollectionsOptions(lca.opts, key, val.Boolean()) + if err != nil { + return nil, err + } default: return nil, fmt.Errorf("unrecognized listCollections option %q", key) } diff --git a/mongo/client.go b/mongo/client.go index e6ae721e84..9140e178af 100644 --- a/mongo/client.go +++ b/mongo/client.go @@ -18,6 +18,7 @@ import ( "go.mongodb.org/mongo-driver/v2/internal/httputil" "go.mongodb.org/mongo-driver/v2/internal/logger" "go.mongodb.org/mongo-driver/v2/internal/mongoutil" + "go.mongodb.org/mongo-driver/v2/internal/optionsutil" "go.mongodb.org/mongo-driver/v2/internal/ptrutil" "go.mongodb.org/mongo-driver/v2/internal/serverselector" "go.mongodb.org/mongo-driver/v2/internal/uuid" @@ -956,7 +957,11 @@ func (c *Client) BulkWrite(ctx context.Context, writes []ClientBulkWrite, client: c, selector: selector, writeConcern: wc, - rawData: bwo.RawData, + } + if rawDataOpt := optionsutil.Value(bwo.Internal, "rawData"); rawDataOpt != nil { + if rawData, ok := rawDataOpt.(bool); ok { + op.rawData = &rawData + } } if bwo.VerboseResults == nil || !(*bwo.VerboseResults) { op.errorsOnly = true diff --git a/mongo/database.go b/mongo/database.go index f90d9027df..8476aeb201 100644 --- a/mongo/database.go +++ b/mongo/database.go @@ -16,6 +16,7 @@ import ( "go.mongodb.org/mongo-driver/v2/internal/csfle" "go.mongodb.org/mongo-driver/v2/internal/csot" "go.mongodb.org/mongo-driver/v2/internal/mongoutil" + "go.mongodb.org/mongo-driver/v2/internal/optionsutil" "go.mongodb.org/mongo-driver/v2/internal/serverselector" "go.mongodb.org/mongo-driver/v2/mongo/options" "go.mongodb.org/mongo-driver/v2/mongo/readconcern" @@ -487,8 +488,10 @@ func (db *Database) ListCollections( if args.AuthorizedCollections != nil { op = op.AuthorizedCollections(*args.AuthorizedCollections) } - if args.RawData != nil { - op = op.RawData(*args.RawData) + if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { + if rawData, ok := rawDataOpt.(bool); ok { + op = op.RawData(rawData) + } } retry := driver.RetryNone diff --git a/mongo/index_view.go b/mongo/index_view.go index e0926f5e4d..7198c4cc43 100644 --- a/mongo/index_view.go +++ b/mongo/index_view.go @@ -14,6 +14,7 @@ import ( "strconv" "go.mongodb.org/mongo-driver/v2/internal/mongoutil" + "go.mongodb.org/mongo-driver/v2/internal/optionsutil" "go.mongodb.org/mongo-driver/v2/internal/serverselector" "go.mongodb.org/mongo-driver/v2/mongo/options" "go.mongodb.org/mongo-driver/v2/mongo/readpref" @@ -101,8 +102,10 @@ func (iv IndexView) List(ctx context.Context, opts ...options.Lister[options.Lis op = op.BatchSize(*args.BatchSize) cursorOpts.BatchSize = *args.BatchSize } - if args.RawData != nil { - op = op.RawData(*args.RawData) + if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { + if rawData, ok := rawDataOpt.(bool); ok { + op = op.RawData(rawData) + } } retry := driver.RetryNone @@ -282,8 +285,10 @@ func (iv IndexView) CreateMany( op.CommitQuorum(commitQuorum) } - if args.RawData != nil { - op = op.RawData(*args.RawData) + if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { + if rawData, ok := rawDataOpt.(bool); ok { + op = op.RawData(rawData) + } } _, err = processWriteError(op.Execute(ctx)) @@ -419,8 +424,10 @@ func (iv IndexView) drop(ctx context.Context, index any, opts ...options.Lister[ Deployment(iv.coll.client.deployment).ServerAPI(iv.coll.client.serverAPI). Timeout(iv.coll.client.timeout).Crypt(iv.coll.client.cryptFLE).Authenticator(iv.coll.client.authenticator) - if args.RawData != nil { - op = op.RawData(*args.RawData) + if rawDataOpt := optionsutil.Value(args.Internal, "rawData"); rawDataOpt != nil { + if rawData, ok := rawDataOpt.(bool); ok { + op = op.RawData(rawData) + } } err = op.Execute(ctx) diff --git a/mongo/options/clientbulkwriteoptions.go b/mongo/options/clientbulkwriteoptions.go index d79b41d482..fd6933822b 100644 --- a/mongo/options/clientbulkwriteoptions.go +++ b/mongo/options/clientbulkwriteoptions.go @@ -7,6 +7,7 @@ package options import ( + "go.mongodb.org/mongo-driver/v2/internal/optionsutil" "go.mongodb.org/mongo-driver/v2/mongo/writeconcern" ) @@ -19,8 +20,11 @@ type ClientBulkWriteOptions struct { Ordered *bool Let interface{} WriteConcern *writeconcern.WriteConcern - RawData *bool VerboseResults *bool + + // Deprecated: This option is for internal use only and should not be set. It may be changed or removed in any + // release. + Internal optionsutil.Options } // ClientBulkWriteOptionsBuilder contains options to configure client-level bulk @@ -109,18 +113,6 @@ func (b *ClientBulkWriteOptionsBuilder) SetWriteConcern(wc *writeconcern.WriteCo return b } -// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries -// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. -func (b *ClientBulkWriteOptionsBuilder) SetRawData(rawData bool) *ClientBulkWriteOptionsBuilder { - b.Opts = append(b.Opts, func(opts *ClientBulkWriteOptions) error { - opts.RawData = &rawData - - return nil - }) - - return b -} - // SetVerboseResults sets the value for the VerboseResults field. Specifies whether detailed // results for each successful operation should be included in the returned BulkWriteResult. // The defaults value is false. diff --git a/mongo/options/indexoptions.go b/mongo/options/indexoptions.go index 9030d2b530..792bd827a7 100644 --- a/mongo/options/indexoptions.go +++ b/mongo/options/indexoptions.go @@ -6,13 +6,18 @@ package options +import "go.mongodb.org/mongo-driver/v2/internal/optionsutil" + // CreateIndexesOptions represents arguments that can be used to configure // IndexView.CreateOne and IndexView.CreateMany operations. // // See corresponding setter methods for documentation. type CreateIndexesOptions struct { CommitQuorum interface{} - RawData *bool + + // Deprecated: This option is for internal use only and should not be set. It may be changed or removed in any + // release. + Internal optionsutil.Options } // CreateIndexesOptionsBuilder contains options to create indexes. Each option @@ -120,22 +125,12 @@ func (c *CreateIndexesOptionsBuilder) SetCommitQuorumVotingMembers() *CreateInde return c } -// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries -// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. -func (c *CreateIndexesOptionsBuilder) SetRawData(rawData bool) *CreateIndexesOptionsBuilder { - c.Opts = append(c.Opts, func(opts *CreateIndexesOptions) error { - opts.RawData = &rawData - - return nil - }) - - return c -} - // DropIndexesOptions represents arguments that can be used to configure // IndexView.DropOne and IndexView.DropAll operations. type DropIndexesOptions struct { - RawData *bool + // Deprecated: This option is for internal use only and should not be set. It may be changed or removed in any + // release. + Internal optionsutil.Options } // DropIndexesOptionsBuilder contains options to configure dropping indexes. @@ -155,25 +150,16 @@ func (d *DropIndexesOptionsBuilder) List() []func(*DropIndexesOptions) error { return d.Opts } -// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries -// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. -func (d *DropIndexesOptionsBuilder) SetRawData(rawData bool) *DropIndexesOptionsBuilder { - d.Opts = append(d.Opts, func(opts *DropIndexesOptions) error { - opts.RawData = &rawData - - return nil - }) - - return d -} - // ListIndexesOptions represents arguments that can be used to configure an // IndexView.List operation. // // See corresponding setter methods for documentation. type ListIndexesOptions struct { BatchSize *int32 - RawData *bool + + // Deprecated: This option is for internal use only and should not be set. It may be changed or removed in any + // release. + Internal optionsutil.Options } // ListIndexesOptionsBuilder contains options to configure count operations. Each @@ -205,18 +191,6 @@ func (l *ListIndexesOptionsBuilder) SetBatchSize(i int32) *ListIndexesOptionsBui return l } -// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries -// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. -func (l *ListIndexesOptionsBuilder) SetRawData(rawData bool) *ListIndexesOptionsBuilder { - l.Opts = append(l.Opts, func(opts *ListIndexesOptions) error { - opts.RawData = &rawData - - return nil - }) - - return l -} - // IndexOptions represents arguments that can be used to configure a new index // created through the IndexView.CreateOne or IndexView.CreateMany operations. // diff --git a/mongo/options/listcollectionsoptions.go b/mongo/options/listcollectionsoptions.go index d307a31bff..14f96cc627 100644 --- a/mongo/options/listcollectionsoptions.go +++ b/mongo/options/listcollectionsoptions.go @@ -6,6 +6,8 @@ package options +import "go.mongodb.org/mongo-driver/v2/internal/optionsutil" + // ListCollectionsOptions represents arguments that can be used to configure a // ListCollections operation. // @@ -14,7 +16,10 @@ type ListCollectionsOptions struct { NameOnly *bool BatchSize *int32 AuthorizedCollections *bool - RawData *bool + + // Deprecated: This option is for internal use only and should not be set. It may be changed or removed in any + // release. + Internal optionsutil.Options } // ListCollectionsOptionsBuilder contains options to configure list collection @@ -71,15 +76,3 @@ func (lc *ListCollectionsOptionsBuilder) SetAuthorizedCollections(b bool) *ListC return lc } - -// SetRawData sets the value for the RawData field. If true, it allows the CRUD operations to access timeseries -// collections on the bucket-level. This option is only valid for MongoDB versions >= 9.0. The default value is false. -func (lc *ListCollectionsOptionsBuilder) SetRawData(rawData bool) *ListCollectionsOptionsBuilder { - lc.Opts = append(lc.Opts, func(opts *ListCollectionsOptions) error { - opts.RawData = &rawData - - return nil - }) - - return lc -} diff --git a/x/mongo/driver/xoptions/options.go b/x/mongo/driver/xoptions/options.go index 52b308a74e..fa11dd60b8 100644 --- a/x/mongo/driver/xoptions/options.go +++ b/x/mongo/driver/xoptions/options.go @@ -86,6 +86,27 @@ func SetInternalBulkWriteOptions(a *options.BulkWriteOptionsBuilder, key string, return nil } +// SetInternalClientBulkWriteOptions sets internal options for ClientBulkWriteOptions. +func SetInternalClientBulkWriteOptions(a *options.ClientBulkWriteOptionsBuilder, key string, option any) error { + typeErrFunc := func(t string) error { + return fmt.Errorf("unexpected type for %q: %T is not %s", key, option, t) + } + switch key { + case "rawData": + b, ok := option.(bool) + if !ok { + return typeErrFunc("bool") + } + a.Opts = append(a.Opts, func(opts *options.ClientBulkWriteOptions) error { + opts.Internal = optionsutil.WithValue(opts.Internal, key, b) + return nil + }) + default: + return fmt.Errorf("unsupported option: %q", key) + } + return nil +} + // SetInternalCountOptions sets internal options for CountOptions. func SetInternalCountOptions(a *options.CountOptionsBuilder, key string, option any) error { typeErrFunc := func(t string) error { @@ -107,6 +128,27 @@ func SetInternalCountOptions(a *options.CountOptionsBuilder, key string, option return nil } +// SetInternalCreateIndexesOptions sets internal options for CreateIndexesOptions. +func SetInternalCreateIndexesOptions(a *options.CreateIndexesOptionsBuilder, key string, option any) error { + typeErrFunc := func(t string) error { + return fmt.Errorf("unexpected type for %q: %T is not %s", key, option, t) + } + switch key { + case "rawData": + b, ok := option.(bool) + if !ok { + return typeErrFunc("bool") + } + a.Opts = append(a.Opts, func(opts *options.CreateIndexesOptions) error { + opts.Internal = optionsutil.WithValue(opts.Internal, key, b) + return nil + }) + default: + return fmt.Errorf("unsupported option: %q", key) + } + return nil +} + // SetInternalDeleteOneOptions sets internal options for DeleteOneOptions. func SetInternalDeleteOneOptions(a *options.DeleteOneOptionsBuilder, key string, option any) error { typeErrFunc := func(t string) error { @@ -170,6 +212,27 @@ func SetInternalDistinctOptions(a *options.DistinctOptionsBuilder, key string, o return nil } +// SetInternalDropIndexesOptions sets internal options for DropIndexesOptions. +func SetInternalDropIndexesOptions(a *options.DropIndexesOptionsBuilder, key string, option any) error { + typeErrFunc := func(t string) error { + return fmt.Errorf("unexpected type for %q: %T is not %s", key, option, t) + } + switch key { + case "rawData": + b, ok := option.(bool) + if !ok { + return typeErrFunc("bool") + } + a.Opts = append(a.Opts, func(opts *options.DropIndexesOptions) error { + opts.Internal = optionsutil.WithValue(opts.Internal, key, b) + return nil + }) + default: + return fmt.Errorf("unsupported option: %q", key) + } + return nil +} + // SetInternalEstimatedDocumentCountOptions sets internal options for EstimatedDocumentCountOptions. func SetInternalEstimatedDocumentCountOptions(a *options.EstimatedDocumentCountOptionsBuilder, key string, option any) error { typeErrFunc := func(t string) error { @@ -338,6 +401,48 @@ func SetInternalInsertOneOptions(a *options.InsertOneOptionsBuilder, key string, return nil } +// SetInternalListCollectionsOptions sets internal options for ListCollectionsOptions. +func SetInternalListCollectionsOptions(a *options.ListCollectionsOptionsBuilder, key string, option any) error { + typeErrFunc := func(t string) error { + return fmt.Errorf("unexpected type for %q: %T is not %s", key, option, t) + } + switch key { + case "rawData": + b, ok := option.(bool) + if !ok { + return typeErrFunc("bool") + } + a.Opts = append(a.Opts, func(opts *options.ListCollectionsOptions) error { + opts.Internal = optionsutil.WithValue(opts.Internal, key, b) + return nil + }) + default: + return fmt.Errorf("unsupported option: %q", key) + } + return nil +} + +// SetInternalListIndexesOptions sets internal options for ListIndexesOptions. +func SetInternalListIndexesOptions(a *options.ListIndexesOptionsBuilder, key string, option any) error { + typeErrFunc := func(t string) error { + return fmt.Errorf("unexpected type for %q: %T is not %s", key, option, t) + } + switch key { + case "rawData": + b, ok := option.(bool) + if !ok { + return typeErrFunc("bool") + } + a.Opts = append(a.Opts, func(opts *options.ListIndexesOptions) error { + opts.Internal = optionsutil.WithValue(opts.Internal, key, b) + return nil + }) + default: + return fmt.Errorf("unsupported option: %q", key) + } + return nil +} + // SetInternalReplaceOptions sets internal options for ReplaceOptions. func SetInternalReplaceOptions(a *options.ReplaceOptionsBuilder, key string, option any) error { typeErrFunc := func(t string) error {