Example #1
0
MojErr MojDbSearchCursor::retrieveCollation(const MojDbQuery& query)
{
    m_collation = MojDbCollationInvalid;

    const MojChar* orderName = query.order().data();
    if (m_kindEngine && !query.order().empty()) {
        // Get index that is set by orderBy
        MojDbKind* kind = NULL;
        MojErr err = m_kindEngine->getKind(query.from().data(), kind);
        MojErrCheck(err);
        MojDbIndex* index = kind->indexForCollation(query);
        if(index != NULL) {
            // Find property name that is equal to orderBy name form index to retrieve collation strenth.
            MojDbIndex::StringVec propNames = index->props();
            for (MojSize idx = 0; idx < propNames.size(); idx++) {
                if(!(propNames.at(idx)).compare(orderName)) {
                    m_collation = index->collation(idx);
                    break;
                }
            }
        }
    }

    return MojErrNone;
}
Example #2
0
void MojoDatabase::GetAutoDownloadEmails(Signal::SlotRef slot, const MojObject& folderId, const MojInt64& rev, MojDbQuery::Page& page, MojInt32 limit)
{
	MojDbQuery query;

	MojErr err = query.from(PopEmailAdapter::POP_EMAIL_KIND);
	ErrorToException(err);

	err = query.where(EmailSchema::FOLDER_ID, MojDbQuery::OpEq, folderId);
	ErrorToException(err);
	
	if (rev > 0) {
		err = query.where(PopFolderAdapter::LAST_SYNC_REV, MojDbQuery::OpGreaterThan, rev);
		ErrorToException(err);
	}

	query.page(page);

	// Sort by timestamp descending
	err = query.order(EmailSchema::TIMESTAMP);
	ErrorToException(err);
	query.desc(true);

	// Set limit
	if(limit > 0) {
		query.limit(limit);
	}

	slot.cancel();
	err = m_dbClient.find(slot, query);
	ErrorToException(err);
}
Example #3
0
MojErr MojDbDistinctTest::initQuery(MojDbQuery& query, const MojChar* queryString)
{
	query.clear();
	MojErr err = query.from(_T("DistinctTest:1"));
	MojTestErrCheck(err);

	err = query.distinct(queryString);
	MojTestErrCheck(err);
    err = query.order(queryString);
    MojTestErrCheck(err);

	return MojErrNone;
}
Example #4
0
void MojoDatabase::GetEmails(Signal::SlotRef slot, const MojObject& folderId, MojInt32 limit)
{
	MojDbQuery q;
	MojErr err = q.from(PopEmailAdapter::POP_EMAIL_KIND);
	ErrorToException(err);

	err = q.where(EmailSchema::FOLDER_ID, MojDbQuery::OpEq, folderId);
	ErrorToException(err);

	err = q.order(EmailSchema::TIMESTAMP);
	ErrorToException(err);

	q.limit(limit);
	q.desc(true);

	err = m_dbClient.find(slot, q);
	ErrorToException(err);
}
Example #5
0
void MojoDatabase::GetEmailSyncList(Signal::SlotRef slot, const MojObject& folderId, const MojInt64& rev, bool desc, MojDbQuery::Page& page, MojInt32 limit)
{
	MojErr err;

	MojDbQuery query;
	err = query.from(PopEmailAdapter::POP_EMAIL_KIND);//EmailSchema::Kind::EMAIL);
	ErrorToException(err);

	// Select relevant fields
	err = query.select(PopEmailAdapter::ID);
	ErrorToException(err);

	err = query.select(PopEmailAdapter::SERVER_UID);
	ErrorToException(err);

	err = query.select(EmailSchema::TIMESTAMP);
	ErrorToException(err);

	err = query.where(EmailSchema::FOLDER_ID, MojDbQuery::OpEq, folderId);
	ErrorToException(err);

	if (rev > 0) {
		err = query.where(PopFolderAdapter::LAST_SYNC_REV, MojDbQuery::OpGreaterThan, rev);
		ErrorToException(err);
	}

	query.page(page);

	// Sort by timestamp descending
	err = query.order(EmailSchema::TIMESTAMP);
	ErrorToException(err);
	query.desc(desc);

	// Set limit
	if(limit > 0) {
		query.limit(limit);
	}

	slot.cancel(); // cancel existing slot in case we're in a callback

	err = m_dbClient.find(slot, query);
	ErrorToException(err);
}
Example #6
0
MojErr MojDbSearchTest::initQuery(MojDbQuery& query, const MojChar* queryStr, const MojChar* orderBy, const MojObject& barVal, bool desc)
{
	query.clear();
	MojErr err = query.from(_T("SearchTest:1"));
	MojTestErrCheck(err);
	MojString val;
	err = val.assign(queryStr);
	MojTestErrCheck(err);
	err = query.where(_T("foo"), MojDbQuery::OpSearch, val, MojDbCollationPrimary);
	MojTestErrCheck(err);
	query.desc(desc);
	if (!barVal.undefined()) {
		err = query.where(_T("bar"), MojDbQuery::OpEq, barVal);
		MojTestErrCheck(err);
	}
	if (orderBy) {
		err = query.order(orderBy);
		MojTestErrCheck(err);
	}
	return MojErrNone;
}
Example #7
0
MojErr MojDbSearchCursor::init(const MojDbQuery& query)
{
    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();
    }
    m_query.limit(MaxResults);
    err = m_query.order(_T(""));
    MojErrCheck(err);

    return MojErrNone;
}
Example #8
0
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;
}
Example #9
0
bool MojDbIndex::canAnswer(const MojDbQuery& query) const
{
    LOG_TRACE("Entering function %s", __FUNCTION__);
	MojAssert(isOpen());
	MojAssert(!m_propNames.empty());

	// if this index is not ready yet, return false
	if (!m_ready)
		return false;

	// The goal here is to figure out whether the results for the query are contiguous in
	// the index. That will be the case if all the props referenced are contiguous in our
	// prop vector, any prop referenced by an inequality op comes at the end of the
	// range of referenced props, any unreferenced props in our vector are at the end,
	// and the order prop is either the last referenced prop or, if all ops are equality ops,
	// the prop following the last referenced prop.
	const MojDbQuery::WhereMap& map = query.where();
	MojSize numQueryProps = map.size();
	// if there are more props in the query than in our index, no can do
	if (numQueryProps > m_propNames.size())
		return false;
	// skip the first prop if we have an incDel index and the query does not reference the del prop
	StringVec::ConstIterator propName = m_propNames.begin();
	PropVec::ConstIterator prop = m_props.begin();
	if (m_includeDeleted && !map.contains(MojDb::DelKey)) {
		++propName;
		++prop;
	}
	// if there are no props in query, but the order matches our first prop, we're good
	const MojString& orderProp = query.order();
	if (numQueryProps == 0) {
		if (orderProp.empty()) {
			return isIdIndex();
		} else {
			return *propName == orderProp;
		}
	}
	// check all remaining props
	for (; propName != m_propNames.end(); ++propName, ++prop) {
		--numQueryProps;
		// ensure that the current prop is referenced in the query (no gaps)
		MojDbQuery::WhereMap::ConstIterator mapIter = map.find(*propName);
		if (mapIter == map.end())
			return false;
		// ensure that if it is an inequality op, it is at the end
		if (numQueryProps > 0 && mapIter->lowerOp() != MojDbQuery::OpEq)
			return false;
		// ensure that collation matches
		if (mapIter->collation() != (*prop)->collation())
			return false;
		// hooray, we made it through all the props in the query without failing any tests.
		// there may still be unreferenced props at the end of the vector, but that's ok.
		if (numQueryProps == 0) {
			// make sure that we can satisfy the ordering. if there is no ordering, or we are
			// ordering on a referenced prop, we're golden
			if (!orderProp.empty() && !map.contains(orderProp)) {
				// ensure that the order prop is next in our vec
				StringVec::ConstIterator next = propName + 1;
				if (next == m_propNames.end() || *next != orderProp)
					return false;
			}
			// can do!
			return true;
		}
	}
	return false;
}
Example #10
0
MojErr MojDb::purge(MojUInt32& countOut, MojInt64 numDays, MojDbReqRef req)
{
	MojLogTrace(s_log);

	countOut = 0;
	if (numDays <= -1) {
		numDays = m_purgeWindow;
	}

	MojErr err = beginReq(req);
	MojErrCheck(err);

	MojLogDebug(s_log, _T("purging objects deleted more than %lld days ago..."), numDays);

	MojTime time;
	err = MojGetCurrentTime(time);
	MojErrCheck(err);

	// store the revision number to current timestamp mapping
	MojObject revTimeMapping;
	MojInt64 rev;
	err = nextId(rev);
	MojErrCheck(err);
	err = revTimeMapping.put(RevNumKey, rev);
	MojErrCheck(err);
	err = revTimeMapping.put(TimestampKey, time.microsecs());
	MojErrCheck(err);
	err = revTimeMapping.putString(KindKey, MojDbKindEngine::RevTimestampId);
	MojErrCheck(err);

	err = putImpl(revTimeMapping, MojDb::FlagNone, req);
	MojErrCheck(err);

	// find the revision number for numDays prior to now
	MojInt64 purgeTime = time.microsecs() - (MojTime::UnitsPerDay * numDays);
	MojDbQuery query;
	err = query.from(MojDbKindEngine::RevTimestampId);
	MojErrCheck(err);
	query.limit(1);
	err = query.where(TimestampKey, MojDbQuery::OpLessThanEq, purgeTime);
	MojErrCheck(err);
	err = query.order(TimestampKey);
	MojErrCheck(err);
	query.desc(true);

	MojDbCursor cursor;
	err = findImpl(query, cursor, NULL, req, OpDelete);
	MojErrCheck(err);
	bool found = false;
	MojObject obj;
	err = cursor.get(obj, found);
	MojErrCheck(err);
	err = cursor.close();
	MojErrCheck(err);

	MojUInt32 batchCount = 0;
	MojUInt32 totalCount = 0;

	while ((found))
	{
		// Do it in AutoBatchSize batches
		batchCount = 0;
		req->fixmode(true);		// purge even if index mis-matches
		err = purgeImpl(obj, batchCount, req);
		MojLogDebug(s_log, _T("purge batch processed: batch: %d; total: %d; err = %d\n"),
					batchCount, (totalCount + batchCount), err);
		MojErrCheck(err);
		totalCount += batchCount;
		countOut = totalCount;
		if (batchCount < AutoBatchSize)	// last batch
			break;
		err = commitBatch(req);
		MojErrCheck(err);
		continue;
	}

	// end request
	err = req->end();
	MojErrCheck(err);

	MojLogDebug(s_log, _T("purged %d objects"), countOut);


	return MojErrNone;
}