Beispiel #1
0
    // 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;
    }
Beispiel #2
0
    /* 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;
    }
Beispiel #3
0
// 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;
}
Beispiel #4
0
    /* 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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
    // 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());
    }
Beispiel #8
0
    // 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
    }
Beispiel #9
0
/* 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;
}
Beispiel #10
0
   // 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;
   }
Beispiel #11
0
   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 ;
   }
Beispiel #12
0
    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 );
    }