Status UpdateDriver::parse(const BSONObj& updateExpr) { clear(); // Check if the update expression is a full object replacement. if (*updateExpr.firstElementFieldName() != '$') { if (_multi) { return Status(ErrorCodes::FailedToParse, "multi update only works with $ operators"); } // Modifiers expect BSONElements as input. But the input to object replace is, by // definition, an object. We wrap the 'updateExpr' as the mod is expecting. Note // that the wrapper is temporary so the object replace mod should make a copy of // the object. auto_ptr<ModifierObjectReplace> mod(new ModifierObjectReplace); BSONObj wrapper = BSON( "dummy" << updateExpr ); Status status = mod->init(wrapper.firstElement(), _modOptions); if (!status.isOK()) { return status; } _mods.push_back(mod.release()); // Register the fact that this driver will only do full object replacements. _replacementMode = true; return Status::OK(); } // The update expression is made of mod operators, that is // { <$mod>: {...}, <$mod>: {...}, ... } BSONObjIterator outerIter(updateExpr); while (outerIter.more()) { BSONElement outerModElem = outerIter.next(); // Check whether this is a valid mod type. modifiertable::ModifierType modType = modifiertable::getType(outerModElem.fieldName()); if (modType == modifiertable::MOD_UNKNOWN) { return Status(ErrorCodes::FailedToParse, "unknown modifier type"); } // Check whether there is indeed a list of mods under this modifier. if (outerModElem.type() != Object) { return Status(ErrorCodes::FailedToParse, "List of mods must be an object"); } // Check whether there are indeed mods under this modifier. if (outerModElem.embeddedObject().isEmpty()) { return Status(ErrorCodes::FailedToParse, "Empty expression after update $mod"); } BSONObjIterator innerIter(outerModElem.embeddedObject()); while (innerIter.more()) { BSONElement innerModElem = innerIter.next(); if (innerModElem.eoo()) { return Status(ErrorCodes::FailedToParse, "empty entry in $mod expression list"); } auto_ptr<ModifierInterface> mod(modifiertable::makeUpdateMod(modType)); dassert(mod.get()); Status status = mod->init(innerModElem, _modOptions); if (!status.isOK()) { return status; } _mods.push_back(mod.release()); } } // Register the fact that there will be only $mod's in this driver -- no object // replacement. _replacementMode = false; return Status::OK(); }
Status UpdateDriver::parse(const BSONObj& updateExpr) { clear(); // Check if the update expression is a full object replacement. if (*updateExpr.firstElementFieldName() != '$') { if (_multi) { return Status(ErrorCodes::FailedToParse, "multi update only works with $ operators"); } // Modifiers expect BSONElements as input. But the input to object replace is, by // definition, an object. We wrap the 'updateExpr' as the mod is expecting. Note // that the wrapper is temporary so the object replace mod should make a copy of // the object. auto_ptr<ModifierObjectReplace> mod(new ModifierObjectReplace); BSONObj wrapper = BSON( "dummy" << updateExpr ); Status status = mod->init(wrapper.firstElement(), _modOptions); if (!status.isOK()) { return status; } _mods.push_back(mod.release()); // Register the fact that this driver will only do full object replacements. _replacementMode = true; return Status::OK(); } // The update expression is made of mod operators, that is // { <$mod>: {...}, <$mod>: {...}, ... } BSONObjIterator outerIter(updateExpr); while (outerIter.more()) { BSONElement outerModElem = outerIter.next(); // Check whether this is a valid mod type. modifiertable::ModifierType modType = modifiertable::getType(outerModElem.fieldName()); if (modType == modifiertable::MOD_UNKNOWN) { return Status(ErrorCodes::FailedToParse, str::stream() << "Unknown modifier: " << outerModElem.fieldName()); } // Check whether there is indeed a list of mods under this modifier. if (outerModElem.type() != Object) { return Status(ErrorCodes::FailedToParse, str::stream() << "Modifiers operate on fields but we found a " << typeName(outerModElem.type()) << " instead. For example: {$mod: {<field>: ...}}" << " not {" << outerModElem.toString() << "}"); } // Check whether there are indeed mods under this modifier. if (outerModElem.embeddedObject().isEmpty()) { return Status(ErrorCodes::FailedToParse, str::stream() << "'" << outerModElem.fieldName() << "' is empty. You must specify a field like so: " "{$mod: {<field>: ...}}"); } BSONObjIterator innerIter(outerModElem.embeddedObject()); while (innerIter.more()) { BSONElement innerModElem = innerIter.next(); Status status = addAndParse(modType, innerModElem); if (!status.isOK()) { return status; } } } // Register the fact that there will be only $mod's in this driver -- no object // replacement. _replacementMode = false; return Status::OK(); }