/// <summary> /// Processing for all JoinOps /// </summary> /// <param name="op">JoinOp</param> /// <param name="n">Current subtree</param> /// <returns>Whether the node was modified</returns> protected bool ProcessJoinOp(JoinBaseOp op, Node n) { VisitChildren(n); // visit all my children first // then check to see if we have any nested subqueries. This can only // occur in the join condition. // What we'll do in this case is to convert the join condition - "p" into // p -> Exists(Filter(SingleRowTableOp, p)) // We will then move the subqueries into an outerApply on the SingleRowTable List <Node> nestedSubqueries; if (!m_nodeSubqueries.TryGetValue(n, out nestedSubqueries)) { return(false); } PlanCompiler.Assert(n.Op.OpType == OpType.InnerJoin || n.Op.OpType == OpType.LeftOuterJoin || n.Op.OpType == OpType.FullOuterJoin, "unexpected op?"); PlanCompiler.Assert(n.HasChild2, "missing second child to JoinOp?"); Node joinCondition = n.Child2; Node inputNode = m_command.CreateNode(m_command.CreateSingleRowTableOp()); inputNode = AugmentWithSubqueries(inputNode, nestedSubqueries, true); Node filterNode = m_command.CreateNode(m_command.CreateFilterOp(), inputNode, joinCondition); Node existsNode = m_command.CreateNode(m_command.CreateExistsOp(), filterNode); n.Child2 = existsNode; return(true); }
protected override Node VisitJoinOp(JoinBaseOp op, Node n) { if (this.ProcessJoinOp(n)) { n.Child2.Child0 = this.BuildDummyProjectForExists(n.Child2.Child0); } return(n); }
/// <summary> /// Processing for all JoinOps /// </summary> /// <param name="op">JoinOp</param> /// <param name="n">Current subtree</param> /// <returns></returns> protected override Node VisitJoinOp(JoinBaseOp op, Node n) { if (base.ProcessJoinOp(op, n)) { // update the join condition // #479372: Build up a dummy project node over the input, as we always wrap the child of exists n.Child2.Child0 = BuildDummyProjectForExists(n.Child2.Child0); } return(n); }
/// <summary> /// JoinOp handling /// CrossJoinOp handling /// InnerJoinOp handling /// LeftOuterJoinOp handling /// FullOuterJoinOp handling /// /// Handler for all JoinOps. For all joins except cross joins, process /// the predicate first, and then the inputs - the inputs can be processed /// in any order. /// /// For cross joins, simply process all the (relop) inputs /// </summary> /// <param name="op">join op</param> /// <param name="n"></param> protected override void VisitJoinOp(JoinBaseOp op, Node n) { if (n.Op.OpType == OpType.CrossJoin) { VisitChildren(n); } else { VisitNode(n.Child2); // the predicate first VisitNode(n.Child0); // then, the left input VisitNode(n.Child1); // the right input } }
protected override void VisitJoinOp(JoinBaseOp op, System.Data.Entity.Core.Query.InternalTrees.Node n) { if (n.Op.OpType == OpType.CrossJoin) { this.VisitChildren(n); } else { this.VisitNode(n.Child2); this.VisitNode(n.Child0); this.VisitNode(n.Child1); } }
protected override System.Data.Entity.Core.Query.InternalTrees.Node VisitJoinOp( JoinBaseOp op, System.Data.Entity.Core.Query.InternalTrees.Node n) { if (n.Op.OpType == OpType.CrossJoin) { this.VisitChildren(n); return(n); } n.Child2 = this.VisitNode(n.Child2); n.Child0 = this.VisitNode(n.Child0); n.Child1 = this.VisitNode(n.Child1); this.m_command.RecomputeNodeInfo(n); return(n); }
// <summary> // Convert CrossApply(X, Filter(Y, p)) => InnerJoin(X, Y, p) // OuterApply(X, Filter(Y, p)) => LeftOuterJoin(X, Y, p) // if "Y" has no external references to X // </summary> // <param name="context"> Rule processing context </param> // <param name="applyNode"> Current ApplyOp </param> // <param name="newNode"> transformed subtree </param> // <returns> Transformation status </returns> private static bool ProcessApplyOverFilter(RuleProcessingContext context, Node applyNode, out Node newNode) { newNode = applyNode; var trc = (TransformationRulesContext)context; if (trc.PlanCompiler.TransformationsDeferred) { return(false); } var filterNode = applyNode.Child1; var command = context.Command; var filterInputNodeInfo = command.GetNodeInfo(filterNode.Child0); var applyLeftChildNodeInfo = command.GetExtendedNodeInfo(applyNode.Child0); // // check to see if the inputNode to the FilterOp has any external references // to the left child of the ApplyOp. If it does, we simply return, we // can't do much more here // if (filterInputNodeInfo.ExternalReferences.Overlaps(applyLeftChildNodeInfo.Definitions)) { return(false); } // // We've now gotten to the stage where the only external references (if any) // are from the filter predicate. // We can now simply convert the apply into an inner/leftouter join with the // filter predicate acting as the join condition // JoinBaseOp joinOp = null; if (applyNode.Op.OpType == OpType.CrossApply) { joinOp = command.CreateInnerJoinOp(); } else { joinOp = command.CreateLeftOuterJoinOp(); } newNode = command.CreateNode(joinOp, applyNode.Child0, filterNode.Child0, filterNode.Child1); return(true); }
protected override System.Data.Entity.Core.Query.InternalTrees.Node VisitJoinOp( JoinBaseOp op, System.Data.Entity.Core.Query.InternalTrees.Node joinNode) { System.Data.Entity.Core.Query.InternalTrees.Node n; if (this.NeedsJoinGraph(joinNode)) { n = this.ProcessJoinGraph(joinNode); if (n != joinNode) { this.m_treeModified = true; } } else { n = joinNode; } return(this.VisitDefaultForAllNodes(n)); }
/// <summary> /// JoinOps /// /// Common handling for all join ops. For all joins (other than crossjoin), /// we must first visit the predicate (to capture any references from it), and /// then visit the relop inputs. The relop inputs can be visited in any order /// because there can be no correlations between them /// For crossjoins, we simply use the default processing - visit all children /// ; there can be no correlations between the nodes anyway /// </summary> /// <param name="op"></param> /// <param name="n">Node for the join subtree</param> /// <returns>modified subtree</returns> protected override Node VisitJoinOp(JoinBaseOp op, Node n) { // Simply visit all children for a CrossJoin if (n.Op.OpType == OpType.CrossJoin) { VisitChildren(n); return(n); } // For other joins, we first need to visit the predicate, and then the // other inputs // first visit the predicate n.Child2 = VisitNode(n.Child2); // then visit the 2 join inputs n.Child0 = VisitNode(n.Child0); n.Child1 = VisitNode(n.Child1); m_command.RecomputeNodeInfo(n); return(n); }
/// <summary> /// Build a join graph for this node for this node if necessary, and process it /// </summary> /// <param name="op">current join op</param> /// <param name="joinNode">current join node</param> /// <returns></returns> protected override Node VisitJoinOp(JoinBaseOp op, Node joinNode) { Node newNode; // Build and process a join graph if necessary if (NeedsJoinGraph(joinNode)) { newNode = ProcessJoinGraph(joinNode); if (newNode != joinNode) { m_treeModified = true; } } else { newNode = joinNode; } // Now do the default processing (ie) visit the children, compute the nodeinfo etc. return(VisitDefaultForAllNodes(newNode)); }
private static bool ProcessApplyOverFilter( RuleProcessingContext context, System.Data.Entity.Core.Query.InternalTrees.Node applyNode, out System.Data.Entity.Core.Query.InternalTrees.Node newNode) { newNode = applyNode; if (((TransformationRulesContext)context).PlanCompiler.TransformationsDeferred) { return(false); } System.Data.Entity.Core.Query.InternalTrees.Node child1 = applyNode.Child1; Command command = context.Command; if (command.GetNodeInfo(child1.Child0).ExternalReferences.Overlaps(command.GetExtendedNodeInfo(applyNode.Child0).Definitions)) { return(false); } JoinBaseOp joinBaseOp = applyNode.Op.OpType != OpType.CrossApply ? (JoinBaseOp)command.CreateLeftOuterJoinOp() : (JoinBaseOp)command.CreateInnerJoinOp(); newNode = command.CreateNode((Op)joinBaseOp, applyNode.Child0, child1.Child0, child1.Child1); return(true); }