Skip to content

Commit f418f6a

Browse files
author
Divjot Arora
committed
Allow SingleResult Decode and DecodeBytes methods to be called more than once.
GODRIVER-1004 Change-Id: Ia1a7471dda022414acccba2b81e13822a24285fb
1 parent d16c4cb commit f418f6a

File tree

2 files changed

+72
-26
lines changed

2 files changed

+72
-26
lines changed

mongo/single_result.go

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,51 +39,49 @@ func (sr *SingleResult) Decode(v interface{}) error {
3939
if sr.reg == nil {
4040
return bson.ErrNilRegistry
4141
}
42-
switch {
43-
case sr.rdr != nil:
44-
if v == nil {
45-
return nil
46-
}
47-
return bson.UnmarshalWithRegistry(sr.reg, sr.rdr, v)
48-
case sr.cur != nil:
49-
defer sr.cur.Close(context.TODO())
50-
if !sr.cur.Next(context.TODO()) {
51-
if err := sr.cur.Err(); err != nil {
52-
return err
53-
}
54-
return ErrNoDocuments
55-
}
56-
if v == nil {
57-
return nil
58-
}
59-
return sr.cur.Decode(v)
60-
}
6142

62-
return ErrNoDocuments
43+
if sr.err = sr.setRdrContents(); sr.err != nil {
44+
return sr.err
45+
}
46+
return bson.UnmarshalWithRegistry(sr.reg, sr.rdr, v)
6347
}
6448

6549
// DecodeBytes will return a copy of the document as a bson.Raw. If there was an
6650
// error from the operation that created this SingleResult then the error
6751
// will be returned. If there were no returned documents, ErrNoDocuments is
6852
// returned.
6953
func (sr *SingleResult) DecodeBytes() (bson.Raw, error) {
54+
if sr.err != nil {
55+
return nil, sr.err
56+
}
57+
58+
if sr.err = sr.setRdrContents(); sr.err != nil {
59+
return nil, sr.err
60+
}
61+
return sr.rdr, nil
62+
}
63+
64+
// setRdrContents will set the contents of rdr by iterating the underlying cursor if necessary.
65+
func (sr *SingleResult) setRdrContents() error {
7066
switch {
7167
case sr.err != nil:
72-
return nil, sr.err
68+
return sr.err
7369
case sr.rdr != nil:
74-
return sr.rdr, nil
70+
return nil
7571
case sr.cur != nil:
7672
defer sr.cur.Close(context.TODO())
7773
if !sr.cur.Next(context.TODO()) {
7874
if err := sr.cur.Err(); err != nil {
79-
return nil, err
75+
return err
8076
}
81-
return nil, ErrNoDocuments
77+
78+
return ErrNoDocuments
8279
}
83-
return sr.cur.Current, nil
80+
sr.rdr = sr.cur.Current
81+
return nil
8482
}
8583

86-
return nil, ErrNoDocuments
84+
return ErrNoDocuments
8785
}
8886

8987
// Err will return the error from the operation that created this SingleResult.

mongo/single_result_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (C) MongoDB, Inc. 2017-present.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
// not use this file except in compliance with the License. You may obtain
5+
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
package mongo
8+
9+
import (
10+
"bytes"
11+
"testing"
12+
13+
"go.mongodb.org/mongo-driver/bson"
14+
)
15+
16+
func TestSingleResult(t *testing.T) {
17+
t.Run("TestDecode", func(t *testing.T) {
18+
t.Run("DecodeTwice", func(t *testing.T) {
19+
// Test that Decode and DecodeBytes can be called more than once
20+
c, err := newCursor(newTestBatchCursor(1, 1), bson.DefaultRegistry)
21+
if err != nil {
22+
t.Fatalf("error creating cursor: %v", err)
23+
}
24+
25+
sr := &SingleResult{cur: c, reg: bson.DefaultRegistry}
26+
var firstDecode, secondDecode bson.Raw
27+
if err = sr.Decode(&firstDecode); err != nil {
28+
t.Fatalf("error on first Decode call: %v", err)
29+
}
30+
if err = sr.Decode(&secondDecode); err != nil {
31+
t.Fatalf("error on second Decode call: %v", err)
32+
}
33+
decodeBytes, err := sr.DecodeBytes()
34+
if err != nil {
35+
t.Fatalf("error on DecodeBytes call: %v", err)
36+
}
37+
38+
if !bytes.Equal(firstDecode, secondDecode) {
39+
t.Fatalf("Decode contents do not match; first returned %v, second returned %v",
40+
firstDecode, secondDecode)
41+
}
42+
if !bytes.Equal(firstDecode, decodeBytes) {
43+
t.Fatalf("Decode and DecodeBytes contents do not match; Decode returned %v, DecodeBytes "+
44+
"returned %v", firstDecode, decodeBytes)
45+
}
46+
})
47+
})
48+
}

0 commit comments

Comments
 (0)