//also used by XPathPatternBuilder
public static QilNode BuildOnePredicate(QilNode nodeset, QilNode predicate, bool isReverseStep,
XPathQilFactory f, FixupVisitor fixupVisitor,
ref int numFixupCurrent, ref int numFixupPosition, ref int numFixupLast)
{
nodeset = f.EnsureNodeSet(nodeset);
// Mirgeing nodeset and predicate:
// 1. Predicate contains 0 last() :
// for $i in nodeset
// where predicate
// return $i
// Note: Currently we are keepeing old output to minimize diff.
// 2. Predicate contains 1 last()
// let $cach := nodeset return
// for $i in $cach
// where predicate(length($cach))
// return $i
// Suggestion: This is a little optimisation we can do or don't do.
// 3. Predicate contains 2+ last()
// let $cash := nodeset return
// let $size := length($cash) return
// for $i in $cash
// where predicate($size)
// return $i
QilNode result;
if (numFixupLast != 0 && fixupVisitor.CountUnfixedLast(predicate) != 0)
{
// this subtree has unfixed last() nodes
QilIterator cash = f.Let(nodeset);
QilIterator size = f.Let(f.XsltConvert(f.Length(cash), T.DoubleX));
QilIterator it = f.For(cash);
predicate = fixupVisitor.Fixup(predicate, /*current:*/ it, /*last:*/ size);
numFixupCurrent -= fixupVisitor.numCurrent;
numFixupPosition -= fixupVisitor.numPosition;
numFixupLast -= fixupVisitor.numLast;
result = f.Loop(cash, f.Loop(size, f.Filter(it, predicate)));
}
else
{
QilIterator it = f.For(nodeset);
predicate = fixupVisitor.Fixup(predicate, /*current:*/ it, /*last:*/ null);
numFixupCurrent -= fixupVisitor.numCurrent;
numFixupPosition -= fixupVisitor.numPosition;
numFixupLast -= fixupVisitor.numLast;
result = f.Filter(it, predicate);
}
if (isReverseStep)
{
result = f.DocOrderDistinct(result);
}
return(result);
}