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