Skip to content

Commit 984598a

Browse files
CSHARP-2987: Allow hinting the delete command
1 parent 169ae39 commit 984598a

File tree

69 files changed

+4265
-149
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+4265
-149
lines changed

src/MongoDB.Driver.Core/Core/Misc/Feature.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ public class Feature
6060
private static readonly Feature __findCommand = new Feature("FindCommand", new SemanticVersion(3, 2, 0));
6161
private static readonly Feature __geoNearCommand = new Feature("GeoNearCommand", new SemanticVersion(1, 0, 0), new SemanticVersion(4, 1, 0, ""));
6262
private static readonly Feature __groupCommand = new Feature("GroupCommand", new SemanticVersion(1, 0, 0), new SemanticVersion(4, 1, 1, ""));
63-
private static readonly HintForFindAndModifyFeature __hintForFindAndModifyFeature = new HintForFindAndModifyFeature("HintForFindAndModify", new SemanticVersion(4, 3, 0, ""));
63+
private static readonly HintForDeleteOperationsFeature __hintForDeleteOperations = new HintForDeleteOperationsFeature("HintForDeleteOperations", new SemanticVersion(4, 3, 4));
64+
private static readonly HintForFindAndModifyFeature __hintForFindAndModifyFeature = new HintForFindAndModifyFeature("HintForFindAndModify", new SemanticVersion(4, 3, 4));
6465
private static readonly HintForUpdateAndReplaceOperationsFeature __hintForUpdateAndReplaceOperations = new HintForUpdateAndReplaceOperationsFeature("HintForUpdateAndReplaceOperations", new SemanticVersion(4, 2, 0));
6566
private static readonly Feature __keepConnectionPoolWhenNotMasterConnectionException = new Feature("KeepConnectionPoolWhenNotMasterConnectionException", new SemanticVersion(4, 1, 10));
6667
private static readonly Feature __keepConnectionPoolWhenReplSetStepDown = new Feature("KeepConnectionPoolWhenReplSetStepDown", new SemanticVersion(4, 1, 10));
@@ -275,13 +276,18 @@ public class Feature
275276
/// </summary>
276277
public static Feature GroupCommand => __groupCommand;
277278

279+
/// <summary>
280+
/// Gets the hint for delete operations feature.
281+
/// </summary>
282+
public static HintForDeleteOperationsFeature HintForDeleteOperations => __hintForDeleteOperations;
283+
278284
/// <summary>
279285
/// Gets the hint for find and modify operations feature.
280286
/// </summary>
281287
public static HintForFindAndModifyFeature HintForFindAndModifyFeature => __hintForFindAndModifyFeature;
282288

283289
/// <summary>
284-
/// Gets the hint for write operations feature.
290+
/// Gets the hint for update and replace operations feature.
285291
/// </summary>
286292
public static HintForUpdateAndReplaceOperationsFeature HintForUpdateAndReplaceOperations => __hintForUpdateAndReplaceOperations;
287293

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* Copyright 2020-present 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+
namespace MongoDB.Driver.Core.Misc
17+
{
18+
/// <summary>
19+
/// Represents the hint for delete operations feature.
20+
/// </summary>
21+
/// <seealso cref="MongoDB.Driver.Core.Misc.Feature" />
22+
public class HintForDeleteOperationsFeature : Feature
23+
{
24+
private readonly SemanticVersion _firstServerVersionWhereWeRelyOnServerToReturnError = new SemanticVersion(3, 4, 0);
25+
26+
/// <summary>
27+
/// Initializes a new instance of the <see cref="HintForDeleteOperationsFeature"/> class.
28+
/// </summary>
29+
/// <param name="name">The name of the feature.</param>
30+
/// <param name="firstSupportedVersion">The first server version that supports the feature.</param>
31+
public HintForDeleteOperationsFeature(string name, SemanticVersion firstSupportedVersion)
32+
: base(name, firstSupportedVersion)
33+
{
34+
}
35+
36+
/// <summary>
37+
/// Determines whether the driver must throw an exception if the feature is not supported by the server.
38+
/// </summary>
39+
/// <param name="serverVersion">The server version.</param>
40+
/// <returns>Whether the driver must throw if feature is not supported.</returns>
41+
public bool DriverMustThrowIfNotSupported(SemanticVersion serverVersion)
42+
{
43+
return serverVersion < _firstServerVersionWhereWeRelyOnServerToReturnError;
44+
}
45+
}
46+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ protected override bool RequestHasCollation(DeleteRequest request)
5050

5151
protected override bool RequestHasHint(DeleteRequest request)
5252
{
53-
return false;
53+
return request.Hint != null;
5454
}
5555
}
5656
}

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

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -314,15 +314,11 @@ private void EnsureCollationIsSupportedIfAnyRequestHasCollation(RetryableWriteCo
314314
private void EnsureHintIsSupportedIfAnyRequestHasHint(RetryableWriteContext context)
315315
{
316316
var serverVersion = context.Channel.ConnectionDescription.ServerVersion;
317-
if (Feature.HintForUpdateAndReplaceOperations.DriverMustThrowIfNotSupported(serverVersion) ||
318-
(!_writeConcern.IsAcknowledged && !Feature.HintForUpdateAndReplaceOperations.IsSupported(serverVersion)))
317+
foreach (var request in _requests)
319318
{
320-
foreach (var request in _requests)
319+
if (RequestHasHint(request) && !IsHintSupportedForRequestWithHint(request, serverVersion))
321320
{
322-
if (RequestHasHint(request))
323-
{
324-
throw new NotSupportedException($"Server version {serverVersion} does not support hints.");
325-
}
321+
throw new NotSupportedException($"Server version {serverVersion} does not support hints.");
326322
}
327323
}
328324
}
@@ -363,6 +359,25 @@ private async Task<BulkWriteBatchResult> ExecuteBatchAsync(RetryableWriteContext
363359
return BulkWriteBatchResult.Create(result, exception, batch.IndexMap);
364360
}
365361

362+
private bool IsHintSupportedForRequestWithHint(WriteRequest request, SemanticVersion serverVersion)
363+
{
364+
if (request is DeleteRequest &&
365+
(Feature.HintForDeleteOperations.DriverMustThrowIfNotSupported(serverVersion) ||
366+
(!_writeConcern.IsAcknowledged && !Feature.HintForDeleteOperations.IsSupported(serverVersion))))
367+
{
368+
return false;
369+
}
370+
371+
if (request is UpdateRequest &&
372+
(Feature.HintForUpdateAndReplaceOperations.DriverMustThrowIfNotSupported(serverVersion) ||
373+
(!_writeConcern.IsAcknowledged && !Feature.HintForUpdateAndReplaceOperations.IsSupported(serverVersion))))
374+
{
375+
return false;
376+
}
377+
378+
return true;
379+
}
380+
366381
private bool RequestHasCollation(WriteRequest request)
367382
{
368383
DeleteRequest deleteRequest;
@@ -382,7 +397,17 @@ private bool RequestHasCollation(WriteRequest request)
382397

383398
private bool RequestHasHint(WriteRequest request)
384399
{
385-
return request is UpdateRequest updateRequest && updateRequest.Hint != null;
400+
if (request is DeleteRequest deleteRequest)
401+
{
402+
return deleteRequest.Hint != null;
403+
}
404+
405+
if (request is UpdateRequest updateRequest)
406+
{
407+
return updateRequest.Hint != null;
408+
}
409+
410+
return false;
386411
}
387412

388413
// nested types

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

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,11 @@ private void EnsureCollationIsSupportedIfAnyRequestHasCollation(RetryableWriteCo
187187
private void EnsureHintIsSupportedIfAnyRequestHasHint(RetryableWriteContext context)
188188
{
189189
var serverVersion = context.Channel.ConnectionDescription.ServerVersion;
190-
if (Feature.HintForUpdateAndReplaceOperations.DriverMustThrowIfNotSupported(serverVersion) ||
191-
(!_writeConcern.IsAcknowledged && !Feature.HintForUpdateAndReplaceOperations.IsSupported(serverVersion)))
190+
foreach (var request in _requests)
192191
{
193-
foreach (var request in _requests)
192+
if (RequestHasHint(request) && !IsHintSupportedForRequestWithHint(request, serverVersion))
194193
{
195-
if (RequestHasHint(request))
196-
{
197-
throw new NotSupportedException($"Server version {serverVersion} does not support hints.");
198-
}
194+
throw new NotSupportedException($"Server version {serverVersion} does not support hints.");
199195
}
200196
}
201197
}
@@ -250,6 +246,25 @@ private async Task<BulkWriteOperationResult> ExecuteBatchesAsync(RetryableWriteC
250246
return helper.CreateFinalResultOrThrow(context.Channel);
251247
}
252248

249+
private bool IsHintSupportedForRequestWithHint(WriteRequest request, SemanticVersion serverVersion)
250+
{
251+
if (request is DeleteRequest &&
252+
(Feature.HintForDeleteOperations.DriverMustThrowIfNotSupported(serverVersion) ||
253+
(!_writeConcern.IsAcknowledged && !Feature.HintForDeleteOperations.IsSupported(serverVersion))))
254+
{
255+
return false;
256+
}
257+
258+
if (request is UpdateRequest &&
259+
(Feature.HintForUpdateAndReplaceOperations.DriverMustThrowIfNotSupported(serverVersion) ||
260+
(!_writeConcern.IsAcknowledged && !Feature.HintForUpdateAndReplaceOperations.IsSupported(serverVersion))))
261+
{
262+
return false;
263+
}
264+
265+
return true;
266+
}
267+
253268
// nested types
254269
private class BatchHelper
255270
{

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ private WriteConcernResult ExecuteProtocol(IChannelHandle channel, CancellationT
186186
{
187187
throw new NotSupportedException("OP_DELETE does not support collations.");
188188
}
189+
if (_request.Hint != null)
190+
{
191+
throw new NotSupportedException("OP_DELETE does not support hints.");
192+
}
189193

190194
return channel.Delete(
191195
_collectionNamespace,
@@ -202,6 +206,10 @@ private Task<WriteConcernResult> ExecuteProtocolAsync(IChannelHandle channel, Ca
202206
{
203207
throw new NotSupportedException("OP_DELETE does not support collations.");
204208
}
209+
if (_request.Hint != null)
210+
{
211+
throw new NotSupportedException("OP_DELETE does not support hints.");
212+
}
205213

206214
return channel.DeleteAsync(
207215
_collectionNamespace,

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public sealed class DeleteRequest : WriteRequest
2727
// fields
2828
private Collation _collation;
2929
private readonly BsonDocument _filter;
30+
private BsonValue _hint;
3031
private int _limit;
3132

3233
// constructors
@@ -59,6 +60,15 @@ public BsonDocument Filter
5960
get { return _filter; }
6061
}
6162

63+
/// <summary>
64+
/// Gets or sets the hint.
65+
/// </summary>
66+
public BsonValue Hint
67+
{
68+
get { return _hint; }
69+
set { _hint = value; }
70+
}
71+
6272
/// <summary>
6373
/// Gets or sets a limit on the number of documents that should be deleted.
6474
/// </summary>

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class FindOneAndDeleteOperation<TResult> : FindAndModifyOperationBase<TRe
3333
{
3434
// fields
3535
private readonly BsonDocument _filter;
36+
private BsonValue _hint;
3637
private TimeSpan? _maxTime;
3738
private BsonDocument _projection;
3839
private BsonDocument _sort;
@@ -63,6 +64,18 @@ public BsonDocument Filter
6364
get { return _filter; }
6465
}
6566

67+
/// <summary>
68+
/// Gets or sets the hint.
69+
/// </summary>
70+
/// <value>
71+
/// The hint.
72+
/// </value>
73+
public BsonValue Hint
74+
{
75+
get { return _hint; }
76+
set { _hint = value; }
77+
}
78+
6679
/// <summary>
6780
/// Gets or sets the maximum time the server should spend on this operation.
6881
/// </summary>
@@ -104,6 +117,14 @@ internal override BsonDocument CreateCommand(ICoreSessionHandle session, Connect
104117
{
105118
var serverVersion = connectionDescription.ServerVersion;
106119
Feature.Collation.ThrowIfNotSupported(serverVersion, Collation);
120+
if (Feature.HintForFindAndModifyFeature.DriverMustThrowIfNotSupported(serverVersion) ||
121+
(WriteConcern != null && !WriteConcern.IsAcknowledged && !Feature.HintForFindAndModifyFeature.IsSupported(serverVersion)))
122+
{
123+
if (_hint != null)
124+
{
125+
throw new NotSupportedException($"Server version {serverVersion} does not support hints.");
126+
}
127+
}
107128

108129
var writeConcern = WriteConcernHelper.GetWriteConcernForCommand(session, WriteConcern, serverVersion, Feature.FindAndModifyWriteConcern);
109130
return new BsonDocument
@@ -116,6 +137,7 @@ internal override BsonDocument CreateCommand(ICoreSessionHandle session, Connect
116137
{ "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue },
117138
{ "writeConcern", writeConcern, writeConcern != null },
118139
{ "collation", () => Collation.ToBsonDocument(), Collation != null },
140+
{ "hint", _hint, _hint != null },
119141
{ "txnNumber", () => transactionNumber, transactionNumber.HasValue }
120142
};
121143
}

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,20 @@ public BatchableSource<DeleteRequest> Deletes
8181
/// <inheritdoc />
8282
protected override BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription, int attempt, long? transactionNumber)
8383
{
84-
if (!Feature.Collation.IsSupported(connectionDescription.ServerVersion))
84+
var serverVersion = connectionDescription.ServerVersion;
85+
if (!Feature.Collation.IsSupported(serverVersion))
8586
{
8687
if (_deletes.Items.Skip(_deletes.Offset).Take(_deletes.Count).Any(d => d.Collation != null))
8788
{
88-
throw new NotSupportedException($"Server version {connectionDescription.ServerVersion} does not support collations.");
89+
throw new NotSupportedException($"Server version {serverVersion} does not support collations.");
90+
}
91+
}
92+
if (Feature.HintForDeleteOperations.DriverMustThrowIfNotSupported(serverVersion) ||
93+
(!WriteConcern.IsAcknowledged && !Feature.HintForDeleteOperations.IsSupported(serverVersion)))
94+
{
95+
if (_deletes.Items.Skip(_deletes.Offset).Take(_deletes.Count).Any(u => u.Hint != null))
96+
{
97+
throw new NotSupportedException($"Server version {serverVersion} does not support hints.");
8998
}
9099
}
91100

@@ -135,6 +144,11 @@ protected override void SerializeValue(BsonSerializationContext context, BsonSer
135144
writer.WriteName("collation");
136145
BsonDocumentSerializer.Instance.Serialize(context, value.Collation.ToBsonDocument());
137146
}
147+
if (value.Hint != null)
148+
{
149+
writer.WriteName("hint");
150+
BsonValueSerializer.Instance.Serialize(context, value.Hint);
151+
}
138152
writer.WriteEndDocument();
139153
}
140154
}

src/MongoDB.Driver/DeleteManyModel.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@
1414
*/
1515

1616
using System;
17-
using System.Collections.Generic;
18-
using System.Linq;
19-
using System.Text;
20-
using System.Threading.Tasks;
17+
using MongoDB.Bson;
2118
using MongoDB.Driver.Core.Misc;
22-
using MongoDB.Driver.Core.Operations;
2319

2420
namespace MongoDB.Driver
2521
{
@@ -35,6 +31,7 @@ public sealed class DeleteManyModel<TDocument> : WriteModel<TDocument>
3531
// fields
3632
private Collation _collation;
3733
private readonly FilterDefinition<TDocument> _filter;
34+
private BsonValue _hint;
3835

3936
// constructors
4037
/// <summary>
@@ -64,6 +61,15 @@ public FilterDefinition<TDocument> Filter
6461
get { return _filter; }
6562
}
6663

64+
/// <summary>
65+
/// Gets or sets the hint.
66+
/// </summary>
67+
public BsonValue Hint
68+
{
69+
get { return _hint; }
70+
set { _hint = value; }
71+
}
72+
6773
/// <summary>
6874
/// Gets the type of the model.
6975
/// </summary>

0 commit comments

Comments
 (0)