summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/ops/modifier_inc.cpp10
-rw-r--r--src/mongo/db/ops/modifier_inc.h15
-rw-r--r--src/mongo/db/ops/modifier_inc_test.cpp28
-rw-r--r--src/mongo/db/ops/modifier_table.cpp13
-rw-r--r--src/mongo/db/ops/modifier_table.h1
5 files changed, 56 insertions, 11 deletions
diff --git a/src/mongo/db/ops/modifier_inc.cpp b/src/mongo/db/ops/modifier_inc.cpp
index 44ee713e430..5f8efc2d768 100644
--- a/src/mongo/db/ops/modifier_inc.cpp
+++ b/src/mongo/db/ops/modifier_inc.cpp
@@ -57,8 +57,9 @@ namespace mongo {
bool noOp;
};
- ModifierInc::ModifierInc()
+ ModifierInc::ModifierInc(ModifierIncMode mode)
: ModifierInterface ()
+ , _mode(mode)
, _fieldRef()
, _posDollar(0)
, _val() {
@@ -166,7 +167,10 @@ namespace mongo {
const SafeNum currentValue = _preparedState->elemFound.getValueSafeNum();
// Update newValue w.r.t to the current value of the found element.
- _preparedState->newValue += currentValue;
+ if (_mode == MODE_INC)
+ _preparedState->newValue += currentValue;
+ else
+ _preparedState->newValue *= currentValue;
// If the result of the addition is invalid, we must return an error.
if (!_preparedState->newValue.isValid())
@@ -236,7 +240,7 @@ namespace mongo {
_preparedState->newValue);
if (!logElement.ok()) {
- return Status(ErrorCodes::InternalError, "cannot append details for $inc mod");
+ return Status(ErrorCodes::InternalError, "cannot append details for $inc/$mul mod");
}
// Now, we attach the {<fieldname>: <value>} Element under the {$set: ...} segment.
diff --git a/src/mongo/db/ops/modifier_inc.h b/src/mongo/db/ops/modifier_inc.h
index 0425f0c3a35..6a3fece395c 100644
--- a/src/mongo/db/ops/modifier_inc.h
+++ b/src/mongo/db/ops/modifier_inc.h
@@ -33,7 +33,19 @@ namespace mongo {
public:
- ModifierInc();
+ // TODO: This is a shortcut to implementing $mul by hijacking $inc. In the near future,
+ // we should consider either pulling $mul into its own operator, or creating a general
+ // purpose "numeric binary op" operator. Potentially, that operator could also subsume
+ // $bit (thought there are some subtleties, like that $bit can have multiple
+ // operations, and doing so with arbirary math operations introduces potential
+ // associativity difficulties). At the very least, if this mechanism is retained, then
+ // this class should be renamed at some point away from ModifierInc.
+ enum ModifierIncMode {
+ MODE_INC,
+ MODE_MUL
+ };
+
+ ModifierInc(ModifierIncMode mode = MODE_INC);
virtual ~ModifierInc();
/**
@@ -58,6 +70,7 @@ namespace mongo {
virtual Status log(LogBuilder* logBuilder) const;
private:
+ const ModifierIncMode _mode;
// Access to each component of fieldName that's the target of this mod.
FieldRef _fieldRef;
diff --git a/src/mongo/db/ops/modifier_inc_test.cpp b/src/mongo/db/ops/modifier_inc_test.cpp
index d81d0f0337d..62d34bcb0e3 100644
--- a/src/mongo/db/ops/modifier_inc_test.cpp
+++ b/src/mongo/db/ops/modifier_inc_test.cpp
@@ -46,12 +46,13 @@ namespace {
/** Helper to build and manipulate a $inc mod. */
class Mod {
public:
- Mod() : _mod() {}
explicit Mod(BSONObj modObj)
: _modObj(modObj)
- , _mod() {
- ASSERT_OK(_mod.init(_modObj["$inc"].embeddedObject().firstElement(),
+ , _mod(mongoutils::str::equals(modObj.firstElement().fieldName(), "$mul") ?
+ ModifierInc::MODE_MUL : ModifierInc::MODE_INC) {
+ const StringData& modName = modObj.firstElement().fieldName();
+ ASSERT_OK(_mod.init(_modObj[modName].embeddedObject().firstElement(),
ModifierInterface::Options::normal()));
}
@@ -418,4 +419,25 @@ namespace {
ASSERT_EQUALS(fromjson("{ a : 2 }"), doc2);
}
+ // Given the current implementation of $mul, we really only need one test for
+ // $mul. However, in the future, we should probably write additional ones, or, perhaps find
+ // a way to run all the obove tests in both modes.
+ TEST(Multiplication, ApplyAndLogSimpleDocument) {
+ Document doc(fromjson("{ a : { b : 2 } }"));
+ Mod incMod(fromjson("{ $mul: { 'a.b' : 3 } }"));
+
+ ModifierInterface::ExecInfo execInfo;
+ ASSERT_OK(incMod.prepare(doc.root(), "", &execInfo));
+ ASSERT_FALSE(execInfo.noOp);
+
+ ASSERT_OK(incMod.apply());
+ ASSERT_TRUE(doc.isInPlaceModeEnabled());
+ ASSERT_EQUALS(fromjson("{ a : { b : 6 } }"), doc);
+
+ Document logDoc;
+ LogBuilder logBuilder(logDoc.root());
+ ASSERT_OK(incMod.log(&logBuilder));
+ ASSERT_EQUALS(fromjson("{ $set : { 'a.b' : 6 } }"), logDoc);
+ }
+
} // namespace
diff --git a/src/mongo/db/ops/modifier_table.cpp b/src/mongo/db/ops/modifier_table.cpp
index 9fa968a8d53..9108cddc22e 100644
--- a/src/mongo/db/ops/modifier_table.cpp
+++ b/src/mongo/db/ops/modifier_table.cpp
@@ -59,6 +59,12 @@ namespace modifiertable {
ModifierEntry* entryBit = new ModifierEntry("$bit", MOD_BIT);
nameMap->insert(make_pair(StringData(entryBit->name), entryBit));
+ ModifierEntry* entryInc = new ModifierEntry("$inc", MOD_INC);
+ nameMap->insert(make_pair(StringData(entryInc->name), entryInc));
+
+ ModifierEntry* entryMul = new ModifierEntry("$mul", MOD_MUL);
+ nameMap->insert(make_pair(StringData(entryMul->name), entryMul));
+
ModifierEntry* entryPop = new ModifierEntry("$pop", MOD_POP);
nameMap->insert(make_pair(StringData(entryPop->name), entryPop));
@@ -74,9 +80,6 @@ namespace modifiertable {
ModifierEntry* entryPushAll = new ModifierEntry("$pushAll", MOD_PUSH_ALL);
nameMap->insert(make_pair(StringData(entryPushAll->name), entryPushAll));
- ModifierEntry* entryInc = new ModifierEntry("$inc", MOD_INC);
- nameMap->insert(make_pair(StringData(entryInc->name), entryInc));
-
ModifierEntry* entrySet = new ModifierEntry("$set", MOD_SET);
nameMap->insert(make_pair(StringData(entrySet->name), entrySet));
@@ -114,7 +117,9 @@ namespace modifiertable {
case MOD_BIT:
return new ModifierBit;
case MOD_INC:
- return new ModifierInc;
+ return new ModifierInc(ModifierInc::MODE_INC);
+ case MOD_MUL:
+ return new ModifierInc(ModifierInc::MODE_MUL);
case MOD_POP:
return new ModifierPop;
case MOD_PULL:
diff --git a/src/mongo/db/ops/modifier_table.h b/src/mongo/db/ops/modifier_table.h
index cd25dc552bb..3f81a64014f 100644
--- a/src/mongo/db/ops/modifier_table.h
+++ b/src/mongo/db/ops/modifier_table.h
@@ -25,6 +25,7 @@ namespace modifiertable {
MOD_ADD_TO_SET,
MOD_BIT,
MOD_INC,
+ MOD_MUL,
MOD_POP,
MOD_PULL,
MOD_PULL_ALL,