@@ -962,74 +962,56 @@ void staticValidateModifiedFields(std::string fieldName,
962
962
}
963
963
}
964
964
965
- std::vector<std::string> staticValidateUpdateObject (bson::BSONObj update, bool multi, bool upsert) {
966
- std::set<std::string> affectedFields;
967
- std::set<std::string> prefixesOfAffectedFields;
968
- for (auto i = update.begin (); i.more ();) {
969
-
970
- auto el = i.next ();
971
- std::string operatorName = el.fieldName ();
972
- if (!el.isABSONObj () || el.Obj ().nFields () == 0 ) {
973
- throw update_operator_empty_parameter ();
974
- }
975
-
976
- if (upsert && operatorName == DocLayerConstants::SET_ON_INSERT)
977
- operatorName = DocLayerConstants::SET;
978
-
979
- for (auto j = el.Obj ().begin (); j.more ();) {
980
- bson::BSONElement subel = j.next ();
981
- auto fn = std::string (subel.fieldName ());
982
- if (fn == DocLayerConstants::ID_FIELD) {
983
- if (operatorName != DocLayerConstants::SET && operatorName != DocLayerConstants::SET_ON_INSERT) {
984
- throw cant_modify_id ();
985
- }
986
- }
987
- staticValidateModifiedFields (fn, &affectedFields, &prefixesOfAffectedFields);
988
- if (operatorName == DocLayerConstants::RENAME) {
989
- if (!subel.isString ())
990
- throw bad_rename_target ();
991
- staticValidateModifiedFields (subel.String (), &affectedFields, &prefixesOfAffectedFields);
992
- }
993
- }
994
- }
995
-
996
- std::vector<std::string> bannedIndexFields;
997
- bannedIndexFields.insert (std::end (bannedIndexFields), std::begin (affectedFields), std::end (affectedFields));
998
- bannedIndexFields.insert (std::end (bannedIndexFields), std::begin (prefixesOfAffectedFields),
999
- std::end (prefixesOfAffectedFields));
1000
-
1001
- return bannedIndexFields;
1002
- }
1003
-
1004
965
bool shouldCreateRoot (std::string operatorName) {
1005
966
return operatorName == DocLayerConstants::SET || operatorName == DocLayerConstants::INC ||
1006
967
operatorName == DocLayerConstants::MUL || operatorName == DocLayerConstants::CURRENT_DATE ||
1007
968
operatorName == DocLayerConstants::MAX || operatorName == DocLayerConstants::MIN ||
1008
969
operatorName == DocLayerConstants::PUSH || operatorName == DocLayerConstants::ADD_TO_SET;
1009
970
}
1010
971
972
+ // #156: staticValidateUpdateObject function is moved to updateDocument constructor
973
+
974
+ /* staticValidateUpdateObject function part has more similar and related functionalities
975
+ * present in updateDocument constructor. Instead of using StaticValidateUpdate function
976
+ * part, that part is moved to updateDocument constructor. So there is no need to call staticValidateUpdate
977
+ * function separately, if operatorUpdate is enabled it will execute updateDocument which now has
978
+ * staticValidateUpdate functionalities also.
979
+ */
980
+
1011
981
ACTOR Future<Void> updateDocument (Reference<IReadWriteContext> cx,
982
+ Reference<UnboundCollectionContext> ucx,
1012
983
bson::BSONObj update,
1013
984
bool upsert,
1014
- Future<Standalone<StringRef>> fEncodedId ) {
985
+ bool multi = false ) {
986
+
987
+ state std::set<std::string> affectedFields;
988
+ state std::set<std::string> prefixesOfAffectedFields;
1015
989
state std::vector<Future<Void>> futures;
1016
- state Standalone<StringRef> encodedId = wait (fEncodedId );
990
+ state Standalone<StringRef> encodedId = wait (cx-> getKeyEncodedId () );
1017
991
for (auto i = update.begin (); i.more ();) {
1018
992
auto el = i.next ();
1019
993
1020
994
std::string operatorName = el.fieldName ();
995
+ if (!el.isABSONObj () || el.Obj ().nFields () == 0 ) {
996
+ throw update_operator_empty_parameter ();
997
+ }
998
+
1021
999
if (upsert && operatorName == DocLayerConstants::SET_ON_INSERT)
1022
1000
operatorName = DocLayerConstants::SET;
1023
1001
for (auto j = el.Obj ().begin (); j.more ();) {
1024
1002
bson::BSONElement subel = j.next ();
1025
1003
auto fn = std::string (subel.fieldName ());
1026
1004
if (fn == DocLayerConstants::ID_FIELD) {
1027
- if (operatorName == DocLayerConstants::SET || operatorName == DocLayerConstants::SET_ON_INSERT) {
1005
+ if (operatorName != DocLayerConstants::SET && operatorName != DocLayerConstants::SET_ON_INSERT) {
1006
+ throw cant_modify_id ();
1007
+ } else if (operatorName == DocLayerConstants::SET || operatorName == DocLayerConstants::SET_ON_INSERT) {
1028
1008
if (extractEncodedIds (subel.wrap ()).get ().keyEncoded != encodedId) {
1029
1009
throw cant_modify_id ();
1030
1010
}
1031
1011
}
1032
1012
}
1013
+
1014
+ staticValidateModifiedFields (fn, &affectedFields, &prefixesOfAffectedFields);
1033
1015
if (shouldCreateRoot (operatorName)) {
1034
1016
auto upOneFn = upOneLevel (fn);
1035
1017
if (!upOneFn.empty ())
@@ -1042,7 +1024,10 @@ ACTOR Future<Void> updateDocument(Reference<IReadWriteContext> cx,
1042
1024
futures.push_back (ensureValidObject (cx, upOneFn, getLastPart (fn), false ));
1043
1025
}
1044
1026
if (operatorName == DocLayerConstants::RENAME) {
1027
+ if (!subel.isString ())
1028
+ throw bad_rename_target ();
1045
1029
auto renameTarget = subel.String ();
1030
+ staticValidateModifiedFields (renameTarget, &affectedFields, &prefixesOfAffectedFields);
1046
1031
auto upOneRenameTarget = upOneLevel (renameTarget);
1047
1032
if (!upOneRenameTarget.empty ())
1048
1033
futures.push_back (ensureValidObject (cx, renameTarget, upOneRenameTarget, false ));
@@ -1054,6 +1039,11 @@ ACTOR Future<Void> updateDocument(Reference<IReadWriteContext> cx,
1054
1039
futures.push_back (ExtUpdateOperator::execute (operatorName, cx, encodeMaybeDotted (fn), subel));
1055
1040
}
1056
1041
}
1042
+ std::vector<std::string> bannedIndexFields;
1043
+ bannedIndexFields.insert (std::end (bannedIndexFields), std::begin (affectedFields), std::end (affectedFields));
1044
+ bannedIndexFields.insert (std::end (bannedIndexFields), std::begin (prefixesOfAffectedFields),
1045
+ std::end (prefixesOfAffectedFields));
1046
+ ucx->setBannedFieldNames (bannedIndexFields);
1057
1047
wait (waitForAll (futures));
1058
1048
return Void ();
1059
1049
}
@@ -1068,32 +1058,27 @@ ACTOR Future<WriteCmdResult> doUpdateCmd(Namespace ns,
1068
1058
try {
1069
1059
state ExtUpdateCmd* cmd = &((*cmds)[idx]);
1070
1060
state int isoperatorUpdate = hasOperatorFieldnames (cmd->update , 0 );
1071
- state std::vector<std::string> bannedIndexFields;
1072
1061
1073
1062
if (!isoperatorUpdate && cmd->multi ) {
1074
1063
throw literal_multi_update ();
1075
1064
}
1076
-
1077
- if (isoperatorUpdate) {
1078
- bannedIndexFields = staticValidateUpdateObject (cmd->update , cmd->multi , cmd->upsert );
1079
- }
1065
+ // #156: staticValidateUpdateObject function is moved to updateDocument constructor
1080
1066
1081
1067
state Optional<bson::BSONObj> upserted = Optional<bson::BSONObj>();
1082
1068
state Reference<DocTransaction> dtr = ec->getOperationTransaction ();
1083
1069
Reference<UnboundCollectionContext> ocx = wait (ec->mm ->getUnboundCollectionContext (dtr, ns));
1084
1070
state Reference<UnboundCollectionContext> cx =
1085
1071
Reference<UnboundCollectionContext>(new UnboundCollectionContext (*ocx));
1086
- cx->setBannedFieldNames (bannedIndexFields);
1087
1072
1088
1073
Reference<IUpdateOp> updater;
1089
1074
Reference<IInsertOp> upserter;
1090
1075
if (isoperatorUpdate)
1091
- updater = operatorUpdate (cmd->update );
1076
+ updater = operatorUpdate (cx, cmd->update , cmd-> multi , cmd-> upsert );
1092
1077
else
1093
1078
updater = replaceUpdate (cmd->update );
1094
1079
if (cmd->upsert ) {
1095
1080
if (isoperatorUpdate)
1096
- upserter = operatorUpsert (cmd->selector , cmd->update );
1081
+ upserter = operatorUpsert (cx, cmd->selector , cmd->update );
1097
1082
else
1098
1083
upserter = simpleUpsert (cmd->selector , cmd->update );
1099
1084
}
@@ -1341,12 +1326,18 @@ Future<Void> ExtMsgKillCursors::run(Reference<ExtConnection> ec) {
1341
1326
/* FIXME: These don't really belong here*/
1342
1327
1343
1328
struct ExtOperatorUpdate : ConcreteUpdateOp<ExtOperatorUpdate> {
1329
+ Reference<UnboundCollectionContext> cx;
1344
1330
bson::BSONObj msgUpdate;
1345
-
1346
- explicit ExtOperatorUpdate (bson::BSONObj const & msgUpdate) : msgUpdate(msgUpdate) {}
1331
+ bool upsert;
1332
+ bool multi;
1333
+ explicit ExtOperatorUpdate (Reference<UnboundCollectionContext> cx,
1334
+ bson::BSONObj const & msgUpdate,
1335
+ bool multi,
1336
+ bool upsert)
1337
+ : msgUpdate(msgUpdate), multi(multi), upsert(upsert), cx(cx) {}
1347
1338
1348
1339
Future<Void> update (Reference<IReadWriteContext> document) override {
1349
- return updateDocument (document, msgUpdate, false , document-> getKeyEncodedId () );
1340
+ return updateDocument (document, cx, msgUpdate, upsert, multi );
1350
1341
}
1351
1342
1352
1343
std::string describe () override { return " OperatorUpdate(" + msgUpdate.toString () + " )" ; }
@@ -1393,10 +1384,12 @@ struct ExtReplaceUpdate : ConcreteUpdateOp<ExtReplaceUpdate> {
1393
1384
};
1394
1385
1395
1386
struct ExtOperatorUpsert : ConcreteInsertOp<ExtOperatorUpsert> {
1387
+ Reference<UnboundCollectionContext> ucx;
1396
1388
bson::BSONObj selector;
1397
1389
bson::BSONObj update;
1398
1390
1399
- ExtOperatorUpsert (bson::BSONObj selector, bson::BSONObj update) : selector(selector), update(update) {}
1391
+ ExtOperatorUpsert (Reference<UnboundCollectionContext> ucx, bson::BSONObj selector, bson::BSONObj update)
1392
+ : selector(selector), update(update), ucx(ucx) {}
1400
1393
1401
1394
ACTOR static Future<Reference<IReadWriteContext>> upsertActor (ExtOperatorUpsert* self,
1402
1395
Reference<CollectionContext> cx) {
@@ -1411,7 +1404,7 @@ struct ExtOperatorUpsert : ConcreteInsertOp<ExtOperatorUpsert> {
1411
1404
thingToInsert = transformOperatorQueryToUpdatableDocument (self->selector );
1412
1405
}
1413
1406
state Reference<IReadWriteContext> dcx = wait (insertDocument (cx, thingToInsert, encodedIds));
1414
- wait (updateDocument (dcx, self->update , true , dcx-> getKeyEncodedId () ));
1407
+ wait (updateDocument (dcx, self->ucx , self-> update , true ));
1415
1408
return dcx;
1416
1409
}
1417
1410
@@ -1442,15 +1435,20 @@ struct ExtSimpleUpsert : ConcreteInsertOp<ExtSimpleUpsert> {
1442
1435
}
1443
1436
};
1444
1437
1445
- Reference<IUpdateOp> operatorUpdate (bson::BSONObj const & msgUpdate) {
1446
- return ref (new ExtOperatorUpdate (msgUpdate));
1438
+ Reference<IUpdateOp> operatorUpdate (Reference<UnboundCollectionContext> cx,
1439
+ bson::BSONObj const & msgUpdate,
1440
+ bool multi,
1441
+ bool upsert) {
1442
+ return ref (new ExtOperatorUpdate (cx, msgUpdate, multi, upsert));
1447
1443
}
1448
1444
Reference<IUpdateOp> replaceUpdate (bson::BSONObj const & replaceWith) {
1449
1445
return ref (new ExtReplaceUpdate (replaceWith));
1450
1446
}
1451
1447
Reference<IInsertOp> simpleUpsert (bson::BSONObj const & selector, bson::BSONObj const & update) {
1452
1448
return ref (new ExtSimpleUpsert (selector, update));
1453
1449
}
1454
- Reference<IInsertOp> operatorUpsert (bson::BSONObj const & selector, bson::BSONObj const & update) {
1455
- return ref (new ExtOperatorUpsert (selector, update));
1450
+ Reference<IInsertOp> operatorUpsert (Reference<UnboundCollectionContext> cx,
1451
+ bson::BSONObj const & selector,
1452
+ bson::BSONObj const & update) {
1453
+ return ref (new ExtOperatorUpsert (cx, selector, update));
1456
1454
}
0 commit comments