// ---------------------------------------------------------------------------- public XPathBuilder(IXPathEnvironment environment) { _environment = environment; _f = _environment.Factory; this.fixupCurrent = _f.Unknown(T.NodeNotRtf); this.fixupPosition = _f.Unknown(T.DoubleX); this.fixupLast = _f.Unknown(T.DoubleX); _fixupVisitor = new FixupVisitor(_f, fixupCurrent, fixupPosition, fixupLast); }
//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); }
/// <summary> /// Костыль для запросов по интерфейсу. Просто вызвать метод. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="q"></param> /// <returns></returns> public static IQueryable <T> Fix <T>(this IQueryable <T> q) { var visitor = new FixupVisitor(); return(q.Provider.CreateQuery <T>(visitor.Visit(q.Expression))); }