// static void IndexBoundsBuilder::translateEquality(const BSONElement& data, bool isHashed, OrderedIntervalList* oil, bool* exact) { // We have to copy the data out of the parse tree and stuff it into the index // bounds. BSONValue will be useful here. BSONObj dataObj; if (isHashed) { dataObj = ExpressionMapping::hash(data); } else { dataObj = objFromElement(data); } // UNITTEST 11738048 if (Array == dataObj.firstElement().type()) { // XXX: bad oil->intervals.push_back(allValues()); *exact = false; } else { verify(dataObj.isOwned()); oil->intervals.push_back(makePointInterval(dataObj)); // XXX: it's exact if the index isn't sparse? if (dataObj.firstElement().isNull() || isHashed) { *exact = false; } else { *exact = true; } } }
// static void IndexBoundsBuilder::translate(const MatchExpression* expr, const BSONElement& elt, OrderedIntervalList* oilOut, bool* exactOut) { int direction = (elt.numberInt() >= 0) ? 1 : -1; Interval interval; bool exact = false; oilOut->name = elt.fieldName(); bool isHashed = false; if (mongoutils::str::equals("hashed", elt.valuestrsafe())) { isHashed = true; } if (isHashed) { verify(MatchExpression::EQ == expr->matchType() || MatchExpression::MATCH_IN == expr->matchType()); } if (MatchExpression::EQ == expr->matchType()) { const EqualityMatchExpression* node = static_cast<const EqualityMatchExpression*>(expr); // We have to copy the data out of the parse tree and stuff it into the index // bounds. BSONValue will be useful here. BSONObj dataObj; if (isHashed) { dataObj = ExpressionMapping::hash(node->getData()); } else { dataObj = objFromElement(node->getData()); } // UNITTEST 11738048 if (Array == dataObj.firstElement().type()) { // XXX: build better bounds warning() << "building lazy bounds for " << expr->toString() << endl; interval = allValues(); exact = false; } else { verify(dataObj.isOwned()); interval = makePointInterval(dataObj); // XXX: it's exact if the index isn't sparse if (dataObj.firstElement().isNull()) { exact = false; } else if (isHashed) { exact = false; } else { exact = true; } } } else if (MatchExpression::LTE == expr->matchType()) { const LTEMatchExpression* node = static_cast<const LTEMatchExpression*>(expr); BSONElement dataElt = node->getData(); BSONObjBuilder bob; bob.appendMinForType("", dataElt.type()); bob.append(dataElt); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, true, true); // XXX: only exact if not (null or array) exact = true; } else if (MatchExpression::LT == expr->matchType()) { const LTMatchExpression* node = static_cast<const LTMatchExpression*>(expr); BSONElement dataElt = node->getData(); BSONObjBuilder bob; bob.appendMinForType("", dataElt.type()); bob.append(dataElt); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, true, false); // XXX: only exact if not (null or array) exact = true; } else if (MatchExpression::GT == expr->matchType()) { const GTMatchExpression* node = static_cast<const GTMatchExpression*>(expr); BSONElement dataElt = node->getData(); BSONObjBuilder bob; bob.append(node->getData()); bob.appendMaxForType("", dataElt.type()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, false, true); // XXX: only exact if not (null or array) exact = true; } else if (MatchExpression::GTE == expr->matchType()) { const GTEMatchExpression* node = static_cast<const GTEMatchExpression*>(expr); BSONElement dataElt = node->getData(); BSONObjBuilder bob; bob.append(dataElt); bob.appendMaxForType("", dataElt.type()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, true, true); // XXX: only exact if not (null or array) exact = true; } else if (MatchExpression::REGEX == expr->matchType()) { warning() << "building lazy bounds for " << expr->toString() << endl; interval = allValues(); exact = false; } else if (MatchExpression::MOD == expr->matchType()) { BSONObjBuilder bob; bob.appendMinForType("", NumberDouble); bob.appendMaxForType("", NumberDouble); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, true, true); exact = false; } else if (MatchExpression::MATCH_IN == expr->matchType()) { warning() << "building lazy bounds for " << expr->toString() << endl; interval = allValues(); exact = false; } else if (MatchExpression::TYPE_OPERATOR == expr->matchType()) { const TypeMatchExpression* tme = static_cast<const TypeMatchExpression*>(expr); BSONObjBuilder bob; bob.appendMinForType("", tme->getData()); bob.appendMaxForType("", tme->getData()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, true, true); exact = false; } else if (MatchExpression::MATCH_IN == expr->matchType()) { warning() << "building lazy bounds for " << expr->toString() << endl; interval = allValues(); exact = false; } else if (MatchExpression::GEO == expr->matchType()) { const GeoMatchExpression* gme = static_cast<const GeoMatchExpression*>(expr); // Can only do this for 2dsphere. if (!mongoutils::str::equals("2dsphere", elt.valuestrsafe())) { warning() << "Planner error trying to build geo bounds for " << elt.toString() << " index element."; verify(0); } const S2Region& region = gme->getGeoQuery().getRegion(); ExpressionMapping::cover2dsphere(region, oilOut); *exactOut = false; // XXX: restructure this method return; } else { warning() << "Planner error, trying to build bounds for expr " << expr->toString() << endl; verify(0); } if (-1 == direction) { reverseInterval(&interval); } oilOut->intervals.push_back(interval); *exactOut = exact; }
// static void IndexBoundsBuilder::translate(const MatchExpression* expr, int direction, OrderedIntervalList* oilOut, bool* exactOut) { Interval interval; bool exact = false; if (expr->isLeaf()) { if (MatchExpression::EQ == expr->matchType()) { const EqualityMatchExpression* node = static_cast<const EqualityMatchExpression*>(expr); // We have to copy the data out of the parse tree and stuff it into the index bounds. // BSONValue will be useful here. BSONObj dataObj = objFromElement(node->getData()); if (dataObj.couldBeArray()) { // XXX: build better bounds warning() << "building lazy bounds for " << expr->toString() << endl; interval = allValues(); exact = false; } else { verify(dataObj.isOwned()); interval = makePointInterval(dataObj); exact = true; } } else if (MatchExpression::LTE == expr->matchType()) { const LTEMatchExpression* node = static_cast<const LTEMatchExpression*>(expr); BSONObjBuilder bob; bob.appendMinKey(""); bob.append(node->getData()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, true, true); exact = true; } else if (MatchExpression::LT == expr->matchType()) { const LTMatchExpression* node = static_cast<const LTMatchExpression*>(expr); BSONObjBuilder bob; bob.appendMinKey(""); bob.append(node->getData()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, true, false); exact = true; } else if (MatchExpression::GT == expr->matchType()) { const GTMatchExpression* node = static_cast<const GTMatchExpression*>(expr); BSONObjBuilder bob; bob.append(node->getData()); bob.appendMaxKey(""); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, false, true); exact = true; } else if (MatchExpression::GTE == expr->matchType()) { const GTEMatchExpression* node = static_cast<const GTEMatchExpression*>(expr); BSONObjBuilder bob; bob.append(node->getData()); bob.appendMaxKey(""); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); interval = makeRangeInterval(dataObj, true, true); exact = true; } else { // XXX: build better bounds warning() << "building lazy bounds for " << expr->toString() << endl; interval = allValues(); exact = false; } } else { // XXX: build better bounds verify(expr->isArray()); warning() << "building lazy bounds for " << expr->toString() << endl; interval = allValues(); exact = false; } if (-1 == direction) { reverseInterval(&interval); } oilOut->intervals.push_back(interval); *exactOut = exact; }