Skip to content

Commit ddbf505

Browse files
CSHARP-3021: GetMore commands are not sent with the namespace returned in the last batch
1 parent 5edca6c commit ddbf505

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

src/MongoDB.Driver.Core/Core/Operations/FindCommandOperation.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
using System.Threading;
1818
using System.Threading.Tasks;
1919
using MongoDB.Bson;
20-
using MongoDB.Bson.IO;
2120
using MongoDB.Bson.Serialization;
2221
using MongoDB.Bson.Serialization.Serializers;
2322
using MongoDB.Driver.Core.Bindings;
@@ -483,11 +482,13 @@ internal BsonDocument CreateCommand(ConnectionDescription connectionDescription,
483482
private AsyncCursor<TDocument> CreateCursor(IChannelSourceHandle channelSource, BsonDocument commandResult)
484483
{
485484
var getMoreChannelSource = new ServerChannelSource(channelSource.Server, channelSource.Session.Fork());
486-
var firstBatch = CreateCursorBatch(commandResult);
485+
var cursorDocument = commandResult["cursor"].AsBsonDocument;
486+
var collectionNamespace = CollectionNamespace.FromFullName(cursorDocument["ns"].AsString);
487+
var firstBatch = CreateFirstCursorBatch(cursorDocument);
487488

488489
return new AsyncCursor<TDocument>(
489490
getMoreChannelSource,
490-
_collectionNamespace,
491+
collectionNamespace,
491492
_filter ?? new BsonDocument(),
492493
firstBatch.Documents,
493494
firstBatch.CursorId,
@@ -498,9 +499,8 @@ private AsyncCursor<TDocument> CreateCursor(IChannelSourceHandle channelSource,
498499
_cursorType == CursorType.TailableAwait ? _maxAwaitTime : null);
499500
}
500501

501-
private CursorBatch<TDocument> CreateCursorBatch(BsonDocument commandResult)
502+
private CursorBatch<TDocument> CreateFirstCursorBatch(BsonDocument cursorDocument)
502503
{
503-
var cursorDocument = commandResult["cursor"].AsBsonDocument;
504504
var cursorId = cursorDocument["id"].ToInt64();
505505
var batch = (RawBsonArray)cursorDocument["firstBatch"];
506506

tests/MongoDB.Bson.TestHelpers/Reflector.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,22 @@ public static object Invoke<T1>(object obj, string name, T1 arg1)
7070
}
7171
}
7272

73+
public static object Invoke<T1, T2>(object obj, string name, T1 arg1, T2 arg2)
74+
{
75+
var parameterTypes = new[] { typeof(T1), typeof(T2) };
76+
var methodInfo = obj.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
77+
.Where(m => m.Name == name && m.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes))
78+
.Single();
79+
try
80+
{
81+
return methodInfo.Invoke(obj, new object[] { arg1, arg2 });
82+
}
83+
catch (TargetInvocationException exception)
84+
{
85+
throw exception.InnerException;
86+
}
87+
}
88+
7389
public static object Invoke<T1, T2>(object obj, string name, out T1 arg1, out T2 arg2)
7490
{
7591
arg1 = default;

tests/MongoDB.Driver.Core.Tests/Core/Operations/FindCommandOperationTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@
1616
using System;
1717
using FluentAssertions;
1818
using MongoDB.Bson;
19+
using MongoDB.Bson.IO;
1920
using MongoDB.Bson.Serialization.Serializers;
21+
using MongoDB.Bson.TestHelpers;
2022
using MongoDB.Bson.TestHelpers.XunitExtensions;
2123
using MongoDB.Driver.Core.Bindings;
2224
using MongoDB.Driver.Core.Clusters;
2325
using MongoDB.Driver.Core.Misc;
2426
using MongoDB.Driver.Core.Servers;
2527
using MongoDB.Driver.Core.TestHelpers;
2628
using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
29+
using Moq;
2730
using Xunit;
2831

2932
namespace MongoDB.Driver.Core.Operations
@@ -818,6 +821,36 @@ public void CreateCommand_should_return_the_expected_result_when_using_causal_co
818821
result.Should().Be(expectedResult);
819822
}
820823

824+
[SkippableFact]
825+
public void CreateCursor_should_use_ns_field_instead_of_namespace_passed_in_constructor()
826+
{
827+
var subject = new FindCommandOperation<BsonDocument>(_collectionNamespace, BsonDocumentSerializer.Instance, _messageEncoderSettings);
828+
var firstBatchSlice = new ByteArrayBuffer(new byte[] { 5, 0, 0, 0, 0 }, isReadOnly: true);
829+
var cursorCollectionNamespace = CollectionNamespace.FromFullName("cursors.lkajlkasdf-3980238d908sdf");
830+
var cursorDocument = new BsonDocument
831+
{
832+
{ "id", 0 },
833+
{ "firstBatch", new RawBsonArray(firstBatchSlice) },
834+
{ "ns", cursorCollectionNamespace.FullName }
835+
};
836+
var commandResult = new BsonDocument
837+
{
838+
{ "ok", 1 },
839+
{ "cursor", cursorDocument }
840+
};
841+
var mockServer = new Mock<IServer>();
842+
var mockSession = new Mock<ICoreSessionHandle>();
843+
var mockSessionFork = new Mock<ICoreSessionHandle>();
844+
mockSession.Setup(x => x.Fork()).Returns(mockSessionFork.Object);
845+
var mockChannelSource = new Mock<IChannelSourceHandle>();
846+
mockChannelSource.Setup(x => x.Server).Returns(mockServer.Object);
847+
mockChannelSource.Setup(x => x.Session).Returns(mockSession.Object);
848+
849+
var cursor = subject.CreateCursor(mockChannelSource.Object, commandResult);
850+
851+
cursor._collectionNamespace().Should().Be(cursorCollectionNamespace);
852+
}
853+
821854
[Theory]
822855
[ParameterAttributeData]
823856
public void CursorType_get_and_set_should_work(
@@ -1353,4 +1386,15 @@ private void EnsureTestData()
13531386
});
13541387
}
13551388
}
1389+
1390+
public static class FindCommandOperationReflector
1391+
{
1392+
public static AsyncCursor<BsonDocument> CreateCursor(
1393+
this FindCommandOperation<BsonDocument> obj,
1394+
IChannelSourceHandle channelSource,
1395+
BsonDocument commandResult)
1396+
{
1397+
return (AsyncCursor<BsonDocument>)Reflector.Invoke(obj, nameof(CreateCursor), channelSource, commandResult);
1398+
}
1399+
}
13561400
}

0 commit comments

Comments
 (0)