Exemple #1
0
        private static bool ProcessProjectOpWithNullSentinel(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node n,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            newNode = n;
            ProjectOp op = (ProjectOp)n.Op;

            if (n.Child1.Children.Where <System.Data.Entity.Core.Query.InternalTrees.Node>((Func <System.Data.Entity.Core.Query.InternalTrees.Node, bool>)(c => c.Child0.Op.OpType == OpType.NullSentinel)).Count <System.Data.Entity.Core.Query.InternalTrees.Node>() == 0)
            {
                return(false);
            }
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;
            Command          command           = transformationRulesContext.Command;
            ExtendedNodeInfo extendedNodeInfo  = command.GetExtendedNodeInfo(n.Child0);
            bool             flag1             = false;
            bool             nullSentinelValue = transformationRulesContext.CanChangeNullSentinelValue;
            Var int32Var;

            if (!nullSentinelValue || !TransformationRulesContext.TryGetInt32Var((IEnumerable <Var>)extendedNodeInfo.NonNullableDefinitions, out int32Var))
            {
                flag1 = true;
                if (!nullSentinelValue || !TransformationRulesContext.TryGetInt32Var(n.Child1.Children.Where <System.Data.Entity.Core.Query.InternalTrees.Node>((Func <System.Data.Entity.Core.Query.InternalTrees.Node, bool>)(child =>
                {
                    if (child.Child0.Op.OpType != OpType.Constant)
                    {
                        return(child.Child0.Op.OpType == OpType.InternalConstant);
                    }
                    return(true);
                })).Select <System.Data.Entity.Core.Query.InternalTrees.Node, Var>((Func <System.Data.Entity.Core.Query.InternalTrees.Node, Var>)(child => ((VarDefOp)child.Op).Var)), out int32Var))
                {
                    int32Var = n.Child1.Children.Where <System.Data.Entity.Core.Query.InternalTrees.Node>((Func <System.Data.Entity.Core.Query.InternalTrees.Node, bool>)(child => child.Child0.Op.OpType == OpType.NullSentinel)).Select <System.Data.Entity.Core.Query.InternalTrees.Node, Var>((Func <System.Data.Entity.Core.Query.InternalTrees.Node, Var>)(child => ((VarDefOp)child.Op).Var)).FirstOrDefault <Var>();
                    if (int32Var == null)
                    {
                        return(false);
                    }
                }
            }
            bool flag2 = false;

            for (int index = n.Child1.Children.Count - 1; index >= 0; --index)
            {
                System.Data.Entity.Core.Query.InternalTrees.Node child = n.Child1.Children[index];
                if (child.Child0.Op.OpType == OpType.NullSentinel)
                {
                    if (!flag1)
                    {
                        VarRefOp varRefOp = command.CreateVarRefOp(int32Var);
                        child.Child0 = command.CreateNode((Op)varRefOp);
                        command.RecomputeNodeInfo(child);
                        flag2 = true;
                    }
                    else if (!int32Var.Equals((object)((VarDefOp)child.Op).Var))
                    {
                        op.Outputs.Clear(((VarDefOp)child.Op).Var);
                        n.Child1.Children.RemoveAt(index);
                        transformationRulesContext.AddVarMapping(((VarDefOp)child.Op).Var, int32Var);
                        flag2 = true;
                    }
                }
            }
            if (flag2)
            {
                command.RecomputeNodeInfo(n.Child1);
            }
            return(flag2);
        }
Exemple #2
0
        // <summary>
        // Convert OuterApply(X, Project(Filter(Y, p), constant)) =>
        // LeftOuterJoin(X, Project(Y, constant), p)
        // if "Y" has no external references to X
        // In an ideal world, we would be able to push the Project below the Filter,
        // and then have the normal ApplyOverFilter rule handle this - but that causes us
        // problems because we always try to pull up ProjectOp's as high as possible. Hence,
        // the special case for this rule
        // </summary>
        // <param name="context"> Rule processing context </param>
        // <param name="applyNode"> Current ApplyOp </param>
        // <param name="newNode"> transformed subtree </param>
        // <returns> Transformation status </returns>
        private static bool ProcessOuterApplyOverDummyProjectOverFilter(RuleProcessingContext context, Node applyNode, out Node newNode)
        {
            newNode = applyNode;
            var projectNode     = applyNode.Child1;
            var projectOp       = (ProjectOp)projectNode.Op;
            var filterNode      = projectNode.Child0;
            var filterInputNode = filterNode.Child0;
            var command         = context.Command;

            var filterInputNodeInfo    = command.GetExtendedNodeInfo(filterInputNode);
            var applyLeftChildNodeInfo = command.GetExtendedNodeInfo(applyNode.Child0);

            //
            // Check if the outputs of the ProjectOp or the inputNode to the FilterOp
            // have any external references to the left child of the ApplyOp.
            // If they do, we simply return, we can't do much more here
            //
            if (projectOp.Outputs.Overlaps(applyLeftChildNodeInfo.Definitions) ||
                filterInputNodeInfo.ExternalReferences.Overlaps(applyLeftChildNodeInfo.Definitions))
            {
                return(false);
            }

            //
            // We've now gotten to the stage where the only external references (if any)
            // are from the filter predicate.
            // First, push the Project node down below the filter - but make sure that
            // all the Vars needed by the Filter are projected out
            //
            var  capWithProject     = false;
            Node joinNodeRightInput = null;

            //
            // Check to see whether there is a sentinel var available - if there is, then
            // we can simply move the ProjectOp above the join we're going to construct
            // and of course, build a NullIf expression for the constant.
            // Otherwise, the ProjectOp will need to be the child of the joinOp that we're
            // building - and we'll need to make sure that the ProjectOp projects out
            // any vars that are required for the Filter in the first place
            //
            var  trc = (TransformationRulesContext)context;
            Var  sentinelVar;
            bool sentinelIsInt32;

            if (TransformationRulesContext.TryGetInt32Var(filterInputNodeInfo.NonNullableDefinitions, out sentinelVar))
            {
                sentinelIsInt32 = true;
            }
            else
            {
                sentinelVar     = filterInputNodeInfo.NonNullableDefinitions.First;
                sentinelIsInt32 = false;
            }

            if (sentinelVar != null)
            {
                capWithProject = true;
                var varDefNode = projectNode.Child1.Child0;
                if (varDefNode.Child0.Op.OpType == OpType.NullSentinel &&
                    sentinelIsInt32 &&
                    trc.CanChangeNullSentinelValue)
                {
                    varDefNode.Child0 = context.Command.CreateNode(context.Command.CreateVarRefOp(sentinelVar));
                }
                else
                {
                    varDefNode.Child0 = trc.BuildNullIfExpression(sentinelVar, varDefNode.Child0);
                }
                command.RecomputeNodeInfo(varDefNode);
                command.RecomputeNodeInfo(projectNode.Child1);
                joinNodeRightInput = filterInputNode;
            }
            else
            {
                // We need to keep the projectNode - unfortunately
                joinNodeRightInput = projectNode;
                //
                // Make sure that every Var that is needed for the filter predicate
                // is captured in the projectOp outputs list
                //
                var filterPredicateNodeInfo = command.GetNodeInfo(filterNode.Child1);
                foreach (var v in filterPredicateNodeInfo.ExternalReferences)
                {
                    if (filterInputNodeInfo.Definitions.IsSet(v))
                    {
                        projectOp.Outputs.Set(v);
                    }
                }
                projectNode.Child0 = filterInputNode;
            }

            context.Command.RecomputeNodeInfo(projectNode);

            //
            // We can now simply convert the apply into an inner/leftouter join with the
            // filter predicate acting as the join condition
            //
            var joinNode = command.CreateNode(command.CreateLeftOuterJoinOp(), applyNode.Child0, joinNodeRightInput, filterNode.Child1);

            if (capWithProject)
            {
                var joinNodeInfo = command.GetExtendedNodeInfo(joinNode);
                projectNode.Child0 = joinNode;
                projectOp.Outputs.Or(joinNodeInfo.Definitions);
                newNode = projectNode;
            }
            else
            {
                newNode = joinNode;
            }
            return(true);
        }
Exemple #3
0
        // <summary>
        // Tries to remove null sentinel definitions by replacing them to vars that are guaranteed
        // to be non-nullable and of integer type, or with reference to other constants defined in the
        // same project. In particular,
        // - If based on the ancestors, the value of the null sentinel can be changed and the
        // input of the project has a var that is guaranteed to be non-nullable and
        // is of integer type, then the definitions of the vars defined as NullSentinels in the ProjectOp
        // are replaced with a reference to that var. I.eg:
        // Project(X, VarDefList(VarDef(ns_var, NullSentinel), ...))
        // can be transformed into
        // Project(X, VarDefList(VarDef(ns_var, VarRef(v))...))
        // where v is known to be non-nullable
        // - Else, if based on the ancestors, the value of the null sentinel can be changed and
        // the project already has definitions of other int constants, the definitions of the null sentinels
        // are removed and the respective vars are remapped to the var representing the constant.
        // - Else, the definitions of the all null sentinels except for one are removed, and the
        // the respective vars are remapped to the remaining null sentinel.
        // </summary>
        // <param name="context"> Rule processing context </param>
        // <param name="n"> current subtree </param>
        // <param name="newNode"> transformed subtree </param>
        // <returns> transformation status </returns>
        private static bool ProcessProjectOpWithNullSentinel(RuleProcessingContext context, Node n, out Node newNode)
        {
            newNode = n;
            var projectOp      = (ProjectOp)n.Op;
            var varDefListNode = n.Child1;

            if (varDefListNode.Children.Where(c => c.Child0.Op.OpType == OpType.NullSentinel).Count() == 0)
            {
                return(false);
            }

            var trc                = (TransformationRulesContext)context;
            var command            = trc.Command;
            var relOpInputNodeInfo = command.GetExtendedNodeInfo(n.Child0);
            Var inputSentinel;
            var reusingConstantFromSameProjectAsSentinel = false;

            var canChangeNullSentinelValue = trc.CanChangeNullSentinelValue;

            if (!canChangeNullSentinelValue ||
                !TransformationRulesContext.TryGetInt32Var(relOpInputNodeInfo.NonNullableDefinitions, out inputSentinel))
            {
                reusingConstantFromSameProjectAsSentinel = true;
                if (!canChangeNullSentinelValue
                    ||
                    !TransformationRulesContext.TryGetInt32Var(
                        n.Child1.Children.Where(
                            child => child.Child0.Op.OpType == OpType.Constant || child.Child0.Op.OpType == OpType.InternalConstant).Select(
                            child => ((VarDefOp)(child.Op)).Var), out inputSentinel))
                {
                    inputSentinel =
                        n.Child1.Children.Where(child => child.Child0.Op.OpType == OpType.NullSentinel).Select(
                            child => ((VarDefOp)(child.Op)).Var).FirstOrDefault();
                    if (inputSentinel == null)
                    {
                        return(false);
                    }
                }
            }

            var modified = false;

            for (var i = n.Child1.Children.Count - 1; i >= 0; i--)
            {
                var varDefNode       = n.Child1.Children[i];
                var definingExprNode = varDefNode.Child0;
                if (definingExprNode.Op.OpType
                    == OpType.NullSentinel)
                {
                    if (!reusingConstantFromSameProjectAsSentinel)
                    {
                        var varRefOp = command.CreateVarRefOp(inputSentinel);
                        varDefNode.Child0 = command.CreateNode(varRefOp);
                        command.RecomputeNodeInfo(varDefNode);
                        modified = true;
                    }
                    else if (!inputSentinel.Equals(((VarDefOp)varDefNode.Op).Var))
                    {
                        projectOp.Outputs.Clear(((VarDefOp)varDefNode.Op).Var);
                        n.Child1.Children.RemoveAt(i);
                        trc.AddVarMapping(((VarDefOp)varDefNode.Op).Var, inputSentinel);
                        modified = true;
                    }
                }
            }

            if (modified)
            {
                command.RecomputeNodeInfo(n.Child1);
            }
            return(modified);
        }
        private static bool ProcessOuterApplyOverDummyProjectOverFilter(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node applyNode,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            newNode = applyNode;
            System.Data.Entity.Core.Query.InternalTrees.Node child1 = applyNode.Child1;
            ProjectOp op = (ProjectOp)child1.Op;

            System.Data.Entity.Core.Query.InternalTrees.Node child0_1 = child1.Child0;
            System.Data.Entity.Core.Query.InternalTrees.Node child0_2 = child0_1.Child0;
            Command          command           = context.Command;
            ExtendedNodeInfo extendedNodeInfo1 = command.GetExtendedNodeInfo(child0_2);
            ExtendedNodeInfo extendedNodeInfo2 = command.GetExtendedNodeInfo(applyNode.Child0);

            if (op.Outputs.Overlaps(extendedNodeInfo2.Definitions) || extendedNodeInfo1.ExternalReferences.Overlaps(extendedNodeInfo2.Definitions))
            {
                return(false);
            }
            bool flag1 = false;
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;
            Var  int32Var;
            bool flag2;

            if (TransformationRulesContext.TryGetInt32Var((IEnumerable <Var>)extendedNodeInfo1.NonNullableDefinitions, out int32Var))
            {
                flag2 = true;
            }
            else
            {
                int32Var = extendedNodeInfo1.NonNullableDefinitions.First;
                flag2    = false;
            }
            System.Data.Entity.Core.Query.InternalTrees.Node node1;
            if (int32Var != null)
            {
                flag1 = true;
                System.Data.Entity.Core.Query.InternalTrees.Node child0_3 = child1.Child1.Child0;
                child0_3.Child0 = child0_3.Child0.Op.OpType != OpType.NullSentinel || !flag2 || !transformationRulesContext.CanChangeNullSentinelValue ? transformationRulesContext.BuildNullIfExpression(int32Var, child0_3.Child0) : context.Command.CreateNode((Op)context.Command.CreateVarRefOp(int32Var));
                command.RecomputeNodeInfo(child0_3);
                command.RecomputeNodeInfo(child1.Child1);
                node1 = child0_2;
            }
            else
            {
                node1 = child1;
                foreach (Var externalReference in command.GetNodeInfo(child0_1.Child1).ExternalReferences)
                {
                    if (extendedNodeInfo1.Definitions.IsSet(externalReference))
                    {
                        op.Outputs.Set(externalReference);
                    }
                }
                child1.Child0 = child0_2;
            }
            context.Command.RecomputeNodeInfo(child1);
            System.Data.Entity.Core.Query.InternalTrees.Node node2 = command.CreateNode((Op)command.CreateLeftOuterJoinOp(), applyNode.Child0, node1, child0_1.Child1);
            if (flag1)
            {
                ExtendedNodeInfo extendedNodeInfo3 = command.GetExtendedNodeInfo(node2);
                child1.Child0 = node2;
                op.Outputs.Or(extendedNodeInfo3.Definitions);
                newNode = child1;
            }
            else
            {
                newNode = node2;
            }
            return(true);
        }