src/Shared/EntityFramework/Core/Query/PlanCompiler/SubqueryTrackingVisitor.cs
// <summary>
// Default processing for RelOps.
// - First, we mark the current node as its own ancestor (so that any
// subqueries that we detect internally will be added to this node's list)
// - then, visit each child
// - finally, accumulate all nested subqueries.
// - if the current RelOp has only one input, then add the nested subqueries via
// Outer apply nodes to this input.
// The interesting RelOps are
// Project, Filter, GroupBy, Sort,
// Should we break this out into separate functions instead?
// </summary>
// <param name="op"> Current RelOp </param>
// <param name="n"> Node to process </param>
// <returns> Current subtree </returns>
Default processing for RelOps.
First, we mark the current node as its own ancestor (so that any
subqueries that we detect internally will be added to this node's list)
then, visit each child
finally, accumulate all nested subqueries.
if the current RelOp has only one input, then add the nested subqueries via
Outer apply nodes to this input.
Default processing for RelOps . First we mark the current node as its own ancestor ( so that any subqueries that we detect internally will be added to this node ' s list ) then visit each child finally accumulate all nested subqueries . if the current RelOp has only one input then add the nested subqueries via Outer apply nodes to this input .
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "VisitRelOpDefault")]
        [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters",
            MessageId = "System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(System.Boolean,System.String)")]
        protected override Node VisitRelOpDefault(RelOp op, Node n)
        {
            VisitChildren(n); 
            List<Node> nestedSubqueries;
            if (m_nodeSubqueries.TryGetValue(n, out nestedSubqueries)
                && nestedSubqueries.Count > 0)
            {
                PlanCompiler.Assert(
                    n.Op.OpType == OpType.Project || n.Op.OpType == OpType.Filter ||
                    n.Op.OpType == OpType.GroupBy || n.Op.OpType == OpType.GroupByInto,
                    "VisitRelOpDefault: Unexpected op?" + n.Op.OpType);
                var newInputNode = AugmentWithSubqueries(n.Child0, nestedSubqueries, true);
                n.Child0 = newInputNode;
            }
            return n;
        }
[ SuppressMessage ( " " , " " , MessageId = " " ) ] [ SuppressMessage ( " " , " " , MessageId = " " ) ] protected override Node VisitRelOpDefault ( RelOp op , Node n ) { VisitChildren ( n ) ; List < Node > nestedSubqueries ; if ( m_nodeSubqueries . TryGetValue ( n , out nestedSubqueries ) && nestedSubqueries . Count > 0 ) { PlanCompiler . Assert ( n . Op . OpType == OpType . Project || n . Op . OpType == OpType . Filter || n . Op . OpType == OpType . GroupBy || n . Op . OpType == OpType . GroupByInto , " " + n . Op . OpType ) ; var newInputNode = AugmentWithSubqueries ( n . Child0 , nestedSubqueries , true ) ; n . Child0 = newInputNode ; } return n ; }
Default processing for RelOps.
Default processing for RelOps .
// visit all my children first // Then identify all the subqueries that have shown up as part of my node // Create Apply Nodes for each of these. // Validate - this must only apply to the following nodes // Now make this the new input child
None
op
RelOp
None
n
Node
Node to process
Node to process