void GeoParser::parseLegacyPoint(const BSONObj &obj, Point *out) { BSONObjIterator it(obj); BSONElement x = it.next(); BSONElement y = it.next(); out->x = x.number(); out->y = y.number(); }
bool GeoParser::parseCap(const BSONObj& obj, CapWithCRS *out) { if (isLegacyCenter(obj)) { BSONObjIterator typeIt(obj); BSONElement type = typeIt.next(); BSONObjIterator objIt(type.embeddedObject()); BSONElement center = objIt.next(); if (!parseLegacyPoint(center.Obj(), &out->circle.center)) { return false; } BSONElement radius = objIt.next(); out->circle.radius = radius.number(); out->crs = FLAT; } else { verify(isLegacyCenterSphere(obj)); BSONObjIterator typeIt(obj); BSONElement type = typeIt.next(); BSONObjIterator objIt(type.embeddedObject()); BSONObj centerObj = objIt.next().Obj(); S2Point centerPoint; BSONObjIterator it(centerObj); BSONElement x = it.next(); BSONElement y = it.next(); centerPoint = coordToPoint(x.Number(), y.Number()); BSONElement radiusElt = objIt.next(); double radius = radiusElt.number(); out->cap = S2Cap::FromAxisAngle(centerPoint, S1Angle::Radians(radius)); out->circle.radius = radius; out->circle.center = Point(x.Number(), y.Number()); out->crs = SPHERE; } return true; }
Status GeoParser::parseCenterSphere(const BSONObj& obj, CapWithCRS *out) { BSONObjIterator objIt(obj); // Center BSONElement center = objIt.next(); Point p; // Check the object has and only has 2 numbers. Status status = parseFlatPoint(center, &p); if (!status.isOK()) return status; S2Point centerPoint; status = coordToPoint(p.x, p.y, ¢erPoint); if (!status.isOK()) return status; // Radius BSONElement radiusElt = objIt.next(); // radius >= 0 and is not NaN if (!radiusElt.isNumber() || !(radiusElt.number() >= 0)) return BAD_VALUE("radius must be a non-negative number"); double radius = radiusElt.number(); // No more elements if (objIt.more()) return BAD_VALUE("Only 2 fields allowed for circular region"); out->cap = S2Cap::FromAxisAngle(centerPoint, S1Angle::Radians(radius)); out->circle.radius = radius; out->circle.center = p; out->crs = SPHERE; return Status::OK(); }
double StatUtil::diff( const string& name , const BSONObj& a , const BSONObj& b ) { BSONElement x = a.getFieldDotted( name.c_str() ); BSONElement y = b.getFieldDotted( name.c_str() ); if ( ! x.isNumber() || ! y.isNumber() ) return -1; return ( y.number() - x.number() ) / _seconds; }
bool GeoParser::parsePointWithMaxDistance(const BSONObj& obj, PointWithCRS* out, double* maxOut) { BSONObjIterator it(obj); if (!it.more()) { return false; } BSONElement lng = it.next(); if (!lng.isNumber()) { return false; } if (!it.more()) { return false; } BSONElement lat = it.next(); if (!lat.isNumber()) { return false; } if (!it.more()) { return false; } BSONElement dist = it.next(); if (!dist.isNumber()) { return false; } if (it.more()) { return false; } out->crs = FLAT; out->oldPoint.x = lng.number(); out->oldPoint.y = lat.number(); *maxOut = dist.number(); if (isValidLngLat(lng.Number(), lat.Number())) { out->flatUpgradedToSphere = true; out->point = coordToPoint(lng.Number(), lat.Number()); out->cell = S2Cell(out->point); } return true; }
static bool parseLegacyPoint(const BSONObj &obj, Point *out) { BSONObjIterator it(obj); BSONElement x = it.next(); BSONElement y = it.next(); out->x = x.number(); out->y = y.number(); return true; }
bool GeoParser::parsePoint(const BSONObj &obj, S2Point *out) { if (isGeoJSONPoint(obj)) { parseGeoJSONPoint(obj, out); return true; } else if (isLegacyPoint(obj)) { BSONObjIterator it(obj); BSONElement x = it.next(); BSONElement y = it.next(); *out = coordToPoint(x.number(), y.number()); return true; } 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; }
/* 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; }
bool IndexBounds::isValidFor(const BSONObj& keyPattern, int direction) { if (isSimpleRange) { return direction == sgn(endKey.woCompare(startKey, keyPattern, false)); } BSONObjIterator it(keyPattern); for (size_t i = 0; i < fields.size(); ++i) { // We expect a bound for each field in the index. if (!it.more()) { return false; } BSONElement elt = it.next(); const OrderedIntervalList& field = fields[i]; // Make sure the names match up. if (field.name != elt.fieldName()) { return false; } // Special indices are all inserted increasing. elt.number() will return 0 if it's // not a number. Special indices are strings, not numbers. int expectedOrientation = direction * ((elt.number() >= 0) ? 1 : -1); if (!field.isValidFor(expectedOrientation)) { return false; } } return !it.more(); }
/* get a table scan cursor, but can be forward or reverse direction. order.$natural - if set, > 0 means forward (asc), < 0 backward (desc). */ shared_ptr<Cursor> findTableScan(const char *ns, const BSONObj& order, const DiskLoc &startLoc) { BSONElement el = order.getField("$natural"); // e.g., { $natural : -1 } if ( el.number() >= 0 ) return DataFileMgr::findAll(ns, startLoc); // "reverse natural order" NamespaceDetails *d = nsdetails(ns); if ( !d ) return shared_ptr<Cursor>(new BasicCursor(DiskLoc())); if ( !d->isCapped() ) { if ( !startLoc.isNull() ) return shared_ptr<Cursor>(new ReverseCursor( startLoc )); Extent *e = d->lastExtent().ext(); while ( e->lastRecord.isNull() && !e->xprev.isNull() ) { OCCASIONALLY out() << " findTableScan: extent empty, skipping ahead" << endl; e = e->getPrevExtent(); } return shared_ptr<Cursor>(new ReverseCursor( e->lastRecord )); } else { return shared_ptr<Cursor>( new ReverseCappedCursor( d, startLoc ) ); } }
void GeoParser::parseLegacyCenter(const BSONObj &obj, Point *centerOut, double *radiusOut) { BSONObjIterator objIt(obj); BSONElement center = objIt.next(); parseLegacyPoint(center.Obj(), centerOut); BSONElement radius = objIt.next(); *radiusOut = radius.number(); }
void TextStage::filterAndScore(BSONObj key, DiskLoc loc) { // Locate score within possibly compound key: {prefix,term,score,suffix}. BSONObjIterator keyIt(key); for (unsigned i = 0; i < _params.spec.numExtraBefore(); i++) { keyIt.next(); } keyIt.next(); // Skip past 'term'. BSONElement scoreElement = keyIt.next(); double documentTermScore = scoreElement.number(); double& documentAggregateScore = _scores[loc]; // Handle filtering. if (documentAggregateScore < 0) { // We have already rejected this document. return; } if (documentAggregateScore == 0 && _filter) { // We have not seen this document before and need to apply a filter. Record* rec_p = loc.rec(); BSONObj doc = BSONObj::make(rec_p); // TODO: Covered index matching logic here. if (!_filter->matchesBSON(doc)) { documentAggregateScore = -1; return; } } // Aggregate relevance score, term keys. documentAggregateScore += documentTermScore; }
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; }
static Status parseFlatPoint(const BSONElement &elem, Point *out, bool allowAddlFields = false) { if (!elem.isABSONObj()) return BAD_VALUE("Point must be an array or object"); BSONObjIterator it(elem.Obj()); BSONElement x = it.next(); if (!x.isNumber()) { return BAD_VALUE("Point must only contain numeric elements"); } BSONElement y = it.next(); if (!y.isNumber()) { return BAD_VALUE("Point must only contain numeric elements"); } if (!allowAddlFields && it.more()) { return BAD_VALUE("Point must only contain two numeric elements"); } out->x = x.number(); out->y = y.number(); // Point coordinates must must be finite numbers, neither NaN or infinite. if (!std::isfinite(out->x) || !std::isfinite(out->y)) { return BAD_VALUE("Point coordinates must must be finite numbers"); } return Status::OK(); }
// 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; }
static void printData( const BSONObj& o , const BSONObj& headers ) { BSONObjIterator i(headers); while ( i.more() ) { BSONElement e = i.next(); BSONObj h = e.Obj(); int w = h["width"].numberInt(); BSONElement data; { BSONElement temp = o[e.fieldName()]; if ( temp.isABSONObj() ) data = temp.Obj()["data"]; } if ( data.type() == String ) cout << setw(w) << data.String(); else if ( data.type() == NumberDouble ) cout << setw(w) << setprecision(3) << data.number(); else if ( data.type() == NumberInt ) cout << setw(w) << data.numberInt(); else if ( data.eoo() ) cout << setw(w) << ""; else cout << setw(w) << "???"; cout << ' '; } cout << endl; }
bool DBClientBase::ensureIndex( const string &ns , BSONObj keys , bool unique, const string & name ) { BSONObjBuilder toSave; toSave.append( "ns" , ns ); toSave.append( "key" , keys ); string cacheKey(ns); cacheKey += "--"; if ( name != "" ) { toSave.append( "name" , name ); cacheKey += name; } else { stringstream ss; bool first = 1; for ( BSONObjIterator i(keys); i.more(); ) { BSONElement f = i.next(); if ( first ) first = 0; else ss << "_"; ss << f.fieldName() << "_"; if ( f.type() == NumberInt ) ss << (int)(f.number() ); else if ( f.type() == NumberDouble ) ss << f.number(); } toSave.append( "name" , ss.str() ); cacheKey += ss.str(); } if ( unique ) toSave.appendBool( "unique", unique ); if ( _seenIndexes.count( cacheKey ) ) return 0; _seenIndexes.insert( cacheKey ); insert( Namespace( ns.c_str() ).getSisterNS( "system.indexes" ).c_str() , toSave.obj() ); return 1; }
ProgramRunner( const BSONObj &args , bool isMongoProgram=true) { assert( !args.isEmpty() ); string program( args.firstElement().valuestrsafe() ); assert( !program.empty() ); boost::filesystem::path programPath = find(program); if (isMongoProgram){ #if 0 if (program == "mongos") { argv_.push_back("valgrind"); argv_.push_back("--log-file=/tmp/mongos-%p.valgrind"); argv_.push_back("--leak-check=yes"); argv_.push_back("--suppressions=valgrind.suppressions"); //argv_.push_back("--error-exitcode=1"); argv_.push_back("--"); } #endif } argv_.push_back( programPath.native_file_string() ); port_ = -1; BSONObjIterator j( args ); j.next(); // skip program name (handled above) while(j.more()) { BSONElement e = j.next(); string str; if ( e.isNumber() ) { stringstream ss; ss << e.number(); str = ss.str(); } else { assert( e.type() == mongo::String ); str = e.valuestr(); } if ( str == "--port" ) port_ = -2; else if ( port_ == -2 ) port_ = strtol( str.c_str(), 0, 10 ); argv_.push_back(str); } if ( program != "mongod" && program != "mongos" && program != "mongobridge" ) port_ = 0; else { if ( port_ <= 0 ) cout << "error: a port number is expected when running mongod (etc.) from the shell" << endl; assert( port_ > 0 ); } if ( port_ > 0 && dbs.count( port_ ) != 0 ){ cerr << "count for port: " << port_ << " is not 0 is: " << dbs.count( port_ ) << endl; assert( dbs.count( port_ ) == 0 ); } }
void GeoParser::parseLegacyCenter(const BSONObj &obj, Circle *out) { BSONObjIterator typeIt(obj); BSONElement type = typeIt.next(); BSONObjIterator objIt(type.embeddedObject()); BSONElement center = objIt.next(); parseLegacyPoint(center.Obj(), &out->center); BSONElement radius = objIt.next(); out->radius = radius.number(); }
INT32 aggrSortParser::buildOrderBy( const BSONElement &elem, qgmOPFieldVec &orderBy, _qgmPtrTable *pTable, const CHAR *pCLName ) { INT32 rc = SDB_OK; try { BSONObj obj = elem.embeddedObject(); BSONObjIterator iter( obj ); while ( iter.more() ) { BSONElement beField = iter.next(); PD_CHECK( beField.isNumber(), SDB_INVALIDARG, error, PDERROR, "type of sort-field must be number!" ); { qgmField obValAttr; qgmField obValRelegation; rc = pTable->getOwnField( AGGR_CL_DEFAULT_ALIAS, obValRelegation ); PD_RC_CHECK( rc, PDERROR, "failed to get the field(%s)", AGGR_CL_DEFAULT_ALIAS ); rc = pTable->getOwnField( beField.fieldName(), obValAttr ); PD_RC_CHECK( rc, PDERROR, "failed to get the field(%s)", beField.fieldName() ); { qgmDbAttr obVal( obValRelegation, obValAttr ); qgmField obAlias; qgmOpField obOpField; obOpField.value = obVal; obOpField.alias = obAlias; if ( beField.number() > 0 ) { obOpField.type = SQL_GRAMMAR::ASC; } else { obOpField.type = SQL_GRAMMAR::DESC; } orderBy.push_back( obOpField ); } } } } catch ( std::exception &e ) { PD_CHECK( SDB_INVALIDARG, SDB_INVALIDARG, error, PDERROR, "failed to parse the \"sort\", received unexpected error:%s", e.what() ); } done: return rc; error: goto done; }
FTSSpec::FTSSpec( const BSONObj& indexInfo ) { _defaultLanguage = indexInfo["default_language"].valuestrsafe(); _languageOverrideField = indexInfo["language_override"].valuestrsafe(); if ( _defaultLanguage.size() == 0 ) _defaultLanguage = "english"; if ( _languageOverrideField.size() == 0 ) _languageOverrideField = "language"; _wildcard = false; // in this block we fill in the _weights map { BSONObjIterator i( indexInfo["weights"].Obj() ); while ( i.more() ) { BSONElement e = i.next(); verify( e.isNumber() ); if ( WILDCARD == e.fieldName() ) { _wildcard = true; } else { double num = e.number(); _weights[ e.fieldName() ] = num; verify( num > 0 && num < MAX_WEIGHT ); } } verify( _wildcard || _weights.size() ); } // extra information { BSONObj keyPattern = indexInfo["key"].Obj(); verify( keyPattern.nFields() >= 2 ); BSONObjIterator i( keyPattern ); bool passedFTS = false; while ( i.more() ) { BSONElement e = i.next(); if ( str::equals( e.fieldName(), "_fts" ) || str::equals( e.fieldName(), "_ftsx" ) ) { passedFTS = true; continue; } if ( passedFTS ) _extraAfter.push_back( e.fieldName() ); else _extraBefore.push_back( e.fieldName() ); } } }
int getSignal( const BSONObj &a ) { int ret = SIGTERM; if ( a.nFields() >= 2 ) { BSONObjIterator i( a ); i.next(); BSONElement e = i.next(); verify( e.isNumber() ); ret = int( e.number() ); } return ret; }
void GeoParser::parseLegacyCenterSphere(const BSONObj &obj, S2Cap *out) { BSONObjIterator typeIt(obj); BSONElement type = typeIt.next(); BSONObjIterator objIt(type.embeddedObject()); BSONElement center = objIt.next(); S2Point centerPoint; parseLegacyPoint(center.Obj(), ¢erPoint); BSONElement radiusElt = objIt.next(); double radius = radiusElt.number(); *out = S2Cap::FromAxisAngle(centerPoint, S1Angle::Radians(radius)); }
BSONObj Chunk::_getExtremeKey(OperationContext* txn, bool doSplitAtLower) const { Query q; if (doSplitAtLower) { q.sort(_manager->getShardKeyPattern().toBSON()); } else { // need to invert shard key pattern to sort backwards // TODO: make a helper in ShardKeyPattern? BSONObj k = _manager->getShardKeyPattern().toBSON(); BSONObjBuilder r; BSONObjIterator i(k); while (i.more()) { BSONElement e = i.next(); uassert(10163, "can only handle numbers here - which i think is correct", e.isNumber()); r.append(e.fieldName(), -1 * e.number()); } q.sort(r.obj()); } // find the extreme key ScopedDbConnection conn(_getShardConnectionString(txn)); BSONObj end; if (doSplitAtLower) { // Splitting close to the lower bound means that the split point will be the // upper bound. Chunk range upper bounds are exclusive so skip a document to // make the lower half of the split end up with a single document. unique_ptr<DBClientCursor> cursor = conn->query(_manager->getns(), q, 1, /* nToReturn */ 1 /* nToSkip */); uassert(28736, str::stream() << "failed to initialize cursor during auto split due to " << "connection problem with " << conn->getServerAddress(), cursor.get() != nullptr); if (cursor->more()) { end = cursor->next().getOwned(); } } else { end = conn->findOne(_manager->getns(), q); } conn.done(); if (end.isEmpty()) return BSONObj(); return _manager->getShardKeyPattern().extractShardKeyFromDoc(end); }
void TextStage::addTerm(const BSONObj& key, const DiskLoc& loc, ScoreMap* curMap) { double *documentAggregateScore = &(*curMap)[loc]; if (curMap != &_negativeScores) ++_specificStats.keysExamined; // Locate score within possibly compound key: {prefix,term,score,suffix}. BSONObjIterator keyIt(key); for (unsigned i = 0; i < _params.spec.numExtraBefore(); i++) { keyIt.next(); } keyIt.next(); // Skip past 'term'. BSONElement scoreElement = keyIt.next(); double documentTermScore = scoreElement.number(); // Handle filtering. if (*documentAggregateScore < 0) { // We have already rejected this document. return; } if (*documentAggregateScore == 0) { if (_filter) { // We have not seen this document before and need to apply a filter. bool fetched = false; TextMatchableDocument tdoc(_params.index->keyPattern(), key, loc, _params.index->getCollection(), &fetched); if (!_filter->matches(&tdoc)) { // We had to fetch but we're not going to return it. if (fetched && curMap != &_negativeScores) { ++_specificStats.fetches; } *documentAggregateScore = -1; return; } } else { // If we're here, we're going to return the doc, and we do a fetch later. if (curMap != &_negativeScores) ++_specificStats.fetches; } } // Aggregate relevance score, term keys. *documentAggregateScore += documentTermScore; }
bool GeoParser::parsePointWithMaxDistance(const BSONObj& obj, PointWithCRS* out, double* maxOut) { BSONObjIterator it(obj); if (!it.more()) { return false; } BSONElement lng = it.next(); if (!lng.isNumber()) { return false; } if (!it.more()) { return false; } BSONElement lat = it.next(); if (!lat.isNumber()) { return false; } if (!it.more()) { return false; } BSONElement dist = it.next(); if (!dist.isNumber()) { return false; } if (it.more()) { return false; } out->oldPoint.x = lng.number(); out->oldPoint.y = lat.number(); out->crs = FLAT; *maxOut = dist.number(); return true; }
Status GeoParser::parseLegacyCenter(const BSONObj& obj, CapWithCRS *out) { BSONObjIterator objIt(obj); // Center BSONElement center = objIt.next(); Status status = parseFlatPoint(center, &out->circle.center); if (!status.isOK()) return status; // Radius BSONElement radius = objIt.next(); // radius >= 0 and is not NaN if (!radius.isNumber() || !(radius.number() >= 0)) return BAD_VALUE("radius must be a non-negative number"); // No more if (objIt.more()) return BAD_VALUE("Only 2 fields allowed for circular region"); out->circle.radius = radius.number(); out->crs = FLAT; return Status::OK(); }
BSONObj Chunk::pickSplitPoint(){ int sort = 0; if ( _manager->getShardKey().globalMin().woCompare( getMin() ) == 0 ){ sort = 1; } else if ( _manager->getShardKey().globalMax().woCompare( getMax() ) == 0 ){ sort = -1; } if ( sort ){ ScopedDbConnection conn( getShard() ); Query q; if ( sort == 1 ) q.sort( _manager->getShardKey().key() ); else { BSONObj k = _manager->getShardKey().key(); BSONObjBuilder r; BSONObjIterator i(k); while( i.more() ) { BSONElement e = i.next(); uassert( 10163 , "can only handle numbers here - which i think is correct" , e.isNumber() ); r.append( e.fieldName() , -1 * e.number() ); } q.sort( r.obj() ); } BSONObj end = conn->findOne( _ns , q ); conn.done(); if ( ! end.isEmpty() ) return _manager->getShardKey().extractKey( end ); } ScopedDbConnection conn( getShard() ); BSONObj result; if ( ! conn->runCommand( "admin" , BSON( "medianKey" << _ns << "keyPattern" << _manager->getShardKey().key() << "min" << getMin() << "max" << getMax() ) , result ) ){ stringstream ss; ss << "medianKey command failed: " << result; uassert( 10164 , ss.str() , 0 ); } conn.done(); return result.getObjectField( "median" ).getOwned(); }
BSONObj QueryPlannerAnalysis::getSortPattern(const BSONObj& indexKeyPattern) { BSONObjBuilder sortBob; BSONObjIterator kpIt(indexKeyPattern); while (kpIt.more()) { BSONElement elt = kpIt.next(); if (elt.type() == mongo::String) { break; } // The canonical check as to whether a key pattern element is "ascending" or "descending" is // (elt.number() >= 0). This is defined by the Ordering class. int sortOrder = (elt.number() >= 0) ? 1 : -1; sortBob.append(elt.fieldName(), sortOrder); } return sortBob.obj(); }