Skip to content

Commit db0b8fa

Browse files
committed
CXX-689: Support bypassDocumentValidation
1 parent 342b0bb commit db0b8fa

13 files changed

+227
-85
lines changed

src/mongo/client/bulk_operation_builder.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,14 @@ inline bool compare(WriteOperation* const lhs, WriteOperation* const rhs) {
3434

3535
BulkOperationBuilder::BulkOperationBuilder(DBClientBase* const client,
3636
const std::string& ns,
37-
bool ordered)
38-
: _client(client), _ns(ns), _ordered(ordered), _executed(false), _currentIndex(0) {}
37+
bool ordered,
38+
bool bypassDocumentValidation)
39+
: _client(client),
40+
_ns(ns),
41+
_ordered(ordered),
42+
_bypassDocumentValidation(bypassDocumentValidation),
43+
_executed(false),
44+
_currentIndex(0) {}
3945

4046
BulkOperationBuilder::~BulkOperationBuilder() {
4147
std::vector<WriteOperation*>::iterator it;
@@ -67,7 +73,8 @@ void BulkOperationBuilder::execute(const WriteConcern* writeConcern, WriteResult
6773
// order to understand what happened to them.
6874
writeResult->_requiresDetailedInsertResults = true;
6975

70-
_client->_write(_ns, _write_operations, _ordered, writeConcern, writeResult);
76+
_client->_write(
77+
_ns, _write_operations, _ordered, _bypassDocumentValidation, writeConcern, writeResult);
7178
}
7279

7380
void BulkOperationBuilder::enqueue(WriteOperation* operation) {

src/mongo/client/bulk_operation_builder.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,12 @@ class MONGO_CLIENT_API BulkOperationBuilder {
6868
* @param client The connection to use.
6969
* @param ns The namespace to apply the operations to.
7070
* @param ordered Whether or not ordering matters for these operations.
71+
* param bypassDocumentValidation Whether to bypass document validation for these operations,
7172
*/
72-
BulkOperationBuilder(DBClientBase* const client, const std::string& ns, bool ordered);
73+
BulkOperationBuilder(DBClientBase* const client,
74+
const std::string& ns,
75+
bool ordered,
76+
bool bypassDocumentValidation = false);
7377

7478
/* Deletes all of the WriteOperations that were created during the Builder's lifetime */
7579
~BulkOperationBuilder();
@@ -105,6 +109,7 @@ class MONGO_CLIENT_API BulkOperationBuilder {
105109
DBClientBase* const _client;
106110
const std::string _ns;
107111
const bool _ordered;
112+
const bool _bypassDocumentValidation;
108113
bool _executed;
109114
size_t _currentIndex;
110115
std::vector<WriteOperation*> _write_operations;

src/mongo/client/command_writer.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ namespace mongo {
2525

2626
const int kOverhead = 8 * 1024;
2727
const char kOrderedKey[] = "ordered";
28+
const char kBypassDocumentValidationKey[] = "bypassDocumentValidation";
2829

2930
CommandWriter::CommandWriter(DBClientBase* client) : _client(client) {}
3031

3132
void CommandWriter::write(const StringData& ns,
3233
const std::vector<WriteOperation*>& write_operations,
3334
bool ordered,
35+
bool bypassDocumentValidation,
3436
const WriteConcern* writeConcern,
3537
WriteResult* writeResult) {
3638
// Effectively a map of batch relative indexes to WriteOperations
@@ -87,7 +89,7 @@ void CommandWriter::write(const StringData& ns,
8789
}
8890

8991
// End the command for this batch.
90-
_endCommand(batch.get(), *batch_iter, ordered, command.get());
92+
_endCommand(batch.get(), *batch_iter, ordered, bypassDocumentValidation, command.get());
9193

9294
// Issue the complete command.
9395
BSONObj batchResult = _send(command.get(), writeConcern, ns);
@@ -119,9 +121,18 @@ bool CommandWriter::_fits(BSONArrayBuilder* builder, WriteOperation* operation)
119121
void CommandWriter::_endCommand(BSONArrayBuilder* batch,
120122
WriteOperation* operation,
121123
bool ordered,
124+
bool bypassDocumentValidation,
122125
BSONObjBuilder* command) {
123126
command->append(operation->batchName(), batch->arr());
124127
command->append(kOrderedKey, ordered);
128+
129+
if (bypassDocumentValidation) {
130+
uassert(0,
131+
"bypassDocumentValidation is not supported for write operations with this server "
132+
"version.",
133+
_client->getMaxWireVersion() >= 4);
134+
command->append(kBypassDocumentValidationKey, true);
135+
}
125136
}
126137

127138
BSONObj CommandWriter::_send(BSONObjBuilder* command,

src/mongo/client/command_writer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ class CommandWriter : public DBClientWriter {
2828
virtual void write(const StringData& ns,
2929
const std::vector<WriteOperation*>& write_operations,
3030
bool ordered,
31+
bool bypassDocumentValidation,
3132
const WriteConcern* writeConcern,
3233
WriteResult* writeResult);
3334

3435
private:
3536
void _endCommand(BSONArrayBuilder* batch,
3637
WriteOperation* op,
3738
bool ordered,
39+
bool bypassDocumentValidation,
3840
BSONObjBuilder* command);
3941

4042
BSONObj _send(BSONObjBuilder* command, const WriteConcern* writeConcern, const StringData& ns);

src/mongo/client/dbclient.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ using std::vector;
7373
AtomicInt64 DBClientBase::ConnectionIdSequence;
7474

7575
const char* const saslCommandUserSourceFieldName = "userSource";
76+
const char kBypassDocumentValidationKey[] = "bypassDocumentValidation";
7677

7778
const int defaultMaxBsonObjectSize = 16 * 1024 * 1024;
7879
const int defaultMaxMessageSizeBytes = defaultMaxBsonObjectSize * 2;
@@ -1344,6 +1345,7 @@ void DBClientBase::_findAndModify(const StringData& ns,
13441345
bool upsert,
13451346
const BSONObj& fields,
13461347
const WriteConcern* writeConcern,
1348+
bool bypassDocumentValidation,
13471349
BSONObjBuilder* out) {
13481350
BSONObjBuilder commandBuilder;
13491351

@@ -1377,6 +1379,14 @@ void DBClientBase::_findAndModify(const StringData& ns,
13771379
writeConcern == NULL);
13781380
}
13791381

1382+
if (bypassDocumentValidation) {
1383+
uassert(
1384+
0,
1385+
"bypassDocumentValidation is not supported for findAndModify with this server version.",
1386+
getMaxWireVersion() >= 4);
1387+
commandBuilder.append(kBypassDocumentValidationKey, true);
1388+
}
1389+
13801390
BSONObj result;
13811391
bool ok = runCommand(nsGetDB(ns.toString()), commandBuilder.obj(), result);
13821392

@@ -1393,9 +1403,11 @@ BSONObj DBClientBase::findAndModify(const StringData& ns,
13931403
bool returnNew,
13941404
const BSONObj& sort,
13951405
const BSONObj& fields,
1396-
const WriteConcern* wc) {
1406+
const WriteConcern* wc,
1407+
bool bypassDocumentValidation) {
13971408
BSONObjBuilder result;
1398-
_findAndModify(ns, query, update, sort, returnNew, upsert, fields, wc, &result);
1409+
_findAndModify(
1410+
ns, query, update, sort, returnNew, upsert, fields, wc, bypassDocumentValidation, &result);
13991411
return result.obj();
14001412
}
14011413

@@ -1405,7 +1417,7 @@ BSONObj DBClientBase::findAndRemove(const StringData& ns,
14051417
const BSONObj& fields,
14061418
const WriteConcern* wc) {
14071419
BSONObjBuilder result;
1408-
_findAndModify(ns, query, BSONObj(), sort, false, false, fields, wc, &result);
1420+
_findAndModify(ns, query, BSONObj(), sort, false, false, fields, wc, false, &result);
14091421
return result.obj();
14101422
}
14111423

@@ -2023,14 +2035,18 @@ unsigned long long DBClientConnection::query(stdx::function<void(DBClientCursorB
20232035
void DBClientBase::_write(const string& ns,
20242036
const vector<WriteOperation*>& writes,
20252037
bool ordered,
2038+
bool bypassDocumentValidation,
20262039
const WriteConcern* writeConcern,
20272040
WriteResult* writeResult) {
20282041
const WriteConcern* operationWriteConcern = writeConcern ? writeConcern : &getWriteConcern();
20292042

2030-
if (getMaxWireVersion() >= 2 && operationWriteConcern->requiresConfirmation())
2031-
_commandWriter->write(ns, writes, ordered, operationWriteConcern, writeResult);
2043+
if (getMaxWireVersion() >= 2 &&
2044+
(operationWriteConcern->requiresConfirmation() || bypassDocumentValidation))
2045+
_commandWriter->write(
2046+
ns, writes, ordered, bypassDocumentValidation, operationWriteConcern, writeResult);
20322047
else
2033-
_wireProtocolWriter->write(ns, writes, ordered, operationWriteConcern, writeResult);
2048+
_wireProtocolWriter->write(
2049+
ns, writes, ordered, bypassDocumentValidation, operationWriteConcern, writeResult);
20342050
}
20352051

20362052
namespace {
@@ -2070,9 +2086,10 @@ void DBClientBase::insert(const string& ns,
20702086
}
20712087

20722088
bool ordered = !(flags & InsertOption_ContinueOnError);
2089+
bool bypassDocumentValidation = flags & InsertOption_BypassDocumentValidation;
20732090

20742091
WriteResult writeResult;
2075-
_write(ns, inserts.ops, ordered, wc, &writeResult);
2092+
_write(ns, inserts.ops, ordered, bypassDocumentValidation, wc, &writeResult);
20762093
}
20772094

20782095
void DBClientBase::remove(const string& ns, Query obj, bool justOne, const WriteConcern* wc) {
@@ -2087,7 +2104,7 @@ void DBClientBase::remove(const string& ns, Query obj, int flags, const WriteCon
20872104
deletes.enqueue(new DeleteWriteOperation(obj.obj, flags));
20882105

20892106
WriteResult writeResult;
2090-
_write(ns, deletes.ops, true, wc, &writeResult);
2107+
_write(ns, deletes.ops, true, false, wc, &writeResult);
20912108
}
20922109

20932110
void DBClientBase::update(
@@ -2110,16 +2127,18 @@ void DBClientBase::update(
21102127
0, "update document exceeds maxBsonObjectSize", obj.objsize() <= getMaxBsonObjectSize());
21112128
updates.enqueue(new UpdateWriteOperation(query.obj, obj, flags));
21122129

2130+
bool bypassDocumentValidation = flags & UpdateOption_BypassDocumentValidation;
2131+
21132132
WriteResult writeResult;
2114-
_write(ns, updates.ops, true, wc, &writeResult);
2133+
_write(ns, updates.ops, true, bypassDocumentValidation, wc, &writeResult);
21152134
}
21162135

21172136
BulkOperationBuilder DBClientBase::initializeOrderedBulkOp(const std::string& ns) {
2118-
return BulkOperationBuilder(this, ns, true);
2137+
return BulkOperationBuilder(this, ns, true, false);
21192138
}
21202139

21212140
BulkOperationBuilder DBClientBase::initializeUnorderedBulkOp(const std::string& ns) {
2122-
return BulkOperationBuilder(this, ns, false);
2141+
return BulkOperationBuilder(this, ns, false, false);
21232142
}
21242143

21252144
list<BSONObj> DBClientWithCommands::getIndexSpecs(const string& ns, int options) {

src/mongo/client/dbclient_writer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class DBClientWriter {
3333
virtual void write(const StringData& ns,
3434
const std::vector<WriteOperation*>& write_operations,
3535
bool ordered,
36+
bool bypassDocumentValidation,
3637
const WriteConcern* writeConcern,
3738
WriteResult* writeResult) = 0;
3839
};

src/mongo/client/dbclientinterface.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,7 @@ class MONGO_CLIENT_API DBClientBase : public DBClientWithCommands, public DBConn
14341434
void _write(const std::string& ns,
14351435
const std::vector<WriteOperation*>& writes,
14361436
bool ordered,
1437+
bool bypassDocumentValidation,
14371438
const WriteConcern* writeConcern,
14381439
WriteResult* writeResult);
14391440

@@ -1612,7 +1613,8 @@ class MONGO_CLIENT_API DBClientBase : public DBClientWithCommands, public DBConn
16121613
bool returnNew = false,
16131614
const BSONObj& sort = BSONObj(),
16141615
const BSONObj& fields = BSONObj(),
1615-
const WriteConcern* wc = NULL);
1616+
const WriteConcern* wc = NULL,
1617+
bool bypassDocumentValidation = false);
16161618

16171619
/**
16181620
* Removes and returns a single document.
@@ -1695,6 +1697,7 @@ class MONGO_CLIENT_API DBClientBase : public DBClientWithCommands, public DBConn
16951697
bool upsert,
16961698
const BSONObj& fields,
16971699
const WriteConcern* wc,
1700+
bool bypassDocumentValidation,
16981701
BSONObjBuilder* out);
16991702

17001703
}; // DBClientBase

src/mongo/client/wire_protocol_writer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ WireProtocolWriter::WireProtocolWriter(DBClientBase* client) : _client(client) {
2828
void WireProtocolWriter::write(const StringData& ns,
2929
const std::vector<WriteOperation*>& write_operations,
3030
bool ordered,
31+
bool bypassDocumentValidation,
3132
const WriteConcern* writeConcern,
3233
WriteResult* writeResult) {
34+
invariant(bypassDocumentValidation == false);
35+
3336
// Effectively a map of batch relative indexes to WriteOperations
3437
std::vector<WriteOperation*> batchOps;
3538

src/mongo/client/wire_protocol_writer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class WireProtocolWriter : public DBClientWriter {
2828
virtual void write(const StringData& ns,
2929
const std::vector<WriteOperation*>& write_operations,
3030
bool ordered,
31+
bool bypassDocumentValidation,
3132
const WriteConcern* writeConcern,
3233
WriteResult* writeResult);
3334

src/mongo/client/write_options.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ enum UpdateOptions {
2626
UpdateOption_Multi = 1 << 1,
2727

2828
/** flag from mongo saying this update went everywhere */
29-
UpdateOption_Broadcast = 1 << 2
29+
UpdateOption_Broadcast = 1 << 2,
30+
31+
// TODO: upsert, and multi are per item in a batch, this is for the whole batch
32+
/** Disables document validation for this operation. */
33+
UpdateOption_BypassDocumentValidation = 1 << 3
3034
};
3135

3236
enum RemoveOptions {
@@ -42,7 +46,11 @@ enum RemoveOptions {
4246
*/
4347
enum InsertOptions {
4448
/** With muli-insert keep processing inserts if one fails */
45-
InsertOption_ContinueOnError = 1 << 0
49+
InsertOption_ContinueOnError = 1 << 0,
50+
51+
/** Disables document validation for this operation. */
52+
InsertOption_BypassDocumentValidation = 1 << 1
53+
4654
};
4755

4856
} // namespace mongo

0 commit comments

Comments
 (0)