MojErr MojDbIsamQuery::nextPage(MojDbQuery::Page& pageOut) { if (limitEnforced()) { pageOut.key() = m_endKey; } else { pageOut.clear(); } return MojErrNone; }
MojErr MojDbSearchTest::pageTest(MojDb& db) { MojDbQuery query; MojErr err = query.from(_T("SearchTest:2")); MojTestErrCheck(err); query.limit(3); // set page id MojString idStr; idStr.assign(_T("++IWp1fmlzpdwxKP")); MojObject obj(idStr); MojDbQuery::Page page; err = page.fromObject(obj); MojTestErrCheck(err); query.page(page); err = check(db, query, _T("[\"++IWp1fmlzpdwxKP\",\"++IWp1fmm+O4QrDA\",\"++IWp1fmm0+i9flc\"]")); MojTestErrCheck(err); return MojErrNone; }
MojErr MojDbSearchCursor::init(const MojDbQuery& query) { LOG_TRACE("Entering function %s", __FUNCTION__); MojErr err = initImpl(query); MojErrCheck(err); err = retrieveCollation(query); MojErrCheck(err); // override limit and sort since we need to retrieve everything // and sort before re-imposing limit m_limit = query.limit(); m_distinct = query.distinct(); if (!m_distinct.empty()) { m_orderProp = m_distinct; } else { m_orderProp = query.order(); } // retrieve page info from query. MojDbQuery::Page page; page = m_query.page(); if(!page.empty()) { MojObject objOut; err = page.toObject(objOut); MojErrCheck(err); m_page.fromObject(objOut); } m_query.limit(MaxResults); err = m_query.order(_T("")); MojErrCheck(err); // delete page info from query for query plan page.clear(); m_query.page(page); return MojErrNone; }
MojErr MojDbServiceHandler::findImpl(MojServiceMessage* msg, MojObject& payload, MojDbReq& req, MojDbCursor& cursor, bool doCount) { MojAssert(msg); MojLogTrace(s_log); MojObject queryObj; MojErr err = payload.getRequired(MojDbServiceDefs::QueryKey, queryObj); MojErrCheck(err); bool doWatch = false; payload.get(MojDbServiceDefs::WatchKey, doWatch); MojDbQuery query; err = query.fromObject(queryObj); MojErrCheck(err); MojUInt32 limit = query.limit(); if (limit == MojDbQuery::LimitDefault){ query.limit(MaxQueryLimit); } else if (limit > MaxQueryLimit) { MojErrThrowMsg(MojErrDbInvalidQuery, _T("db: limit greater than %d not allowed"), MaxQueryLimit); } if (doWatch) { MojRefCountedPtr<Watcher> watcher(new Watcher(msg)); MojAllocCheck(watcher.get()); err = m_db.find(query, cursor, watcher->m_watchSlot, req); MojErrCheck(err); } else { err = m_db.find(query, cursor, req); MojErrCheck(err); } // append results MojObjectVisitor& writer = msg->writer(); err = writer.beginObject(); MojErrCheck(err); err = writer.boolProp(MojServiceMessage::ReturnValueKey, true); MojErrCheck(err); err = writer.propName(MojDbServiceDefs::ResultsKey); MojErrCheck(err); err = writer.beginArray(); MojErrCheck(err); err = cursor.visit(writer); MojErrCheck(err); err = writer.endArray(); MojErrCheck(err); // append next page MojDbQuery::Page page; err = cursor.nextPage(page); MojErrCheck(err); if (!page.empty()) { MojObject pageObj; err = page.toObject(pageObj); MojErrCheck(err); err = writer.objectProp(MojDbServiceDefs::NextKey, pageObj); MojErrCheck(err); } // append count if (doCount) { MojUInt32 count = 0; err = cursor.count(count); MojErrCheck(err); err = writer.intProp(MojDbServiceDefs::CountKey, (MojInt64) count); MojErrCheck(err); } err = writer.endObject(); MojErrCheck(err); if (doWatch) { // if this is a watched query, it cannot be part of a batch so it's safe to reply here err = msg->reply(); MojErrCheck(err); } // notifications can fire any time after the cursor is closed, // so don't close it until after sending the reply. err = cursor.close(); MojErrCheck(err); return MojErrNone; }