void _getKeysArrEltFixed( vector<const char*> &fieldNames , vector<BSONElement> &fixed , const BSONElement &arrEntry, BSONObjSet &keys, int numNotFound, const BSONElement &arrObjElt, const set< unsigned > &arrIdxs, bool mayExpandArrayUnembedded ) const { // set up any terminal array values for( set<unsigned>::const_iterator j = arrIdxs.begin(); j != arrIdxs.end(); ++j ) { if ( *fieldNames[ *j ] == '\0' ) { fixed[ *j ] = mayExpandArrayUnembedded ? arrEntry : arrObjElt; } } // recurse _getKeys( fieldNames, fixed, ( arrEntry.type() == Object ) ? arrEntry.embeddedObject() : BSONObj(), keys, numNotFound, arrObjElt.embeddedObject() ); }
void IndexSpec::getKeys( const BSONObj &obj, BSONObjSetDefaultOrder &keys ) const { if ( _indexType.get() ){ _indexType->getKeys( obj , keys ); return; } vector<const char*> fieldNames( _fieldNames ); vector<BSONElement> fixed( _fixed ); _getKeys( fieldNames , fixed , obj, keys ); if ( keys.empty() ) keys.insert( _nullKey ); }
void getKeys( const BSONObj &obj, BSONObjSet &keys ) const { if ( _spec._indexType.get() ) { //plugin (eg geo) _spec._indexType->getKeys( obj , keys ); return; } vector<const char*> fieldNames( _spec._fieldNames ); vector<BSONElement> fixed( _spec._fixed ); _getKeys( fieldNames , fixed , obj, keys ); if ( keys.empty() && ! _spec._sparse ) keys.insert( _spec._nullKey ); }
// PD_TRACE_DECLARE_FUNCTION ( SDB__IXMKEYGEN_GETKEYS, "_ixmKeyGenerator::getKeys" ) INT32 getKeys ( const BSONObj &obj, BSONObjSet &keys, BSONElement *pArrEle ) const { INT32 rc = SDB_OK ; PD_TRACE_ENTRY ( SDB__IXMKEYGEN_GETKEYS ); SDB_ASSERT( _keygen, "spec can't be NULL" ) ; SDB_ASSERT( !_keygen->_fieldNames.empty(), "can not be empty" ) ; vector<const CHAR*> fieldNames ( _keygen->_fieldNames ) ; BSONElement arrEle ; try { rc = _getKeys( fieldNames, obj, keys, &arrEle ) ; } catch ( std::exception &e ) { PD_LOG( PDERROR, "unexpected err:%s", e.what() ) ; rc = SDB_INVALIDARG ; goto error ; } if ( SDB_OK != rc ) { PD_LOG ( PDERROR, "Failed to generate key from object: %s", obj.toString().c_str() ) ; goto error ; } if ( keys.empty() ) { keys.insert ( _keygen->_undefinedKey ) ; } if ( NULL != pArrEle && !arrEle.eoo() ) { *pArrEle = arrEle ; } done : PD_TRACE_EXITRC ( SDB__IXMKEYGEN_GETKEYS, rc ); return rc ; error : goto done ; }
void IndexSpec::_getKeys( vector<const char*> fieldNames , vector<BSONElement> fixed , const BSONObj &obj, BSONObjSetDefaultOrder &keys ) const { BSONElement arrElt; unsigned arrIdx = ~0; for( unsigned i = 0; i < fieldNames.size(); ++i ) { if ( *fieldNames[ i ] == '\0' ) continue; BSONElement e = obj.getFieldDottedOrArray( fieldNames[ i ] ); if ( e.eoo() ) e = _nullElt; // no matching field if ( e.type() != Array ) fieldNames[ i ] = ""; // no matching field or non-array match if ( *fieldNames[ i ] == '\0' ) fixed[ i ] = e; // no need for further object expansion (though array expansion still possible) if ( e.type() == Array && arrElt.eoo() ) { // we only expand arrays on a single path -- track the path here arrIdx = i; arrElt = e; } // enforce single array path here uassert( 10088 , "cannot index parallel arrays", e.type() != Array || e.rawdata() == arrElt.rawdata() ); } bool allFound = true; // have we found elements for all field names in the key spec? for( vector<const char*>::const_iterator i = fieldNames.begin(); i != fieldNames.end(); ++i ){ if ( **i != '\0' ){ allFound = false; break; } } bool insertArrayNull = false; if ( allFound ) { if ( arrElt.eoo() ) { // no terminal array element to expand BSONObjBuilder b(_sizeTracker); for( vector< BSONElement >::iterator i = fixed.begin(); i != fixed.end(); ++i ) b.appendAs( *i, "" ); keys.insert( b.obj() ); } else { // terminal array element to expand, so generate all keys BSONObjIterator i( arrElt.embeddedObject() ); if ( i.more() ){ while( i.more() ) { BSONObjBuilder b(_sizeTracker); for( unsigned j = 0; j < fixed.size(); ++j ) { if ( j == arrIdx ) b.appendAs( i.next(), "" ); else b.appendAs( fixed[ j ], "" ); } keys.insert( b.obj() ); } } else if ( fixed.size() > 1 ){ insertArrayNull = true; } } } else { // nonterminal array element to expand, so recurse assert( !arrElt.eoo() ); BSONObjIterator i( arrElt.embeddedObject() ); if ( i.more() ){ while( i.more() ) { BSONElement e = i.next(); if ( e.type() == Object ){ _getKeys( fieldNames, fixed, e.embeddedObject(), keys ); } } } else { insertArrayNull = true; } } if ( insertArrayNull ) { // x : [] - need to insert undefined BSONObjBuilder b(_sizeTracker); for( unsigned j = 0; j < fixed.size(); ++j ) { if ( j == arrIdx ){ b.appendUndefined( "" ); } else { BSONElement e = fixed[j]; if ( e.eoo() ) b.appendNull( "" ); else b.appendAs( e , "" ); } } keys.insert( b.obj() ); } }