Skip to content

Commit ab4874d

Browse files
committed
CSHARP-2117: If any request in a bulk write specifies a collation and server is < 3.4 the entire bulk write must fail.
1 parent d72beef commit ab4874d

File tree

9 files changed

+219
-10
lines changed

9 files changed

+219
-10
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2010-2017 MongoDB Inc.
1+
/* Copyright 2010-2018 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
1515

1616
using System;
1717
using System.Collections.Generic;
18-
using System.Linq;
1918
using MongoDB.Bson;
2019
using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
2120

@@ -60,5 +59,10 @@ protected override IExecutableInRetryableWriteContext<BulkWriteOperationResult>
6059
WriteConcern = WriteConcern
6160
};
6261
}
62+
63+
protected override bool RequestHasCollation(DeleteRequest request)
64+
{
65+
return request.Collation != null;
66+
}
6367
}
6468
}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2010-2017 MongoDB Inc.
1+
/* Copyright 2010-2018 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -15,11 +15,9 @@
1515

1616
using System;
1717
using System.Collections.Generic;
18-
using System.Linq;
1918
using MongoDB.Bson;
2019
using MongoDB.Bson.Serialization;
2120
using MongoDB.Bson.Serialization.Serializers;
22-
using MongoDB.Driver.Core.Misc;
2321
using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
2422

2523
namespace MongoDB.Driver.Core.Operations
@@ -65,6 +63,11 @@ protected override IExecutableInRetryableWriteContext<BulkWriteOperationResult>
6563
};
6664
}
6765

66+
protected override bool RequestHasCollation(InsertRequest request)
67+
{
68+
return false;
69+
}
70+
6871
// nested types
6972
private class InsertRequestSerializer : SealedClassSerializerBase<InsertRequest>
7073
{

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

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2010-2017 MongoDB Inc.
1+
/* Copyright 2010-2018 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -213,6 +213,7 @@ public BulkWriteOperationResult Execute(IWriteBinding binding, CancellationToken
213213
using (EventContext.BeginOperation())
214214
using (var context = RetryableWriteContext.Create(binding, _retryRequested, cancellationToken))
215215
{
216+
EnsureCollationIsSupportedIfAnyRequestHasCollation(context);
216217
context.DisableRetriesIfAnyWriteRequestIsNotRetryable(_requests);
217218
var helper = new BatchHelper(_requests, _isOrdered, _writeConcern);
218219
foreach (var batch in helper.GetBatches())
@@ -229,6 +230,7 @@ public async Task<BulkWriteOperationResult> ExecuteAsync(IWriteBinding binding,
229230
using (EventContext.BeginOperation())
230231
using (var context = await RetryableWriteContext.CreateAsync(binding, _retryRequested, cancellationToken).ConfigureAwait(false))
231232
{
233+
EnsureCollationIsSupportedIfAnyRequestHasCollation(context);
232234
context.DisableRetriesIfAnyWriteRequestIsNotRetryable(_requests);
233235
var helper = new BatchHelper(_requests, _isOrdered, _writeConcern);
234236
foreach (var batch in helper.GetBatches())
@@ -292,6 +294,21 @@ private IExecutableInRetryableWriteContext<BulkWriteOperationResult> CreateUnmix
292294
}
293295
}
294296

297+
private void EnsureCollationIsSupportedIfAnyRequestHasCollation(RetryableWriteContext context)
298+
{
299+
var serverVersion = context.Channel.ConnectionDescription.ServerVersion;
300+
if (!Feature.Collation.IsSupported(serverVersion))
301+
{
302+
foreach (var request in _requests)
303+
{
304+
if (RequestHasCollation(request))
305+
{
306+
throw new NotSupportedException($"Server version {serverVersion} does not support collations.");
307+
}
308+
}
309+
}
310+
}
311+
295312
private BulkWriteBatchResult ExecuteBatch(RetryableWriteContext context, Batch batch, CancellationToken cancellationToken)
296313
{
297314
BulkWriteOperationResult result;
@@ -328,6 +345,23 @@ private async Task<BulkWriteBatchResult> ExecuteBatchAsync(RetryableWriteContext
328345
return BulkWriteBatchResult.Create(result, exception, batch.IndexMap);
329346
}
330347

348+
private bool RequestHasCollation(WriteRequest request)
349+
{
350+
DeleteRequest deleteRequest;
351+
if ((deleteRequest = request as DeleteRequest) != null)
352+
{
353+
return deleteRequest.Collation != null;
354+
}
355+
356+
UpdateRequest updateRequest;
357+
if ((updateRequest = request as UpdateRequest) != null)
358+
{
359+
return updateRequest.Collation != null;
360+
}
361+
362+
return false;
363+
}
364+
331365
// nested types
332366
private class Batch
333367
{

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2010-2017 MongoDB Inc.
1+
/* Copyright 2010-2018 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using System.Collections.Generic;
1718
using System.Linq;
1819
using System.Threading;
@@ -114,6 +115,7 @@ public WriteConcern WriteConcern
114115
// public methods
115116
public BulkWriteOperationResult Execute(RetryableWriteContext context, CancellationToken cancellationToken)
116117
{
118+
EnsureCollationIsSupportedIfAnyRequestHasCollation(context, _requests);
117119
if (Feature.WriteCommands.IsSupported(context.Channel.ConnectionDescription.ServerVersion))
118120
{
119121
return ExecuteBatches(context, cancellationToken);
@@ -137,6 +139,7 @@ public BulkWriteOperationResult Execute(IWriteBinding binding, CancellationToken
137139

138140
public Task<BulkWriteOperationResult> ExecuteAsync(RetryableWriteContext context, CancellationToken cancellationToken)
139141
{
142+
EnsureCollationIsSupportedIfAnyRequestHasCollation(context, _requests);
140143
if (Feature.WriteCommands.IsSupported(context.Channel.ConnectionDescription.ServerVersion))
141144
{
142145
return ExecuteBatchesAsync(context, cancellationToken);
@@ -173,6 +176,8 @@ protected WriteConcern GetBatchWriteConcern(Batch batch)
173176
return writeConcern;
174177
}
175178

179+
protected abstract bool RequestHasCollation(TWriteRequest request);
180+
176181
// private methods
177182
private BulkWriteBatchResult CreateBatchResult(Batch batch, BsonDocument writeCommandResult)
178183
{
@@ -186,6 +191,20 @@ private BulkWriteBatchResult CreateBatchResult(Batch batch, BsonDocument writeCo
186191
indexMap);
187192
}
188193

194+
private void EnsureCollationIsSupportedIfAnyRequestHasCollation(RetryableWriteContext context, IEnumerable<TWriteRequest> requests)
195+
{
196+
var serverVersion = context.Channel.ConnectionDescription.ServerVersion;
197+
if (!Feature.Collation.IsSupported(serverVersion))
198+
{
199+
foreach (var request in requests)
200+
{
201+
if (RequestHasCollation(request))
202+
{
203+
throw new NotSupportedException($"Server version {serverVersion} does not support collations.");
204+
}
205+
}
206+
}
207+
}
189208
private BulkWriteBatchResult ExecuteBatch(RetryableWriteContext context, Batch batch, CancellationToken cancellationToken)
190209
{
191210
var operation = CreateBatchOperation(batch);

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2010-2017 MongoDB Inc.
1+
/* Copyright 2010-2018 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
1515

1616
using System;
1717
using System.Collections.Generic;
18-
using System.Linq;
1918
using MongoDB.Bson;
2019
using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
2120

@@ -61,5 +60,10 @@ protected override IExecutableInRetryableWriteContext<BulkWriteOperationResult>
6160
WriteConcern = WriteConcern
6261
};
6362
}
63+
64+
protected override bool RequestHasCollation(UpdateRequest request)
65+
{
66+
return request.Collation != null;
67+
}
6468
}
6569
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* Copyright 2018 MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using FluentAssertions;
19+
using MongoDB.Bson;
20+
using MongoDB.Bson.TestHelpers.XunitExtensions;
21+
using MongoDB.Driver.Core.Misc;
22+
using Xunit;
23+
24+
namespace MongoDB.Driver.Core.Operations
25+
{
26+
public class BulkDeleteOperationTests : OperationTestBase
27+
{
28+
[Theory]
29+
[ParameterAttributeData]
30+
public void Execute_with_collation_should_throw_when_collation_is_not_supported(
31+
[Values(false, true)] bool async)
32+
{
33+
var collation = new Collation("en_US");
34+
var requests = new List<DeleteRequest>
35+
{
36+
new DeleteRequest(new BsonDocument("x", 1)),
37+
new DeleteRequest(new BsonDocument("x", 1)) { Collation = collation }
38+
};
39+
var subject = new BulkDeleteOperation(_collectionNamespace, requests, _messageEncoderSettings);
40+
41+
var exception = Record.Exception(() => ExecuteOperation(subject, async));
42+
43+
if (Feature.Collation.IsSupported(CoreTestConfiguration.ServerVersion))
44+
{
45+
exception.Should().BeNull();
46+
}
47+
else
48+
{
49+
exception.Should().BeOfType<NotSupportedException>();
50+
}
51+
}
52+
53+
}
54+
}

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2013-2017 MongoDB Inc.
1+
/* Copyright 2013-2018 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -167,6 +167,41 @@ public void Execute_with_zero_requests_should_throw_an_exception(
167167
act.ShouldThrow<InvalidOperationException>();
168168
}
169169

170+
[Theory]
171+
[ParameterAttributeData]
172+
public void Execute_with_collation_should_throw_when_collation_is_not_supported(
173+
[Values(typeof(DeleteRequest), typeof(UpdateRequest))] Type requestWithCollationType,
174+
[Values(false, true)] bool async)
175+
{
176+
var collation = new Collation("en_US");
177+
var requests = new List<WriteRequest>
178+
{
179+
new DeleteRequest(new BsonDocument("x", 1)),
180+
new InsertRequest(new BsonDocument("x", 1)),
181+
new UpdateRequest(UpdateType.Update, new BsonDocument("x", 1), new BsonDocument("$set", new BsonDocument("x", 2)))
182+
};
183+
if (requestWithCollationType == typeof(DeleteRequest))
184+
{
185+
requests.Add(new DeleteRequest(new BsonDocument("x", 1)) { Collation = collation });
186+
}
187+
if (requestWithCollationType == typeof(UpdateRequest))
188+
{
189+
requests.Add(new UpdateRequest(UpdateType.Update, new BsonDocument("x", 1), new BsonDocument("$set", new BsonDocument("x", 2))) { Collation = collation });
190+
}
191+
var subject = new BulkMixedWriteOperation(_collectionNamespace, requests, _messageEncoderSettings);
192+
193+
var exception = Record.Exception(() => ExecuteOperation(subject, async));
194+
195+
if (Feature.Collation.IsSupported(CoreTestConfiguration.ServerVersion))
196+
{
197+
exception.Should().BeNull();
198+
}
199+
else
200+
{
201+
exception.Should().BeOfType<NotSupportedException>();
202+
}
203+
}
204+
170205
[SkippableTheory]
171206
[ParameterAttributeData]
172207
public void Execute_with_one_delete_against_a_matching_document(
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* Copyright 2018 MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using FluentAssertions;
19+
using MongoDB.Bson;
20+
using MongoDB.Bson.TestHelpers.XunitExtensions;
21+
using MongoDB.Driver.Core.Misc;
22+
using Xunit;
23+
24+
namespace MongoDB.Driver.Core.Operations
25+
{
26+
public class BulkUpdateOperationTests : OperationTestBase
27+
{
28+
[Theory]
29+
[ParameterAttributeData]
30+
public void Execute_with_collation_should_throw_when_collation_is_not_supported(
31+
[Values(false, true)] bool async)
32+
{
33+
var collation = new Collation("en_US");
34+
var requests = new List<UpdateRequest>
35+
{
36+
new UpdateRequest(UpdateType.Update, new BsonDocument("x", 1), new BsonDocument("$set", new BsonDocument("x", 2))),
37+
new UpdateRequest(UpdateType.Update, new BsonDocument("x", 1), new BsonDocument("$set", new BsonDocument("x", 2))) { Collation = collation }
38+
};
39+
var subject = new BulkUpdateOperation(_collectionNamespace, requests, _messageEncoderSettings);
40+
41+
var exception = Record.Exception(() => ExecuteOperation(subject, async));
42+
43+
if (Feature.Collation.IsSupported(CoreTestConfiguration.ServerVersion))
44+
{
45+
exception.Should().BeNull();
46+
}
47+
else
48+
{
49+
exception.Should().BeOfType<NotSupportedException>();
50+
}
51+
}
52+
53+
}
54+
}

tests/MongoDB.Driver.Core.Tests/MongoDB.Driver.Core.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@
9999
<Compile Include="Core\Operations\AggregateExplainOperationTests.cs" />
100100
<Compile Include="Core\Operations\AsyncCursorEnumeratorTests.cs" />
101101
<Compile Include="Core\Operations\AsyncCursorTests.cs" />
102+
<Compile Include="Core\Operations\BulkDeleteOperationTests.cs" />
102103
<Compile Include="Core\Operations\BulkMixedWriteOperationTests.cs" />
104+
<Compile Include="Core\Operations\BulkUpdateOperationTests.cs" />
103105
<Compile Include="Core\Operations\BulkWriteOperationErrorTests.cs" />
104106
<Compile Include="Core\Operations\AsyncCursorSourceEnumerableAdapterTests.cs" />
105107
<Compile Include="Core\Operations\AsyncCursorEnumerableOneTimeAdapterTests.cs" />

0 commit comments

Comments
 (0)