MojErr MojDbPropExtractor::handleVal(const MojObject& val, KeySet& valsOut, MojSize idx) const { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssert(idx < m_prop.size()); MojErr err = MojErrNone; if (idx == m_prop.size() - 1) { // if we're at the end of the prop path, use this object as the value if (m_tokenizer.get() && val.type() == MojObject::TypeString) { MojString text; err = val.stringValue(text); MojErrCheck(err); if (m_tokenizer.get()) { err = m_tokenizer->tokenize(text, m_collator.get(), valsOut); MojErrCheck(err); } } else { MojDbKey key; err = key.assign(val, m_collator.get()); MojErrCheck(err); err = valsOut.put(key); MojErrCheck(err); } } else { // otherwise, keep recursing err = valsImpl(val, valsOut, idx + 1); MojErrCheck(err); } return MojErrNone; }
MojErr MojDbTextTokenizer::tokenize(const MojString& text, MojDbTextCollator* collator, KeySet& keysOut) const { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssert(m_ubrk.get()); // convert to UChar from str MojDbTextUtils::UnicodeVec unicodeStr; MojErr err = MojDbTextUtils::strToUnicode(text, unicodeStr); MojErrCheck(err); // clone break iterator and set text MojByte buf[U_BRK_SAFECLONE_BUFFERSIZE]; UErrorCode status = U_ZERO_ERROR; MojInt32 size = sizeof(buf); IterPtr ubrk(ubrk_safeClone(m_ubrk.get(), buf, &size, &status)); MojUnicodeErrCheck(status); MojAssert(ubrk.get()); ubrk_setText(ubrk.get(), unicodeStr.begin(), (MojInt32) unicodeStr.size(), &status); MojUnicodeErrCheck(status); MojInt32 tokBegin = -1; MojInt32 pos = ubrk_first(ubrk.get()); while (pos != UBRK_DONE) { UWordBreak status = (UWordBreak) ubrk_getRuleStatus(ubrk.get()); if (status != UBRK_WORD_NONE) { MojAssert(tokBegin != -1); MojDbKey key; const UChar* tokChars = unicodeStr.begin() + tokBegin; MojSize tokSize = (MojSize) (pos - tokBegin); if (collator) { err = collator->sortKey(tokChars, tokSize, key); MojErrCheck(err); } else { MojString tok; err = MojDbTextUtils::unicodeToStr(tokChars, tokSize, tok); MojErrCheck(err); err = key.assign(tok); MojErrCheck(err); } err = keysOut.put(key); MojErrCheck(err); } tokBegin = pos; pos = ubrk_next(ubrk.get()); } return MojErrNone; }
MojErr MojDbPropExtractor::valsImpl(const MojObject& obj, KeySet& valsOut, MojSize idx) const { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssert(!m_prop.empty() && idx < m_prop.size()); MojErr err = MojErrNone; const MojString& propKey = m_prop[idx]; if (propKey == WildcardKey) { // get all prop vals if we have a wildcard for (MojObject::ConstIterator i = obj.begin(); i != obj.end(); ++i) { err = handleVal(*i, valsOut, idx); MojErrCheck(err); } } else { // get object corresponding to the current component in the prop path MojObject::ConstIterator i = obj.find(propKey); if (i == obj.end()) { err = valsOut.put(m_default); MojErrCheck(err); } else { if (i->type() == MojObject::TypeArray) { // if the value is an array, act on its elements rather than the array object itself MojObject::ConstArrayIterator end = i->arrayEnd(); for (MojObject::ConstArrayIterator j = i->arrayBegin(); j != end; ++j) { err = handleVal(*j, valsOut, idx); MojErrCheck(err); } } else { // not an array err = handleVal(*i, valsOut, idx); MojErrCheck(err); } } } return MojErrNone; }
MojErr MojDbIndex::update(const MojObject* newObj, const MojObject* oldObj, MojDbStorageTxn* txn, bool forcedel) { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssert(isOpen()); MojAssert(newObj || oldObj); // figure out which versions we include bool includeOld = includeObj(oldObj); bool includeNew = includeObj(newObj); if (includeNew && !includeOld) { // we include the new but not the old, so just put all the new keys MojAssert(newObj); KeySet newKeys; MojErr err = getKeys(*newObj, newKeys); MojErrCheck(err); err = insertKeys(newKeys, txn); MojErrCheck(err); err = notifyWatches(newKeys, txn); MojErrCheck(err); LOG_DEBUG("[db_mojodb] IndexAdd: %s; Keys= %zu \n", this->m_name.data(), newKeys.size()); } else if (includeOld && !includeNew) { // we include the old but not the new objects, so del all the old keys MojAssert(oldObj); KeySet oldKeys; MojErr err = getKeys(*oldObj, oldKeys); MojErrCheck(err); err = delKeys(oldKeys, txn, forcedel); MojErrCheck(err); err = notifyWatches(oldKeys, txn); MojErrCheck(err); LOG_DEBUG("[db_mojodb] IndexDel: %s; Keys= %zu \n", this->name().data(), oldKeys.size()); } else if (includeNew && includeOld) { // we include old and new objects MojAssert(newObj && oldObj); KeySet newKeys; MojErr err = getKeys(*newObj, newKeys); MojErrCheck(err); KeySet oldKeys; err = getKeys(*oldObj, oldKeys); MojErrCheck(err); // we need to put the keys that are in the new set, but not in the old KeySet keysToPut; err = newKeys.diff(oldKeys, keysToPut); MojErrCheck(err); // we need to del the keys that are in the old set, but not in the new KeySet keysToDel; err = oldKeys.diff(newKeys, keysToDel); MojErrCheck(err); err = insertKeys(keysToPut, txn); MojErrCheck(err); err = delKeys(keysToDel, txn, forcedel); LOG_DEBUG("[db_mojodb] IndexMerge: %s; OldKeys= %zu; NewKeys= %zu; Dropped= %zu; Added= %zu ; err = %d\n", this->name().data(), oldKeys.size(), newKeys.size(), keysToDel.size(), keysToPut.size(), (int)err); MojErrCheck(err); // notify on union of old and new keys err = newKeys.put(oldKeys); MojErrCheck(err); err = notifyWatches(newKeys, txn); MojErrCheck(err); } return MojErrNone; }