void checkMarkWithUpdate(MojUInt32 expect = 50ul, int mark = -1, MojDbReqRef req = MojDbReq()) { MojDbQuery query; MojAssertNoErr( query.from(_T("Test:1")) ); MojAssertNoErr( query.where(_T("bar"), MojDbQuery::OpEq, mark) ); MojObject update; MojUInt32 count = (MojUInt32)(-1); MojAssertNoErr( db.merge(query, MojObject(), count, MojDb::FlagNone, req) ); EXPECT_EQ( expect, count ); }
MojErr MojDbWatchTest::merge(MojDb& db, const MojObject& id, const MojObject& barVal) { MojObject obj; MojErr err = obj.put(MojDb::IdKey, id); MojTestErrCheck(err); err = obj.put(_T("bar"), barVal); MojTestErrCheck(err); err = db.merge(obj); MojTestErrCheck(err); return MojErrNone; }
void mark3(MojDbReqRef req = MojDbReq()) { MojDbQuery query; MojAssertNoErr( query.from(_T("Test:1")) ); MojAssertNoErr( query.where(_T("bar"), MojDbQuery::OpLessThan, 2) ); MojObject update; MojAssertNoErr( update.put(_T("bar"), -3) ); MojUInt32 count = 0xbaddcafe; MojAssertNoErr( db.merge(query, update, count, MojDb::FlagNone, req) ); EXPECT_EQ( 33ul, count ); }
void mark1(MojDbReqRef req = MojDbReq()) { // mark half with bar=-1 MojDbQuery query; MojAssertNoErr( query.from(_T("Test:1")) ); MojAssertNoErr( query.where(_T("foo"), MojDbQuery::OpLessThan, 50) ); MojObject update; MojAssertNoErr( update.put(_T("bar"), -1) ); MojUInt32 count = 0xbaddcafe; // differentiat 0 from non-filled count MojAssertNoErr( db.merge(query, update, count) ); EXPECT_EQ( 50ul, count ); // db: x0 = (25, -1) .. x24 = (49,-1), x25 = (50,1)i .. x74 = (99,2), x75 = (0,-1) .. x99 = (24, -1) }
void mark2(MojDbReqRef req = MojDbReq()) { // re-mark half with bar=-1 to bar=-2 MojDbQuery query; MojAssertNoErr( query.from(_T("Test:1")) ); MojAssertNoErr( query.where(_T("bar"), MojDbQuery::OpEq, -1) ); MojObject update; MojAssertNoErr( update.put(_T("bar"), -2) ); MojUInt32 count = 0xbaddcafe; MojAssertNoErr( db.merge(query, update, count, MojDb::FlagNone, req) ); EXPECT_EQ( 50ul, count ); // db: x0 = (25, -1) .. x24 = (49,-1), x25 = (50,1)i .. x74 = (99,2), x75 = (0,-1) .. x99 = (24, -1) }
MojErr MojDbPerfUpdateTest::queryMergeObj(MojDb& db, MojDbQuery& query, MojObject& props, MojUInt32& count, MojTime& objTime) { MojTime startTime; MojTime endTime; for (MojUInt64 i = 0; i < numBatchMergeIterations; i++) { MojErr err = MojGetCurrentTime(startTime); MojTestErrCheck(err); err = db.merge(query, props, count); MojTestErrCheck(err); err = MojGetCurrentTime(endTime); MojTestErrCheck(err); objTime += (endTime - startTime); totalTestTime += (endTime - startTime); } return MojErrNone; }
MojErr MojDbPerfUpdateTest::batchMergeObj(MojDb& db, MojObject* begin, const MojObject* end, MojTime& objTime) { MojTime startTime; MojTime endTime; for (MojUInt64 i = 0; i < numBatchMergeIterations; i++) { MojErr err = MojGetCurrentTime(startTime); MojTestErrCheck(err); err = db.merge(begin, end); MojTestErrCheck(err); err = MojGetCurrentTime(endTime); MojTestErrCheck(err); objTime += (endTime - startTime); totalTestTime += (endTime - startTime); } return MojErrNone; }
MojErr MojDbPerfUpdateTest::mergeObj(MojDb& db, MojObject& obj, MojTime& objTime) { MojTime startTime; MojTime endTime; for (MojUInt64 i = 0; i < numMergeIterations; i++) { MojErr err = MojGetCurrentTime(startTime); MojTestErrCheck(err); err = obj.putInt(_T("newProp"), i); MojTestErrCheck(err); err = db.merge(obj); MojTestErrCheck(err); err = MojGetCurrentTime(endTime); MojTestErrCheck(err); objTime += (endTime - startTime); totalTestTime += (endTime - startTime); } return MojErrNone; }
MojErr MojDbTxnTest::run() { MojErr err; MojDb db; err = MojDbTestEnv::run(MojDbTestDir); MojTestErrCheck(err); // open err = db.open(MojDbTestDir, env()); MojTestErrCheck(err); // add type MojObject obj; err = obj.fromJson(MojKindStr); MojTestErrCheck(err); err = db.putKind(obj); MojTestErrCheck(err); for (int i = 0; i < 100; ++i) { MojObject obj; MojErr err = obj.putString(MojDb::KindKey, _T("Test:1")); MojTestErrCheck(err); err = obj.put(_T("foo"), (i + 25) % 100); MojTestErrCheck(err); err = obj.put(_T("bar"), i % 3); MojTestErrCheck(err); err = db.put(obj); MojTestErrCheck(err); } // db: x0 = (25, 0), (26, 1), (27, 2), (28, 0) .. x74 = (99,2), x75 = (0,0) .. x99 = (24,0) { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("foo"), MojDbQuery::OpLessThan, 50); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -1); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 50); } // db: x0 = (25, -1) .. x24 = (49,-1), x25 = (50,1)i .. x74 = (99,2), x75 = (0,-1) .. x99 = (24, -1) // test visibility with update { MojDbReq req; // start transaction req.begin(&db, false); MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -1); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -2); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count, MojDb::FlagNone, req); MojTestErrCheck(err); MojTestAssert(count == 50); // txn: x0 = (25, -2) .. x24 = (49,-2), x25 = (50,1) .. x74 = (99,2), x75 = (0,-2) .. x99 = (24, -2) // visible within transaction { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -2); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count, MojDb::FlagNone, req); MojTestErrCheck(err); MojTestAssert(count == 50); } // With BerkeleyDB parallel transaction is locked // invisible outside of transaction if (engineName().compare(_T("leveldb")) == 0) { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -2); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 0); } } // invisible after aborted transaction { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -2); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 0); } // test visibility with delete { MojDbReq req; // start transaction req.begin(&db, false); MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -1); MojTestErrCheck(err); MojUInt32 count = 0; err = db.del(query, count, MojDb::FlagNone, req); MojTestErrCheck(err); MojTestAssert(count == 50); // txn: x25 = (50,1) .. x74 = (99,2) // visible within transaction { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpLessThan, 2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -3); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count, MojDb::FlagNone, req); MojTestErrCheck(err); MojTestAssert(count == 33); } // With BerkeleyDB parallel transaction is locked // invisible outside of transaction if (engineName().compare(_T("leveldb")) == 0) { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpLessThan, 2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -3); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 83); } } // invisible after aborted transaction { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpLessThan, 2); MojTestErrCheck(err); MojObject update; // Note that if we change bar=1 here we might get double-update when // record we just updated moved into records range ahead of our current // cursor position MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 83); } err = db.close(); MojTestErrCheck(err); return MojErrNone; }
MojErr MojDbRevTest::run() { MojDb db; MojErr err = db.open(MojDbTestDir); MojTestErrCheck(err); // put type MojObject obj; err = obj.fromJson(MojKindStr); MojTestErrCheck(err); // put obj err = db.putKind(obj); MojTestErrCheck(err); err = obj.fromJson(MojTestObjStr1); MojTestErrCheck(err); err = db.put(obj); MojTestErrCheck(err); MojObject id; err = obj.getRequired(MojDb::IdKey, id); MojTestErrCheck(err); // get obj and verify rev eq MojObject rev; err = obj.getRequired(MojDb::RevKey, rev); MojTestErrCheck(err); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // put identical obj and verify rev not changed err = db.put(obj); MojTestErrCheck(err); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // put with changed prop and verify rev gt err = obj.fromJson(MojTestObjStr2); MojTestErrCheck(err); err = obj.put(MojDb::IdKey, id); MojTestErrCheck(err); err = db.put(obj); // this put will fail because we haven't included a rev MojTestErrExpected(err, MojErrDbRevNotSpecified); bool found = false; err = db.del(id, found); // verify that we can put without a rev if the object is deleted MojTestErrCheck(err); MojTestAssert(found); err = db.put(obj); MojTestErrCheck(err); err = obj.getRequired(MojDb::RevKey, rev); MojTestErrCheck(err); err = obj.put(MojDb::RevKey, 1); MojTestErrCheck(err); err = db.put(obj); // this put will fail because the revision num is lower MojTestErrExpected(err, MojErrDbRevisionMismatch); err = obj.put(MojDb::RevKey, rev); MojTestErrCheck(err); err = db.put(obj); // now this should succeed MojTestErrCheck(err); // merge with unchanged prop and verify rev not changed err = obj.fromJson(MojTestObjStr3); MojTestErrCheck(err); err = obj.put(MojDb::IdKey, id); MojTestErrCheck(err); err = db.merge(obj); MojTestErrCheck(err); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // merge with changed prop and verify rev gt err = obj.fromJson(MojTestObjStr4); MojTestErrCheck(err); err = obj.put(MojDb::IdKey, id); MojTestErrCheck(err); err = db.merge(obj); MojTestErrCheck(err); err = checkRevGt(db, id, rev); MojTestErrCheck(err); // query merge with unchanged prop and verify rev not changed MojDbQuery query; err = query.from("RevTest:1"); MojTestErrCheck(err); err = obj.fromJson(MojTestObjStr4); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, obj, count); MojTestErrCheck(err); MojTestAssert(count == 1); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // query merge with changed prop and verify rev gt err = obj.fromJson(MojTestObjStr3); MojTestErrCheck(err); err = db.merge(query, obj, count); MojTestErrCheck(err); MojTestAssert(count == 1); err = checkRevGt(db, id, rev); MojTestErrCheck(err); // del verify rev gt err = db.del(id, found); MojTestErrCheck(err); MojTestAssert(found); err = checkRevGt(db, id, rev); MojTestErrCheck(err); // del again and verify rev not changed err = db.del(id, found); MojTestErrCheck(err); MojTestAssert(found); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // undel and verify rev gt err = obj.fromJson(MojTestObjStr5); MojTestErrCheck(err); err = obj.put(MojDb::IdKey, id); MojTestErrCheck(err); err = db.merge(obj); MojTestErrCheck(err); err = checkRevGt(db, id, rev); MojTestErrCheck(err); // query del and verify rev gt err = db.del(query, count); MojTestErrCheck(err); MojTestAssert(count == 1); err = checkRevGt(db, id, rev); MojTestErrCheck(err); err = db.close(); MojTestErrCheck(err); return MojErrNone; }