Status LiteParsedQuery::init(const string& ns, int ntoskip, int ntoreturn, int queryOptions, const BSONObj& queryObj, const BSONObj& proj, bool fromQueryMessage) { _ns = ns; _ntoskip = ntoskip; _ntoreturn = ntoreturn; _options = queryOptions; _proj = proj.getOwned(); if (_ntoskip < 0) { return Status(ErrorCodes::BadValue, "bad skip value in query"); } if (_ntoreturn < 0) { // _ntoreturn greater than zero is simply a hint on how many objects to send back per // "cursor batch". A negative number indicates a hard limit. _wantMore = false; _ntoreturn = -_ntoreturn; } if (fromQueryMessage) { BSONElement queryField = queryObj["query"]; if (!queryField.isABSONObj()) { queryField = queryObj["$query"]; } if (queryField.isABSONObj()) { _filter = queryField.embeddedObject().getOwned(); Status status = initFullQuery(queryObj); if (!status.isOK()) { return status; } } else { // TODO: Does this ever happen? _filter = queryObj.getOwned(); } } else { // This is the debugging code path. _filter = queryObj.getOwned(); } _hasReadPref = queryObj.hasField("$readPreference"); if (!isValidSortOrder(_sort)) { return Status(ErrorCodes::BadValue, "bad sort specification"); } _sort = normalizeSortOrder(_sort); return Status::OK(); }
Status LiteParsedQuery::init(const string& ns, int ntoskip, int ntoreturn, int queryOptions, const BSONObj& queryObj, const BSONObj& proj, bool fromQueryMessage) { _ns = ns; _ntoskip = ntoskip; _ntoreturn = ntoreturn; _options = queryOptions; _proj = proj.getOwned(); if (_ntoskip < 0) { return Status(ErrorCodes::BadValue, "bad skip value in query"); } if (_ntoreturn == std::numeric_limits<int>::min()) { // _ntoreturn is negative but can't be negated. return Status(ErrorCodes::BadValue, "bad limit value in query"); } if (_ntoreturn < 0) { // _ntoreturn greater than zero is simply a hint on how many objects to send back per // "cursor batch". A negative number indicates a hard limit. _wantMore = false; _ntoreturn = -_ntoreturn; } if (fromQueryMessage) { BSONElement queryField = queryObj["query"]; if (!queryField.isABSONObj()) { queryField = queryObj["$query"]; } if (queryField.isABSONObj()) { _filter = queryField.embeddedObject().getOwned(); Status status = initFullQuery(queryObj); if (!status.isOK()) { return status; } } else { // TODO: Does this ever happen? _filter = queryObj.getOwned(); } } else { // This is the debugging code path. _filter = queryObj.getOwned(); } _hasReadPref = queryObj.hasField("$readPreference"); if (!_sort.isEmpty()) { if (!isValidSortOrder(_sort)) { return Status(ErrorCodes::BadValue, "bad sort specification"); } _sort = normalizeSortOrder(_sort); } // Min and Max objects must have the same fields. if (!_min.isEmpty() && !_max.isEmpty()) { if (!_min.isFieldNamePrefixOf(_max) || (_min.nFields() != _max.nFields())) { return Status(ErrorCodes::BadValue, "min and max must have the same field names"); } } // Can't combine a normal sort and a $meta projection on the same field. BSONObjIterator projIt(_proj); while (projIt.more()) { BSONElement projElt = projIt.next(); if (isTextScoreMeta(projElt)) { BSONElement sortElt = _sort[projElt.fieldName()]; if (!sortElt.eoo() && !isTextScoreMeta(sortElt)) { return Status(ErrorCodes::BadValue, "can't have a non-$meta sort on a $meta projection"); } } } // All fields with a $meta sort must have a corresponding $meta projection. BSONObjIterator sortIt(_sort); while (sortIt.more()) { BSONElement sortElt = sortIt.next(); if (isTextScoreMeta(sortElt)) { BSONElement projElt = _proj[sortElt.fieldName()]; if (projElt.eoo() || !isTextScoreMeta(projElt)) { return Status(ErrorCodes::BadValue, "must have $meta projection for all $meta sort keys"); } } } return Status::OK(); }
Status LiteParsedQuery::init(const string& ns, int ntoskip, int ntoreturn, int queryOptions, const BSONObj& queryObj, bool fromQueryMessage) { _ns = ns; _ntoskip = ntoskip; _ntoreturn = ntoreturn; _options = queryOptions; // TODO: If pq.hasOption(QueryOption_CursorTailable) make sure it's a capped collection and // make sure the order(??) is $natural: 1. if (_ntoskip < 0) { return Status(ErrorCodes::BadValue, "bad skip value in query"); } if (_ntoreturn < 0) { // _ntoreturn greater than zero is simply a hint on how many objects to send back per // "cursor batch". A negative number indicates a hard limit. _wantMore = false; _ntoreturn = -_ntoreturn; } if (fromQueryMessage) { BSONElement queryField = queryObj["query"]; if (!queryField.isABSONObj()) { queryField = queryObj["$query"]; } if (queryField.isABSONObj()) { _filter = queryField.embeddedObject().getOwned(); Status status = initFullQuery(queryObj); if (!status.isOK()) { return status; } } else { // TODO: Does this ever happen? _filter = queryObj.getOwned(); } } else { // This is the debugging code path. _filter = queryObj.getOwned(); } // // Parse options that are valid for both queries and commands // // $readPreference _hasReadPref = queryObj.hasField("$readPreference"); // $maxTimeMS BSONElement maxTimeMSElt = queryObj.getField("$maxTimeMS"); if (!maxTimeMSElt.eoo() && !maxTimeMSElt.isNumber()) { return Status(ErrorCodes::BadValue, "$maxTimeMS must be a number"); } // If $maxTimeMS was not specified, _maxTimeMS is set to 0 (special value for "allow to // run indefinitely"). long long maxTimeMSLongLong = maxTimeMSElt.safeNumberLong(); if (maxTimeMSLongLong < 0 || maxTimeMSLongLong > INT_MAX) { return Status(ErrorCodes::BadValue, "$maxTimeMS is out of range"); } _maxTimeMS = static_cast<int>(maxTimeMSLongLong); return Status::OK(); }