/*********************************************************************** * setPagePosition * * Move cursor position to page id provided in query. * 1. Find item "_id" which is equal to page id iteratively. * 2. If found, set begin/last position and next page. ***********************************************************************/ MojErr MojDbSearchCursor::setPagePosition() { LOG_TRACE("Entering function %s", __FUNCTION__); MojErr err; MojDbStorageItem* item; m_pos = m_items.begin(); ItemVec::ConstIterator last = m_items.end(); m_limitPos = last; // retrieve page id from query MojObject pageKey; err = m_page.toObject(pageKey); MojErrCheck(err); while (m_pos != last) { // retrieve id from query item = m_pos->get(); const MojObject id = item->id(); // If match, set begin/last position and next page if(pageKey.compare(id) == 0) { if (m_limit >= (last-m_pos)) { m_limitPos = m_items.end(); m_page.clear(); } else { m_limitPos = m_pos + m_limit; // set next page MojDbStorageItem* nextItem = m_limitPos->get(); const MojObject nextId = nextItem->id(); m_page.fromObject(nextId); // print log for nextId MojString strOut; err = nextId.toJson(strOut); MojErrCheck(err); LOG_DEBUG("[db_mojodb] nextId : %s \n", strOut.data()); } break; } ++m_pos; } return MojErrNone; }
MojErr MojDb::merge(const MojDbQuery& query, const MojObject& props, MojUInt32& countOut, MojUInt32 flags, MojDbReqRef req) { MojLogTrace(s_log); countOut = 0; MojErr err = beginReq(req); MojErrCheck(err); MojDbCursor cursor; err = findImpl(query, cursor, NULL, req, OpUpdate); MojErrCheck(err); MojAssert(cursor.txn()); MojUInt32 count = 0; MojUInt32 warns = 0; bool found = false; MojObject prev; for (;;) { // get prev rev from cursor MojDbStorageItem* prevItem = NULL; err = cursor.get(prevItem, found); if (err == MojErrInternalIndexOnFind) { warns++; continue; } MojErrCheck(err); if (!found) break; err = prevItem->toObject(prev, m_kindEngine); MojErrCheck(err); // merge obj into prev MojObject merged; err = mergeInto(merged, props, prev); MojErrCheck(err); // and update the db const MojObject& id = prevItem->id(); err = putObj(id, merged, &prev, prevItem, req, OpUpdate); MojErrCheck(err); ++count; } if (warns > 0) MojLogWarning(s_log, _T("Merge index_warnings: %s; count: %d\n"), query.from().data(), warns); err = cursor.close(); MojErrCheck(err); err = req->end(); MojErrCheck(err); countOut = count; return MojErrNone; }
MojErr MojDbSearchCursor::load() { LOG_TRACE("Entering function %s", __FUNCTION__); // pull unique ids from index ObjectSet ids; MojErr err = loadIds(ids); MojErrCheck(err); // load objects into memory err = loadObjects(ids); MojErrCheck(err); // sort results if (!m_orderProp.empty()) { err = sort(); MojErrCheck(err); } // distinct if (!m_distinct.empty()) { distinct(); } // reverse for desc if (m_query.desc()) { err = m_items.reverse(); MojErrCheck(err); } // next page if (!m_page.empty()) { err = setPagePosition(); MojErrCheck(err); } else { // set begin/last position. m_pos = m_items.begin(); if (m_limit >= m_items.size()) { m_limitPos = m_items.end(); } else { // if item size is bigger than limit, set next page. m_limitPos = m_items.begin() + m_limit; MojDbStorageItem* nextItem = m_limitPos->get(); const MojObject nextId = nextItem->id(); m_page.fromObject(nextId); } } // set remainder count m_count = m_items.end() - m_pos; return MojErrNone; }
MojErr MojDb::delImpl(const MojDbQuery& quer, MojUInt32& countOut, MojDbReq& req, MojUInt32 flags) { MojLogTrace(s_log); countOut = 0; MojInt32 warns = 0; MojDbQuery newQuery = quer; MojUInt32 queryLimit = newQuery.limit(); if(newQuery.limit() == MojDbQuery::LimitDefault) newQuery.limit(AutoBatchSize); while(queryLimit > 0) { MojDbCursor cursor; MojErr err = findImpl(newQuery, cursor, NULL, req, OpDelete); MojErrCheck(err); MojAssert(cursor.txn()); MojUInt32 count = 0; MojUInt32 numberInBatch = 0; bool found = false; MojObject obj; for (;;) { MojDbStorageItem* item = NULL; err = cursor.get(item, found); // We simply skip ghost keys and continue; A warning is already written to the system log earlier if (err == MojErrInternalIndexOnFind) { warns++; numberInBatch++; continue; } MojErrCheck(err); if (!found) break; err = item->toObject(obj, m_kindEngine); MojErrCheck(err); const MojObject& id = item->id(); MojObject deleted; err = delObj(id, obj, item, deleted, req, flags); MojErrCheck(err); ++count; numberInBatch++; } if (warns > 0) MojLogInfo(s_log, _T("delquery index_warnings: %s, count: %d\n"), newQuery.from().data(), warns); countOut += count; err = cursor.close(); MojErrCheck(err); if(numberInBatch >= AutoBatchSize) // sing > - just in case something messed up { err = commitBatch(req); MojErrCheck(err); } if(count == 0) break; queryLimit -= newQuery.limit(); if(queryLimit > AutoBatchSize) newQuery.limit(AutoBatchSize); else newQuery.limit(queryLimit); } return MojErrNone; }