protected override void VisitJoinOp(JoinBaseOp op, Node n) { VisitRelOpDefault(op, n); if (op.OpType == OpType.CrossJoin) { Assert(n.Children.Count >= 2, "CrossJoinOp needs at least 2 arguments; found only {0}", n.Children.Count); return; } AssertRelOpOrPhysicalOp(n.Child0.Op); AssertRelOpOrPhysicalOp(n.Child1.Op); AssertScalarOp(n.Child2.Op); AssertBooleanOp(n.Child2.Op); }
protected override void VisitJoinOp(JoinBaseOp op, Node n) { using (new AutoXml(this, op)) { if (n.Children.Count > 2) { using (new AutoXml(this, "condition")) { VisitNode(n.Child2); } } using (new AutoXml(this, "input")) { VisitNode(n.Child0); } using (new AutoXml(this, "input")) { VisitNode(n.Child1); } } }
/// <summary> /// JoinOp common processing /// </summary> /// <param name="op"></param> /// <param name="n"></param> /// <returns></returns> protected override Node VisitJoinOp(JoinBaseOp op, Node n) { return ApplyOpJoinOp(op, 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) { // Only LeftOuterJoin and InnerJoin are handled by JoinElimination if (op.OpType == OpType.InnerJoin || op.OpType == OpType.LeftOuterJoin) { m_compilerState.MarkPhaseAsNeeded(PlanCompilerPhase.JoinElimination); } // If a subquery was added with an exists node, we have to go througth Normalization if (base.ProcessJoinOp(n)) { m_compilerState.MarkPhaseAsNeeded(PlanCompilerPhase.Normalization); } 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); }
/// <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> /// 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; }
/// <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 } }
/// <summary> /// Default handler for all JoinOps /// </summary> /// <param name="op">join op</param> /// <param name="n"></param> protected virtual void VisitJoinOp(JoinBaseOp op, Node n) { VisitRelOpDefault(op, n); }