forked from mongodb/mongo-go-driver
/
crud_helpers.go
172 lines (153 loc) · 4.45 KB
/
crud_helpers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// 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 unified
import (
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/bsontype"
"go.mongodb.org/mongo-driver/internal/testutil/helpers"
"go.mongodb.org/mongo-driver/mongo/options"
)
// newMissingArgumentError creates an error to convey that an argument that is required to run an operation is missing
// from the operation's arguments document.
func newMissingArgumentError(arg string) error {
return fmt.Errorf("operation arguments document is missing required field %q", arg)
}
type updateArguments struct {
filter bson.Raw
update interface{}
opts *options.UpdateOptions
}
func createUpdateArguments(args bson.Raw) (*updateArguments, error) {
ua := &updateArguments{
opts: options.Update(),
}
var err error
elems, _ := args.Elements()
for _, elem := range elems {
key := elem.Key()
val := elem.Value()
switch key {
case "arrayFilters":
ua.opts.SetArrayFilters(options.ArrayFilters{
Filters: helpers.RawToInterfaces(helpers.RawToDocuments(val.Array())...),
})
case "bypassDocumentValidation":
ua.opts.SetBypassDocumentValidation(val.Boolean())
case "collation":
collation, err := createCollation(val.Document())
if err != nil {
return nil, fmt.Errorf("error creating collation: %v", 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: %v", err)
}
ua.opts.SetHint(hint)
case "let":
ua.opts.SetLet(val.Document())
case "update":
ua.update, err = createUpdateValue(val)
if err != nil {
return nil, fmt.Errorf("error processing update value: %v", err)
}
case "upsert":
ua.opts.SetUpsert(val.Boolean())
default:
return nil, fmt.Errorf("unrecognized update option %q", key)
}
}
if ua.filter == nil {
return nil, newMissingArgumentError("filter")
}
if ua.update == nil {
return nil, newMissingArgumentError("update")
}
return ua, nil
}
type listCollectionsArguments struct {
filter bson.Raw
opts *options.ListCollectionsOptions
}
func createListCollectionsArguments(args bson.Raw) (*listCollectionsArguments, error) {
lca := &listCollectionsArguments{
opts: options.ListCollections(),
}
lca.filter = emptyDocument
elems, _ := args.Elements()
for _, elem := range elems {
key := elem.Key()
val := elem.Value()
switch key {
case "batchSize":
lca.opts.SetBatchSize(val.Int32())
case "filter":
lca.filter = val.Document()
case "nameOnly":
lca.opts.SetNameOnly(val.Boolean())
default:
return nil, fmt.Errorf("unrecognized listCollections option %q", key)
}
}
return lca, nil
}
func createCollation(args bson.Raw) (*options.Collation, error) {
var collation options.Collation
elems, _ := args.Elements()
for _, elem := range elems {
switch elem.Key() {
case "locale":
collation.Locale = elem.Value().StringValue()
case "caseLevel":
collation.CaseLevel = elem.Value().Boolean()
case "caseFirst":
collation.CaseFirst = elem.Value().StringValue()
case "strength":
collation.Strength = int(elem.Value().Int32())
case "numericOrdering":
collation.NumericOrdering = elem.Value().Boolean()
case "alternate":
collation.Alternate = elem.Value().StringValue()
case "maxVariable":
collation.MaxVariable = elem.Value().StringValue()
case "normalization":
collation.Normalization = elem.Value().Boolean()
case "backwards":
collation.Backwards = elem.Value().Boolean()
default:
return nil, fmt.Errorf("unrecognized collation option %q", elem.Key())
}
}
return &collation, nil
}
func createHint(val bson.RawValue) (interface{}, error) {
var hint interface{}
switch val.Type {
case bsontype.String:
hint = val.StringValue()
case bsontype.EmbeddedDocument:
hint = val.Document()
default:
return nil, fmt.Errorf("unrecognized hint value type %s", val.Type)
}
return hint, nil
}
func createCommentString(val bson.RawValue) (string, error) {
switch val.Type {
case bsontype.String:
return val.StringValue(), nil
case bsontype.EmbeddedDocument:
return val.String(), nil
default:
return "", fmt.Errorf("unrecognized 'comment' value type: %T", val)
}
}