private static bool ProcessApplyIntoScalarSubquery(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node applyNode,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            Command          command           = context.Command;
            ExtendedNodeInfo extendedNodeInfo1 = command.GetExtendedNodeInfo(applyNode.Child1);
            OpType           opType            = applyNode.Op.OpType;

            if (!ApplyOpRules.CanRewriteApply(applyNode.Child1, extendedNodeInfo1, opType))
            {
                newNode = applyNode;
                return(false);
            }
            ExtendedNodeInfo extendedNodeInfo2 = command.GetExtendedNodeInfo(applyNode.Child0);
            Var    first  = extendedNodeInfo1.Definitions.First;
            VarVec varVec = command.CreateVarVec(extendedNodeInfo2.Definitions);
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;

            transformationRulesContext.RemapSubtree(applyNode.Child1);
            ApplyOpRules.VarDefinitionRemapper.RemapSubtree(applyNode.Child1, command, first);
            System.Data.Entity.Core.Query.InternalTrees.Node node = command.CreateNode((Op)command.CreateElementOp(first.Type), applyNode.Child1);
            Var computedVar;

            System.Data.Entity.Core.Query.InternalTrees.Node varDefListNode = command.CreateVarDefListNode(node, out computedVar);
            varVec.Set(computedVar);
            newNode = command.CreateNode((Op)command.CreateProjectOp(varVec), applyNode.Child0, varDefListNode);
            transformationRulesContext.AddVarMapping(first, computedVar);
            return(true);
        }
Exemple #2
0
        private static bool ProcessSetOpOverEmptySet(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node setOpNode,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            bool flag1 = context.Command.GetExtendedNodeInfo(setOpNode.Child0).MaxRows == RowCount.Zero;
            bool flag2 = context.Command.GetExtendedNodeInfo(setOpNode.Child1).MaxRows == RowCount.Zero;

            if (!flag1 && !flag2)
            {
                newNode = setOpNode;
                return(false);
            }
            SetOp op    = (SetOp)setOpNode.Op;
            int   index = !flag2 && op.OpType == OpType.UnionAll || !flag1 && op.OpType == OpType.Intersect ? 1 : 0;

            newNode = setOpNode.Children[index];
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;

            foreach (KeyValuePair <Var, Var> keyValuePair in (Dictionary <Var, Var>)op.VarMap[index])
            {
                transformationRulesContext.AddVarMapping(keyValuePair.Key, keyValuePair.Value);
            }
            return(true);
        }
Exemple #3
0
        private static bool ProcessJoinOverFilter(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node joinNode,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            newNode = joinNode;
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;
            Command command = transformationRulesContext.Command;

            System.Data.Entity.Core.Query.InternalTrees.Node node1  = (System.Data.Entity.Core.Query.InternalTrees.Node)null;
            System.Data.Entity.Core.Query.InternalTrees.Node child0 = joinNode.Child0;
            if (joinNode.Child0.Op.OpType == OpType.Filter)
            {
                node1  = joinNode.Child0.Child1;
                child0 = joinNode.Child0.Child0;
            }
            System.Data.Entity.Core.Query.InternalTrees.Node node2 = joinNode.Child1;
            if (joinNode.Child1.Op.OpType == OpType.Filter && joinNode.Op.OpType != OpType.LeftOuterJoin)
            {
                node1 = node1 != null?command.CreateNode((Op)command.CreateConditionalOp(OpType.And), node1, joinNode.Child1.Child1) : joinNode.Child1.Child1;

                node2 = joinNode.Child1.Child0;
            }
            if (node1 == null)
            {
                return(false);
            }
            System.Data.Entity.Core.Query.InternalTrees.Node node3 = joinNode.Op.OpType != OpType.CrossJoin ? command.CreateNode(joinNode.Op, child0, node2, joinNode.Child2) : command.CreateNode(joinNode.Op, child0, node2);
            FilterOp filterOp = command.CreateFilterOp();

            newNode = command.CreateNode((Op)filterOp, node3, node1);
            transformationRulesContext.SuppressFilterPushdown(newNode);
            return(true);
        }
        private static bool ProcessOuterApplyOverProject(
            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_1 = applyNode.Child1;
            System.Data.Entity.Core.Query.InternalTrees.Node child1_2 = child1_1.Child1;
            TransformationRulesContext transformationRulesContext     = (TransformationRulesContext)context;
            Var computedVar = context.Command.GetExtendedNodeInfo(child1_1.Child0).NonNullableDefinitions.First;

            if (computedVar == null && child1_2.Children.Count == 1 && (child1_2.Child0.Child0.Op.OpType == OpType.InternalConstant || child1_2.Child0.Child0.Op.OpType == OpType.NullSentinel))
            {
                return(false);
            }
            Command command = context.Command;

            System.Data.Entity.Core.Query.InternalTrees.Node node1 = (System.Data.Entity.Core.Query.InternalTrees.Node)null;
            InternalConstantOp internalConstantOp = (InternalConstantOp)null;
            ExtendedNodeInfo   extendedNodeInfo1  = command.GetExtendedNodeInfo(child1_1.Child0);
            bool flag = false;

            foreach (System.Data.Entity.Core.Query.InternalTrees.Node child in child1_2.Children)
            {
                System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(child.Op.OpType == OpType.VarDef, "Expected VarDefOp. Found " + (object)child.Op.OpType + " instead");
                VarRefOp op = child.Child0.Op as VarRefOp;
                if (op == null || !extendedNodeInfo1.Definitions.IsSet(op.Var))
                {
                    if (computedVar == null)
                    {
                        internalConstantOp = command.CreateInternalConstantOp(command.IntegerType, (object)1);
                        System.Data.Entity.Core.Query.InternalTrees.Node node2          = command.CreateNode((Op)internalConstantOp);
                        System.Data.Entity.Core.Query.InternalTrees.Node varDefListNode = command.CreateVarDefListNode(node2, out computedVar);
                        ProjectOp projectOp = command.CreateProjectOp(computedVar);
                        projectOp.Outputs.Or(extendedNodeInfo1.Definitions);
                        node1 = command.CreateNode((Op)projectOp, child1_1.Child0, varDefListNode);
                    }
                    System.Data.Entity.Core.Query.InternalTrees.Node node3 = internalConstantOp == null || !internalConstantOp.IsEquivalent(child.Child0.Op) && child.Child0.Op.OpType != OpType.NullSentinel ? transformationRulesContext.BuildNullIfExpression(computedVar, child.Child0) : command.CreateNode((Op)command.CreateVarRefOp(computedVar));
                    child.Child0 = node3;
                    command.RecomputeNodeInfo(child);
                    flag = true;
                }
            }
            if (flag)
            {
                command.RecomputeNodeInfo(child1_2);
            }
            applyNode.Child1 = node1 ?? child1_1.Child0;
            command.RecomputeNodeInfo(applyNode);
            child1_1.Child0 = applyNode;
            ExtendedNodeInfo extendedNodeInfo2 = command.GetExtendedNodeInfo(applyNode.Child0);

            ((ProjectOp)child1_1.Op).Outputs.Or(extendedNodeInfo2.Definitions);
            newNode = child1_1;
            return(true);
        }
Exemple #5
0
        private static bool ProcessGroupByWithSimpleVarRedefinitions(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node n,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            newNode = n;
            GroupByOp op1 = (GroupByOp)n.Op;

            if (n.Child1.Children.Count == 0)
            {
                return(false);
            }
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;
            Command          command          = transformationRulesContext.Command;
            ExtendedNodeInfo extendedNodeInfo = command.GetExtendedNodeInfo(n);
            bool             flag             = false;

            foreach (System.Data.Entity.Core.Query.InternalTrees.Node child in n.Child1.Children)
            {
                System.Data.Entity.Core.Query.InternalTrees.Node child0 = child.Child0;
                if (child0.Op.OpType == OpType.VarRef)
                {
                    VarRefOp op2 = (VarRefOp)child0.Op;
                    if (!extendedNodeInfo.ExternalReferences.IsSet(op2.Var))
                    {
                        flag = true;
                    }
                }
            }
            if (!flag)
            {
                return(false);
            }
            List <System.Data.Entity.Core.Query.InternalTrees.Node> args = new List <System.Data.Entity.Core.Query.InternalTrees.Node>();

            foreach (System.Data.Entity.Core.Query.InternalTrees.Node child in n.Child1.Children)
            {
                VarDefOp op2 = (VarDefOp)child.Op;
                VarRefOp op3 = child.Child0.Op as VarRefOp;
                if (op3 != null && !extendedNodeInfo.ExternalReferences.IsSet(op3.Var))
                {
                    op1.Outputs.Clear(op2.Var);
                    op1.Outputs.Set(op3.Var);
                    op1.Keys.Clear(op2.Var);
                    op1.Keys.Set(op3.Var);
                    transformationRulesContext.AddVarMapping(op2.Var, op3.Var);
                }
                else
                {
                    args.Add(child);
                }
            }
            System.Data.Entity.Core.Query.InternalTrees.Node node = command.CreateNode((Op)command.CreateVarDefListOp(), args);
            n.Child1 = node;
            return(true);
        }
Exemple #6
0
        // <summary>
        // Apply the rules that belong to the specified rules table to the given query tree.
        // </summary>
        // <param name="projectionPruningRequired"> is projection pruning required after the rule application </param>
        // <returns> Whether any rule has been applied after which reapplying nullability rules may be useful </returns>
        private static bool Process(
            PlanCompiler compilerState, ReadOnlyCollection <ReadOnlyCollection <Rule> > rulesTable, out bool projectionPruningRequired)
        {
            var ruleProcessor = new RuleProcessor();
            var context       = new TransformationRulesContext(compilerState);

            compilerState.Command.Root = ruleProcessor.ApplyRulesToSubtree(context, rulesTable, compilerState.Command.Root);
            projectionPruningRequired  = context.ProjectionPrunningRequired;
            return(context.ReapplyNullabilityRules);
        }
Exemple #7
0
        private static bool Process(
            System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler compilerState,
            ReadOnlyCollection <ReadOnlyCollection <System.Data.Entity.Core.Query.InternalTrees.Rule> > rulesTable,
            out bool projectionPruningRequired)
        {
            RuleProcessor ruleProcessor = new RuleProcessor();
            TransformationRulesContext transformationRulesContext = new TransformationRulesContext(compilerState);

            compilerState.Command.Root = ruleProcessor.ApplyRulesToSubtree((RuleProcessingContext)transformationRulesContext, rulesTable, compilerState.Command.Root);
            projectionPruningRequired  = transformationRulesContext.ProjectionPrunningRequired;
            return(transformationRulesContext.ReapplyNullabilityRules);
        }
Exemple #8
0
 internal static bool HasOpNotSafeForNullSentinelValueChange(System.Data.Entity.Core.Query.InternalTrees.Node n)
 {
     if (TransformationRulesContext.IsOpNotSafeForNullSentinelValueChange(n.Op.OpType))
     {
         return(true);
     }
     foreach (System.Data.Entity.Core.Query.InternalTrees.Node child in n.Children)
     {
         if (TransformationRulesContext.HasOpNotSafeForNullSentinelValueChange(child))
         {
             return(true);
         }
     }
     return(false);
 }
Exemple #9
0
        private static bool ProcessProjectOverProject(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node projectNode,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            newNode = projectNode;
            ProjectOp op1 = (ProjectOp)projectNode.Op;

            System.Data.Entity.Core.Query.InternalTrees.Node child1 = projectNode.Child1;
            System.Data.Entity.Core.Query.InternalTrees.Node child0 = projectNode.Child0;
            ProjectOp op2 = (ProjectOp)child0.Op;
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;
            Dictionary <Var, int>      varRefMap = new Dictionary <Var, int>();

            foreach (System.Data.Entity.Core.Query.InternalTrees.Node child in child1.Children)
            {
                if (!transformationRulesContext.IsScalarOpTree(child.Child0, varRefMap))
                {
                    return(false);
                }
            }
            Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node> varMap = transformationRulesContext.GetVarMap(child0.Child1, varRefMap);

            if (varMap == null)
            {
                return(false);
            }
            System.Data.Entity.Core.Query.InternalTrees.Node node = transformationRulesContext.Command.CreateNode((Op)transformationRulesContext.Command.CreateVarDefListOp());
            foreach (System.Data.Entity.Core.Query.InternalTrees.Node child in child1.Children)
            {
                child.Child0 = transformationRulesContext.ReMap(child.Child0, varMap);
                transformationRulesContext.Command.RecomputeNodeInfo(child);
                node.Children.Add(child);
            }
            ExtendedNodeInfo extendedNodeInfo = transformationRulesContext.Command.GetExtendedNodeInfo(projectNode);

            foreach (System.Data.Entity.Core.Query.InternalTrees.Node child in child0.Child1.Children)
            {
                VarDefOp op3 = (VarDefOp)child.Op;
                if (extendedNodeInfo.Definitions.IsSet(op3.Var))
                {
                    node.Children.Add(child);
                }
            }
            projectNode.Child0 = child0.Child0;
            projectNode.Child1 = node;
            return(true);
        }
Exemple #10
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 #11
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);
        }
Exemple #12
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);
        }
        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);
        }
 // <summary>
 // Apply the rules that belong to the specified rules table to the given query tree.
 // </summary>
 // <param name="projectionPruningRequired"> is projection pruning required after the rule application </param>
 // <returns> Whether any rule has been applied after which reapplying nullability rules may be useful </returns>
 private static bool Process(
     PlanCompiler compilerState, ReadOnlyCollection<ReadOnlyCollection<Rule>> rulesTable, out bool projectionPruningRequired)
 {
     var ruleProcessor = new RuleProcessor();
     var context = new TransformationRulesContext(compilerState);
     compilerState.Command.Root = ruleProcessor.ApplyRulesToSubtree(context, rulesTable, compilerState.Command.Root);
     projectionPruningRequired = context.ProjectionPrunningRequired;
     return context.ReapplyNullabilityRules;
 }
Exemple #15
0
        private static bool ProcessJoinOverProject(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node joinNode,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            newNode = joinNode;
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;
            Command command = transformationRulesContext.Command;

            System.Data.Entity.Core.Query.InternalTrees.Node node1 = joinNode.HasChild2 ? joinNode.Child2 : (System.Data.Entity.Core.Query.InternalTrees.Node)null;
            Dictionary <Var, int> varRefMap = new Dictionary <Var, int>();

            if (node1 != null && !transformationRulesContext.IsScalarOpTree(node1, varRefMap))
            {
                return(false);
            }
            VarVec varVec1 = command.CreateVarVec();
            List <System.Data.Entity.Core.Query.InternalTrees.Node> args = new List <System.Data.Entity.Core.Query.InternalTrees.Node>();

            if (joinNode.Op.OpType != OpType.LeftOuterJoin && joinNode.Child0.Op.OpType == OpType.Project && joinNode.Child1.Op.OpType == OpType.Project)
            {
                ProjectOp op1 = (ProjectOp)joinNode.Child0.Op;
                ProjectOp op2 = (ProjectOp)joinNode.Child1.Op;
                Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node> varMap1 = transformationRulesContext.GetVarMap(joinNode.Child0.Child1, varRefMap);
                Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node> varMap2 = transformationRulesContext.GetVarMap(joinNode.Child1.Child1, varRefMap);
                if (varMap1 == null || varMap2 == null)
                {
                    return(false);
                }
                System.Data.Entity.Core.Query.InternalTrees.Node node2;
                if (node1 != null)
                {
                    System.Data.Entity.Core.Query.InternalTrees.Node node3 = transformationRulesContext.ReMap(node1, varMap1);
                    System.Data.Entity.Core.Query.InternalTrees.Node node4 = transformationRulesContext.ReMap(node3, varMap2);
                    node2 = context.Command.CreateNode(joinNode.Op, joinNode.Child0.Child0, joinNode.Child1.Child0, node4);
                }
                else
                {
                    node2 = context.Command.CreateNode(joinNode.Op, joinNode.Child0.Child0, joinNode.Child1.Child0);
                }
                varVec1.InitFrom(op1.Outputs);
                foreach (Var output in op2.Outputs)
                {
                    varVec1.Set(output);
                }
                ProjectOp projectOp = command.CreateProjectOp(varVec1);
                args.AddRange((IEnumerable <System.Data.Entity.Core.Query.InternalTrees.Node>)joinNode.Child0.Child1.Children);
                args.AddRange((IEnumerable <System.Data.Entity.Core.Query.InternalTrees.Node>)joinNode.Child1.Child1.Children);
                System.Data.Entity.Core.Query.InternalTrees.Node node5 = command.CreateNode((Op)command.CreateVarDefListOp(), args);
                System.Data.Entity.Core.Query.InternalTrees.Node node6 = command.CreateNode((Op)projectOp, node2, node5);
                newNode = node6;
                return(true);
            }
            int index1;
            int index2;

            if (joinNode.Child0.Op.OpType == OpType.Project)
            {
                index1 = 0;
                index2 = 1;
            }
            else
            {
                System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(joinNode.Op.OpType != OpType.LeftOuterJoin, "unexpected non-LeftOuterJoin");
                index1 = 1;
                index2 = 0;
            }
            System.Data.Entity.Core.Query.InternalTrees.Node child = joinNode.Children[index1];
            ProjectOp op = child.Op as ProjectOp;
            Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node> varMap = transformationRulesContext.GetVarMap(child.Child1, varRefMap);

            if (varMap == null)
            {
                return(false);
            }
            ExtendedNodeInfo extendedNodeInfo = command.GetExtendedNodeInfo(joinNode.Children[index2]);
            VarVec           varVec2          = command.CreateVarVec(op.Outputs);

            varVec2.Or(extendedNodeInfo.Definitions);
            op.Outputs.InitFrom(varVec2);
            if (node1 != null)
            {
                System.Data.Entity.Core.Query.InternalTrees.Node node2 = transformationRulesContext.ReMap(node1, varMap);
                joinNode.Child2 = node2;
            }
            joinNode.Children[index1] = child.Child0;
            context.Command.RecomputeNodeInfo(joinNode);
            newNode = context.Command.CreateNode((Op)op, joinNode, child.Child1);
            return(true);
        }