Skip to content

Commit

Permalink
update createUpdateArguments()
Browse files Browse the repository at this point in the history
  • Loading branch information
qingyang-hu committed Sep 20, 2024
1 parent 3b76520 commit 8306537
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1316,7 +1316,7 @@ func executeUpdateOne(ctx context.Context, operation *operation) (*operationResu
return nil, err
}

updateArgs, err := createUpdateArguments[options.UpdateOneOptions](operation.Arguments)
updateArgs, err := createUpdateOneArguments(operation.Arguments)
if err != nil {
return nil, err
}
Expand All @@ -1335,7 +1335,7 @@ func executeUpdateMany(ctx context.Context, operation *operation) (*operationRes
return nil, err
}

updateArgs, err := createUpdateArguments[options.UpdateManyOptions](operation.Arguments)
updateArgs, err := createUpdateManyArguments(operation.Arguments)
if err != nil {
return nil, err
}
Expand Down
101 changes: 72 additions & 29 deletions internal/integration/unified/crud_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ package unified

import (
"fmt"
"reflect"
"strings"

"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/internal/bsonutil"
Expand All @@ -22,74 +20,120 @@ func newMissingArgumentError(arg string) error {
return fmt.Errorf("operation arguments document is missing required field %q", arg)
}

type updateArguments[Options options.UpdateManyOptions | options.UpdateOneOptions] struct {
type updateManyArguments struct {
filter bson.Raw
update interface{}
opts options.Lister[Options]
opts *options.UpdateManyOptionsBuilder
}

func createUpdateArguments[Options options.UpdateManyOptions | options.UpdateOneOptions](
args bson.Raw,
) (*updateArguments[Options], error) {
ua := &updateArguments[Options]{}
var builder reflect.Value
switch any((*Options)(nil)).(type) {
case *options.UpdateManyOptions:
builder = reflect.ValueOf(options.UpdateMany())
case *options.UpdateOneOptions:
builder = reflect.ValueOf(options.UpdateOne())
func createUpdateManyArguments(args bson.Raw) (*updateManyArguments, error) {
ua := &updateManyArguments{
opts: options.UpdateMany(),
}

elems, _ := args.Elements()
for _, elem := range elems {
key := elem.Key()
val := elem.Value()

var arg reflect.Value
switch key {
case "arrayFilters":
arg = reflect.ValueOf(
ua.opts.SetArrayFilters(
bsonutil.RawToInterfaces(bsonutil.RawArrayToDocuments(val.Array())...),
)
case "bypassDocumentValidation":
arg = reflect.ValueOf(val.Boolean())
ua.opts.SetBypassDocumentValidation(val.Boolean())
case "collation":
collation, err := createCollation(val.Document())
if err != nil {
return nil, fmt.Errorf("error creating collation: %w", err)
}
arg = reflect.ValueOf(collation)
ua.opts.SetCollation(collation)
case "comment":
arg = reflect.ValueOf(val)
ua.opts.SetComment(val)
case "filter":
ua.filter = val.Document()
case "hint":
hint, err := createHint(val)
if err != nil {
return nil, fmt.Errorf("error creating hint: %w", err)
}
arg = reflect.ValueOf(hint)
ua.opts.SetHint(hint)
case "let":
arg = reflect.ValueOf(val.Document())
ua.opts.SetLet(val.Document())
case "update":
var err error
ua.update, err = createUpdateValue(val)
if err != nil {
return nil, fmt.Errorf("error processing update value: %w", err)
}
case "upsert":
arg = reflect.ValueOf(val.Boolean())
ua.opts.SetUpsert(val.Boolean())
default:
return nil, fmt.Errorf("unrecognized update option %q", key)
}
if arg.IsValid() {
fn := builder.MethodByName(
fmt.Sprintf("Set%s%s", strings.ToUpper(string(key[0])), key[1:]),
}
if ua.filter == nil {
return nil, newMissingArgumentError("filter")
}
if ua.update == nil {
return nil, newMissingArgumentError("update")
}

return ua, nil
}

type updateOneArguments struct {
filter bson.Raw
update interface{}
opts *options.UpdateOneOptionsBuilder
}

func createUpdateOneArguments(args bson.Raw) (*updateOneArguments, error) {
ua := &updateOneArguments{
opts: options.UpdateOne(),
}

elems, _ := args.Elements()
for _, elem := range elems {
key := elem.Key()
val := elem.Value()

switch key {
case "arrayFilters":
ua.opts.SetArrayFilters(
bsonutil.RawToInterfaces(bsonutil.RawArrayToDocuments(val.Array())...),
)
if !fn.IsValid() {
return nil, fmt.Errorf("unrecognized update option %q", key)
case "bypassDocumentValidation":
ua.opts.SetBypassDocumentValidation(val.Boolean())
case "collation":
collation, err := createCollation(val.Document())
if err != nil {
return nil, fmt.Errorf("error creating collation: %w", err)
}
ua.opts.SetCollation(collation)
case "comment":
ua.opts.SetComment(val)
case "filter":
ua.filter = val.Document()
case "hint":
hint, err := createHint(val)
if err != nil {
return nil, fmt.Errorf("error creating hint: %w", err)
}
ua.opts.SetHint(hint)
case "let":
ua.opts.SetLet(val.Document())
case "update":
var err error
ua.update, err = createUpdateValue(val)
if err != nil {
return nil, fmt.Errorf("error processing update value: %w", err)
}
fn.Call([]reflect.Value{arg})
case "upsert":
ua.opts.SetUpsert(val.Boolean())
default:
return nil, fmt.Errorf("unrecognized update option %q", key)
}
}
if ua.filter == nil {
Expand All @@ -98,7 +142,6 @@ func createUpdateArguments[Options options.UpdateManyOptions | options.UpdateOne
if ua.update == nil {
return nil, newMissingArgumentError("update")
}
ua.opts = builder.Interface().(options.Lister[Options])

return ua, nil
}
Expand Down

0 comments on commit 8306537

Please sign in to comment.