Skip to content

Commit b2de715

Browse files
committed
JAVA-1985: Throw exception if bypassDocumentValidation is specified, server version is at least 3.2, and the write concern is unacknowledged.
1 parent 9e3221a commit b2de715

File tree

5 files changed

+94
-1
lines changed

5 files changed

+94
-1
lines changed

driver-core/src/main/com/mongodb/operation/BaseWriteOperation.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.mongodb.DuplicateKeyException;
2020
import com.mongodb.ErrorCategory;
2121
import com.mongodb.MongoBulkWriteException;
22+
import com.mongodb.MongoClientException;
2223
import com.mongodb.MongoException;
2324
import com.mongodb.MongoNamespace;
2425
import com.mongodb.WriteConcern;
@@ -32,6 +33,7 @@
3233
import com.mongodb.bulk.WriteRequest;
3334
import com.mongodb.connection.AsyncConnection;
3435
import com.mongodb.connection.Connection;
36+
import com.mongodb.connection.ConnectionDescription;
3537
import org.bson.BsonBoolean;
3638
import org.bson.BsonDocument;
3739
import org.bson.BsonInt32;
@@ -46,6 +48,7 @@
4648
import static com.mongodb.operation.OperationHelper.AsyncCallableWithConnection;
4749
import static com.mongodb.operation.OperationHelper.CallableWithConnection;
4850
import static com.mongodb.operation.OperationHelper.releasingCallback;
51+
import static com.mongodb.operation.OperationHelper.serverIsAtLeastVersionThreeDotTwo;
4952
import static com.mongodb.operation.OperationHelper.serverIsAtLeastVersionTwoDotSix;
5053
import static com.mongodb.operation.OperationHelper.withConnection;
5154

@@ -132,6 +135,9 @@ public WriteConcernResult execute(final WriteBinding binding) {
132135
@Override
133136
public WriteConcernResult call(final Connection connection) {
134137
try {
138+
if (bypassDocumentValidationNotSupported(connection.getDescription())) {
139+
throw getBypassDocumentValidationException();
140+
}
135141
if (writeConcern.isAcknowledged() && serverIsAtLeastVersionTwoDotSix(connection.getDescription())) {
136142
return translateBulkWriteResult(executeCommandProtocol(connection));
137143
} else {
@@ -151,6 +157,8 @@ public void executeAsync(final AsyncWriteBinding binding, final SingleResultCall
151157
public void call(final AsyncConnection connection, final Throwable t) {
152158
if (t != null) {
153159
errorHandlingCallback(callback).onResult(null, t);
160+
} else if (bypassDocumentValidationNotSupported(connection.getDescription())) {
161+
releasingCallback(errorHandlingCallback(callback), connection).onResult(null, getBypassDocumentValidationException());
154162
} else {
155163
final SingleResultCallback<WriteConcernResult> wrappedCallback = releasingCallback(errorHandlingCallback(callback),
156164
connection);
@@ -212,6 +220,15 @@ public void onResult(final WriteConcernResult result, final Throwable t) {
212220
*/
213221
protected abstract void executeCommandProtocolAsync(AsyncConnection connection, SingleResultCallback<BulkWriteResult> callback);
214222

223+
private boolean bypassDocumentValidationNotSupported(final ConnectionDescription description) {
224+
return bypassDocumentValidation != null && serverIsAtLeastVersionThreeDotTwo(description) && !writeConcern.isAcknowledged();
225+
}
226+
227+
private MongoClientException getBypassDocumentValidationException() {
228+
return new MongoClientException("Specifying bypassDocumentValidation with an unacknowledged WriteConcern "
229+
+ "is not supported");
230+
}
231+
215232
private MongoException translateException(final Throwable t) {
216233
MongoException checkedError = MongoException.fromThrowable(t);
217234
if (t instanceof MongoBulkWriteException) {

driver-core/src/main/com/mongodb/operation/MixedBulkWriteOperation.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.mongodb.operation;
1818

1919
import com.mongodb.MongoBulkWriteException;
20+
import com.mongodb.MongoClientException;
2021
import com.mongodb.MongoNamespace;
2122
import com.mongodb.WriteConcern;
2223
import com.mongodb.WriteConcernException;
@@ -58,6 +59,7 @@
5859
import static com.mongodb.operation.OperationHelper.AsyncCallableWithConnection;
5960
import static com.mongodb.operation.OperationHelper.CallableWithConnection;
6061
import static com.mongodb.operation.OperationHelper.releasingCallback;
62+
import static com.mongodb.operation.OperationHelper.serverIsAtLeastVersionThreeDotTwo;
6163
import static com.mongodb.operation.OperationHelper.withConnection;
6264
import static java.lang.String.format;
6365
import static java.util.Arrays.asList;
@@ -166,6 +168,10 @@ public BulkWriteResult execute(final WriteBinding binding) {
166168
return withConnection(binding, new CallableWithConnection<BulkWriteResult>() {
167169
@Override
168170
public BulkWriteResult call(final Connection connection) {
171+
if (bypassDocumentValidationNotSupported(connection.getDescription())) {
172+
throw getBypassDocumentValidationException();
173+
}
174+
169175
BulkWriteBatchCombiner bulkWriteBatchCombiner = new BulkWriteBatchCombiner(connection.getDescription().getServerAddress(),
170176
ordered, writeConcern);
171177
for (Run run : getRunGenerator(connection.getDescription())) {
@@ -194,6 +200,8 @@ public void executeAsync(final AsyncWriteBinding binding, final SingleResultCall
194200
public void call(final AsyncConnection connection, final Throwable t) {
195201
if (t != null) {
196202
wrappedCallback.onResult(null, t);
203+
} else if (bypassDocumentValidationNotSupported(connection.getDescription())) {
204+
releasingCallback(wrappedCallback, connection).onResult(null, getBypassDocumentValidationException());
197205
} else {
198206
Iterator<Run> runs = getRunGenerator(connection.getDescription()).iterator();
199207
executeRunsAsync(runs, connection, new BulkWriteBatchCombiner(connection.getDescription().getServerAddress(), ordered,
@@ -203,6 +211,15 @@ public void call(final AsyncConnection connection, final Throwable t) {
203211
});
204212
}
205213

214+
private boolean bypassDocumentValidationNotSupported(final ConnectionDescription description) {
215+
return bypassDocumentValidation != null && serverIsAtLeastVersionThreeDotTwo(description) && !writeConcern.isAcknowledged();
216+
}
217+
218+
private MongoClientException getBypassDocumentValidationException() {
219+
return new MongoClientException("Specifying bypassDocumentValidation with an unacknowledged WriteConcern "
220+
+ "is not supported");
221+
}
222+
206223
private void executeRunsAsync(final Iterator<Run> runs, final AsyncConnection connection,
207224
final BulkWriteBatchCombiner bulkWriteBatchCombiner,
208225
final SingleResultCallback<BulkWriteResult> callback) {

driver-core/src/test/functional/com/mongodb/operation/InsertOperationSpecification.groovy

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.mongodb.operation
1919
import category.Async
2020
import category.Slow
2121
import com.mongodb.DuplicateKeyException
22+
import com.mongodb.MongoClientException
2223
import com.mongodb.MongoException
2324
import com.mongodb.OperationFunctionalSpecification
2425
import com.mongodb.bulk.InsertRequest
@@ -28,11 +29,13 @@ import org.bson.BsonInt32
2829
import org.bson.BsonSerializationException
2930
import org.bson.codecs.BsonDocumentCodec
3031
import org.junit.experimental.categories.Category
32+
import spock.lang.IgnoreIf
3133

3234
import static com.mongodb.ClusterFixture.executeAsync
3335
import static com.mongodb.ClusterFixture.getAsyncSingleConnectionBinding
3436
import static com.mongodb.ClusterFixture.getBinding
3537
import static com.mongodb.ClusterFixture.getSingleConnectionBinding
38+
import static com.mongodb.ClusterFixture.serverVersionAtLeast
3639
import static com.mongodb.WriteConcern.ACKNOWLEDGED
3740
import static com.mongodb.WriteConcern.UNACKNOWLEDGED
3841
import static java.util.Arrays.asList
@@ -299,4 +302,26 @@ class InsertOperationSpecification extends OperationFunctionalSpecification {
299302
then:
300303
getCollectionHelper().find().get(0).keySet() as List == ['_id', 'x']
301304
}
305+
306+
@IgnoreIf({ !serverVersionAtLeast(asList(3, 2, 0)) })
307+
def 'should throw if bypassDocumentValidation is set and write is unacknowledged'() {
308+
given:
309+
def op = new InsertOperation(getNamespace(), true, UNACKNOWLEDGED, [new InsertRequest(new BsonDocument())])
310+
.bypassDocumentValidation(bypassDocumentValidation)
311+
312+
when:
313+
op.execute(getBinding())
314+
315+
then:
316+
thrown(MongoClientException)
317+
318+
when:
319+
executeAsync(op)
320+
321+
then:
322+
thrown(MongoClientException)
323+
324+
where:
325+
bypassDocumentValidation << [true, false]
326+
}
302327
}

driver-core/src/test/functional/com/mongodb/operation/MixedBulkWriteOperationAsyncSpecification.groovy

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import category.Async
2020
import category.Slow
2121
import com.mongodb.ClusterFixture
2222
import com.mongodb.MongoBulkWriteException
23+
import com.mongodb.MongoClientException
2324
import com.mongodb.MongoException
2425
import com.mongodb.MongoNamespace
2526
import com.mongodb.OperationFunctionalSpecification
@@ -709,6 +710,22 @@ class MixedBulkWriteOperationAsyncSpecification extends OperationFunctionalSpeci
709710
ordered << [true, false]
710711
}
711712

713+
@IgnoreIf({ !serverVersionAtLeast(asList(3, 2, 0)) })
714+
def 'should throw if bypassDocumentValidation is set and write is unacknowledged'() {
715+
given:
716+
def op = new MixedBulkWriteOperation(getNamespace(), [new InsertRequest(BsonDocument.parse('{ level: 9 }'))], true, UNACKNOWLEDGED)
717+
.bypassDocumentValidation(bypassDocumentValidation)
718+
719+
when:
720+
executeAsync(op)
721+
722+
then:
723+
thrown(MongoClientException)
724+
725+
where:
726+
bypassDocumentValidation << [true, false]
727+
}
728+
712729
private static List<WriteRequest> getTestWrites() {
713730
[new UpdateRequest(new BsonDocument('_id', new BsonInt32(1)),
714731
new BsonDocument('$set', new BsonDocument('x', new BsonInt32(2))),

driver-core/src/test/functional/com/mongodb/operation/MixedBulkWriteOperationSpecification.groovy

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.mongodb.operation
1919
import category.Slow
2020
import com.mongodb.ClusterFixture
2121
import com.mongodb.MongoBulkWriteException
22+
import com.mongodb.MongoClientException
2223
import com.mongodb.MongoNamespace
2324
import com.mongodb.OperationFunctionalSpecification
2425
import com.mongodb.ReadPreference
@@ -709,7 +710,23 @@ class MixedBulkWriteOperationSpecification extends OperationFunctionalSpecificat
709710
ordered << [true, false]
710711
}
711712

712-
@IgnoreIf({ !serverVersionAtLeast(asList(3, 1, 8)) })
713+
@IgnoreIf({ !serverVersionAtLeast(asList(3, 2, 0)) })
714+
def 'should throw if bypassDocumentValidation is set and write is unacknowledged'() {
715+
given:
716+
def op = new MixedBulkWriteOperation(getNamespace(), [new InsertRequest(BsonDocument.parse('{ level: 9 }'))], true, UNACKNOWLEDGED)
717+
.bypassDocumentValidation(bypassDocumentValidation)
718+
719+
when:
720+
op.execute(getBinding())
721+
722+
then:
723+
thrown(MongoClientException)
724+
725+
where:
726+
bypassDocumentValidation << [true, false]
727+
}
728+
729+
@IgnoreIf({ !serverVersionAtLeast(asList(3, 2, 0)) })
713730
def 'should honour the bypass validation flag for inserts'() {
714731
given:
715732
def namespace = new MongoNamespace(getDatabaseName(), 'collection')

0 commit comments

Comments
 (0)