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); }
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); }
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); }
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); }
// <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); }
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); }
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); }
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); }
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); }
// <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); }
// <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; }
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); }