Пример #1
0
 Interval:: Interval()
     : _intervalData(BSONObj())
     , start(BSONElement())
     , startInclusive(false)
     , end(BSONElement())
     , endInclusive(false) {
 }
Пример #2
0
ElementIterator::Context SimpleArrayElementIterator::next() {
    if (_iterator.more()) {
        Context e;
        e.reset(_iterator.next(), BSONElement());
        return e;
    }
    _returnArrayLast = false;
    Context e;
    e.reset(_theArray, BSONElement());
    return e;
}
Пример #3
0
        /**
         * @param arrayNestedArray - set if the returned element is an array nested directly within arr.
         */
        BSONElement extractNextElement( const BSONObj &obj, const BSONObj &arr, const char *&field, bool &arrayNestedArray ) const {
            string firstField = mongoutils::str::before( field, '.' );
            bool haveObjField = !obj.getField( firstField ).eoo();
            BSONElement arrField = arr.getField( firstField );
            bool haveArrField = !arrField.eoo();

            // An index component field name cannot exist in both a document array and one of that array's children.
            uassert( 15855,
                     mongoutils::str::stream() <<
                         "Ambiguous field name found in array (do not use numeric field names in "
                         "embedded elements in an array), field: '" << arrField.fieldName() <<
                         "' for array: " << arr,
                     !haveObjField || !haveArrField );

            arrayNestedArray = false;
			if ( haveObjField ) {
                return obj.getFieldDottedOrArray( field );
            }
            else if ( haveArrField ) {
                if ( arrField.type() == Array ) {
                    arrayNestedArray = true;
                }
                return arr.getFieldDottedOrArray( field );
            }
            return BSONElement();
        }
Пример #4
0
   INT32 _rtnSQLMax::result( BSONObjBuilder &builder )
   {
      INT32 rc = SDB_OK ;

      try
      {
         if ( _ele.eoo() )
         {
            builder.appendNull( _alias.toString() ) ;
         }
         else
         {
            builder.appendAs( _ele, _alias.toString() ) ;
         }

         _obj = BSONObj() ;
         _ele = BSONElement() ;
      }
      catch ( std::exception &e )
      {
         PD_LOG( PDERROR, "unexcepted err happened:%s",
                 e.what() ) ;
         rc = SDB_SYS ;
         goto error ;
      }

   done:
      return rc ;
   error:
      goto done ;
   }
Пример #5
0
BSONElement BtreeKeyGeneratorV1::extractNextElement(const BSONObj& obj,
                                                    const PositionalPathInfo& positionalInfo,
                                                    const char** field,
                                                    bool* arrayNestedArray) const {
    std::string firstField = mongoutils::str::before(*field, '.');
    bool haveObjField = !obj.getField(firstField).eoo();
    BSONElement arrField = positionalInfo.positionallyIndexedElt;

    // An index component field name cannot exist in both a document
    // array and one of that array's children.
    uassert(16746,
            mongoutils::str::stream()
                << "Ambiguous field name found in array (do not use numeric field names in "
                   "embedded elements in an array), field: '"
                << arrField.fieldName()
                << "' for array: "
                << positionalInfo.arrayObj,
            !haveObjField || !positionalInfo.hasPositionallyIndexedElt());

    *arrayNestedArray = false;
    if (haveObjField) {
        return dps::extractElementAtPathOrArrayAlongPath(obj, *field);
    } else if (positionalInfo.hasPositionallyIndexedElt()) {
        if (arrField.type() == Array) {
            *arrayNestedArray = true;
        }
        *field = positionalInfo.remainingPath;
        return positionalInfo.dottedElt;
    }
    return BSONElement();
}
Пример #6
0
    void IndexSpec::_init(){
        assert( keyPattern.objsize() );
        
        string pluginName = IndexPlugin::findPluginName( keyPattern );
        
        BSONObjBuilder nullKeyB;
        BSONObjIterator i( keyPattern );
        
        while( i.more() ) {
            BSONElement e = i.next();
            _fieldNames.push_back( e.fieldName() );
            _fixed.push_back( BSONElement() );
            nullKeyB.appendNull( "" );            
        }
        
        _nullKey = nullKeyB.obj();

        BSONObjBuilder b;
        b.appendNull( "" );
        _nullObj = b.obj();
        _nullElt = _nullObj.firstElement();
        
        if ( pluginName.size() ){
            IndexPlugin * plugin = IndexPlugin::get( pluginName );
            if ( ! plugin ){
                log() << "warning: can't find plugin [" << pluginName << "]" << endl;
            }
            else {
                _indexType.reset( plugin->generate( this ) );
            }
        }
        _finishedInit = true;
    }
Пример #7
0
    SortStage::SortStage(const SortStageParams& params, WorkingSet* ws, PlanStage* child)
        : _ws(ws),
          _child(child),
          _pattern(params.pattern),
          _sorted(false),
          _resultIterator(_data.end()),
          _bounds(params.bounds),
          _hasBounds(params.hasBounds),
          _memUsage(0) {

        _cmp.reset(new WorkingSetComparator(_pattern));

        // We'll need to treat arrays as if we were to create an index over them. that is,
        // we may need to unnest the first level and consider each array element to decide
        // the sort order.
        std::vector<const char *> fieldNames;
        std::vector<BSONElement> fixed;
        BSONObjIterator it(_pattern);
        while (it.more()) {
            BSONElement patternElt = it.next();
            fieldNames.push_back(patternElt.fieldName());
            fixed.push_back(BSONElement());
        }
        _keyGen.reset(new BtreeKeyGeneratorV1(fieldNames, fixed, false /* not sparse */));

        // See comment on the operator() call about sort semantics and why we need a
        // to use a bounds checker here.
        _boundsChecker.reset(new IndexBoundsChecker(&_bounds, _pattern, 1 /* == order */));
    }
Пример #8
0
        void getKeys( const BSONObj &obj, BSONObjSet &keys ) const {

            BSONElement loc = obj.getFieldDotted( _geo );
            if ( loc.eoo() )
                return;

            uassert( 13323 , "latlng not an array" , loc.isABSONObj() );
            string root;
            {
                BSONObjIterator i( loc.Obj() );
                BSONElement x = i.next();
                BSONElement y = i.next();
                root = makeString( hash(x) , hash(y) );
            }


            verify( _other.size() == 1 );

            BSONElementSet all;
            obj.getFieldsDotted( _other[0] , all );

            if ( all.size() == 0 ) {
                _add( obj , root , BSONElement() , keys );
            }
            else {
                for ( BSONElementSet::iterator i=all.begin(); i!=all.end(); ++i ) {
                    _add( obj , root , *i , keys );
                }
            }

        }
Пример #9
0
SortKeyGenerator::SortKeyGenerator(OperationContext* txn,
                                   const BSONObj& sortSpec,
                                   const BSONObj& queryObj) {
    _hasBounds = false;
    _sortHasMeta = false;
    _rawSortSpec = sortSpec;

    // 'sortSpec' can be a mix of $meta and index key expressions.  We pick it apart so that
    // we only generate Btree keys for the index key expressions.

    // The Btree key fields go in here.  We pass this fake index key pattern to the Btree
    // key generator below as part of generating sort keys for the docs.
    BSONObjBuilder btreeBob;

    BSONObjIterator it(sortSpec);
    while (it.more()) {
        BSONElement elt = it.next();
        if (elt.isNumber()) {
            // Btree key.  elt (should be) foo: 1 or foo: -1.
            btreeBob.append(elt);
        } else if (LiteParsedQuery::isTextScoreMeta(elt)) {
            _sortHasMeta = true;
        } else {
            // Sort spec. should have been validated before here.
            verify(false);
        }
    }

    // The fake index key pattern used to generate Btree keys.
    _btreeObj = btreeBob.obj();

    // If we're just sorting by meta, don't bother with all the key stuff.
    if (_btreeObj.isEmpty()) {
        return;
    }

    // We'll need to treat arrays as if we were to create an index over them. that is,
    // we may need to unnest the first level and consider each array element to decide
    // the sort order.
    std::vector<const char*> fieldNames;
    std::vector<BSONElement> fixed;
    BSONObjIterator btreeIt(_btreeObj);
    while (btreeIt.more()) {
        BSONElement patternElt = btreeIt.next();
        fieldNames.push_back(patternElt.fieldName());
        fixed.push_back(BSONElement());
    }

    // TODO SERVER-23095: change nullptr to the appropriate CollationInterface*.
    _keyGen.reset(new BtreeKeyGeneratorV1(fieldNames, fixed, false /* not sparse */, nullptr));

    // The bounds checker only works on the Btree part of the sort key.
    getBoundsForSort(txn, queryObj, _btreeObj);

    if (_hasBounds) {
        _boundsChecker.reset(new IndexBoundsChecker(&_bounds, _btreeObj, 1 /* == order */));
    }
}
Пример #10
0
    void IndexSpec::_init() {
        verify( keyPattern.objsize() );

        // some basics
        _nFields = keyPattern.nFields();
        _sparse = info["sparse"].trueValue();
        uassert( 13529 , "sparse only works for single field keys" , ! _sparse || _nFields );


        {
            // build _nullKey

            BSONObjBuilder b;
            BSONObjIterator i( keyPattern );

            while( i.more() ) {
                BSONElement e = i.next();
                _fieldNames.push_back( e.fieldName() );
                _fixed.push_back( BSONElement() );
                b.appendNull( "" );
            }
            _nullKey = b.obj();
        }

        {
            // _nullElt
            BSONObjBuilder b;
            b.appendNull( "" );
            _nullObj = b.obj();
            _nullElt = _nullObj.firstElement();
        }

        {
            // _undefinedElt
            BSONObjBuilder b;
            b.appendUndefined( "" );
            _undefinedObj = b.obj();
            _undefinedElt = _undefinedObj.firstElement();
        }
        
        {
            // handle plugins
            string pluginName = IndexPlugin::findPluginName( keyPattern );
            if ( pluginName.size() ) {
                IndexPlugin * plugin = IndexPlugin::get( pluginName );
                if ( ! plugin ) {
                    log() << "warning: can't find plugin [" << pluginName << "]" << endl;
                }
                else {
                    _indexType.reset( plugin->generate( this ) );
                }
            }
        }

        _finishedInit = true;
    }
Пример #11
0
bool BSONElementIterator::subCursorHasMore() {
    // While we still are still finding arrays along the path, keep traversing deeper.
    while (_subCursor) {
        if (_subCursor->more()) {
            return true;
        }
        _subCursor.reset();

        // If the subcursor doesn't have more, see if the current element is an array offset
        // match (see comment in BSONElementIterator::more() for an example).  If it is indeed
        // an array offset match, create a new subcursor and examine it.
        if (_arrayIterationState.isArrayOffsetMatch(_arrayIterationState._current.fieldName())) {
            if (_arrayIterationState.nextEntireRest()) {
                // Our path terminates at the array offset.  _next should point at the current
                // array element. _next._arrayOffset should be EOO, since this is not an implicit
                // array traversal.
                _next.reset(_arrayIterationState._current, BSONElement());
                _arrayIterationState._current = BSONElement();
                return true;
            }

            _subCursorPath.reset(new ElementPath());
            _subCursorPath->init(_arrayIterationState.restOfPath.substr(
                _arrayIterationState.nextPieceOfPath.size() + 1));
            _subCursorPath->setLeafArrayBehavior(_path->leafArrayBehavior());

            // If we're here, we must be able to traverse nonleaf arrays.
            dassert(_path->nonLeafArrayBehavior() == ElementPath::NonLeafArrayBehavior::kTraverse);
            dassert(_subCursorPath->nonLeafArrayBehavior() ==
                    ElementPath::NonLeafArrayBehavior::kTraverse);

            _subCursor.reset(
                new BSONElementIterator(_subCursorPath.get(), _arrayIterationState._current.Obj()));

            // Set _arrayIterationState._current to EOO. This is not an implicit array traversal, so
            // we should not override the array offset of the subcursor with the current array
            // offset.
            _arrayIterationState._current = BSONElement();
        }
    }

    return false;
}
Пример #12
0
 INT32 _ixmIndexKeyGen::getKeys ( const BSONObj &obj, BSONObjSet &keys,
                                  BSONElement *pArrEle ) const
 {
    ixmKeyGenerator g (this) ;
    if ( pArrEle )
    {
       *pArrEle = BSONElement() ;
    }
    return g.getKeys ( obj, keys, pArrEle ) ;
 }
Пример #13
0
OpMsgRequest upconvertRequest(StringData db, BSONObj cmdObj, int queryFlags) {
    cmdObj = cmdObj.getOwned();  // Usually this is a no-op since it is already owned.

    auto readPrefContainer = BSONObj();
    const StringData firstFieldName = cmdObj.firstElementFieldName();
    if (firstFieldName == "$query" || firstFieldName == "query") {
        // Commands sent over OP_QUERY specify read preference by putting it at the top level and
        // putting the command in a nested field called either query or $query.

        // Check if legacyCommand has an invalid $maxTimeMS option.
        uassert(ErrorCodes::InvalidOptions,
                "cannot use $maxTimeMS query option with commands; use maxTimeMS command option "
                "instead",
                !cmdObj.hasField("$maxTimeMS"));

        if (auto readPref = cmdObj["$readPreference"])
            readPrefContainer = readPref.wrap();

        cmdObj = cmdObj.firstElement().Obj().shareOwnershipWith(cmdObj);
    } else if (auto queryOptions = cmdObj["$queryOptions"]) {
        // Mongos rewrites commands with $readPreference to put it in a field nested inside of
        // $queryOptions. Its command implementations often forward commands in that format to
        // shards. This function is responsible for rewriting it to a format that the shards
        // understand.
        readPrefContainer = queryOptions.Obj().shareOwnershipWith(cmdObj);
        cmdObj = cmdObj.removeField("$queryOptions");
    }

    if (!readPrefContainer.isEmpty()) {
        cmdObj = BSONObjBuilder(std::move(cmdObj)).appendElements(readPrefContainer).obj();
    } else if (!cmdObj.hasField("$readPreference") && (queryFlags & QueryOption_SlaveOk)) {
        BSONObjBuilder bodyBuilder(std::move(cmdObj));
        ReadPreferenceSetting(ReadPreference::SecondaryPreferred).toContainingBSON(&bodyBuilder);
        cmdObj = bodyBuilder.obj();
    }

    // Try to move supported array fields into document sequences.
    auto docSequenceIt = docSequenceFieldsForCommands.find(cmdObj.firstElementFieldName());
    auto docSequenceElem = docSequenceIt == docSequenceFieldsForCommands.end()
        ? BSONElement()
        : cmdObj[docSequenceIt->second];
    if (!isArrayOfObjects(docSequenceElem))
        return OpMsgRequest::fromDBAndBody(db, std::move(cmdObj));

    auto docSequenceName = docSequenceElem.fieldNameStringData();

    // Note: removing field before adding "$db" to avoid the need to copy the potentially large
    // array.
    auto out = OpMsgRequest::fromDBAndBody(db, cmdObj.removeField(docSequenceName));
    out.sequences.push_back({docSequenceName.toString()});
    for (auto elem : docSequenceElem.Obj()) {
        out.sequences[0].objs.push_back(elem.Obj().shareOwnershipWith(cmdObj));
    }
    return out;
}
Пример #14
0
int ixmBucketManager::ixmBucket::removeIndex(unsigned int hashNum,
                                             ixmEleHash &eleHash)
{
   int rc = EDB_OK;
   BSONElement destEle;
   BSONElement sourEle;
   ixmEleHash existEle;
   std::pair<std::multimap<unsigned int, ixmEleHash>::iterator,
             std::multimap<unsigned int, ixmEleHash>::iterator> ret;
   _mutex.get();
   ret = _bucketMap.equal_range(hashNum);
   sourEle = BSONElement(eleHash.data);
   for(std::multimap<unsigned int, ixmEleHash>::iterator it = ret.first;
         it != ret.second; ++it)
   {
      existEle = it->second;
      destEle = BSONElement(existEle.data);
      if(sourEle.type() == destEle.type())
      {
         if(sourEle.valuesize() == destEle.valuesize())
         {
            if(!memcmp(sourEle.value(), destEle.value(),
                           destEle.valuesize()))
            {
               eleHash.recordID = existEle.recordID;
               _bucketMap.erase(it);
               goto done;
            }
         }
      }
   }
   rc = EDB_INVALIDARG;
   PD_LOG(PDERROR, "record _id does not exist");
   goto error;
done:
   _mutex.release();
   return rc;
error:
   goto done;
}
Пример #15
0
BSONElement extractElementAtPathOrArrayAlongPath(const BSONObj& obj, const char*& path) {
    const char* p = strchr(path, '.');

    BSONElement sub;

    if (p) {
        sub = obj.getField(std::string(path, p - path));
        path = p + 1;
    } else {
        sub = obj.getField(path);
        path = path + strlen(path);
    }

    if (sub.eoo())
        return BSONElement();
    else if (sub.type() == Array || path[0] == '\0')
        return sub;
    else if (sub.type() == Object)
        return extractElementAtPathOrArrayAlongPath(sub.embeddedObject(), path);
    else
        return BSONElement();
}
Пример #16
0
void BSONElementIterator::reset(const ElementPath* path,
                                size_t suffixIndex,
                                BSONElement elementToIterate) {
    _path = path;
    _traversalStartIndex = 0;
    _traversalStart = BSONElement();
    _setTraversalStart(suffixIndex, elementToIterate);
    _state = BEGIN;
    _next.reset();

    _subCursor.reset();
    _subCursorPath.reset();
}
Пример #17
0
 BSONElement BSONObj::getFieldUsingIndexNames(const char *fieldName, const BSONObj &indexKey) const {
     BSONObjIterator i( indexKey );
     int j = 0;
     while( i.more() ) {
         BSONElement f = i.next();
         if ( f.eoo() )
             return BSONElement();
         if ( strcmp( f.fieldName(), fieldName ) == 0 )
             break;
         ++j;
     }
     BSONObjIterator k( *this );
     while( k.more() ) {
         BSONElement g = k.next();
         if ( g.eoo() )
             return BSONElement();
         if ( j == 0 ) {
             return g;
         }
         --j;
     }
     return BSONElement();
 }
Пример #18
0
BSONElement extractElementAtPath(const BSONObj& obj, StringData path) {
    BSONElement e = obj.getField(path);
    if (e.eoo()) {
        size_t dot_offset = path.find('.');
        if (dot_offset != std::string::npos) {
            StringData left = path.substr(0, dot_offset);
            StringData right = path.substr(dot_offset + 1);
            BSONObj sub = obj.getObjectField(left);
            return sub.isEmpty() ? BSONElement() : extractElementAtPath(sub, right);
        }
    }

    return e;
}
Пример #19
0
int ixmBucketManager::ixmBucket::isIDExist(unsigned int hashNum,
                                           ixmEleHash &eleHash)
{
   int rc = EDB_OK;
   BSONElement destEle;
   BSONElement sourEle;
   ixmEleHash existEle;
   std::pair<std::multimap<unsigned int, ixmEleHash>::iterator,
             std::multimap<unsigned int, ixmEleHash>::iterator> ret;
   _mutex.get_shared();
   ret = _bucketMap.equal_range(hashNum);
   sourEle = BSONElement(eleHash.data);
   for(std::multimap<unsigned int, ixmEleHash>::iterator it = ret.first;
         it != ret.second; ++it)
   {
      existEle = it->second;
      destEle = BSONElement(existEle.data);
      if(sourEle.type() == destEle.type())
      {
         if(sourEle.valuesize() == destEle.valuesize())
         {
            if(!memcmp(sourEle.value(), destEle.value(),
                           destEle.valuesize()))
            {
               rc = EDB_IXM_ID_EXIST;
               PD_LOG(PDERROR, "record _id does exist");
               goto error;
            }
         }
      }
   }
done:
   _mutex.release_shared();
   return rc;
error:
   goto done;
}
Пример #20
0
bool BSONElementIterator::subCursorHasMore() {
    // While we still are still finding arrays along the path, keep traversing deeper.
    while (_subCursor) {
        if (_subCursor->more()) {
            return true;
        }
        _subCursor.reset();

        // If the subcursor doesn't have more, see if the current element is an array offset
        // match (see comment in BSONElementIterator::more() for an example).  If it is indeed
        // an array offset match, create a new subcursor and examine it.
        if (_arrayIterationState.isArrayOffsetMatch(_arrayIterationState._current.fieldName())) {
            if (_arrayIterationState.nextEntireRest()) {
                // Our path terminates at the array offset.  _next should point at the current
                // array element.
                _next.reset(_arrayIterationState._current, _arrayIterationState._current, true);
                _arrayIterationState._current = BSONElement();
                return true;
            }

            _subCursorPath.reset(new ElementPath());
            _subCursorPath->init(_arrayIterationState.restOfPath.substr(
                _arrayIterationState.nextPieceOfPath.size() + 1));
            _subCursorPath->setTraverseLeafArray(_path->shouldTraverseLeafArray());

            // If we're here, we must be able to traverse nonleaf arrays.
            dassert(_path->shouldTraverseNonleafArrays());
            dassert(_subCursorPath->shouldTraverseNonleafArrays());

            _subCursor.reset(
                new BSONElementIterator(_subCursorPath.get(), _arrayIterationState._current.Obj()));
            _arrayIterationState._current = BSONElement();
        }
    }

    return false;
}
Пример #21
0
   ///PD_TRACE_DECLARE_FUNCTION ( SDB__MTHELEMMATCHGETN, "mthElemMatchGetN" )
   static INT32 mthElemMatchGetN( const CHAR *fieldName,
                                  const bson::BSONElement &in,
                                  _mthSAction *action,
                                  bson::BSONElement &out,
                                  INT32 n )
   {
      INT32 rc = SDB_OK ;
      PD_TRACE_ENTRY( SDB__MTHELEMMATCHGETN ) ;
      if ( Array == in.type() )
      {
         BSONObjBuilder objBuilder ;
         BSONArrayBuilder arrayBuilder( objBuilder.subarrayStart( fieldName ) ) ;
         _mthElemMatchIterator i( in.embeddedObject(),
                                  &( action->getMatcher() ),
                                  n ) ;
         do
         {
            BSONElement next ;
            rc = i.next( next ) ;
            if ( SDB_OK == rc )
            {
               arrayBuilder.append( next ) ;
            }
            else if ( SDB_DMS_EOC == rc )
            {
               arrayBuilder.doneFast() ;
               rc = SDB_OK ;
               break ;
            }
            else
            {
               PD_LOG( PDERROR, "failed to get next element:%d", rc ) ;
               goto error ;
            }
         } while ( TRUE ) ;

         action->setObj( objBuilder.obj() ) ;
         out = action->getObj().getField( fieldName ) ;
      }
      else
      {
         out = BSONElement() ;
      }
   done:
      PD_TRACE_EXITRC( SDB__MTHELEMMATCHGETN, rc ) ;
      return rc ;
   error:
      goto done ;
   }
Пример #22
0
    BSONElement getErrField(const BSONObj& o) {
        BSONElement first = o.firstElement();
        if( strcmp(first.fieldName(), "$err") == 0 )
            return first;

        // temp - will be DEV only later
        /*DEV*/ 
        if( 1 ) {
            BSONElement e = o["$err"];
            if( !e.eoo() ) { 
                wassert(false);
            }
            return e;
        }

        return BSONElement();
    }
Пример #23
0
 // PD_TRACE_DECLARE_FUNCTION ( SDB__IXMINXKEYGEN__INIT, "_ixmIndexKeyGen::_init" )
 void _ixmIndexKeyGen::_init()
 {
    PD_TRACE_ENTRY ( SDB__IXMINXKEYGEN__INIT );
    _nFields = _keyPattern.nFields () ;
    INT32 fieldNum = 0 ;
    {
       BSONObjIterator i(_keyPattern) ;
       while ( i.more())
       {
          BSONElement e = i.next() ;
          _fieldNames.push_back(e.fieldName()) ;
          _fixedElements.push_back(BSONElement()) ;
          ++fieldNum ;
       }
       _undefinedKey = ixmGetUndefineKeyObj( fieldNum ) ;
    }
    PD_TRACE_EXIT ( SDB__IXMINXKEYGEN__INIT );
 }
Пример #24
0
    BSONElement getFieldDottedOrArray( const BSONObj& doc,
                                       const FieldRef& path,
                                       size_t* idxPath ) {
        if ( path.numParts() == 0 )
            return doc.getField( "" );

        BSONElement res;

        BSONObj curr = doc;
        bool stop = false;
        size_t partNum = 0;
        while ( partNum < path.numParts() && !stop ) {

            res = curr.getField( path.getPart( partNum ) );

            switch ( res.type() ) {

            case EOO:
                stop = true;
                break;

            case Object:
                curr = res.Obj();
                ++partNum;
                break;

            case Array:
                stop = true;
                break;

            default:
                if ( partNum+1 < path.numParts() ) {
                    res = BSONElement();
                }
                stop = true;

            }
        }

        *idxPath = partNum;
        return res;
    }
Пример #25
0
        void getKeys(const BSONObj &obj, BSONObjSet &keys) const {
            BSONElement loc = obj.getFieldDotted(_geoField);
            if (loc.eoo())
                return;

            uassert(13323, "latlng not an array", loc.isABSONObj());
            string root;
            {
                BSONObjIterator i(loc.Obj());
                BSONElement x = i.next();
                BSONElement y = i.next();
                root = makeString(hash(x), hash(y));
            }

            verify(_otherFields.size() == 1);

            BSONElementSet all;

            // This is getFieldsDotted (plural not singular) since the object we're indexing
            // may be an array.
            obj.getFieldsDotted(_otherFields[0], all);

            if (all.size() == 0) {
                // We're indexing a document that doesn't have the secondary non-geo field present.
                // XXX: do we want to add this even if all.size() > 0?  result:empty search terms
                // match everything instead of only things w/empty search terms)
                addKey(root, BSONElement(), keys);
            } else {
                // Ex:If our secondary field is type: "foo" or type: {a:"foo", b:"bar"},
                // all.size()==1.  We can query on the complete field.
                // Ex: If our secondary field is type: ["A", "B"] all.size()==2 and all has values
                // "A" and "B".  The query looks for any of the fields in the array.
                for (BSONElementSet::iterator i = all.begin(); i != all.end(); ++i) {
                    addKey(root, *i, keys);
                }
            }
        }
Пример #26
0
// Standard Btree implementation below.
BtreeAccessMethod::BtreeAccessMethod(IndexCatalogEntry* btreeState)
    : BtreeBasedAccessMethod(btreeState) {

    // The key generation wants these values.
    vector<const char*> fieldNames;
    vector<BSONElement> fixed;

    BSONObjIterator it(_descriptor->keyPattern());
    while (it.more()) {
        BSONElement elt = it.next();
        fieldNames.push_back(elt.fieldName());
        fixed.push_back(BSONElement());
    }

    if (0 == _descriptor->version()) {
        _keyGenerator.reset(new BtreeKeyGeneratorV0(fieldNames, fixed,
                            _descriptor->isSparse()));
    } else if (1 == _descriptor->version()) {
        _keyGenerator.reset(new BtreeKeyGeneratorV1(fieldNames, fixed,
                            _descriptor->isSparse()));
    } else {
        massert(16745, "Invalid index version for key generation.", false );
    }
}
Пример #27
0
void ElementIterator::Context::reset() {
    _element = BSONElement();
}
Пример #28
0
bool BSONElementIterator::more() {
    if (subCursorHasMore()) {
        return true;
    }

    if (!_next.element().eoo()) {
        return true;
    }

    if (_state == DONE) {
        return false;
    }

    if (_state == BEGIN) {
        if (_traversalStart.type() != Array) {
            _next.reset(_traversalStart, BSONElement());
            _state = DONE;
            return true;
        }

        // It's an array.

        _arrayIterationState.reset(_path->fieldRef(), _traversalStartIndex + 1);

        if (_arrayIterationState.hasMore &&
            _path->nonLeafArrayBehavior() != ElementPath::NonLeafArrayBehavior::kTraverse) {
            // Don't allow traversing the array.
            if (_path->nonLeafArrayBehavior() == ElementPath::NonLeafArrayBehavior::kMatchSubpath) {
                _next.reset(_traversalStart, BSONElement());
                _state = DONE;
                return true;
            }

            _state = DONE;
            return false;
        } else if (!_arrayIterationState.hasMore &&
                   _path->leafArrayBehavior() == ElementPath::LeafArrayBehavior::kNoTraversal) {
            // Return the leaf array.
            _next.reset(_traversalStart, BSONElement());
            _state = DONE;
            return true;
        }

        _arrayIterationState.startIterator(_traversalStart);
        _state = IN_ARRAY;

        invariant(_next.element().eoo());
    }

    if (_state == IN_ARRAY) {
        // We're traversing an array.  Look at each array element.

        while (_arrayIterationState.more()) {
            BSONElement eltInArray = _arrayIterationState.next();
            if (!_arrayIterationState.hasMore) {
                // Our path terminates at this array.  _next should point at the current array
                // element.
                _next.reset(eltInArray, eltInArray);
                return true;
            }

            // Our path does not terminate at this array; there's a subpath left over.  Inspect
            // the current array element to see if it could match the subpath.

            if (eltInArray.type() == Object) {
                // The current array element is a subdocument.  See if the subdocument generates
                // any elements matching the remaining subpath.
                _subCursorPath.reset(new ElementPath());
                _subCursorPath->init(_arrayIterationState.restOfPath);
                _subCursorPath->setLeafArrayBehavior(_path->leafArrayBehavior());

                _subCursor.reset(new BSONElementIterator(_subCursorPath.get(), eltInArray.Obj()));
                if (subCursorHasMore()) {
                    return true;
                }
            } else if (_arrayIterationState.isArrayOffsetMatch(eltInArray.fieldName())) {
                // The path we're traversing has an array offset component, and the current
                // array element corresponds to the offset we're looking for (for example: our
                // path has a ".0" component, and we're looking at the first element of the
                // array, so we should look inside this element).

                if (_arrayIterationState.nextEntireRest()) {
                    // Our path terminates at the array offset.  _next should point at the
                    // current array element. _next._arrayOffset should be EOO, since this is not an
                    // implicit array traversal.
                    _next.reset(eltInArray, BSONElement());
                    return true;
                }

                invariant(eltInArray.type() != Object);  // Handled above.
                if (eltInArray.type() == Array) {
                    // The current array element is itself an array.  See if the nested array
                    // has any elements matching the remainihng.
                    _subCursorPath.reset(new ElementPath());
                    _subCursorPath->init(_arrayIterationState.restOfPath.substr(
                        _arrayIterationState.nextPieceOfPath.size() + 1));
                    _subCursorPath->setLeafArrayBehavior(_path->leafArrayBehavior());
                    BSONElementIterator* real = new BSONElementIterator(
                        _subCursorPath.get(), _arrayIterationState._current.Obj());
                    _subCursor.reset(real);
                    real->_arrayIterationState.reset(_subCursorPath->fieldRef(), 0);
                    real->_arrayIterationState.startIterator(eltInArray);
                    real->_state = IN_ARRAY;

                    // Set _arrayIterationState._current to EOO. This is not an implicit array
                    // traversal, so we should not override the array offset of the subcursor with
                    // the current array offset.
                    _arrayIterationState._current = BSONElement();

                    if (subCursorHasMore()) {
                        return true;
                    }
                }
            }
        }

        if (_arrayIterationState.hasMore) {
            return false;
        }

        _next.reset(_arrayIterationState._theArray, BSONElement());
        _state = DONE;
        return true;
    }

    return false;
}
Пример #29
0
    bool BSONElementIterator::more() {
        if ( _subCursor ) {

            if ( _subCursor->more() )
                return true;

            _subCursor.reset();

            if ( _arrayIterationState.isArrayOffsetMatch( _arrayIterationState._current.fieldName() ) ) {
                if ( _arrayIterationState.nextEntireRest() ) {
                    _next.reset( _arrayIterationState._current, _arrayIterationState._current, true );
                    _arrayIterationState._current = BSONElement();
                    return true;
                }

                _subCursorPath.reset( new ElementPath() );
                _subCursorPath->init( _arrayIterationState.restOfPath.substr( _arrayIterationState.nextPieceOfPath.size() + 1 ) );
                _subCursorPath->setTraverseLeafArray( _path->shouldTraverseLeafArray() );
                _subCursor.reset( new BSONElementIterator( _subCursorPath.get(), _arrayIterationState._current.Obj() ) );
                _arrayIterationState._current = BSONElement();
                return more();
            }

        }

        if ( !_next.element().eoo() )
            return true;

        if ( _state == DONE ){
            return false;
        }

        if ( _state == BEGIN ) {
            size_t idxPath = 0;
            BSONElement e = getFieldDottedOrArray( _context, _path->fieldRef(), &idxPath );

            if ( e.type() != Array ) {
                _next.reset( e, BSONElement(), false );
                _state = DONE;
                return true;
            }

            // its an array

            _arrayIterationState.reset( _path->fieldRef(), idxPath + 1 );

            if ( !_arrayIterationState.hasMore && !_path->shouldTraverseLeafArray() ) {
                _next.reset( e, BSONElement(), true );
                _state = DONE;
                return true;
            }

            _arrayIterationState.startIterator( e );
            _state = IN_ARRAY;
            return more();
        }

        if ( _state == IN_ARRAY ) {

            while ( _arrayIterationState.more() ) {

                BSONElement x = _arrayIterationState.next();
                if ( !_arrayIterationState.hasMore ) {
                    _next.reset( x, x, false );
                    return true;
                }

                // i have deeper to go

                if ( x.type() == Object ) {
                    _subCursorPath.reset( new ElementPath() );
                    _subCursorPath->init( _arrayIterationState.restOfPath );
                    _subCursorPath->setTraverseLeafArray( _path->shouldTraverseLeafArray() );

                    _subCursor.reset( new BSONElementIterator( _subCursorPath.get(), x.Obj() ) );
                    return more();
                }


                if ( _arrayIterationState.isArrayOffsetMatch( x.fieldName() ) ) {

                    if ( _arrayIterationState.nextEntireRest() ) {
                        _next.reset( x, x, false );
                        return true;
                    }

                    if ( x.isABSONObj() ) {
                        _subCursorPath.reset( new ElementPath() );
                        _subCursorPath->init( _arrayIterationState.restOfPath.substr( _arrayIterationState.nextPieceOfPath.size() + 1 ) );
                        _subCursorPath->setTraverseLeafArray( _path->shouldTraverseLeafArray() );
                        BSONElementIterator* real = new BSONElementIterator( _subCursorPath.get(), _arrayIterationState._current.Obj() );
                        _subCursor.reset( real );
                        real->_arrayIterationState.reset( _subCursorPath->fieldRef(), 0 );
                        real->_arrayIterationState.startIterator( x );
                        real->_state = IN_ARRAY;
                        _arrayIterationState._current = BSONElement();
                        return more();
                    }
                }

            }

            if ( _arrayIterationState.hasMore )
                return false;

            _next.reset( _arrayIterationState._theArray, BSONElement(), true );
            _state = DONE;
            return true;
        }

        return false;
    }
Пример #30
0
bool BSONElementIterator::more() {
    if (subCursorHasMore()) {
        return true;
    }

    if (!_next.element().eoo()) {
        return true;
    }

    if (_state == DONE) {
        return false;
    }

    if (_state == BEGIN) {
        size_t idxPath = 0;
        BSONElement e = getFieldDottedOrArray(_context, _path->fieldRef(), &idxPath);

        if (e.type() != Array) {
            _next.reset(e, BSONElement(), false);
            _state = DONE;
            return true;
        }

        // It's an array.

        _arrayIterationState.reset(_path->fieldRef(), idxPath + 1);

        if (_arrayIterationState.hasMore && !_path->shouldTraverseNonleafArrays()) {
            // Don't allow traversing the array.
            _state = DONE;
            return false;
        } else if (!_arrayIterationState.hasMore && !_path->shouldTraverseLeafArray()) {
            // Return the leaf array.
            _next.reset(e, BSONElement(), true);
            _state = DONE;
            return true;
        }

        _arrayIterationState.startIterator(e);
        _state = IN_ARRAY;

        invariant(_next.element().eoo());
    }

    if (_state == IN_ARRAY) {
        // We're traversing an array.  Look at each array element.

        while (_arrayIterationState.more()) {
            BSONElement eltInArray = _arrayIterationState.next();
            if (!_arrayIterationState.hasMore) {
                // Our path terminates at this array.  _next should point at the current array
                // element.
                _next.reset(eltInArray, eltInArray, false);
                return true;
            }

            // Our path does not terminate at this array; there's a subpath left over.  Inspect
            // the current array element to see if it could match the subpath.

            if (eltInArray.type() == Object) {
                // The current array element is a subdocument.  See if the subdocument generates
                // any elements matching the remaining subpath.
                _subCursorPath.reset(new ElementPath());
                _subCursorPath->init(_arrayIterationState.restOfPath);
                _subCursorPath->setTraverseLeafArray(_path->shouldTraverseLeafArray());

                _subCursor.reset(new BSONElementIterator(_subCursorPath.get(), eltInArray.Obj()));
                if (subCursorHasMore()) {
                    return true;
                }
            } else if (_arrayIterationState.isArrayOffsetMatch(eltInArray.fieldName())) {
                // The path we're traversing has an array offset component, and the current
                // array element corresponds to the offset we're looking for (for example: our
                // path has a ".0" component, and we're looking at the first element of the
                // array, so we should look inside this element).

                if (_arrayIterationState.nextEntireRest()) {
                    // Our path terminates at the array offset.  _next should point at the
                    // current array element.
                    _next.reset(eltInArray, eltInArray, false);
                    return true;
                }

                invariant(eltInArray.type() != Object);  // Handled above.
                if (eltInArray.type() == Array) {
                    // The current array element is itself an array.  See if the nested array
                    // has any elements matching the remainihng.
                    _subCursorPath.reset(new ElementPath());
                    _subCursorPath->init(_arrayIterationState.restOfPath.substr(
                        _arrayIterationState.nextPieceOfPath.size() + 1));
                    _subCursorPath->setTraverseLeafArray(_path->shouldTraverseLeafArray());
                    BSONElementIterator* real = new BSONElementIterator(
                        _subCursorPath.get(), _arrayIterationState._current.Obj());
                    _subCursor.reset(real);
                    real->_arrayIterationState.reset(_subCursorPath->fieldRef(), 0);
                    real->_arrayIterationState.startIterator(eltInArray);
                    real->_state = IN_ARRAY;
                    _arrayIterationState._current = BSONElement();
                    if (subCursorHasMore()) {
                        return true;
                    }
                }
            }
        }

        if (_arrayIterationState.hasMore) {
            return false;
        }

        _next.reset(_arrayIterationState._theArray, BSONElement(), true);
        _state = DONE;
        return true;
    }

    return false;
}