StatusWith<UpdateZoneKeyRangeRequest> UpdateZoneKeyRangeRequest::_parseFromCommand( const BSONObj& cmdObj, bool forMongos) { string rawNS; auto parseNamespaceStatus = bsonExtractStringField( cmdObj, (forMongos ? kMongosUpdateZoneKeyRange : kConfigsvrUpdateZoneKeyRange), &rawNS); if (!parseNamespaceStatus.isOK()) { return parseNamespaceStatus; } NamespaceString ns(rawNS); if (!ns.isValid()) { return {ErrorCodes::InvalidNamespace, str::stream() << rawNS << " is not a valid namespace"}; } auto parseRangeStatus = ChunkRange::fromBSON(cmdObj); if (!parseRangeStatus.isOK()) { return parseRangeStatus.getStatus(); } BSONElement zoneElem; auto parseZoneNameStatus = bsonExtractField(cmdObj, kZoneName, &zoneElem); if (!parseZoneNameStatus.isOK()) { return parseZoneNameStatus; } bool isRemove = false; string zoneName; if (zoneElem.type() == String) { zoneName = zoneElem.str(); } else if (zoneElem.isNull()) { isRemove = true; } else { return {ErrorCodes::TypeMismatch, str::stream() << "\"" << kZoneName << "\" had the wrong type. Expected " << typeName(String) << " or " << typeName(jstNULL) << ", found " << typeName(zoneElem.type())}; } if (isRemove) { return UpdateZoneKeyRangeRequest(std::move(ns), std::move(parseRangeStatus.getValue())); } return UpdateZoneKeyRangeRequest( std::move(ns), std::move(parseRangeStatus.getValue()), std::move(zoneName)); }
void ExpressionKeysPrivate::getS2Keys(const BSONObj& obj, const BSONObj& keyPattern, const S2IndexingParams& params, BSONObjSet* keys) { BSONObjSet keysToAdd; // Does one of our documents have a geo field? bool haveGeoField = false; // We output keys in the same order as the fields we index. BSONObjIterator i(keyPattern); while (i.more()) { BSONElement e = i.next(); // First, we get the keys that this field adds. Either they're added literally from // the value of the field, or they're transformed if the field is geo. BSONElementSet fieldElements; // false means Don't expand the last array, duh. obj.getFieldsDotted(e.fieldName(), fieldElements, false); BSONObjSet keysForThisField; if (IndexNames::GEO_2DSPHERE == e.valuestr()) { if (params.indexVersion >= S2_INDEX_VERSION_2) { // For >= V2, // geo: null, // geo: undefined // geo: [] // should all behave like there is no geo field. So we look for these cases and // throw out the field elements if we find them. if (1 == fieldElements.size()) { BSONElement elt = *fieldElements.begin(); // Get the :null and :undefined cases. if (elt.isNull() || Undefined == elt.type()) { fieldElements.clear(); } else if (elt.isABSONObj()) { // And this is the :[] case. BSONObj obj = elt.Obj(); if (0 == obj.nFields()) { fieldElements.clear(); } } } // >= V2 2dsphere indices require that at least one geo field to be present in a // document in order to index it. if (fieldElements.size() > 0) { haveGeoField = true; } } getS2GeoKeys(obj, fieldElements, params, &keysForThisField); } else { getS2LiteralKeys(fieldElements, params.collator, &keysForThisField); } // We expect there to be the missing field element present in the keys if data is // missing. So, this should be non-empty. verify(!keysForThisField.empty()); // We take the Cartesian product of all of the keys. This requires that we have // some keys to take the Cartesian product with. If keysToAdd.empty(), we // initialize it. if (keysToAdd.empty()) { keysToAdd = keysForThisField; continue; } BSONObjSet updatedKeysToAdd; for (BSONObjSet::const_iterator it = keysToAdd.begin(); it != keysToAdd.end(); ++it) { for (BSONObjSet::const_iterator newIt = keysForThisField.begin(); newIt != keysForThisField.end(); ++newIt) { BSONObjBuilder b; b.appendElements(*it); b.append(newIt->firstElement()); updatedKeysToAdd.insert(b.obj()); } } keysToAdd = updatedKeysToAdd; } // Make sure that if we're >= V2 there's at least one geo field present in the doc. if (params.indexVersion >= S2_INDEX_VERSION_2) { if (!haveGeoField) { return; } } if (keysToAdd.size() > params.maxKeysPerInsert) { warning() << "Insert of geo object generated a high number of keys." << " num keys: " << keysToAdd.size() << " obj inserted: " << obj; } *keys = keysToAdd; }
// static bool QueryPlannerTestLib::solutionMatches(const BSONObj& testSoln, const QuerySolutionNode* trueSoln) { // // leaf nodes // if (STAGE_COLLSCAN == trueSoln->getType()) { const CollectionScanNode* csn = static_cast<const CollectionScanNode*>(trueSoln); BSONElement el = testSoln["cscan"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj csObj = el.Obj(); BSONElement dir = csObj["dir"]; if (dir.eoo() || !dir.isNumber()) { return false; } if (dir.numberInt() != csn->direction) { return false; } BSONElement filter = csObj["filter"]; if (filter.eoo()) { return true; } else if (filter.isNull()) { return NULL == csn->filter; } else if (!filter.isABSONObj()) { return false; } BSONObj collation; if (BSONElement collationElt = csObj["collation"]) { if (!collationElt.isABSONObj()) { return false; } collation = collationElt.Obj(); } return filterMatches(filter.Obj(), collation, trueSoln); } else if (STAGE_IXSCAN == trueSoln->getType()) { const IndexScanNode* ixn = static_cast<const IndexScanNode*>(trueSoln); BSONElement el = testSoln["ixscan"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj ixscanObj = el.Obj(); BSONElement pattern = ixscanObj["pattern"]; if (pattern.eoo() || !pattern.isABSONObj()) { return false; } if (pattern.Obj() != ixn->indexKeyPattern) { return false; } BSONElement bounds = ixscanObj["bounds"]; if (!bounds.eoo()) { if (!bounds.isABSONObj()) { return false; } else if (!boundsMatch(bounds.Obj(), ixn->bounds)) { return false; } } BSONElement dir = ixscanObj["dir"]; if (!dir.eoo() && NumberInt == dir.type()) { if (dir.numberInt() != ixn->direction) { return false; } } BSONElement filter = ixscanObj["filter"]; if (filter.eoo()) { return true; } else if (filter.isNull()) { return NULL == ixn->filter; } else if (!filter.isABSONObj()) { return false; } BSONObj collation; if (BSONElement collationElt = ixscanObj["collation"]) { if (!collationElt.isABSONObj()) { return false; } collation = collationElt.Obj(); } return filterMatches(filter.Obj(), collation, trueSoln); } else if (STAGE_GEO_NEAR_2D == trueSoln->getType()) { const GeoNear2DNode* node = static_cast<const GeoNear2DNode*>(trueSoln); BSONElement el = testSoln["geoNear2d"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj geoObj = el.Obj(); return geoObj == node->indexKeyPattern; } else if (STAGE_GEO_NEAR_2DSPHERE == trueSoln->getType()) { const GeoNear2DSphereNode* node = static_cast<const GeoNear2DSphereNode*>(trueSoln); BSONElement el = testSoln["geoNear2dsphere"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj geoObj = el.Obj(); BSONElement pattern = geoObj["pattern"]; if (pattern.eoo() || !pattern.isABSONObj()) { return false; } if (pattern.Obj() != node->indexKeyPattern) { return false; } BSONElement bounds = geoObj["bounds"]; if (!bounds.eoo()) { if (!bounds.isABSONObj()) { return false; } else if (!boundsMatch(bounds.Obj(), node->baseBounds)) { return false; } } return true; } else if (STAGE_TEXT == trueSoln->getType()) { // {text: {search: "somestr", language: "something", filter: {blah: 1}}} const TextNode* node = static_cast<const TextNode*>(trueSoln); BSONElement el = testSoln["text"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj textObj = el.Obj(); BSONElement searchElt = textObj["search"]; if (!searchElt.eoo()) { if (searchElt.String() != node->ftsQuery->getQuery()) { return false; } } BSONElement languageElt = textObj["language"]; if (!languageElt.eoo()) { if (languageElt.String() != node->ftsQuery->getLanguage()) { return false; } } BSONElement caseSensitiveElt = textObj["caseSensitive"]; if (!caseSensitiveElt.eoo()) { if (caseSensitiveElt.trueValue() != node->ftsQuery->getCaseSensitive()) { return false; } } BSONElement diacriticSensitiveElt = textObj["diacriticSensitive"]; if (!diacriticSensitiveElt.eoo()) { if (diacriticSensitiveElt.trueValue() != node->ftsQuery->getDiacriticSensitive()) { return false; } } BSONElement indexPrefix = textObj["prefix"]; if (!indexPrefix.eoo()) { if (!indexPrefix.isABSONObj()) { return false; } if (0 != indexPrefix.Obj().woCompare(node->indexPrefix)) { return false; } } BSONObj collation; if (BSONElement collationElt = textObj["collation"]) { if (!collationElt.isABSONObj()) { return false; } collation = collationElt.Obj(); } BSONElement filter = textObj["filter"]; if (!filter.eoo()) { if (filter.isNull()) { if (NULL != node->filter) { return false; } } else if (!filter.isABSONObj()) { return false; } else if (!filterMatches(filter.Obj(), collation, trueSoln)) { return false; } } return true; } // // internal nodes // if (STAGE_FETCH == trueSoln->getType()) { const FetchNode* fn = static_cast<const FetchNode*>(trueSoln); BSONElement el = testSoln["fetch"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj fetchObj = el.Obj(); BSONObj collation; if (BSONElement collationElt = fetchObj["collation"]) { if (!collationElt.isABSONObj()) { return false; } collation = collationElt.Obj(); } BSONElement filter = fetchObj["filter"]; if (!filter.eoo()) { if (filter.isNull()) { if (NULL != fn->filter) { return false; } } else if (!filter.isABSONObj()) { return false; } else if (!filterMatches(filter.Obj(), collation, trueSoln)) { return false; } } BSONElement child = fetchObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return solutionMatches(child.Obj(), fn->children[0]); } else if (STAGE_OR == trueSoln->getType()) { const OrNode* orn = static_cast<const OrNode*>(trueSoln); BSONElement el = testSoln["or"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj orObj = el.Obj(); return childrenMatch(orObj, orn); } else if (STAGE_AND_HASH == trueSoln->getType()) { const AndHashNode* ahn = static_cast<const AndHashNode*>(trueSoln); BSONElement el = testSoln["andHash"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj andHashObj = el.Obj(); BSONObj collation; if (BSONElement collationElt = andHashObj["collation"]) { if (!collationElt.isABSONObj()) { return false; } collation = collationElt.Obj(); } BSONElement filter = andHashObj["filter"]; if (!filter.eoo()) { if (filter.isNull()) { if (NULL != ahn->filter) { return false; } } else if (!filter.isABSONObj()) { return false; } else if (!filterMatches(filter.Obj(), collation, trueSoln)) { return false; } } return childrenMatch(andHashObj, ahn); } else if (STAGE_AND_SORTED == trueSoln->getType()) { const AndSortedNode* asn = static_cast<const AndSortedNode*>(trueSoln); BSONElement el = testSoln["andSorted"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj andSortedObj = el.Obj(); BSONObj collation; if (BSONElement collationElt = andSortedObj["collation"]) { if (!collationElt.isABSONObj()) { return false; } collation = collationElt.Obj(); } BSONElement filter = andSortedObj["filter"]; if (!filter.eoo()) { if (filter.isNull()) { if (NULL != asn->filter) { return false; } } else if (!filter.isABSONObj()) { return false; } else if (!filterMatches(filter.Obj(), collation, trueSoln)) { return false; } } return childrenMatch(andSortedObj, asn); } else if (STAGE_PROJECTION == trueSoln->getType()) { const ProjectionNode* pn = static_cast<const ProjectionNode*>(trueSoln); BSONElement el = testSoln["proj"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj projObj = el.Obj(); BSONElement projType = projObj["type"]; if (!projType.eoo()) { string projTypeStr = projType.str(); if (!((pn->projType == ProjectionNode::DEFAULT && projTypeStr == "default") || (pn->projType == ProjectionNode::SIMPLE_DOC && projTypeStr == "simple") || (pn->projType == ProjectionNode::COVERED_ONE_INDEX && projTypeStr == "coveredIndex"))) { return false; } } BSONElement spec = projObj["spec"]; if (spec.eoo() || !spec.isABSONObj()) { return false; } BSONElement child = projObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return (spec.Obj() == pn->projection) && solutionMatches(child.Obj(), pn->children[0]); } else if (STAGE_SORT == trueSoln->getType()) { const SortNode* sn = static_cast<const SortNode*>(trueSoln); BSONElement el = testSoln["sort"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj sortObj = el.Obj(); BSONElement patternEl = sortObj["pattern"]; if (patternEl.eoo() || !patternEl.isABSONObj()) { return false; } BSONElement limitEl = sortObj["limit"]; if (!limitEl.isNumber()) { return false; } BSONElement child = sortObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } size_t expectedLimit = limitEl.numberInt(); return (patternEl.Obj() == sn->pattern) && (expectedLimit == sn->limit) && solutionMatches(child.Obj(), sn->children[0]); } else if (STAGE_SORT_KEY_GENERATOR == trueSoln->getType()) { const SortKeyGeneratorNode* keyGenNode = static_cast<const SortKeyGeneratorNode*>(trueSoln); BSONElement el = testSoln["sortKeyGen"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj keyGenObj = el.Obj(); BSONElement child = keyGenObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return solutionMatches(child.Obj(), keyGenNode->children[0]); } else if (STAGE_SORT_MERGE == trueSoln->getType()) { const MergeSortNode* msn = static_cast<const MergeSortNode*>(trueSoln); BSONElement el = testSoln["mergeSort"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj mergeSortObj = el.Obj(); return childrenMatch(mergeSortObj, msn); } else if (STAGE_SKIP == trueSoln->getType()) { const SkipNode* sn = static_cast<const SkipNode*>(trueSoln); BSONElement el = testSoln["skip"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj sortObj = el.Obj(); BSONElement skipEl = sortObj["n"]; if (!skipEl.isNumber()) { return false; } BSONElement child = sortObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return (skipEl.numberInt() == sn->skip) && solutionMatches(child.Obj(), sn->children[0]); } else if (STAGE_LIMIT == trueSoln->getType()) { const LimitNode* ln = static_cast<const LimitNode*>(trueSoln); BSONElement el = testSoln["limit"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj sortObj = el.Obj(); BSONElement limitEl = sortObj["n"]; if (!limitEl.isNumber()) { return false; } BSONElement child = sortObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return (limitEl.numberInt() == ln->limit) && solutionMatches(child.Obj(), ln->children[0]); } else if (STAGE_KEEP_MUTATIONS == trueSoln->getType()) { const KeepMutationsNode* kn = static_cast<const KeepMutationsNode*>(trueSoln); BSONElement el = testSoln["keep"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj keepObj = el.Obj(); // Doesn't have any parameters really. BSONElement child = keepObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return solutionMatches(child.Obj(), kn->children[0]); } else if (STAGE_SHARDING_FILTER == trueSoln->getType()) { const ShardingFilterNode* fn = static_cast<const ShardingFilterNode*>(trueSoln); BSONElement el = testSoln["sharding_filter"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj keepObj = el.Obj(); BSONElement child = keepObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return solutionMatches(child.Obj(), fn->children[0]); } else if (STAGE_ENSURE_SORTED == trueSoln->getType()) { const EnsureSortedNode* esn = static_cast<const EnsureSortedNode*>(trueSoln); BSONElement el = testSoln["ensureSorted"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj esObj = el.Obj(); BSONElement patternEl = esObj["pattern"]; if (patternEl.eoo() || !patternEl.isABSONObj()) { return false; } BSONElement child = esObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return (patternEl.Obj() == esn->pattern) && solutionMatches(child.Obj(), esn->children[0]); } return false; }
void ExpressionKeysPrivate::getS2Keys(const BSONObj& obj, const BSONObj& keyPattern, const S2IndexingParams& params, BSONObjSet* keys, MultikeyPaths* multikeyPaths) { BSONObjSet keysToAdd = SimpleBSONObjComparator::kInstance.makeBSONObjSet(); // Does one of our documents have a geo field? bool haveGeoField = false; if (multikeyPaths) { invariant(multikeyPaths->empty()); multikeyPaths->resize(keyPattern.nFields()); } size_t posInIdx = 0; // We output keys in the same order as the fields we index. for (const auto keyElem : keyPattern) { // First, we get the keys that this field adds. Either they're added literally from // the value of the field, or they're transformed if the field is geo. BSONElementSet fieldElements; const bool expandArrayOnTrailingField = false; std::set<size_t>* arrayComponents = multikeyPaths ? &(*multikeyPaths)[posInIdx] : nullptr; dps::extractAllElementsAlongPath( obj, keyElem.fieldName(), fieldElements, expandArrayOnTrailingField, arrayComponents); // Trailing array values aren't being expanded, so we still need to determine whether the // last component of the indexed path 'keyElem.fieldName()' causes the index to be multikey. // We say that it does if // (a) the last component of the indexed path ever refers to an array value (regardless of // the number of array elements) // (b) the last component of the indexed path ever refers to GeoJSON data that requires // multiple cells for its covering. bool lastPathComponentCausesIndexToBeMultikey; BSONObjSet keysForThisField = SimpleBSONObjComparator::kInstance.makeBSONObjSet(); if (IndexNames::GEO_2DSPHERE == keyElem.valuestr()) { if (params.indexVersion >= S2_INDEX_VERSION_2) { // For >= V2, // geo: null, // geo: undefined // geo: [] // should all behave like there is no geo field. So we look for these cases and // throw out the field elements if we find them. if (1 == fieldElements.size()) { BSONElement elt = *fieldElements.begin(); // Get the :null and :undefined cases. if (elt.isNull() || Undefined == elt.type()) { fieldElements.clear(); } else if (elt.isABSONObj()) { // And this is the :[] case. BSONObj obj = elt.Obj(); if (0 == obj.nFields()) { fieldElements.clear(); } } } // >= V2 2dsphere indices require that at least one geo field to be present in a // document in order to index it. if (fieldElements.size() > 0) { haveGeoField = true; } } lastPathComponentCausesIndexToBeMultikey = getS2GeoKeys(obj, fieldElements, params, &keysForThisField); } else { lastPathComponentCausesIndexToBeMultikey = getS2LiteralKeys(fieldElements, params.collator, &keysForThisField); } // We expect there to be the missing field element present in the keys if data is // missing. So, this should be non-empty. verify(!keysForThisField.empty()); if (multikeyPaths && lastPathComponentCausesIndexToBeMultikey) { const size_t pathLengthOfThisField = FieldRef{keyElem.fieldNameStringData()}.numParts(); invariant(pathLengthOfThisField > 0); (*multikeyPaths)[posInIdx].insert(pathLengthOfThisField - 1); } // We take the Cartesian product of all of the keys. This requires that we have // some keys to take the Cartesian product with. If keysToAdd.empty(), we // initialize it. if (keysToAdd.empty()) { keysToAdd = keysForThisField; ++posInIdx; continue; } BSONObjSet updatedKeysToAdd = SimpleBSONObjComparator::kInstance.makeBSONObjSet(); for (BSONObjSet::const_iterator it = keysToAdd.begin(); it != keysToAdd.end(); ++it) { for (BSONObjSet::const_iterator newIt = keysForThisField.begin(); newIt != keysForThisField.end(); ++newIt) { BSONObjBuilder b; b.appendElements(*it); b.append(newIt->firstElement()); updatedKeysToAdd.insert(b.obj()); } } keysToAdd = updatedKeysToAdd; ++posInIdx; } // Make sure that if we're >= V2 there's at least one geo field present in the doc. if (params.indexVersion >= S2_INDEX_VERSION_2) { if (!haveGeoField) { return; } } if (keysToAdd.size() > params.maxKeysPerInsert) { warning() << "Insert of geo object generated a high number of keys." << " num keys: " << keysToAdd.size() << " obj inserted: " << redact(obj); } *keys = keysToAdd; }
// static bool QueryPlannerTestLib::solutionMatches(const BSONObj& testSoln, const QuerySolutionNode* trueSoln) { // // leaf nodes // if (STAGE_COLLSCAN == trueSoln->getType()) { const CollectionScanNode* csn = static_cast<const CollectionScanNode*>(trueSoln); BSONElement el = testSoln["cscan"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj csObj = el.Obj(); BSONElement dir = csObj["dir"]; if (dir.eoo() || !dir.isNumber()) { return false; } if (dir.numberInt() != csn->direction) { return false; } BSONElement filter = csObj["filter"]; if (filter.eoo()) { return true; } else if (filter.isNull()) { return NULL == csn->filter; } else if (!filter.isABSONObj()) { return false; } return filterMatches(filter.Obj(), trueSoln); } else if (STAGE_IXSCAN == trueSoln->getType()) { const IndexScanNode* ixn = static_cast<const IndexScanNode*>(trueSoln); BSONElement el = testSoln["ixscan"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj ixscanObj = el.Obj(); BSONElement pattern = ixscanObj["pattern"]; if (pattern.eoo() || !pattern.isABSONObj()) { return false; } if (pattern.Obj() != ixn->indexKeyPattern) { return false; } BSONElement bounds = ixscanObj["bounds"]; if (!bounds.eoo()) { if (!bounds.isABSONObj()) { return false; } else if (!boundsMatch(bounds.Obj(), ixn->bounds)) { return false; } } BSONElement dir = ixscanObj["dir"]; if (!dir.eoo() && NumberInt == dir.type()) { if (dir.numberInt() != ixn->direction) { return false; } } BSONElement filter = ixscanObj["filter"]; if (filter.eoo()) { return true; } else if (filter.isNull()) { return NULL == ixn->filter; } else if (!filter.isABSONObj()) { return false; } return filterMatches(filter.Obj(), trueSoln); } else if (STAGE_GEO_2D == trueSoln->getType()) { const Geo2DNode* node = static_cast<const Geo2DNode*>(trueSoln); BSONElement el = testSoln["geo2d"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj geoObj = el.Obj(); return geoObj == node->indexKeyPattern; } else if (STAGE_GEO_NEAR_2D == trueSoln->getType()) { const GeoNear2DNode* node = static_cast<const GeoNear2DNode*>(trueSoln); BSONElement el = testSoln["geoNear2d"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj geoObj = el.Obj(); return geoObj == node->indexKeyPattern; } else if (STAGE_GEO_NEAR_2DSPHERE == trueSoln->getType()) { const GeoNear2DSphereNode* node = static_cast<const GeoNear2DSphereNode*>(trueSoln); BSONElement el = testSoln["geoNear2dsphere"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj geoObj = el.Obj(); return geoObj == node->indexKeyPattern; } else if (STAGE_TEXT == trueSoln->getType()) { // {text: {search: "somestr", language: "something", filter: {blah: 1}}} const TextNode* node = static_cast<const TextNode*>(trueSoln); BSONElement el = testSoln["text"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj textObj = el.Obj(); BSONElement searchElt = textObj["search"]; if (!searchElt.eoo()) { if (searchElt.String() != node->query) { return false; } } BSONElement languageElt = textObj["language"]; if (!languageElt.eoo()) { if (languageElt.String() != node->language) { return false; } } BSONElement indexPrefix = textObj["prefix"]; if (!indexPrefix.eoo()) { if (!indexPrefix.isABSONObj()) { return false; } if (0 != indexPrefix.Obj().woCompare(node->indexPrefix)) { return false; } } BSONElement filter = textObj["filter"]; if (!filter.eoo()) { if (filter.isNull()) { if (NULL != node->filter) { return false; } } else if (!filter.isABSONObj()) { return false; } else if (!filterMatches(filter.Obj(), trueSoln)) { return false; } } return true; } // // internal nodes // if (STAGE_FETCH == trueSoln->getType()) { const FetchNode* fn = static_cast<const FetchNode*>(trueSoln); BSONElement el = testSoln["fetch"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj fetchObj = el.Obj(); BSONElement filter = fetchObj["filter"]; if (!filter.eoo()) { if (filter.isNull()) { if (NULL != fn->filter) { return false; } } else if (!filter.isABSONObj()) { return false; } else if (!filterMatches(filter.Obj(), trueSoln)) { return false; } } BSONElement child = fetchObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return solutionMatches(child.Obj(), fn->children[0]); } else if (STAGE_OR == trueSoln->getType()) { const OrNode * orn = static_cast<const OrNode*>(trueSoln); BSONElement el = testSoln["or"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj orObj = el.Obj(); return childrenMatch(orObj, orn); } else if (STAGE_AND_HASH == trueSoln->getType()) { const AndHashNode* ahn = static_cast<const AndHashNode*>(trueSoln); BSONElement el = testSoln["andHash"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj andHashObj = el.Obj(); // XXX: andHashObj can have filter return childrenMatch(andHashObj, ahn); } else if (STAGE_AND_SORTED == trueSoln->getType()) { const AndSortedNode* asn = static_cast<const AndSortedNode*>(trueSoln); BSONElement el = testSoln["andSorted"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj andSortedObj = el.Obj(); // XXX: anSortedObj can have filter too return childrenMatch(andSortedObj, asn); } else if (STAGE_PROJECTION == trueSoln->getType()) { const ProjectionNode* pn = static_cast<const ProjectionNode*>(trueSoln); BSONElement el = testSoln["proj"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj projObj = el.Obj(); BSONElement spec = projObj["spec"]; if (spec.eoo() || !spec.isABSONObj()) { return false; } BSONElement child = projObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return (spec.Obj() == pn->projection) && solutionMatches(child.Obj(), pn->children[0]); } else if (STAGE_SORT == trueSoln->getType()) { const SortNode* sn = static_cast<const SortNode*>(trueSoln); BSONElement el = testSoln["sort"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj sortObj = el.Obj(); BSONElement patternEl = sortObj["pattern"]; if (patternEl.eoo() || !patternEl.isABSONObj()) { return false; } BSONElement limitEl = sortObj["limit"]; if (!limitEl.isNumber()) { return false; } BSONElement child = sortObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return (patternEl.Obj() == sn->pattern) && (limitEl.numberInt() == sn->limit) && solutionMatches(child.Obj(), sn->children[0]); } else if (STAGE_SORT_MERGE == trueSoln->getType()) { const MergeSortNode* msn = static_cast<const MergeSortNode*>(trueSoln); BSONElement el = testSoln["mergeSort"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj mergeSortObj = el.Obj(); return childrenMatch(mergeSortObj, msn); } else if (STAGE_SKIP == trueSoln->getType()) { const SkipNode* sn = static_cast<const SkipNode*>(trueSoln); BSONElement el = testSoln["skip"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj sortObj = el.Obj(); BSONElement skipEl = sortObj["n"]; if (!skipEl.isNumber()) { return false; } BSONElement child = sortObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return (skipEl.numberInt() == sn->skip) && solutionMatches(child.Obj(), sn->children[0]); } else if (STAGE_LIMIT == trueSoln->getType()) { const LimitNode* ln = static_cast<const LimitNode*>(trueSoln); BSONElement el = testSoln["limit"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj sortObj = el.Obj(); BSONElement limitEl = sortObj["n"]; if (!limitEl.isNumber()) { return false; } BSONElement child = sortObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return (limitEl.numberInt() == ln->limit) && solutionMatches(child.Obj(), ln->children[0]); } else if (STAGE_KEEP_MUTATIONS == trueSoln->getType()) { const KeepMutationsNode* kn = static_cast<const KeepMutationsNode*>(trueSoln); BSONElement el = testSoln["keep"]; if (el.eoo() || !el.isABSONObj()) { return false; } BSONObj keepObj = el.Obj(); // Doesn't have any parameters really. BSONElement child = keepObj["node"]; if (child.eoo() || !child.isABSONObj()) { return false; } return solutionMatches(child.Obj(), kn->children[0]); } return false; }
void Dictionary::open(const BSONObj &info, const mongo::Descriptor &descriptor, const bool may_create, const bool hot_index) { int readPageSize = 65536; int pageSize = 4 * 1024 * 1024; TOKU_COMPRESSION_METHOD compression = TOKU_ZLIB_WITHOUT_CHECKSUM_METHOD; BSONObj key_pattern = info["key"].Obj(); BSONElement e; e = info["readPageSize"]; if (e.ok() && !e.isNull()) { readPageSize = BytesQuantity<int>(e); uassert(16743, "readPageSize must be a number > 0.", readPageSize > 0); TOKULOG(1) << "db " << _dname << ", using read page size " << readPageSize << endl; } e = info["pageSize"]; if (e.ok() && !e.isNull()) { pageSize = BytesQuantity<int>(e); uassert(16445, "pageSize must be a number > 0.", pageSize > 0); TOKULOG(1) << "db " << _dname << ", using page size " << pageSize << endl; } e = info["compression"]; if (e.ok() && !e.isNull()) { std::string str = e.String(); if (str == "lzma") { compression = TOKU_LZMA_METHOD; } else if (str == "quicklz") { compression = TOKU_QUICKLZ_METHOD; } else if (str == "zlib") { compression = TOKU_ZLIB_WITHOUT_CHECKSUM_METHOD; } else if (str == "none") { compression = TOKU_NO_COMPRESSION; } else { uassert(16442, "compression must be one of: lzma, quicklz, zlib, none.", false); } TOKULOG(1) << "db " << _dname << ", using compression method \"" << str << "\"" << endl; } int r = _db->set_readpagesize(_db, readPageSize); if (r != 0) { handle_ydb_error(r); } r = _db->set_pagesize(_db, pageSize); if (r != 0) { handle_ydb_error(r); } r = _db->set_compression_method(_db, compression); if (r != 0) { handle_ydb_error(r); } // If this is a non-creating open for a read-only (or non-existent) // transaction, we can use an alternate stack since there's nothing // to roll back and no locktree locks to hold. const bool needAltTxn = !may_create && (!cc().hasTxn() || cc().txn().readOnly()); scoped_ptr<Client::AlternateTransactionStack> altStack(!needAltTxn ? NULL : new Client::AlternateTransactionStack()); scoped_ptr<Client::Transaction> altTxn(!needAltTxn ? NULL : new Client::Transaction(0)); const int db_flags = may_create ? DB_CREATE : 0; r = _db->open(_db, cc().txn().db_txn(), _dname.c_str(), NULL, DB_BTREE, db_flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (r == ENOENT && !may_create) { throw NeedsCreate(); } if (r != 0) { handle_ydb_error(r); } if (may_create) { set_db_descriptor(_db, descriptor, hot_index); } verify_or_upgrade_db_descriptor(_db, descriptor, hot_index); if (altTxn.get() != NULL) { altTxn->commit(); } }