// static IndexBoundsChecker::Location IndexBoundsChecker::intervalCmp(const Interval& interval, const BSONElement& key, const int expectedDirection) { int cmp = sgn(key.woCompare(interval.start, false)); bool startOK = (cmp == expectedDirection) || (cmp == 0 && interval.startInclusive); if (!startOK) { return BEHIND; } cmp = sgn(key.woCompare(interval.end, false)); bool endOK = (cmp == -expectedDirection) || (cmp == 0 && interval.endInclusive); if (!endOK) { return AHEAD; } return WITHIN; }
/* well ordered compare */ int BSONObj::woSortOrder(const BSONObj& other, const BSONObj& sortKey ) const{ if ( isEmpty() ) return other.isEmpty() ? 0 : -1; if ( other.isEmpty() ) return 1; uassert( "woSortOrder needs a non-empty sortKey" , ! sortKey.isEmpty() ); BSONObjIterator i(sortKey); while ( 1 ){ BSONElement f = i.next(); if ( f.eoo() ) return 0; BSONElement l = getField( f.fieldName() ); if ( l.eoo() ) l = staticNull.firstElement(); BSONElement r = other.getField( f.fieldName() ); if ( r.eoo() ) r = staticNull.firstElement(); int x = l.woCompare( r, false ); if ( f.number() < 0 ) x = -x; if ( x != 0 ) return x; } return -1; }
// Is lhs less than rhs? Note that priority_queue is a max heap by default so we invert // the return from the expected value. bool MergeSortStage::StageWithValueComparison::operator()(const MergingRef& lhs, const MergingRef& rhs) { WorkingSetMember* lhsMember = _ws->get(lhs->id); WorkingSetMember* rhsMember = _ws->get(rhs->id); BSONObjIterator it(_pattern); while (it.more()) { BSONElement patternElt = it.next(); string fn = patternElt.fieldName(); BSONElement lhsElt; verify(lhsMember->getFieldDotted(fn, &lhsElt)); BSONElement rhsElt; verify(rhsMember->getFieldDotted(fn, &rhsElt)); // false means don't compare field name. int x = lhsElt.woCompare(rhsElt, false); if (-1 == patternElt.number()) { x = -x; } if (x != 0) { return x > 0; } } // A comparator for use with sort is required to model a strict weak ordering, so // to satisfy irreflexivity we must return 'false' for elements that we consider // equivalent under the pattern. return false; }
/* well ordered compare */ int BSONObj::woCompare(const BSONObj &r, const BSONObj &idxKey, bool considerFieldName) const { if ( isEmpty() ) return r.isEmpty() ? 0 : -1; if ( r.isEmpty() ) return 1; bool ordered = !idxKey.isEmpty(); BSONObjIterator i(*this); BSONObjIterator j(r); BSONObjIterator k(idxKey); while ( 1 ) { // so far, equal... BSONElement l = i.next(); BSONElement r = j.next(); BSONElement o; if ( ordered ) o = k.next(); if ( l.eoo() ) return r.eoo() ? 0 : -1; if ( r.eoo() ) return 1; int x = l.woCompare( r, considerFieldName ); if ( ordered && o.number() < 0 ) x = -x; if ( x != 0 ) return x; } return -1; }
int compareObjectsAccordingToSort(const BSONObj& firstObj, const BSONObj& secondObj, const BSONObj& sortKey, bool assumeDottedPaths) { if (firstObj.isEmpty()) return secondObj.isEmpty() ? 0 : -1; if (secondObj.isEmpty()) return 1; uassert(10060, "compareObjectsAccordingToSort() needs a non-empty sortKey", !sortKey.isEmpty()); BSONObjIterator i(sortKey); while (1) { BSONElement f = i.next(); if (f.eoo()) return 0; BSONElement l = assumeDottedPaths ? extractElementAtPath(firstObj, f.fieldName()) : firstObj.getField(f.fieldName()); if (l.eoo()) l = kNullElt; BSONElement r = assumeDottedPaths ? extractElementAtPath(secondObj, f.fieldName()) : secondObj.getField(f.fieldName()); if (r.eoo()) r = kNullElt; int x = l.woCompare(r, false); if (f.number() < 0) x = -x; if (x != 0) return x; } return -1; }
int BSONObj::woCompare(const BSONObj& r, const Ordering &o, bool considerFieldName) const { if ( isEmpty() ) return r.isEmpty() ? 0 : -1; if ( r.isEmpty() ) return 1; BSONObjIterator i(*this); BSONObjIterator j(r); unsigned mask = 1; while ( 1 ) { // so far, equal... BSONElement l = i.next(); BSONElement r = j.next(); if ( l.eoo() ) return r.eoo() ? 0 : -1; if ( r.eoo() ) return 1; int x; { x = l.woCompare( r, considerFieldName ); if( o.descending(mask) ) x = -x; } if ( x != 0 ) return x; mask <<= 1; } return -1; }
// static void OrderedIntervalList::complement() { BSONObjBuilder minBob; minBob.appendMinKey(""); BSONObj minObj = minBob.obj(); // We complement by scanning the entire range of BSON values // from MinKey to MaxKey. The value from which we must begin // the next complemented interval is kept in 'curBoundary'. BSONElement curBoundary = minObj.firstElement(); // If 'curInclusive' is true, then 'curBoundary' is // included in one of the original intervals, and hence // should not be included in the complement (and vice-versa // if 'curInclusive' is false). bool curInclusive = false; // We will build up a list of intervals that represents // the inversion of those in the OIL. vector<Interval> newIntervals; for (size_t j = 0; j < intervals.size(); ++j) { Interval curInt = intervals[j]; if (0 != curInt.start.woCompare(curBoundary) || (!curInclusive && !curInt.startInclusive)) { // Make a new interval from 'curBoundary' to // the start of 'curInterval'. BSONObjBuilder intBob; intBob.append(curBoundary); intBob.append(curInt.start); Interval newInt(intBob.obj(), !curInclusive, !curInt.startInclusive); newIntervals.push_back(newInt); } // Reset the boundary for the next iteration. curBoundary = curInt.end; curInclusive = curInt.endInclusive; } // We may have to add a final interval which ends in MaxKey. BSONObjBuilder maxBob; maxBob.appendMaxKey(""); BSONObj maxObj = maxBob.obj(); BSONElement maxKey = maxObj.firstElement(); if (0 != maxKey.woCompare(curBoundary) || !curInclusive) { BSONObjBuilder intBob; intBob.append(curBoundary); intBob.append(maxKey); Interval newInt(intBob.obj(), !curInclusive, true); newIntervals.push_back(newInt); } // Replace the old list of intervals with the new one. intervals.clear(); intervals.insert(intervals.end(), newIntervals.begin(), newIntervals.end()); }
// This should behave the same as customBSONCmp from btree_logic.cpp. // // Reading the comment in the .h file is highly recommended if you need to understand what this // function is doing int IndexEntryComparison::compare(const IndexKeyEntry& lhs, const IndexKeyEntry& rhs) const { BSONObjIterator lhsIt(lhs.key); BSONObjIterator rhsIt(rhs.key); // Iterate through both BSONObjects, comparing individual elements one by one for (unsigned mask = 1; lhsIt.more(); mask <<= 1) { if (!rhsIt.more()) return _order.descending(mask) ? -1 : 1; const BSONElement l = lhsIt.next(); const BSONElement r = rhsIt.next(); if (int cmp = l.woCompare(r, /*compareFieldNames=*/false)) { if (cmp == std::numeric_limits<int>::min()) { // can't be negated cmp = -1; } return _order.descending(mask) ? -cmp : cmp; } // Here is where the weirdness begins. We sometimes want to fudge the comparison // when a key == the query to implement exclusive ranges. BehaviorIfFieldIsEqual lEqBehavior = BehaviorIfFieldIsEqual(l.fieldName()[0]); BehaviorIfFieldIsEqual rEqBehavior = BehaviorIfFieldIsEqual(r.fieldName()[0]); if (lEqBehavior) { // lhs is the query, rhs is the stored data invariant(rEqBehavior == normal); return lEqBehavior == less ? -1 : 1; } if (rEqBehavior) { // rhs is the query, lhs is the stored data, so reverse the returns invariant(lEqBehavior == normal); return rEqBehavior == less ? 1 : -1; } } if(rhsIt.more()) return -1; // This means just look at the key, not the loc. if (lhs.loc.isNull() || rhs.loc.isNull()) return 0; return lhs.loc.compare(rhs.loc); // is supposed to ignore ordering }
/* well ordered compare */ int BSONObj::woCompare(const BSONObj& r, const BSONObj& idxKey, bool considerFieldName, const StringData::ComparatorInterface* comparator) const { if (isEmpty()) return r.isEmpty() ? 0 : -1; if (r.isEmpty()) return 1; bool ordered = !idxKey.isEmpty(); BSONObjIterator i(*this); BSONObjIterator j(r); BSONObjIterator k(idxKey); while (1) { // so far, equal... BSONElement l = i.next(); BSONElement r = j.next(); BSONElement o; if (ordered) o = k.next(); if (l.eoo()) return r.eoo() ? 0 : -1; if (r.eoo()) return 1; int x; /* if( ordered && o.type() == String && strcmp(o.valuestr(), "ascii-proto") == 0 && l.type() == String && r.type() == String ) { // note: no negative support yet, as this is just sort of a POC x = _stricmp(l.valuestr(), r.valuestr()); } else*/ { x = l.woCompare(r, considerFieldName, comparator); if (ordered && o.number() < 0) x = -x; } if (x != 0) return x; } return -1; }
// PD_TRACE_DECLARE_FUNCTION ( SDB__IXMINXCB_ISSAMEDEF, "_ixmIndexCB::isSameDef" ) BOOLEAN _ixmIndexCB::isSameDef( const BSONObj &defObj, BOOLEAN strict ) const { BOOLEAN rs = TRUE; SDB_ASSERT( TRUE == _isInitialized, "indexCB must be intialized!" ); try { BSONElement beLKey = _infoObj.getField( IXM_KEY_FIELD ); BSONElement beRKey = defObj.getField( IXM_KEY_FIELD ); if ( 0 != beLKey.woCompare( beRKey, false ) ) { rs = FALSE; goto done; } BOOLEAN lIsUnique = FALSE; BOOLEAN rIsUnique = FALSE; BSONElement beLUnique = _infoObj.getField( IXM_UNIQUE_FIELD ); BSONElement beRUnique = defObj.getField( IXM_UNIQUE_FIELD ); if ( beLUnique.booleanSafe() ) { lIsUnique = TRUE; } if ( beRUnique.booleanSafe() ) { rIsUnique = TRUE; } if ( !strict ) { if ( lIsUnique ) { rs = TRUE ; goto done ; } else if ( lIsUnique != rIsUnique ) { rs = FALSE; goto done; } else { } } else { if ( lIsUnique != rIsUnique ) { rs = FALSE; goto done ; } } BOOLEAN lEnforced = FALSE; BOOLEAN rEnforced = FALSE; BSONElement beLEnforced = _infoObj.getField( IXM_ENFORCED_FIELD ); BSONElement beREnforced = defObj.getField( IXM_ENFORCED_FIELD ); if ( beLEnforced.booleanSafe() ) { lEnforced = TRUE; } if ( beREnforced.booleanSafe() ) { rEnforced = TRUE; } if ( lEnforced != rEnforced ) { rs = FALSE; goto done; } } catch( std::exception &e ) { rs = FALSE; PD_LOG( PDERROR, "occur unexpected error(%s)", e.what() ); } done: return rs; }
INT32 _qgmMatcher::_match( const _qgmConditionNode *node, const qgmFetchOut &fetch, BOOLEAN &r ) { PD_TRACE_ENTRY( SDB__QGMMATCHER__MATCH ) ; SDB_ASSERT( NULL != node, "impossible" ) ; INT32 rc = SDB_OK ; BSONObj obj ; BSONElement fromFetch ; BSONElement fromCondition ; try { if ( SQL_GRAMMAR::EG == node->type || SQL_GRAMMAR::NE == node->type || SQL_GRAMMAR::GT == node->type || SQL_GRAMMAR::LT == node->type || SQL_GRAMMAR::GTE == node->type || SQL_GRAMMAR::LTE == node->type || SQL_GRAMMAR::IS == node->type ) { rc = fetch.element( node->left->value, fromFetch ) ; if ( SDB_OK != rc ) { PD_LOG( PDERROR, "failed to get element from fetchout, rc=%d", rc ) ; goto error ; } if ( fromFetch.eoo() ) { r = SQL_GRAMMAR::NULLL == node->right->type ? TRUE : FALSE ; goto done ; } obj = _qgmConditionNodeHelper::toBson( node->right, node->left->value.attr().begin(), node->left->value.attr().size() ) ; fromCondition = obj.firstElement() ; if ( fromCondition.eoo() ) { SDB_ASSERT( FALSE, "impossible" ) ; rc = SDB_SYS ; goto error ; } if ( SQL_GRAMMAR::EG == node->type || SQL_GRAMMAR::IS == node->type ) { r = (0 == fromCondition.woCompare( fromFetch, FALSE )) ? TRUE : FALSE ; } else if ( SQL_GRAMMAR::NE == node->type ) { r = (0 == fromCondition.woCompare( fromFetch, FALSE )) ? FALSE : TRUE ; } else if ( SQL_GRAMMAR::LT == node->type ) { r = (0 < fromCondition.woCompare( fromFetch, FALSE )) ? TRUE : FALSE ; } else if ( SQL_GRAMMAR::GT == node->type ) { r = (0 > fromCondition.woCompare( fromFetch, FALSE )) ? TRUE : FALSE ; } else if ( SQL_GRAMMAR::GTE == node->type ) { INT32 wo = fromCondition.woCompare( fromFetch, FALSE ) ; r = ( 0 > wo ) || ( 0 == wo )? TRUE : FALSE ; } else { INT32 wo = fromCondition.woCompare( fromFetch, FALSE ) ; r = ( 0 < wo ) || ( 0 == wo )? TRUE : FALSE ; } } else if ( SQL_GRAMMAR::LIKE == node->type ) { rc = fetch.element( node->left->value, fromFetch ) ; if ( SDB_OK != rc ) { PD_LOG( PDERROR, "failed to get element from fetchout, rc=%d", rc ) ; goto error ; } if ( fromFetch.eoo() ) { r = FALSE ; goto done ; } if ( String != fromFetch.type() ) { r = FALSE ; } else { pcrecpp::RE regexMatch( node->right->value.toString().c_str() ) ; r = regexMatch.PartialMatch( fromFetch.valuestr() ) ; } } else if ( SQL_GRAMMAR::INN == node->type ) { SDB_ASSERT( NULL != node->right->var, "impossible" ) ; SDB_ASSERT( Array == node->right->var->type(), "impossible" ) ; rc = fetch.element( node->left->value, fromFetch ) ; if ( SDB_OK != rc ) { PD_LOG( PDERROR, "failed to get element from fetchout, rc=%d", rc ) ; goto error ; } if ( fromFetch.eoo() ) { r = FALSE ; goto done ; } r = FALSE ; { BSONObjIterator itr( node->right->var->embeddedObject()) ; while ( itr.more() ) { if ( 0 == itr.next().woCompare( fromFetch, FALSE ) ) { r = TRUE ; break ; } } } } else if ( SQL_GRAMMAR::NOT == node->type ) { BOOLEAN rleft = FALSE ; rc = _match( node->left, fetch, rleft ) ; if ( rc ) { goto error ; } r = !rleft ; } else { SDB_ASSERT( SQL_GRAMMAR::AND == node->type || SQL_GRAMMAR::OR == node->type, "impossible" ) ; BOOLEAN rleft = FALSE ; BOOLEAN rright = FALSE ; rc = _match( node->left, fetch, rleft ) ; if ( SDB_OK != rc ) { goto error ; } if ( !rleft && SQL_GRAMMAR::AND == node->type ) { r = FALSE ; goto done ; } else if ( rleft && SQL_GRAMMAR::OR == node->type ) { r = TRUE ; goto done ; } rc = _match( node->right, fetch, rright ) ; if ( SDB_OK != rc ) { goto error ; } r = rright ; } } catch ( std::exception & e) { PD_LOG( PDERROR, "unexpected err happened:%s", e.what() ) ; rc = SDB_SYS ; goto error ; } done: PD_TRACE_EXITRC( SDB__QGMMATCHER__MATCH, rc ) ; return rc ; error: goto done ; }
void Model::save( bool safe ) { scoped_ptr<ScopedDbConnection> conn( ScopedDbConnection::getScopedDbConnection (modelServer() ) ); BSONObjBuilder b; serialize( b ); BSONElement myId; { BSONObjIterator i = b.iterator(); while ( i.more() ) { BSONElement e = i.next(); if ( strcmp( e.fieldName() , "_id" ) == 0 ) { myId = e; break; } } } if ( myId.type() ) { if ( _id.isEmpty() ) { _id = myId.wrap(); } else if ( myId.woCompare( _id.firstElement() ) ) { stringstream ss; ss << "_id from serialize and stored differ: "; ss << '[' << myId << "] != "; ss << '[' << _id.firstElement() << ']'; throw UserException( 13121 , ss.str() ); } } if ( _id.isEmpty() ) { OID oid; oid.init(); b.appendOID( "_id" , &oid ); BSONObj o = b.obj(); conn->get()->insert( getNS() , o ); _id = o["_id"].wrap().getOwned(); LOG(4) << "inserted new model " << getNS() << " " << o << endl; } else { if ( myId.eoo() ) { myId = _id["_id"]; b.append( myId ); } verify( ! myId.eoo() ); BSONObjBuilder qb; qb.append( myId ); BSONObj q = qb.obj(); BSONObj o = b.obj(); LOG(4) << "updated model" << getNS() << " " << q << " " << o << endl; conn->get()->update( getNS() , q , o , true ); } string errmsg = ""; if ( safe ) errmsg = conn->get()->getLastError(); conn->done(); if ( safe && errmsg.size() ) throw UserException( 9003 , (string)"error on Model::save: " + errmsg ); }