MojErr MojDbIndex::getKeys(const MojObject& obj, KeySet& keysOut) const { LOG_TRACE("Entering function %s", __FUNCTION__); // build the set of unique keys from object MojDbKeyBuilder builder; MojErr err = builder.push(m_idSet); MojErrCheck(err); MojSize idx = 0; for (PropVec::ConstIterator i = m_props.begin(); i != m_props.end(); ++i, ++idx) { KeySet vals; err = (*i)->vals(obj, vals); MojErrCheck(err); err = builder.push(vals); MojErrCheck(err); } err = builder.keys(keysOut); MojErrCheck(err); return MojErrNone; }
MojErr MojDbQueryPlan::buildRanges(const MojDbIndex& index) { MojAssert(!index.props().empty()); MojErr err = MojErrNone; const MojDbQuery::WhereMap& where = m_query.where(); const StringVec& props = index.props(); const MojDbQuery::WhereClause* lastClause = NULL; MojDbKeyBuilder lowerBuilder; MojDbKeyBuilder upperBuilder; MojDbKeyBuilder::KeySet prefixKeys; err = pushVal(lowerBuilder, index.id(), NULL); MojErrCheck(err); err = pushVal(upperBuilder, index.id(), NULL); MojErrCheck(err); // push vals for all props in index prop order to create upper and lower bounds for (StringVec::ConstIterator i = props.begin(); i != props.end(); ++i) { // get clause for prop MojDbQuery::WhereMap::ConstIterator clause = where.find(*i); if (clause == where.end()) { MojAssert((MojSize)(i - props.begin()) == where.size()); break; } // create collator MojRefCountedPtr<MojDbTextCollator> collator; MojDbCollationStrength coll = clause->collation(); if (coll != MojDbCollationInvalid) { collator.reset(new MojDbTextCollator); MojAllocCheck(collator.get()); err = collator->init(m_locale, coll); MojErrCheck(err); } // push vals for clause MojDbQuery::CompOp lowerOp = clause->lowerOp(); if (lowerOp == MojDbQuery::OpSearch) { // tokenize search strings err = pushSearch(lowerBuilder, upperBuilder, clause->lowerVal(), collator.get()); MojErrCheck(err); } else { // copy off prefix before writing an inequality val if (lowerOp != MojDbQuery::OpEq && lowerOp != MojDbQuery::OpPrefix) { err = lowerBuilder.keys(prefixKeys); MojErrCheck(err); if (prefixKeys.empty()) { // if there is no prefix yet, put an empty key err = prefixKeys.put(MojDbKey()); MojErrCheck(err); } } // append lower-value to lower-key err = pushVal(lowerBuilder, clause->lowerVal(), collator.get()); MojErrCheck(err); // append appropriate value to upper-key if (clause->upperOp() == MojDbQuery::OpNone) { err = pushVal(upperBuilder, clause->lowerVal(), collator.get()); MojErrCheck(err); } else { err = pushVal(upperBuilder, clause->upperVal(), collator.get()); MojErrCheck(err); } } lastClause = &clause.value(); } // go from builders to ranges KeySet lowerKeys; err = lowerBuilder.keys(lowerKeys); MojErrCheck(err); KeySet upperKeys; err = upperBuilder.keys(upperKeys); MojErrCheck(err); if (prefixKeys.empty()) { prefixKeys = lowerKeys; } err = rangesFromKeySets(lowerKeys, upperKeys, prefixKeys, lastClause); MojErrCheck(err); return MojErrNone; }