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;
	}
Beispiel #2
0
/** 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
	}
Beispiel #3
0
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;
	}