static bool spCheckForConstraint( const ZTName& iPropName, const ZTBSpec::CriterionSect& iCriterionSect) { for (ZTBSpec::CriterionSect::const_iterator critIter = iCriterionSect.begin(), theEnd = iCriterionSect.end(); critIter != theEnd; ++critIter) { // It's a criteria on the current property. if (1 == (*critIter).GetComparator().fStrength && ZTBSpec::eRel_Equal == (*critIter).GetComparator().fRel && (*critIter).GetTValue().PGet<string8>() && (*critIter).GetPropName() == iPropName) { // It's a 1-strength equality search on our property name, // so we can handle it. Remove the criteria from ioCriteria // and return success. return true; } } // We didn't find a 1-strength equality search on our property name. return false; }
/** Remove tautologies, collapse overlapping ranges. If there are any contradictions return false. If ioCrit is a tautology empty ioCrit and return true. Otherwise return true. */ static bool sSimplify(ZTBSpec::CriterionSect& ioCrit) { // AG2005-10-02. For the moment I'm disabling the simplification of criteria. The // precise technique I'm using causes a lot of allocations/deallocations and // we end up spending oodles of time in free/malloc, far more than we save when using // the simplified form. I have in mind a more complicated and less memory manager-intensive // technique, but that can wait a bit. return true; #if 0 // Look at each Criterion in turn. for (vector<ZTBSpec::Criterion>::iterator i = ioCrit.begin(); i != ioCrit.end(); /*no increment*/) { ZTupleValue smallestLess, smallestLessEqual, largestGreater, largestGreaterEqual; bool gotSmallestLess = false; bool gotSmallestLessEqual = false; bool gotLargestGreater = false; bool gotLargestGreaterEqual = false; // For simplicity we simplify only if strength is zero if ((*i).fComparator.fStrength != 0) { ++i; continue; } switch ((*i).fComparator.fRel) { case ZTBSpec::eRel_Less: smallestLess = (*i).fTupleValue; gotSmallestLess = true; break; case ZTBSpec::eRel_LessEqual: smallestLessEqual = (*i).fTupleValue; gotSmallestLessEqual = true; break; case ZTBSpec::eRel_Equal: smallestLessEqual = (*i).fTupleValue; gotSmallestLessEqual = true; largestGreaterEqual = (*i).fTupleValue; gotLargestGreaterEqual = true; break; case ZTBSpec::eRel_GreaterEqual: largestGreaterEqual = (*i).fTupleValue; gotLargestGreaterEqual = true; break; case ZTBSpec::eRel_Greater: largestGreater = (*i).fTupleValue; gotLargestGreater = true; break; default: ++i; continue; } string propName = (*i).fPropName; // The criteria is one for which we can easily spot contradictions, // so erase the criteria (we'll reinstate equivalents later). i = ioCrit.erase(i); // Find subsequent criteria that could be simplified with this one. bool isContradiction = false; bool isTautology = false; for (vector<ZTBSpec::Criterion>::iterator j = i; j != ioCrit.end(); /* no increment */) { if (propName != (*j).fPropName || 0 != (*j).fComparator.fStrength) { ++j; continue; } switch ((*j).fComparator.fRel) { case ZTBSpec::eRel_Less: { if (gotSmallestLess) { if (smallestLess > (*j).fTupleValue) smallestLess = (*j).fTupleValue; } else if (gotSmallestLessEqual) { if (smallestLessEqual >= (*j).fTupleValue) { smallestLess = (*j).fTupleValue; gotSmallestLessEqual = false; gotSmallestLess = true; } } else { smallestLess = (*j).fTupleValue; gotSmallestLess = true; } break; } case ZTBSpec::eRel_Greater: { if (gotLargestGreater) { if (largestGreater < (*j).fTupleValue) largestGreater = (*j).fTupleValue; } else if (gotLargestGreaterEqual) { if (largestGreaterEqual <= (*j).fTupleValue) { largestGreater = (*j).fTupleValue; gotLargestGreaterEqual = false; gotLargestGreater = true; } } else { largestGreater = (*j).fTupleValue; gotLargestGreater = true; } } break; case ZTBSpec::eRel_LessEqual: case ZTBSpec::eRel_Equal: case ZTBSpec::eRel_GreaterEqual: break; default: { ++j; continue; } } if ((*j).fComparator.fRel == ZTBSpec::eRel_Equal || (*j).fComparator.fRel == ZTBSpec::eRel_LessEqual) { if (gotSmallestLess) { if (smallestLess > (*j).fTupleValue) { gotSmallestLess = false; gotSmallestLessEqual = true; smallestLessEqual = (*j).fTupleValue; } } else if (gotSmallestLessEqual) { if (smallestLessEqual > (*j).fTupleValue) smallestLessEqual = (*j).fTupleValue; } else { gotSmallestLessEqual = true; smallestLessEqual = (*j).fTupleValue; } } if ((*j).fComparator.fRel == ZTBSpec::eRel_Equal || (*j).fComparator.fRel == ZTBSpec::eRel_GreaterEqual) { if (gotLargestGreater) { if (largestGreater < (*j).fTupleValue) { gotLargestGreater = false; gotLargestGreaterEqual = true; largestGreaterEqual = (*j).fTupleValue; } } else if (gotLargestGreaterEqual) { if (largestGreaterEqual < (*j).fTupleValue) largestGreaterEqual = (*j).fTupleValue; } else { gotLargestGreaterEqual = true; largestGreaterEqual = (*j).fTupleValue; } } // Erase this criteria, need to update i too, in case the vector is reallocated. size_t offset = i - ioCrit.begin(); j = ioCrit.erase(j); i = offset + ioCrit.begin(); } // Make sure we haven't messed up. ZAssertStop(2, (!gotSmallestLess || !gotSmallestLessEqual) && (!gotLargestGreater || !gotLargestGreaterEqual)); if (gotSmallestLess) { if (gotLargestGreater) { if (!(smallestLess > largestGreater)) isContradiction = true; } else if (gotLargestGreaterEqual) { if (!(smallestLess > largestGreaterEqual)) isContradiction = true; } } else if (gotSmallestLessEqual) { if (gotLargestGreater) { if (!(smallestLessEqual > largestGreater)) isContradiction = true; } else if (gotLargestGreaterEqual) { if (!(smallestLessEqual >= largestGreaterEqual)) isContradiction = true; } } if (isContradiction) return false; if (isTautology) { // We don't actually recognize tautologies yet, so isTautology // never gets set true and we won't execute this. ioCrit.clear(); return true; } // It's neither a contradiction nor a tautology. So reinstate the // one or two entries we need to represent the criteria. if (gotSmallestLessEqual && gotLargestGreaterEqual && smallestLessEqual == largestGreaterEqual) { i = ioCrit.insert(i, ZTBSpec::Criterion(propName, ZTBSpec::eRel_Equal, smallestLessEqual)); } else { if (gotSmallestLess) { i = ioCrit.insert(i, ZTBSpec::Criterion(propName, ZTBSpec::eRel_Less, smallestLess)); } else if (gotSmallestLessEqual) { i = ioCrit.insert(i, ZTBSpec::Criterion(propName, ZTBSpec::eRel_LessEqual, smallestLessEqual)); } if (gotLargestGreater) { i = ioCrit.insert(i, ZTBSpec::Criterion(propName, ZTBSpec::eRel_Greater, largestGreater)); } else if (gotLargestGreaterEqual) { i = ioCrit.insert(i, ZTBSpec::Criterion(propName, ZTBSpec::eRel_GreaterEqual, largestGreaterEqual)); } } // Move on to the next Criterion. ++i; } return true; #endif }
size_t ZTupleIndex_General::CanHandle(const ZTBSpec::CriterionSect& iCriterionSect) { vector<const ZTBSpec::Criterion*> remainingCriteria; remainingCriteria.reserve(iCriterionSect.size()); for (ZTBSpec::CriterionSect::const_iterator i = iCriterionSect.begin(), theEnd = iCriterionSect.end(); i != theEnd; ++i) { remainingCriteria.push_back(&(*i)); } size_t likelyResultSize = fSet.size(); size_t propertyCount = 0; const ZTupleValue* valueEqual; const ZTupleValue* bestValueLess; const ZTupleValue* bestValueLessEqual; const ZTupleValue* bestValueGreater; const ZTupleValue* bestValueGreaterEqual; // Walk through our properties, looking for and removing entries in // remainingCriteria where where the effective constraint is equivalence. for (const ZTuplePropName* propNameIter = fPropNames; propertyCount < fPropNameCount; ++propertyCount) { if (!sGatherMergeConstraints(*propNameIter++, remainingCriteria, valueEqual, bestValueLess, bestValueLessEqual, bestValueGreater, bestValueGreaterEqual)) { // We found a contradiction, so we can trivially handle this search. return 1; } if (!valueEqual) break; ZAssert(!bestValueLess && !bestValueLessEqual && !bestValueGreater && !bestValueGreaterEqual); likelyResultSize /= 2; } if (propertyCount != fPropNameCount) { // We still have properties on which we index not referenced by the criteria we've seen. if (bestValueLess || bestValueLessEqual || bestValueGreater || bestValueGreaterEqual) { // We at least had a range check on the last item, so move on. likelyResultSize /= 2; ++propertyCount; } } if (!propertyCount) { // We didn't see any matching property names at all, so we can't help. return 0; } // Add 1, so we can't return zero. return likelyResultSize + 1; }