Skip to content

Commit ad1166b

Browse files
authored
GODRIVER-3339 Separate Many and One for UpdateOptions and DeleteOptions. (#1819)
1 parent f7e18a6 commit ad1166b

File tree

11 files changed

+484
-183
lines changed

11 files changed

+484
-183
lines changed

docs/migration-2.0.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,10 @@ for _, set := range options.Client().ApplyURI(uri).Opts {
627627
return clientOptionAdder{option: &opts}
628628
```
629629

630+
### DeleteManyOptions / DeleteOneOptions
631+
632+
The `DeleteOptions` has been separated into `DeleteManyOptions` and `DeleteOneOptions` to configure the corresponding `DeleteMany` and `DeleteOne` operations.
633+
630634
### FindOneOptions
631635

632636
The following types are not valid for a `findOne` operation and have been removed:
@@ -636,6 +640,10 @@ The following types are not valid for a `findOne` operation and have been remove
636640
- `MaxAwaitTime`
637641
- `NoCursorTimeout`
638642

643+
### UpdateManyOptions / UpdateOneOptions
644+
645+
The `UpdateOptions` has been separated into `UpdateManyOptions` and `UpdateOneOptions` to configure the corresponding `UpdateMany` and `UpdateOne` operations.
646+
639647
### Merge\*Options
640648

641649
All functions that merge options have been removed in favor of a generic solution. See [GODRIVER-2696](https://jira.mongodb.org/browse/GODRIVER-2696) for more information.

internal/integration/collection_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ func TestCollection(t *testing.T) {
296296
})
297297
mt.RunOpts("not found with options", mtest.NewOptions().MinServerVersion("3.4"), func(mt *mtest.T) {
298298
initCollection(mt, mt.Coll)
299-
opts := options.Delete().SetCollation(&options.Collation{Locale: "en_US"})
299+
opts := options.DeleteOne().SetCollation(&options.Collation{Locale: "en_US"})
300300
res, err := mt.Coll.DeleteOne(context.Background(), bson.D{{"x", 0}}, opts)
301301
assert.Nil(mt, err, "DeleteOne error: %v", err)
302302
assert.Equal(mt, int64(0), res.DeletedCount, "expected DeletedCount 0, got %v", res.DeletedCount)
@@ -339,13 +339,13 @@ func TestCollection(t *testing.T) {
339339
})
340340
assert.Nil(mt, err, "CreateOne error: %v", err)
341341

342-
opts := options.Delete().SetHint(bson.M{"x": 1})
342+
opts := options.DeleteOne().SetHint(bson.M{"x": 1})
343343
res, err := mt.Coll.DeleteOne(context.Background(), bson.D{{"x", 1}}, opts)
344344
assert.Nil(mt, err, "DeleteOne error: %v", err)
345345
assert.Equal(mt, int64(1), res.DeletedCount, "expected DeletedCount 1, got %v", res.DeletedCount)
346346
})
347347
mt.RunOpts("multikey map index", mtest.NewOptions().MinServerVersion("4.4"), func(mt *mtest.T) {
348-
opts := options.Delete().SetHint(bson.M{"x": 1, "y": 1})
348+
opts := options.DeleteOne().SetHint(bson.M{"x": 1, "y": 1})
349349
_, err := mt.Coll.DeleteOne(context.Background(), bson.D{{"x", 0}}, opts)
350350
assert.Equal(mt, mongo.ErrMapForOrderedArgument{"hint"}, err, "expected error %v, got %v", mongo.ErrMapForOrderedArgument{"hint"}, err)
351351
})
@@ -365,7 +365,7 @@ func TestCollection(t *testing.T) {
365365
})
366366
mt.RunOpts("not found with options", mtest.NewOptions().MinServerVersion("3.4"), func(mt *mtest.T) {
367367
initCollection(mt, mt.Coll)
368-
opts := options.Delete().SetCollation(&options.Collation{Locale: "en_US"})
368+
opts := options.DeleteMany().SetCollation(&options.Collation{Locale: "en_US"})
369369
res, err := mt.Coll.DeleteMany(context.Background(), bson.D{{"x", bson.D{{"$lt", 1}}}}, opts)
370370
assert.Nil(mt, err, "DeleteMany error: %v", err)
371371
assert.Equal(mt, int64(0), res.DeletedCount, "expected DeletedCount 0, got %v", res.DeletedCount)
@@ -408,13 +408,13 @@ func TestCollection(t *testing.T) {
408408
})
409409
assert.Nil(mt, err, "index CreateOne error: %v", err)
410410

411-
opts := options.Delete().SetHint(bson.M{"x": 1})
411+
opts := options.DeleteOne().SetHint(bson.M{"x": 1})
412412
res, err := mt.Coll.DeleteOne(context.Background(), bson.D{{"x", 1}}, opts)
413413
assert.Nil(mt, err, "DeleteOne error: %v", err)
414414
assert.Equal(mt, int64(1), res.DeletedCount, "expected DeletedCount 1, got %v", res.DeletedCount)
415415
})
416416
mt.RunOpts("multikey map index", mtest.NewOptions().MinServerVersion("4.4"), func(mt *mtest.T) {
417-
opts := options.Delete().SetHint(bson.M{"x": 1, "y": 1})
417+
opts := options.DeleteMany().SetHint(bson.M{"x": 1, "y": 1})
418418
_, err := mt.Coll.DeleteMany(context.Background(), bson.D{{"x", 0}}, opts)
419419
assert.Equal(mt, mongo.ErrMapForOrderedArgument{"hint"}, err, "expected error %v, got %v", mongo.ErrMapForOrderedArgument{"hint"}, err)
420420
})
@@ -451,7 +451,7 @@ func TestCollection(t *testing.T) {
451451
filter := bson.D{{"x", 0}}
452452
update := bson.D{{"$inc", bson.D{{"x", 1}}}}
453453

454-
res, err := mt.Coll.UpdateOne(context.Background(), filter, update, options.Update().SetUpsert(true))
454+
res, err := mt.Coll.UpdateOne(context.Background(), filter, update, options.UpdateOne().SetUpsert(true))
455455
assert.Nil(mt, err, "UpdateOne error: %v", err)
456456
assert.Equal(mt, int64(0), res.MatchedCount, "expected matched count 0, got %v", res.MatchedCount)
457457
assert.Equal(mt, int64(0), res.ModifiedCount, "expected matched count 0, got %v", res.ModifiedCount)
@@ -570,7 +570,7 @@ func TestCollection(t *testing.T) {
570570
update := bson.D{{"$inc", bson.D{{"x", 1}}}}
571571

572572
id := "blah"
573-
res, err := mt.Coll.UpdateByID(context.Background(), id, update, options.Update().SetUpsert(true))
573+
res, err := mt.Coll.UpdateByID(context.Background(), id, update, options.UpdateOne().SetUpsert(true))
574574
assert.Nil(mt, err, "UpdateByID error: %v", err)
575575
assert.Equal(mt, int64(0), res.MatchedCount, "expected matched count 0, got %v", res.MatchedCount)
576576
assert.Equal(mt, int64(0), res.ModifiedCount, "expected modified count 0, got %v", res.ModifiedCount)
@@ -633,7 +633,7 @@ func TestCollection(t *testing.T) {
633633
filter := bson.D{{"x", bson.D{{"$lt", 1}}}}
634634
update := bson.D{{"$inc", bson.D{{"x", 1}}}}
635635

636-
res, err := mt.Coll.UpdateMany(context.Background(), filter, update, options.Update().SetUpsert(true))
636+
res, err := mt.Coll.UpdateMany(context.Background(), filter, update, options.UpdateMany().SetUpsert(true))
637637
assert.Nil(mt, err, "UpdateMany error: %v", err)
638638
assert.Equal(mt, int64(0), res.MatchedCount, "expected matched count 0, got %v", res.MatchedCount)
639639
assert.Equal(mt, int64(0), res.ModifiedCount, "expected modified count 0, got %v", res.ModifiedCount)

internal/integration/crud_helpers_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ func executeDeleteOne(mt *mtest.T, sess *mongo.Session, args bson.Raw) (*mongo.D
801801
mt.Helper()
802802

803803
filter := emptyDoc
804-
opts := options.Delete()
804+
opts := options.DeleteOne()
805805

806806
elems, _ := args.Elements()
807807
for _, elem := range elems {
@@ -837,7 +837,7 @@ func executeDeleteMany(mt *mtest.T, sess *mongo.Session, args bson.Raw) (*mongo.
837837
mt.Helper()
838838

839839
filter := emptyDoc
840-
opts := options.Delete()
840+
opts := options.DeleteMany()
841841

842842
elems, _ := args.Elements()
843843
for _, elem := range elems {
@@ -874,7 +874,7 @@ func executeUpdateOne(mt *mtest.T, sess *mongo.Session, args bson.Raw) (*mongo.U
874874

875875
filter := emptyDoc
876876
var update interface{} = emptyDoc
877-
opts := options.Update()
877+
opts := options.UpdateOne()
878878

879879
elems, _ := args.Elements()
880880
for _, elem := range elems {
@@ -902,7 +902,7 @@ func executeUpdateOne(mt *mtest.T, sess *mongo.Session, args bson.Raw) (*mongo.U
902902
}
903903
}
904904

905-
updateArgs, err := mongoutil.NewOptions[options.UpdateOptions](opts)
905+
updateArgs, err := mongoutil.NewOptions[options.UpdateOneOptions](opts)
906906
require.NoError(mt, err, "failed to construct options from builder")
907907

908908
if updateArgs.Upsert == nil {
@@ -926,7 +926,7 @@ func executeUpdateMany(mt *mtest.T, sess *mongo.Session, args bson.Raw) (*mongo.
926926

927927
filter := emptyDoc
928928
var update interface{} = emptyDoc
929-
opts := options.Update()
929+
opts := options.UpdateMany()
930930

931931
elems, _ := args.Elements()
932932
for _, elem := range elems {
@@ -954,7 +954,7 @@ func executeUpdateMany(mt *mtest.T, sess *mongo.Session, args bson.Raw) (*mongo.
954954
}
955955
}
956956

957-
updateArgs, err := mongoutil.NewOptions[options.UpdateOptions](opts)
957+
updateArgs, err := mongoutil.NewOptions[options.UpdateManyOptions](opts)
958958
require.NoError(mt, err, "failed to construct options from builder")
959959

960960
if updateArgs.Upsert == nil {

internal/integration/crud_prose_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ func TestHintErrors(t *testing.T) {
297297
mt.Run("UpdateMany", func(mt *mtest.T) {
298298

299299
_, got := mt.Coll.UpdateMany(context.Background(), bson.D{{"a", 1}}, bson.D{{"$inc", bson.D{{"a", 1}}}},
300-
options.Update().SetHint("_id_"))
300+
options.UpdateMany().SetHint("_id_"))
301301
assert.NotNil(mt, got, "expected non-nil error, got nil")
302302
assert.Equal(mt, got, expected, "expected: %v got: %v", expected, got)
303303
})

internal/integration/unified/collection_operation_execution.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ func executeDeleteOne(ctx context.Context, operation *operation) (*operationResu
403403
}
404404

405405
var filter bson.Raw
406-
opts := options.Delete()
406+
opts := options.DeleteOne()
407407

408408
elems, err := operation.Arguments.Elements()
409409
if err != nil {
@@ -457,7 +457,7 @@ func executeDeleteMany(ctx context.Context, operation *operation) (*operationRes
457457
}
458458

459459
var filter bson.Raw
460-
opts := options.Delete()
460+
opts := options.DeleteMany()
461461

462462
elems, err := operation.Arguments.Elements()
463463
if err != nil {
@@ -1316,12 +1316,12 @@ func executeUpdateOne(ctx context.Context, operation *operation) (*operationResu
13161316
return nil, err
13171317
}
13181318

1319-
updateArgs, err := createUpdateArguments(operation.Arguments)
1319+
updateArgs, updateOpts, err := createUpdateOneArguments(operation.Arguments)
13201320
if err != nil {
13211321
return nil, err
13221322
}
13231323

1324-
res, err := coll.UpdateOne(ctx, updateArgs.filter, updateArgs.update, updateArgs.opts)
1324+
res, err := coll.UpdateOne(ctx, updateArgs.filter, updateArgs.update, updateOpts)
13251325
raw, buildErr := buildUpdateResultDocument(res)
13261326
if buildErr != nil {
13271327
return nil, buildErr
@@ -1335,12 +1335,12 @@ func executeUpdateMany(ctx context.Context, operation *operation) (*operationRes
13351335
return nil, err
13361336
}
13371337

1338-
updateArgs, err := createUpdateArguments(operation.Arguments)
1338+
updateArgs, updateOpts, err := createUpdateManyArguments(operation.Arguments)
13391339
if err != nil {
13401340
return nil, err
13411341
}
13421342

1343-
res, err := coll.UpdateMany(ctx, updateArgs.filter, updateArgs.update, updateArgs.opts)
1343+
res, err := coll.UpdateMany(ctx, updateArgs.filter, updateArgs.update, updateOpts)
13441344
raw, buildErr := buildUpdateResultDocument(res)
13451345
if buildErr != nil {
13461346
return nil, buildErr

internal/integration/unified/crud_helpers.go

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,67 @@ func newMissingArgumentError(arg string) error {
2323
type updateArguments struct {
2424
filter bson.Raw
2525
update interface{}
26-
opts *options.UpdateOptionsBuilder
2726
}
2827

29-
func createUpdateArguments(args bson.Raw) (*updateArguments, error) {
30-
ua := &updateArguments{
31-
opts: options.Update(),
28+
func createUpdateManyArguments(args bson.Raw) (*updateArguments, *options.UpdateManyOptionsBuilder, error) {
29+
ua := &updateArguments{}
30+
opts := options.UpdateMany()
31+
32+
elems, _ := args.Elements()
33+
for _, elem := range elems {
34+
key := elem.Key()
35+
val := elem.Value()
36+
37+
switch key {
38+
case "arrayFilters":
39+
opts.SetArrayFilters(
40+
bsonutil.RawToInterfaces(bsonutil.RawArrayToDocuments(val.Array())...),
41+
)
42+
case "bypassDocumentValidation":
43+
opts.SetBypassDocumentValidation(val.Boolean())
44+
case "collation":
45+
collation, err := createCollation(val.Document())
46+
if err != nil {
47+
return nil, nil, fmt.Errorf("error creating collation: %w", err)
48+
}
49+
opts.SetCollation(collation)
50+
case "comment":
51+
opts.SetComment(val)
52+
case "filter":
53+
ua.filter = val.Document()
54+
case "hint":
55+
hint, err := createHint(val)
56+
if err != nil {
57+
return nil, nil, fmt.Errorf("error creating hint: %w", err)
58+
}
59+
opts.SetHint(hint)
60+
case "let":
61+
opts.SetLet(val.Document())
62+
case "update":
63+
var err error
64+
ua.update, err = createUpdateValue(val)
65+
if err != nil {
66+
return nil, nil, fmt.Errorf("error processing update value: %w", err)
67+
}
68+
case "upsert":
69+
opts.SetUpsert(val.Boolean())
70+
default:
71+
return nil, nil, fmt.Errorf("unrecognized update option %q", key)
72+
}
3273
}
33-
var err error
74+
if ua.filter == nil {
75+
return nil, nil, newMissingArgumentError("filter")
76+
}
77+
if ua.update == nil {
78+
return nil, nil, newMissingArgumentError("update")
79+
}
80+
81+
return ua, opts, nil
82+
}
83+
84+
func createUpdateOneArguments(args bson.Raw) (*updateArguments, *options.UpdateOneOptionsBuilder, error) {
85+
ua := &updateArguments{}
86+
opts := options.UpdateOne()
3487

3588
elems, _ := args.Elements()
3689
for _, elem := range elems {
@@ -39,48 +92,49 @@ func createUpdateArguments(args bson.Raw) (*updateArguments, error) {
3992

4093
switch key {
4194
case "arrayFilters":
42-
ua.opts.SetArrayFilters(
95+
opts.SetArrayFilters(
4396
bsonutil.RawToInterfaces(bsonutil.RawArrayToDocuments(val.Array())...),
4497
)
4598
case "bypassDocumentValidation":
46-
ua.opts.SetBypassDocumentValidation(val.Boolean())
99+
opts.SetBypassDocumentValidation(val.Boolean())
47100
case "collation":
48101
collation, err := createCollation(val.Document())
49102
if err != nil {
50-
return nil, fmt.Errorf("error creating collation: %w", err)
103+
return nil, nil, fmt.Errorf("error creating collation: %w", err)
51104
}
52-
ua.opts.SetCollation(collation)
105+
opts.SetCollation(collation)
53106
case "comment":
54-
ua.opts.SetComment(val)
107+
opts.SetComment(val)
55108
case "filter":
56109
ua.filter = val.Document()
57110
case "hint":
58111
hint, err := createHint(val)
59112
if err != nil {
60-
return nil, fmt.Errorf("error creating hint: %w", err)
113+
return nil, nil, fmt.Errorf("error creating hint: %w", err)
61114
}
62-
ua.opts.SetHint(hint)
115+
opts.SetHint(hint)
63116
case "let":
64-
ua.opts.SetLet(val.Document())
117+
opts.SetLet(val.Document())
65118
case "update":
119+
var err error
66120
ua.update, err = createUpdateValue(val)
67121
if err != nil {
68-
return nil, fmt.Errorf("error processing update value: %w", err)
122+
return nil, nil, fmt.Errorf("error processing update value: %w", err)
69123
}
70124
case "upsert":
71-
ua.opts.SetUpsert(val.Boolean())
125+
opts.SetUpsert(val.Boolean())
72126
default:
73-
return nil, fmt.Errorf("unrecognized update option %q", key)
127+
return nil, nil, fmt.Errorf("unrecognized update option %q", key)
74128
}
75129
}
76130
if ua.filter == nil {
77-
return nil, newMissingArgumentError("filter")
131+
return nil, nil, newMissingArgumentError("filter")
78132
}
79133
if ua.update == nil {
80-
return nil, newMissingArgumentError("update")
134+
return nil, nil, newMissingArgumentError("update")
81135
}
82136

83-
return ua, nil
137+
return ua, opts, nil
84138
}
85139

86140
type listCollectionsArguments struct {

0 commit comments

Comments
 (0)