Normalizer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Query / PlanCompiler / Normalizer.cs / 1305376 / Normalizer.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Query.InternalTrees; 
//using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class...
 
// 
// The normalizer performs transformations of the tree to bring it to a 'normalized' format
// In particular it does the following: 
//  (a) Transforms collection aggregate functions into a GroupBy.
//  (b) Translates Exists(X) into Exists(select 1 from X)
//
namespace System.Data.Query.PlanCompiler 
{
    ///  
    /// The normalizer performs transformations of the tree to bring it to a 'normalized' format 
    /// 
    internal class Normalizer : SubqueryTrackingVisitor 
    {
        #region constructors
        private Normalizer(PlanCompiler planCompilerState)
            :base(planCompilerState) 
        {
        } 
        #endregion 

        #region public methods 
        /// 
        /// The driver routine.
        /// 
        /// plan compiler state 
        internal static void Process(PlanCompiler planCompilerState)
        { 
            Normalizer normalizer = new Normalizer(planCompilerState); 
            normalizer.Process();
        } 

        #endregion

        #region private methods 

        #region driver 
        private void Process() 
        {
            m_command.Root = VisitNode(m_command.Root); 
        }
        #endregion

        #region visitor methods 

        #region ScalarOps 
 
        /// 
        /// Translate Exists(X) into Exists(select 1 from X) 
        /// 
        /// 
        /// 
        ///  
        public override Node Visit(ExistsOp op, Node n)
        { 
            VisitChildren(n); 

            // Build up a dummy project node over the input 
            n.Child0 = BuildDummyProjectForExists(n.Child0);

            return n;
        } 

        ///  
        /// Build Project(select 1 from child). 
        /// 
        ///  
        /// 
        private Node BuildDummyProjectForExists(Node child)
        {
            Var newVar; 
            Node projectNode = m_command.BuildProject(
                child, 
                m_command.CreateNode(m_command.CreateInternalConstantOp(m_command.IntegerType, 1)), 
                out newVar);
            return projectNode; 
        }

        /// 
        /// Build up an unnest above a scalar op node 
        ///    X => unnest(X)
        ///  
        /// the scalarop collection node 
        /// the unnest node
        private Node BuildUnnest(Node collectionNode) 
        {
            PlanCompiler.Assert(collectionNode.Op.IsScalarOp, "non-scalar usage of Unnest?");
            PlanCompiler.Assert(TypeSemantics.IsCollectionType(collectionNode.Op.Type), "non-collection usage for Unnest?");
 
            Var newVar;
            Node varDefNode = m_command.CreateVarDefNode(collectionNode, out newVar); 
            UnnestOp unnestOp = m_command.CreateUnnestOp(newVar); 
            Node unnestNode = m_command.CreateNode(unnestOp, varDefNode);
 
            return unnestNode;
        }

        ///  
        /// Converts a reference to a TVF, by the following
        ///    Collect(PhysicalProject(Unnest(Func))) 
        ///  
        /// current function op
        /// current function subtree 
        /// the new expression that corresponds to the TVF
        private Node VisitCollectionFunction(FunctionOp op, Node n)
        {
            PlanCompiler.Assert(TypeSemantics.IsCollectionType(op.Type), "non-TVF function?"); 

            Node unnestNode = BuildUnnest(n); 
            UnnestOp unnestOp = unnestNode.Op as UnnestOp; 
            PhysicalProjectOp projectOp = m_command.CreatePhysicalProjectOp(unnestOp.Table.Columns[0]);
            Node projectNode = m_command.CreateNode(projectOp, unnestNode); 
            CollectOp collectOp = m_command.CreateCollectOp(n.Op.Type);
            Node collectNode = m_command.CreateNode(collectOp, projectNode);

            return collectNode; 
        }
 
        ///  
        /// 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
        /// 
        /// 
        /// the functionOp for the collection agg 
        /// current subtree 
        /// the VarRef node that should replace the function
        private Node VisitCollectionAggregateFunction(FunctionOp op, Node n) 
        {
            TypeUsage softCastType = null;
            Node argNode = n.Child0;
            if (OpType.SoftCast == argNode.Op.OpType) 
            {
                softCastType = TypeHelpers.GetEdmType(argNode.Op.Type).TypeUsage; 
                argNode = argNode.Child0; 

                while (OpType.SoftCast == argNode.Op.OpType) 
                {
                    argNode = argNode.Child0;
                }
            } 

            Node unnestNode = BuildUnnest(argNode); 
            UnnestOp unnestOp = unnestNode.Op as UnnestOp; 
            Var unnestOutputVar = unnestOp.Table.Columns[0];
 
            AggregateOp aggregateOp = m_command.CreateAggregateOp(op.Function, false);
            VarRefOp unnestVarRefOp = m_command.CreateVarRefOp(unnestOutputVar);
            Node unnestVarRefNode = m_command.CreateNode(unnestVarRefOp);
            if (softCastType != null) 
            {
                unnestVarRefNode = m_command.CreateNode(m_command.CreateSoftCastOp(softCastType), unnestVarRefNode); 
            } 
            Node aggExprNode = m_command.CreateNode(aggregateOp, unnestVarRefNode);
 
            VarVec keyVars = m_command.CreateVarVec(); // empty keys
            Node keyVarDefListNode = m_command.CreateNode(m_command.CreateVarDefListOp());

            VarVec gbyOutputVars = m_command.CreateVarVec(); 
            Var aggVar;
            Node aggVarDefListNode = m_command.CreateVarDefListNode(aggExprNode, out aggVar); 
            gbyOutputVars.Set(aggVar); 
            GroupByOp gbyOp = m_command.CreateGroupByOp(keyVars, gbyOutputVars);
            Node gbySubqueryNode = m_command.CreateNode(gbyOp, unnestNode, keyVarDefListNode, aggVarDefListNode); 

            // "Move" this subquery to my parent relop
            Node ret = AddSubqueryToParentRelOp(aggVar, gbySubqueryNode);
 
            return ret;
        } 
 
        /// 
        /// Pre-processing for a function. Does the default thing. In addition, if the 
        /// function is a TVF (ie) returns a collection, convert this expression into
        ///    Nest(select value p from unnest(f) as p)
        /// 
        ///  
        /// 
        ///  
        public override Node Visit(FunctionOp op, Node n) 
        {
            VisitScalarOpDefault(op, n); 
            Node newNode = null;

            // Is this a TVF?
            if (TypeSemantics.IsCollectionType(op.Type)) 
            {
                newNode = VisitCollectionFunction(op, n); 
            } 
            // Is this a collection-aggregate function?
            else if (PlanCompilerUtil.IsCollectionAggregateFunction(op, n)) 
            {
                newNode = VisitCollectionAggregateFunction(op, n);
            }
            else 
            {
                newNode = n; 
            } 

            PlanCompiler.Assert(newNode != null, "failure to construct a functionOp?"); 
            return newNode;
        }

        #endregion 

        #region RelOps 
        ///  
        /// Processing for all JoinOps
        ///  
        /// JoinOp
        /// Current subtree
        /// 
        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;
        } 

        #endregion 
 
        #endregion
 
        #endregion
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Query.InternalTrees; 
//using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class...
 
// 
// The normalizer performs transformations of the tree to bring it to a 'normalized' format
// In particular it does the following: 
//  (a) Transforms collection aggregate functions into a GroupBy.
//  (b) Translates Exists(X) into Exists(select 1 from X)
//
namespace System.Data.Query.PlanCompiler 
{
    ///  
    /// The normalizer performs transformations of the tree to bring it to a 'normalized' format 
    /// 
    internal class Normalizer : SubqueryTrackingVisitor 
    {
        #region constructors
        private Normalizer(PlanCompiler planCompilerState)
            :base(planCompilerState) 
        {
        } 
        #endregion 

        #region public methods 
        /// 
        /// The driver routine.
        /// 
        /// plan compiler state 
        internal static void Process(PlanCompiler planCompilerState)
        { 
            Normalizer normalizer = new Normalizer(planCompilerState); 
            normalizer.Process();
        } 

        #endregion

        #region private methods 

        #region driver 
        private void Process() 
        {
            m_command.Root = VisitNode(m_command.Root); 
        }
        #endregion

        #region visitor methods 

        #region ScalarOps 
 
        /// 
        /// Translate Exists(X) into Exists(select 1 from X) 
        /// 
        /// 
        /// 
        ///  
        public override Node Visit(ExistsOp op, Node n)
        { 
            VisitChildren(n); 

            // Build up a dummy project node over the input 
            n.Child0 = BuildDummyProjectForExists(n.Child0);

            return n;
        } 

        ///  
        /// Build Project(select 1 from child). 
        /// 
        ///  
        /// 
        private Node BuildDummyProjectForExists(Node child)
        {
            Var newVar; 
            Node projectNode = m_command.BuildProject(
                child, 
                m_command.CreateNode(m_command.CreateInternalConstantOp(m_command.IntegerType, 1)), 
                out newVar);
            return projectNode; 
        }

        /// 
        /// Build up an unnest above a scalar op node 
        ///    X => unnest(X)
        ///  
        /// the scalarop collection node 
        /// the unnest node
        private Node BuildUnnest(Node collectionNode) 
        {
            PlanCompiler.Assert(collectionNode.Op.IsScalarOp, "non-scalar usage of Unnest?");
            PlanCompiler.Assert(TypeSemantics.IsCollectionType(collectionNode.Op.Type), "non-collection usage for Unnest?");
 
            Var newVar;
            Node varDefNode = m_command.CreateVarDefNode(collectionNode, out newVar); 
            UnnestOp unnestOp = m_command.CreateUnnestOp(newVar); 
            Node unnestNode = m_command.CreateNode(unnestOp, varDefNode);
 
            return unnestNode;
        }

        ///  
        /// Converts a reference to a TVF, by the following
        ///    Collect(PhysicalProject(Unnest(Func))) 
        ///  
        /// current function op
        /// current function subtree 
        /// the new expression that corresponds to the TVF
        private Node VisitCollectionFunction(FunctionOp op, Node n)
        {
            PlanCompiler.Assert(TypeSemantics.IsCollectionType(op.Type), "non-TVF function?"); 

            Node unnestNode = BuildUnnest(n); 
            UnnestOp unnestOp = unnestNode.Op as UnnestOp; 
            PhysicalProjectOp projectOp = m_command.CreatePhysicalProjectOp(unnestOp.Table.Columns[0]);
            Node projectNode = m_command.CreateNode(projectOp, unnestNode); 
            CollectOp collectOp = m_command.CreateCollectOp(n.Op.Type);
            Node collectNode = m_command.CreateNode(collectOp, projectNode);

            return collectNode; 
        }
 
        ///  
        /// 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
        /// 
        /// 
        /// the functionOp for the collection agg 
        /// current subtree 
        /// the VarRef node that should replace the function
        private Node VisitCollectionAggregateFunction(FunctionOp op, Node n) 
        {
            TypeUsage softCastType = null;
            Node argNode = n.Child0;
            if (OpType.SoftCast == argNode.Op.OpType) 
            {
                softCastType = TypeHelpers.GetEdmType(argNode.Op.Type).TypeUsage; 
                argNode = argNode.Child0; 

                while (OpType.SoftCast == argNode.Op.OpType) 
                {
                    argNode = argNode.Child0;
                }
            } 

            Node unnestNode = BuildUnnest(argNode); 
            UnnestOp unnestOp = unnestNode.Op as UnnestOp; 
            Var unnestOutputVar = unnestOp.Table.Columns[0];
 
            AggregateOp aggregateOp = m_command.CreateAggregateOp(op.Function, false);
            VarRefOp unnestVarRefOp = m_command.CreateVarRefOp(unnestOutputVar);
            Node unnestVarRefNode = m_command.CreateNode(unnestVarRefOp);
            if (softCastType != null) 
            {
                unnestVarRefNode = m_command.CreateNode(m_command.CreateSoftCastOp(softCastType), unnestVarRefNode); 
            } 
            Node aggExprNode = m_command.CreateNode(aggregateOp, unnestVarRefNode);
 
            VarVec keyVars = m_command.CreateVarVec(); // empty keys
            Node keyVarDefListNode = m_command.CreateNode(m_command.CreateVarDefListOp());

            VarVec gbyOutputVars = m_command.CreateVarVec(); 
            Var aggVar;
            Node aggVarDefListNode = m_command.CreateVarDefListNode(aggExprNode, out aggVar); 
            gbyOutputVars.Set(aggVar); 
            GroupByOp gbyOp = m_command.CreateGroupByOp(keyVars, gbyOutputVars);
            Node gbySubqueryNode = m_command.CreateNode(gbyOp, unnestNode, keyVarDefListNode, aggVarDefListNode); 

            // "Move" this subquery to my parent relop
            Node ret = AddSubqueryToParentRelOp(aggVar, gbySubqueryNode);
 
            return ret;
        } 
 
        /// 
        /// Pre-processing for a function. Does the default thing. In addition, if the 
        /// function is a TVF (ie) returns a collection, convert this expression into
        ///    Nest(select value p from unnest(f) as p)
        /// 
        ///  
        /// 
        ///  
        public override Node Visit(FunctionOp op, Node n) 
        {
            VisitScalarOpDefault(op, n); 
            Node newNode = null;

            // Is this a TVF?
            if (TypeSemantics.IsCollectionType(op.Type)) 
            {
                newNode = VisitCollectionFunction(op, n); 
            } 
            // Is this a collection-aggregate function?
            else if (PlanCompilerUtil.IsCollectionAggregateFunction(op, n)) 
            {
                newNode = VisitCollectionAggregateFunction(op, n);
            }
            else 
            {
                newNode = n; 
            } 

            PlanCompiler.Assert(newNode != null, "failure to construct a functionOp?"); 
            return newNode;
        }

        #endregion 

        #region RelOps 
        ///  
        /// Processing for all JoinOps
        ///  
        /// JoinOp
        /// Current subtree
        /// 
        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;
        } 

        #endregion 
 
        #endregion
 
        #endregion
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK