Example #1
0
        public override void Visit(VarDefOp op, System.Data.Entity.Core.Query.InternalTrees.Node n)
        {
            this.VisitDefault(n);
            System.Data.Entity.Core.Query.InternalTrees.Node child0 = n.Child0;
            Op op1 = child0.Op;
            GroupAggregateVarInfo groupAggregateVarInfo;

            System.Data.Entity.Core.Query.InternalTrees.Node templateNode;
            bool isUnnested;

            if (GroupAggregateVarComputationTranslator.TryTranslateOverGroupAggregateVar(child0, true, this._command, this._groupAggregateVarInfoManager, out groupAggregateVarInfo, out templateNode, out isUnnested))
            {
                this._groupAggregateVarInfoManager.Add(op.Var, groupAggregateVarInfo, templateNode, isUnnested);
            }
            else
            {
                if (op1.OpType != OpType.NewRecord)
                {
                    return;
                }
                NewRecordOp newRecordOp = (NewRecordOp)op1;
                for (int index = 0; index < child0.Children.Count; ++index)
                {
                    if (GroupAggregateVarComputationTranslator.TryTranslateOverGroupAggregateVar(child0.Children[index], true, this._command, this._groupAggregateVarInfoManager, out groupAggregateVarInfo, out templateNode, out isUnnested))
                    {
                        this._groupAggregateVarInfoManager.Add(op.Var, groupAggregateVarInfo, templateNode, isUnnested, (EdmMember)newRecordOp.Properties[index]);
                    }
                }
            }
        }
Example #2
0
        // <summary>
        // Determines whether the var or a property of the var (if the var is defined as a NewRecord)
        // is defined exclusively over a single group aggregate. If so, it registers it as such with the
        // group aggregate var info manager.
        // </summary>
        public override void Visit(VarDefOp op, Node n)
        {
            VisitDefault(n);

            var definingNode   = n.Child0;
            var definingNodeOp = definingNode.Op;

            GroupAggregateVarInfo referencedVarInfo;
            Node templateNode;
            bool isUnnested;

            if (GroupAggregateVarComputationTranslator.TryTranslateOverGroupAggregateVar(
                    definingNode, true, _command, _groupAggregateVarInfoManager, out referencedVarInfo, out templateNode, out isUnnested))
            {
                _groupAggregateVarInfoManager.Add(op.Var, referencedVarInfo, templateNode, isUnnested);
            }
            else if (definingNodeOp.OpType
                     == OpType.NewRecord)
            {
                var newRecordOp = (NewRecordOp)definingNodeOp;
                for (var i = 0; i < definingNode.Children.Count; i++)
                {
                    var argumentNode = definingNode.Children[i];
                    if (GroupAggregateVarComputationTranslator.TryTranslateOverGroupAggregateVar(
                            argumentNode, true, _command, _groupAggregateVarInfoManager, out referencedVarInfo, out templateNode, out isUnnested))
                    {
                        _groupAggregateVarInfoManager.Add(op.Var, referencedVarInfo, templateNode, isUnnested, newRecordOp.Properties[i]);
                    }
                }
            }
        }
        public override void Visit(FunctionOp op, Node n)
        {
            VisitDefault(n);
            if (!PlanCompilerUtil.IsCollectionAggregateFunction(op, n))
            {
                return;
            }

            if (n.Children.Count > 1)
            {
                return;
            }

            GroupAggregateVarInfo referencedGroupAggregateVarInfo;
            Node templateNode;
            bool isUnnested;

            if (GroupAggregateVarComputationTranslator.TryTranslateOverGroupAggregateVar(
                    n.Child0, false, _command, _groupAggregateVarInfoManager, out referencedGroupAggregateVarInfo, out templateNode,
                    out isUnnested)
                &&
                (isUnnested || AggregatePushdownUtil.IsVarRefOverGivenVar(templateNode, referencedGroupAggregateVarInfo.GroupAggregateVar)))
            {
                referencedGroupAggregateVarInfo.CandidateAggregateNodes.Add(new KeyValuePair <Node, List <Node> >(n, new List <Node> {
                    templateNode
                }));
            }
        }
Example #4
0
        public static bool TryTranslateOverGroupAggregateVar(
            System.Data.Entity.Core.Query.InternalTrees.Node subtree,
            bool isVarDefinition,
            Command command,
            GroupAggregateVarInfoManager groupAggregateVarInfoManager,
            out GroupAggregateVarInfo groupAggregateVarInfo,
            out System.Data.Entity.Core.Query.InternalTrees.Node templateNode,
            out bool isUnnested)
        {
            GroupAggregateVarComputationTranslator computationTranslator = new GroupAggregateVarComputationTranslator(command, groupAggregateVarInfoManager);

            System.Data.Entity.Core.Query.InternalTrees.Node n = subtree;
            SoftCastOp softCastOp1 = (SoftCastOp)null;

            if (n.Op.OpType == OpType.SoftCast)
            {
                softCastOp1 = (SoftCastOp)n.Op;
                n           = n.Child0;
            }
            bool flag;

            if (n.Op.OpType == OpType.Collect)
            {
                templateNode = computationTranslator.VisitCollect(n);
                flag         = true;
            }
            else
            {
                templateNode = computationTranslator.VisitNode(n);
                flag         = false;
            }
            groupAggregateVarInfo = computationTranslator._targetGroupAggregateVarInfo;
            isUnnested            = computationTranslator._isUnnested;
            if (computationTranslator._targetGroupAggregateVarInfo == null || templateNode == null)
            {
                return(false);
            }
            if (softCastOp1 != null)
            {
                SoftCastOp softCastOp2 = flag || !isVarDefinition && AggregatePushdownUtil.IsVarRefOverGivenVar(templateNode, computationTranslator._targetGroupAggregateVarInfo.GroupAggregateVar) ? command.CreateSoftCastOp(TypeHelpers.GetEdmType <CollectionType>(softCastOp1.Type).TypeUsage) : softCastOp1;
                templateNode = command.CreateNode((Op)softCastOp2, templateNode);
            }
            return(true);
        }
Example #5
0
        public override void Visit(FunctionOp op, System.Data.Entity.Core.Query.InternalTrees.Node n)
        {
            this.VisitDefault(n);
            if (!PlanCompilerUtil.IsCollectionAggregateFunction(op, n))
            {
                return;
            }
            System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(n.Children.Count == 1, "Aggregate Function must have one argument");
            System.Data.Entity.Core.Query.InternalTrees.Node child0 = n.Child0;
            GroupAggregateVarInfo groupAggregateVarInfo;

            System.Data.Entity.Core.Query.InternalTrees.Node templateNode;
            bool isUnnested;

            if (!GroupAggregateVarComputationTranslator.TryTranslateOverGroupAggregateVar(n.Child0, false, this._command, this._groupAggregateVarInfoManager, out groupAggregateVarInfo, out templateNode, out isUnnested) || !isUnnested && !AggregatePushdownUtil.IsVarRefOverGivenVar(templateNode, groupAggregateVarInfo.GroupAggregateVar))
            {
                return;
            }
            groupAggregateVarInfo.CandidateAggregateNodes.Add(new KeyValuePair <System.Data.Entity.Core.Query.InternalTrees.Node, System.Data.Entity.Core.Query.InternalTrees.Node>(n, templateNode));
        }
Example #6
0
        public override void Visit(FunctionOp op, Node n)
        {
            VisitDefault(n);
            if (!PlanCompilerUtil.IsCollectionAggregateFunction(op, n))
            {
                return;
            }
            PlanCompiler.Assert(n.Children.Count == 1, "Aggregate Function must have one argument");

            var argumentNode = n.Child0;

            GroupAggregateVarInfo referencedGroupAggregateVarInfo;
            Node templateNode;
            bool isUnnested;

            if (GroupAggregateVarComputationTranslator.TryTranslateOverGroupAggregateVar(
                    n.Child0, false, _command, _groupAggregateVarInfoManager, out referencedGroupAggregateVarInfo, out templateNode,
                    out isUnnested)
                &&
                (isUnnested || AggregatePushdownUtil.IsVarRefOverGivenVar(templateNode, referencedGroupAggregateVarInfo.GroupAggregateVar)))
            {
                referencedGroupAggregateVarInfo.CandidateAggregateNodes.Add(new KeyValuePair <Node, Node>(n, templateNode));
            }
        }
        // <summary>
        // Try to produce an equivalent tree to the input subtree, over a single group aggregate variable.
        // Such translation can only be produced if all external references of the input subtree are to a
        // single group aggregate var, or to vars that are can be translated over that single group
        // aggregate var
        // </summary>
        // <param name="subtree"> The input subtree </param>
        // <param name="groupAggregateVarInfo"> The groupAggregateVarInfo over which the input subtree can be translated </param>
        // <param name="templateNode"> A tree that is equvalent to the input tree, but over the group aggregate variable represented by the groupAggregetVarInfo </param>
        // <returns> True, if the translation can be done, false otherwise </returns>
        public static bool TryTranslateOverGroupAggregateVar(
            Node subtree,
            bool isVarDefinition,
            Command command,
            GroupAggregateVarInfoManager groupAggregateVarInfoManager,
            out GroupAggregateVarInfo groupAggregateVarInfo,
            out Node templateNode,
            out bool isUnnested)
        {
            var handler = new GroupAggregateVarComputationTranslator(command, groupAggregateVarInfoManager);

            var        inputNode  = subtree;
            SoftCastOp softCastOp = null;
            bool       isCollect;

            if (inputNode.Op.OpType
                == OpType.SoftCast)
            {
                softCastOp = (SoftCastOp)inputNode.Op;
                inputNode  = inputNode.Child0;
            }

            if (inputNode.Op.OpType
                == OpType.Collect)
            {
                templateNode = handler.VisitCollect(inputNode);
                isCollect    = true;
            }
            else
            {
                templateNode = handler.VisitNode(inputNode);
                isCollect    = false;
            }

            groupAggregateVarInfo = handler._targetGroupAggregateVarInfo;
            isUnnested            = handler._isUnnested;

            if (handler._targetGroupAggregateVarInfo == null ||
                templateNode == null)
            {
                return(false);
            }
            if (softCastOp != null)
            {
                SoftCastOp newSoftCastOp;
                //
                // The type needs to be fixed only if the unnesting happened during this translation.
                // That can be recognized by these two cases:
                //      1) if the input node was a collect, or
                //      2) if the input did not represent a var definition, but a function aggregate argument and
                //              the template is VarRef of a group aggregate var.
                //
                if (isCollect
                    ||
                    !isVarDefinition &&
                    AggregatePushdownUtil.IsVarRefOverGivenVar(templateNode, handler._targetGroupAggregateVarInfo.GroupAggregateVar))
                {
                    newSoftCastOp = command.CreateSoftCastOp(TypeHelpers.GetEdmType <CollectionType>(softCastOp.Type).TypeUsage);
                }
                else
                {
                    newSoftCastOp = softCastOp;
                }
                templateNode = command.CreateNode(newSoftCastOp, templateNode);
            }
            return(true);
        }
Example #8
0
        private System.Data.Entity.Core.Query.InternalTrees.Node VisitCollect(System.Data.Entity.Core.Query.InternalTrees.Node n)
        {
            System.Data.Entity.Core.Query.InternalTrees.Node child0 = n.Child0;
            Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node> dictionary = new Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node>();

            while (child0.Child0.Op.OpType == OpType.Project)
            {
                child0 = child0.Child0;
                if (this.VisitDefault(child0.Child1) == null)
                {
                    return((System.Data.Entity.Core.Query.InternalTrees.Node)null);
                }
                foreach (System.Data.Entity.Core.Query.InternalTrees.Node child in child0.Child1.Children)
                {
                    if (GroupAggregateVarComputationTranslator.IsConstant(child.Child0))
                    {
                        dictionary.Add(((VarDefOp)child.Op).Var, child.Child0);
                    }
                }
            }
            if (child0.Child0.Op.OpType != OpType.Unnest)
            {
                return((System.Data.Entity.Core.Query.InternalTrees.Node)null);
            }
            GroupAggregateVarRefInfo groupAggregateVarRefInfo;

            if (!this._groupAggregateVarInfoManager.TryGetReferencedGroupAggregateVarInfo(((UnnestOp)child0.Child0.Op).Var, out groupAggregateVarRefInfo))
            {
                return((System.Data.Entity.Core.Query.InternalTrees.Node)null);
            }
            if (this._targetGroupAggregateVarInfo == null)
            {
                this._targetGroupAggregateVarInfo = groupAggregateVarRefInfo.GroupAggregateVarInfo;
            }
            else if (this._targetGroupAggregateVarInfo != groupAggregateVarRefInfo.GroupAggregateVarInfo)
            {
                return((System.Data.Entity.Core.Query.InternalTrees.Node)null);
            }
            if (!this._isUnnested)
            {
                return((System.Data.Entity.Core.Query.InternalTrees.Node)null);
            }
            PhysicalProjectOp op = (PhysicalProjectOp)n.Child0.Op;

            System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(op.Outputs.Count == 1, "Physical project should only have one output at this stage");
            Var output = op.Outputs[0];

            System.Data.Entity.Core.Query.InternalTrees.Node node1 = this.TranslateOverGroupAggregateVar(output, (EdmMember)null);
            if (node1 != null)
            {
                this._isUnnested = true;
                return(node1);
            }
            System.Data.Entity.Core.Query.InternalTrees.Node node2;
            if (!dictionary.TryGetValue(output, out node2))
            {
                return((System.Data.Entity.Core.Query.InternalTrees.Node)null);
            }
            this._isUnnested = true;
            return(node2);
        }
        /// <summary>
        ///     Try to produce an equivalent tree to the input subtree, over a single group aggregate variable.
        ///     Such translation can only be produced if all external references of the input subtree are to a
        ///     single group aggregate var, or to vars that are can be translated over that single group
        ///     aggregate var
        /// </summary>
        /// <param name="subtree"> The input subtree </param>
        /// <param name="isVarDefinition"> </param>
        /// <param name="command"> </param>
        /// <param name="groupAggregateVarInfoManager"> </param>
        /// <param name="groupAggregateVarInfo"> The groupAggregateVarInfo over which the input subtree can be translated </param>
        /// <param name="templateNode"> A tree that is equvalent to the input tree, but over the group aggregate variable represented by the groupAggregetVarInfo </param>
        /// <param name="isUnnested"> </param>
        /// <returns> True, if the translation can be done, false otherwise </returns>
        public static bool TryTranslateOverGroupAggregateVar(
            Node subtree,
            bool isVarDefinition,
            Command command,
            GroupAggregateVarInfoManager groupAggregateVarInfoManager,
            out GroupAggregateVarInfo groupAggregateVarInfo,
            out Node templateNode,
            out bool isUnnested)
        {
            var handler = new GroupAggregateVarComputationTranslator(command, groupAggregateVarInfoManager);

            var inputNode = subtree;
            SoftCastOp softCastOp = null;
            bool isCollect;
            if (inputNode.Op.OpType
                == OpType.SoftCast)
            {
                softCastOp = (SoftCastOp)inputNode.Op;
                inputNode = inputNode.Child0;
            }

            if (inputNode.Op.OpType
                == OpType.Collect)
            {
                templateNode = handler.VisitCollect(inputNode);
                isCollect = true;
            }
            else
            {
                templateNode = handler.VisitNode(inputNode);
                isCollect = false;
            }

            groupAggregateVarInfo = handler._targetGroupAggregateVarInfo;
            isUnnested = handler._isUnnested;

            if (handler._targetGroupAggregateVarInfo == null
                || templateNode == null)
            {
                return false;
            }
            if (softCastOp != null)
            {
                SoftCastOp newSoftCastOp;
                // 
                // The type needs to be fixed only if the unnesting happened during this translation.
                // That can be recognized by these two cases: 
                //      1) if the input node was a collect, or 
                //      2) if the input did not represent a var definition, but a function aggregate argument and 
                //              the template is VarRef of a group aggregate var.
                //
                if (isCollect
                    ||
                    !isVarDefinition
                    && AggregatePushdownUtil.IsVarRefOverGivenVar(templateNode, handler._targetGroupAggregateVarInfo.GroupAggregateVar))
                {
                    newSoftCastOp = command.CreateSoftCastOp(TypeHelpers.GetEdmType<CollectionType>(softCastOp.Type).TypeUsage);
                }
                else
                {
                    newSoftCastOp = softCastOp;
                }
                templateNode = command.CreateNode(newSoftCastOp, templateNode);
            }
            return true;
        }