@@ -43,9 +43,11 @@ namespace Poco {
43
43
namespace MongoDB {
44
44
45
45
46
- static const std::string keyCursor {" cursor" };
47
- static const std::string keyFirstBatch {" firstBatch" };
48
- static const std::string keyNextBatch {" nextBatch" };
46
+ static const std::string keyCursor {" cursor" s};
47
+ static const std::string keyCursors {" cursors" s};
48
+ static const std::string keyBatchSize {" batchSize" s};
49
+ static const std::string keyId {" id" s};
50
+ static const std::string keyCursorsKilled {" cursorsKilled" s};
49
51
50
52
static Poco::Int64 cursorIdFromResponse (const MongoDB::Document& doc);
51
53
@@ -95,23 +97,42 @@ Int32 OpMsgCursor::batchSize() const
95
97
}
96
98
97
99
100
+ bool OpMsgCursor::isActive () const
101
+ {
102
+ return (_cursorID > 0 || _query.commandName () != OpMsgMessage::CMD_GET_MORE);
103
+ }
104
+
105
+
98
106
OpMsgMessage& OpMsgCursor::next (Connection& connection)
99
107
{
100
108
if (_cursorID == 0 )
101
109
{
102
110
_response.clear ();
103
111
112
+ if (!isActive ())
113
+ {
114
+ // Cursor reached the end of data. Nothing to provide.
115
+ return _response;
116
+ }
117
+
104
118
if (_emptyFirstBatch || _batchSize > 0 )
105
119
{
106
120
Int32 bsize = _emptyFirstBatch ? 0 : _batchSize;
121
+ auto & body { _query.body () };
107
122
if (_query.commandName () == OpMsgMessage::CMD_FIND)
108
123
{
109
- _query.body ().add (" batchSize" , bsize);
124
+ // Prevent duplicated fields if next() fails due to communication
125
+ // issues and is the used again.
126
+ body.remove (keyBatchSize);
127
+ body.add (keyBatchSize, bsize);
110
128
}
111
129
else if (_query.commandName () == OpMsgMessage::CMD_AGGREGATE)
112
130
{
113
- auto & cursorDoc = _query.body ().addNewDocument (" cursor" );
114
- cursorDoc.add (" batchSize" , bsize);
131
+ // Prevent duplicated fields if next() fails due to communication
132
+ // issues and is the used again.
133
+ body.remove (keyCursor);
134
+ auto & cursorDoc = body.addNewDocument (keyCursor);
135
+ cursorDoc.add (keyBatchSize, bsize);
115
136
}
116
137
}
117
138
@@ -155,11 +176,11 @@ void OpMsgCursor::kill(Connection& connection)
155
176
156
177
MongoDB::Array::Ptr cursors = new MongoDB::Array ();
157
178
cursors->add <Poco::Int64>(_cursorID);
158
- _query.body ().add (" cursors " , cursors);
179
+ _query.body ().add (keyCursors , cursors);
159
180
160
181
connection.sendRequest (_query, _response);
161
182
162
- const auto killed = _response.body ().get <MongoDB::Array::Ptr>(" cursorsKilled " , nullptr );
183
+ const auto killed = _response.body ().get <MongoDB::Array::Ptr>(keyCursorsKilled , nullptr );
163
184
if (!killed || killed->size () != 1 || killed->get <Poco::Int64>(0 , -1 ) != _cursorID)
164
185
{
165
186
throw Poco::ProtocolException (" Cursor not killed as expected: " + std::to_string (_cursorID));
@@ -178,7 +199,7 @@ Poco::Int64 cursorIdFromResponse(const MongoDB::Document& doc)
178
199
auto cursorDoc = doc.get <Document::Ptr>(keyCursor, nullptr );
179
200
if (cursorDoc)
180
201
{
181
- id = cursorDoc->get <Poco::Int64>(" id " , 0 );
202
+ id = cursorDoc->get <Poco::Int64>(keyId , 0 );
182
203
}
183
204
return id;
184
205
}
0 commit comments