Expr extractCurINExprFromNodeAFilter(LogicNode nodeA, InSubqueryExpr curInExpr, ExprRef markerFilter) { var nodeAFilter = nodeA.filter_; if (nodeAFilter != null) { // a1 > @1 and a2 > @2 and a3 > 2, scalarExpr = @1 // keeplist: a1 > @1 and a3 > 2 // andlist after removal: a2 > @2 // nodeAFilter = a1 > @1 and a3 > 2 // var andlist = nodeAFilter.FilterToAndList(); var keeplist = andlist.Where(x => x.VisitEachExists(e => e.Equals(curInExpr))).ToList(); andlist.RemoveAll(x => x.VisitEachExists(e => e.Equals(curInExpr))); if (andlist.Count == 0) { nodeA.NullifyFilter(); } else { nodeA.filter_ = andlist.AndListToExpr(); if (keeplist.Count > 0) { nodeAFilter = keeplist.AndListToExpr(); } else { nodeAFilter = markerFilter; } } } return(nodeAFilter); }
LogicNode inToMarkJoin(LogicNode planWithSubExpr, InSubqueryExpr inExpr) { LogicNode nodeA = planWithSubExpr; // nodeB contains the join filter var nodeB = inExpr.query_.logicPlan_; var nodeBFilter = nodeB.filter_; nodeB.NullifyFilter(); // nullify nodeA's filter: the rest is push to top filter. However, // if nodeA is a Filter|MarkJoin, keep its mark filter. var markerFilter = new ExprRef(new MarkerExpr(nodeBFilter.tableRefs_, inExpr.subqueryid_), 0); var nodeAFilter = extractCurINExprFromNodeAFilter(nodeA, inExpr, markerFilter); // consider SQL ...a1 in select b1 from... // a1 is outerExpr and b1 is selectExpr Expr outerExpr = inExpr.child_(); Debug.Assert(inExpr.query_.selection_.Count == 1); Expr selectExpr = inExpr.query_.selection_[0]; BinExpr inToEqual = BinExpr.MakeBooleanExpr(outerExpr, selectExpr, "=", true); // make a mark join LogicMarkJoin markjoin; if (inExpr.hasNot_) { markjoin = new LogicMarkAntiSemiJoin(nodeA, nodeB, inExpr.subqueryid_); } else { markjoin = new LogicMarkSemiJoin(nodeA, nodeB, inExpr.subqueryid_); } // make a filter on top of the mark join collecting all filters Expr topfilter = nodeAFilter.SearchAndReplace(inExpr, markerFilter); nodeBFilter.DeParameter(nodeA.InclusiveTableRefs()); topfilter = topfilter.AddAndFilter(nodeBFilter); // TODO mutiple nested insubquery subquery // seperate the overlapping code with existsToSubquery to a new method // when the PR in #support nestted exist subquery pass LogicFilter Filter = new LogicFilter(markjoin, topfilter); Filter = new LogicFilter(Filter, inToEqual); return(Filter); }