Skip to content

Commit a29da95

Browse files
committed
Ensure primitives are returned as insertedIDs
This change updates InsertOne and InsertMany to return a Go or BSON primitive type instead of a bsonx type. GODRIVER-651 Change-Id: Iccaae5ee169cbf72cce09d996e3e55f46659faf8
1 parent aab8cf4 commit a29da95

File tree

4 files changed

+56
-16
lines changed

4 files changed

+56
-16
lines changed

mongo/collection.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,11 @@ func (coll *Collection) InsertOne(ctx context.Context, document interface{},
213213
ctx = context.Background()
214214
}
215215

216-
doc, err := transformDocument(coll.registry, document)
216+
doc, insertedID, err := transformAndEnsureID(coll.registry, document)
217217
if err != nil {
218218
return nil, err
219219
}
220220

221-
doc, insertedID := ensureID(doc)
222-
223221
sess := sessionFromContext(ctx)
224222

225223
err = coll.client.ValidSession(sess)
@@ -277,11 +275,10 @@ func (coll *Collection) InsertMany(ctx context.Context, documents []interface{},
277275
docs := make([]bsonx.Doc, len(documents))
278276

279277
for i, doc := range documents {
280-
bdoc, err := transformDocument(coll.registry, doc)
278+
bdoc, insertedID, err := transformAndEnsureID(coll.registry, doc)
281279
if err != nil {
282280
return nil, err
283281
}
284-
bdoc, insertedID := ensureID(bdoc)
285282

286283
docs[i] = bdoc
287284
result[i] = insertedID

mongo/collection_internal_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ func TestCollection_InsertOne(t *testing.T) {
283283
t.Parallel()
284284

285285
id := primitive.NewObjectID()
286-
want := bsonx.Elem{"_id", bsonx.ObjectID(id)}
287-
doc := bsonx.Doc{want, {"x", bsonx.Int32(1)}}
286+
want := id
287+
doc := bsonx.Doc{bsonx.Elem{"_id", bsonx.ObjectID(id)}, {"x", bsonx.Int32(1)}}
288288
coll := createTestCollection(t, nil, nil)
289289

290290
result, err := coll.InsertOne(context.Background(), doc)
@@ -358,12 +358,12 @@ func TestCollection_InsertMany(t *testing.T) {
358358

359359
t.Parallel()
360360

361-
want1 := bsonx.Elem{"_id", bsonx.Int32(11)}
362-
want2 := bsonx.Elem{"_id", bsonx.Int32(12)}
361+
want1 := int32(11)
362+
want2 := int32(12)
363363
docs := []interface{}{
364-
bsonx.Doc{want1},
364+
bsonx.Doc{bsonx.Elem{"_id", bsonx.Int32(11)}},
365365
bsonx.Doc{{"x", bsonx.Int32(6)}},
366-
bsonx.Doc{want2},
366+
bsonx.Doc{bsonx.Elem{"_id", bsonx.Int32(12)}},
367367
}
368368
coll := createTestCollection(t, nil, nil)
369369

mongo/crud_util_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ func verifyInsertOneResult(t *testing.T, res *InsertOneResult, result json.RawMe
591591

592592
if expectedID != nil {
593593
require.NotNil(t, res)
594-
require.Equal(t, expectedID, res.InsertedID.(bsonx.Elem).Value.Interface())
594+
require.Equal(t, expectedID, res.InsertedID)
595595
}
596596
}
597597

@@ -606,10 +606,6 @@ func verifyInsertManyResult(t *testing.T, res *InsertManyResult, result json.Raw
606606
if expected.InsertedIds != nil {
607607
replaceFloatsWithInts(expected.InsertedIds)
608608

609-
for i, elem := range res.InsertedIDs {
610-
res.InsertedIDs[i] = elem.(bsonx.Elem).Value.Interface()
611-
}
612-
613609
for _, val := range expected.InsertedIds {
614610
require.Contains(t, res.InsertedIDs, val)
615611
}

mongo/mongo.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,53 @@ func (me MarshalError) Error() string {
6969
//
7070
type Pipeline []bson.D
7171

72+
// transformAndEnsureID is a hack that makes it easy to get a RawValue as the _id value. This will
73+
// be removed when we switch from using bsonx to bsoncore for the driver package.
74+
func transformAndEnsureID(registry *bsoncodec.Registry, val interface{}) (bsonx.Doc, interface{}, error) {
75+
// TODO: performance is going to be pretty bad for bsonx.Doc here since we turn it into a []byte
76+
// only to turn it back into a bsonx.Doc. We can fix this post beta1 when we refactor the driver
77+
// package to use bsoncore.Document instead of bsonx.Doc.
78+
if registry == nil {
79+
registry = bson.NewRegistryBuilder().Build()
80+
}
81+
switch tt := val.(type) {
82+
case nil:
83+
val = bsonx.Doc{}
84+
case bsonx.Doc:
85+
val = tt.Copy()
86+
case []byte:
87+
// Slight optimization so we'll just use MarshalBSON and not go through the codec machinery.
88+
val = bson.Raw(tt)
89+
}
90+
91+
// TODO(skriptble): Use a pool of these instead.
92+
buf := make([]byte, 0, 256)
93+
b, err := bson.MarshalAppendWithRegistry(registry, buf, val)
94+
if err != nil {
95+
return nil, nil, MarshalError{Value: val, Err: err}
96+
}
97+
98+
d, err := bsonx.ReadDoc(b)
99+
if err != nil {
100+
return nil, nil, err
101+
}
102+
103+
var id interface{}
104+
105+
v, err := bson.Raw(b).LookupErr("_id")
106+
switch err.(type) {
107+
case nil:
108+
if err := v.Unmarshal(&id); err != nil {
109+
return nil, nil, err
110+
}
111+
default:
112+
oid := primitive.NewObjectID()
113+
d = append(d, bsonx.Elem{"_id", bsonx.ObjectID(oid)})
114+
id = oid
115+
}
116+
return d, id, nil
117+
}
118+
72119
func transformDocument(registry *bsoncodec.Registry, val interface{}) (bsonx.Doc, error) {
73120
if registry == nil {
74121
registry = bson.NewRegistryBuilder().Build()

0 commit comments

Comments
 (0)