src/Shared/EntityFramework/Core/Query/PlanCompiler/Normalizer.cs
// <summary>
// Converts a collection aggregate function count(X), where X is a collection into
// two parts. Part A is a groupby subquery that looks like
// GroupBy(Unnest(X), empty, count(y))
// where "empty" describes the fact that the groupby has no keys, and y is an
// element var of the Unnest
// Part 2 is a VarRef that refers to the aggregate var for count(y) described above.
// Logically, we would replace the entire functionOp by element(GroupBy...). However,
// since we also want to translate element() into single-row-subqueries, we do this
// here as well.
// The function itself is replaced by the VarRef, and the GroupBy is added to the list
// of scalar subqueries for the current relOp node on the stack
// </summary>
// <param name="op"> the functionOp for the collection agg </param>
// <param name="n"> current subtree </param>
// <returns> the VarRef node that should replace the function </returns>
Converts a collection aggregate function count(X), where X is a collection into
two parts. Part A is a groupby subquery that looks like
GroupBy(Unnest(X), empty, count(y))
where "empty" describes the fact that the groupby has no keys, and y is an
element var of the Unnest
Part 2 is a VarRef that refers to the aggregate var for count(y) described above.
Logically, we would replace the entire functionOp by element(GroupBy...). However,
since we also want to translate element() into single-row-subqueries, we do this
here as well.
The function itself is replaced by the VarRef, and the GroupBy is added to the list
of scalar subqueries for the current relOp node on the stack
Converts a collection aggregate function count ( X ) where X is a collection into two parts . Part A is a groupby subquery that looks like GroupBy ( Unnest ( X ) empty count ( y )) where " empty " describes the fact that the groupby has no keys and y is an element var of the Unnest Part 2 is a VarRef that refers to the aggregate var for count ( y ) described above . Logically we would replace the entire functionOp by element ( GroupBy ... ) . However since we also want to translate element () into single - row - subqueries we do this here as well . The function itself is replaced by the VarRef and the GroupBy is added to the list of scalar subqueries for the current relOp node on the stack
private Node VisitCollectionAggregateFunction(FunctionOp op, Node n)
        {
            TypeUsage softCastType = null;
            var argNode = n.Child0;
            if (OpType.SoftCast
                == argNode.Op.OpType)
            {
                softCastType = TypeHelpers.GetEdmType<CollectionType>(argNode.Op.Type).TypeUsage;
                argNode = argNode.Child0;
                while (OpType.SoftCast
                       == argNode.Op.OpType)
                {
                    argNode = argNode.Child0;
                }
            }
            var unnestNode = BuildUnnest(argNode);
            var unnestOp = unnestNode.Op as UnnestOp;
            var unnestOutputVar = unnestOp.Table.Columns[0];
            var aggregateOp = m_command.CreateAggregateOp(op.Function, false);
            var unnestVarRefOp = m_command.CreateVarRefOp(unnestOutputVar);
            var unnestVarRefNode = m_command.CreateNode(unnestVarRefOp);
            if (softCastType != null)
            {
                unnestVarRefNode = m_command.CreateNode(m_command.CreateSoftCastOp(softCastType), unnestVarRefNode);
            }
            var aggExprNode = m_command.CreateNode(aggregateOp, unnestVarRefNode);
            var keyVars = m_command.CreateVarVec(); 
            var keyVarDefListNode = m_command.CreateNode(m_command.CreateVarDefListOp());
            var gbyOutputVars = m_command.CreateVarVec();
            Var aggVar;
            var aggVarDefListNode = m_command.CreateVarDefListNode(aggExprNode, out aggVar);
            gbyOutputVars.Set(aggVar);
            var gbyOp = m_command.CreateGroupByOp(keyVars, gbyOutputVars);
            var gbySubqueryNode = m_command.CreateNode(gbyOp, unnestNode, keyVarDefListNode, aggVarDefListNode);
            var ret = AddSubqueryToParentRelOp(aggVar, gbySubqueryNode);
            return ret;
        }
private Node VisitCollectionAggregateFunction ( FunctionOp op , Node n ) { TypeUsage softCastType = null ; var argNode = n . Child0 ; if ( OpType . SoftCast == argNode . Op . OpType ) { softCastType = TypeHelpers . GetEdmType < CollectionType > ( argNode . Op . Type ) . TypeUsage ; argNode = argNode . Child0 ; while ( OpType . SoftCast == argNode . Op . OpType ) { argNode = argNode . Child0 ; } } var unnestNode = BuildUnnest ( argNode ) ; var unnestOp = unnestNode . Op as UnnestOp ; var unnestOutputVar = unnestOp . Table . Columns [ 0 ] ; var aggregateOp = m_command . CreateAggregateOp ( op . Function , false ) ; var unnestVarRefOp = m_command . CreateVarRefOp ( unnestOutputVar ) ; var unnestVarRefNode = m_command . CreateNode ( unnestVarRefOp ) ; if ( softCastType != null ) { unnestVarRefNode = m_command . CreateNode ( m_command . CreateSoftCastOp ( softCastType ) , unnestVarRefNode ) ; } var aggExprNode = m_command . CreateNode ( aggregateOp , unnestVarRefNode ) ; var keyVars = m_command . CreateVarVec ( ) ; var keyVarDefListNode = m_command . CreateNode ( m_command . CreateVarDefListOp ( ) ) ; var gbyOutputVars = m_command . CreateVarVec ( ) ; Var aggVar ; var aggVarDefListNode = m_command . CreateVarDefListNode ( aggExprNode , out aggVar ) ; gbyOutputVars . Set ( aggVar ) ; var gbyOp = m_command . CreateGroupByOp ( keyVars , gbyOutputVars ) ; var gbySubqueryNode = m_command . CreateNode ( gbyOp , unnestNode , keyVarDefListNode , aggVarDefListNode ) ; var ret = AddSubqueryToParentRelOp ( aggVar , gbySubqueryNode ) ; return ret ; }
Converts a collection aggregate function count(X), where X is a collection into
two parts.
Converts a collection aggregate function count ( X ) where X is a collection into two parts .
// empty keys // "Move" this subquery to my parent relop
the VarRef node that should replace the function
the VarRef node that should replace the function
op
FunctionOp
the functionOp for the collection agg
the functionOp for the collection agg
n
Node
None