/// <summary> /// Helper method for removing redundant constant keys from GroupByOp and DistictOp. /// It only examines the keys defined in the given varDefListNode. /// It removes all constant and null keys that are not referenced elsewhere, /// but ensuring that at least one key is left. /// It should not be called with empty keyVec. /// </summary> /// <param name="keyVec"> The keys </param> /// <param name="outputVec"> The var vec that needs to be updated along with the keys </param> /// <param name="varDefListNode"> Var def list node for the keys </param> private void RemoveRedundantConstantKeys(VarVec keyVec, VarVec outputVec, Node varDefListNode) { //Find all the keys that are nulls and constants var constantKeys = varDefListNode.Children.Where( d => d.Op.OpType == OpType.VarDef && PlanCompilerUtil.IsConstantBaseOp(d.Child0.Op.OpType)).ToList(); var constantKeyVars = m_command.CreateVarVec(constantKeys.Select(d => ((VarDefOp)d.Op).Var)); //Get the list of unreferenced constant keys constantKeyVars.Minus(m_referencedVars); //Remove the unreferenced constant keys keyVec.Minus(constantKeyVars); outputVec.Minus(constantKeyVars); varDefListNode.Children.RemoveAll(c => constantKeys.Contains(c) && constantKeyVars.IsSet(((VarDefOp)c.Op).Var)); //If no keys are left add one. if (keyVec.Count == 0) { var keyNode = constantKeys.First(); var keyVar = ((VarDefOp)keyNode.Op).Var; keyVec.Set(keyVar); outputVec.Set(keyVar); varDefListNode.Children.Add(keyNode); } }
private void RemoveRedundantConstantKeys(VarVec keyVec, VarVec outputVec, System.Data.Entity.Core.Query.InternalTrees.Node varDefListNode) { List <System.Data.Entity.Core.Query.InternalTrees.Node> constantKeys = varDefListNode.Children.Where <System.Data.Entity.Core.Query.InternalTrees.Node>((Func <System.Data.Entity.Core.Query.InternalTrees.Node, bool>)(d => { if (d.Op.OpType == OpType.VarDef) { return(PlanCompilerUtil.IsConstantBaseOp(d.Child0.Op.OpType)); } return(false); })).ToList <System.Data.Entity.Core.Query.InternalTrees.Node>(); VarVec constantKeyVars = this.m_command.CreateVarVec(constantKeys.Select <System.Data.Entity.Core.Query.InternalTrees.Node, Var>((Func <System.Data.Entity.Core.Query.InternalTrees.Node, Var>)(d => ((VarDefOp)d.Op).Var))); constantKeyVars.Minus(this.m_referencedVars); keyVec.Minus(constantKeyVars); outputVec.Minus(constantKeyVars); varDefListNode.Children.RemoveAll((Predicate <System.Data.Entity.Core.Query.InternalTrees.Node>)(c => { if (constantKeys.Contains(c)) { return(constantKeyVars.IsSet(((VarDefOp)c.Op).Var)); } return(false); })); if (keyVec.Count != 0) { return; } System.Data.Entity.Core.Query.InternalTrees.Node node = constantKeys.First <System.Data.Entity.Core.Query.InternalTrees.Node>(); Var var = ((VarDefOp)node.Op).Var; keyVec.Set(var); outputVec.Set(var); varDefListNode.Children.Add(node); }
internal static System.Data.Entity.Core.Query.InternalTrees.Node CombinePredicates( System.Data.Entity.Core.Query.InternalTrees.Node predicate1, System.Data.Entity.Core.Query.InternalTrees.Node predicate2, Command command) { IEnumerable <System.Data.Entity.Core.Query.InternalTrees.Node> nodes1 = PlanCompilerUtil.BreakIntoAndParts(predicate1); IEnumerable <System.Data.Entity.Core.Query.InternalTrees.Node> nodes2 = PlanCompilerUtil.BreakIntoAndParts(predicate2); System.Data.Entity.Core.Query.InternalTrees.Node node1 = predicate1; foreach (System.Data.Entity.Core.Query.InternalTrees.Node other in nodes2) { bool flag = false; foreach (System.Data.Entity.Core.Query.InternalTrees.Node node2 in nodes1) { if (node2.IsEquivalent(other)) { flag = true; break; } } if (!flag) { node1 = command.CreateNode((Op)command.CreateConditionalOp(OpType.And), node1, other); } } return(node1); }
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 })); } }
public override Node Visit(FunctionOp op, Node n) { this.VisitScalarOpDefault((ScalarOp)op, n); Node node = !TypeSemantics.IsCollectionType(op.Type) ? (!PlanCompilerUtil.IsCollectionAggregateFunction(op, n) ? n : this.VisitCollectionAggregateFunction(op, n)) : this.VisitCollectionFunction(op, n); System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(node != null, "failure to construct a functionOp?"); return(node); }
private static bool IsConstant(System.Data.Entity.Core.Query.InternalTrees.Node node) { System.Data.Entity.Core.Query.InternalTrees.Node node1 = node; while (node1.Op.OpType == OpType.Cast) { node1 = node1.Child0; } return(PlanCompilerUtil.IsConstantBaseOp(node1.Op.OpType)); }
// <summary> // Determines whether the given Node is a constant subtree // It only recognizes any of the constant base ops // and possibly casts over these nodes. // </summary> private static bool IsConstant(Node node) { var currentNode = node; while (currentNode.Op.OpType == OpType.Cast) { currentNode = currentNode.Child0; } return(PlanCompilerUtil.IsConstantBaseOp(currentNode.Op.OpType)); }
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)); }
public override Node Visit(FunctionOp op, Node n) { VisitScalarOpDefault(op, n); Node newNode = null; // Is this a TVF? if (TypeSemantics.IsCollectionType(op.Type)) { newNode = VisitCollectionFunction(op, n); } // Is this a collection-aggregate function? else if (PlanCompilerUtil.IsCollectionAggregateFunction(op, n)) { newNode = VisitCollectionAggregateFunction(op, n); } else { newNode = n; } PlanCompiler.Assert(newNode != null, "failure to construct a functionOp?"); return(newNode); }
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)); } }
private static bool ProcessFilterOverJoin(RuleProcessingContext context, Node filterNode, out Node newNode) { newNode = filterNode; var trc = (TransformationRulesContext)context; // // Have we shut off filter pushdown for this node? Return // if (trc.IsFilterPushdownSuppressed(filterNode)) { return(false); } var joinNode = filterNode.Child0; var joinOp = joinNode.Op; var leftInputNode = joinNode.Child0; var rightInputNode = joinNode.Child1; var command = trc.Command; var needsTransformation = false; var rightTableNodeInfo = command.GetExtendedNodeInfo(rightInputNode); var predicate = new Predicate(command, filterNode.Child1); var leftTableInfo = command.GetExtendedNodeInfo(leftInputNode); // // Check to see if the predicate contains any "single-table-filters". In those // cases, we could simply push that filter down to the child. // We can do this for inner joins and cross joins - for both inputs. // For left-outer joins, however, we can only do this for the left-side input // Further note that we only want to do the pushdown if it will help us - if // the join input is a ScanTable (or some other cases), then it doesn't help us. // Node leftSingleTablePredicateNode = null; if (leftInputNode.Op.OpType != OpType.ScanTable) { var leftSingleTablePredicates = predicate.GetSingleTablePredicates(leftTableInfo.Definitions, out predicate); leftSingleTablePredicateNode = leftSingleTablePredicates.BuildAndTree(); } Node rightSingleTablePredicateNode = null; if ((rightInputNode.Op.OpType != OpType.ScanTable) && (joinOp.OpType != OpType.LeftOuterJoin)) { var rightSingleTablePredicates = predicate.GetSingleTablePredicates(rightTableNodeInfo.Definitions, out predicate); rightSingleTablePredicateNode = rightSingleTablePredicates.BuildAndTree(); } // // Now check to see if the predicate contains some "join predicates". We can // add these to the existing join predicate (if any). // We can only do this for inner joins and cross joins - not for LOJs // Node newJoinPredicateNode = null; if (joinOp.OpType == OpType.CrossJoin || joinOp.OpType == OpType.InnerJoin) { var joinPredicate = predicate.GetJoinPredicates(leftTableInfo.Definitions, rightTableNodeInfo.Definitions, out predicate); newJoinPredicateNode = joinPredicate.BuildAndTree(); } // // Now for the dirty work. We've identified some predicates that could be pushed // into the left table, some predicates that could be pushed into the right table // and some that could become join predicates. // if (leftSingleTablePredicateNode != null) { leftInputNode = command.CreateNode(command.CreateFilterOp(), leftInputNode, leftSingleTablePredicateNode); needsTransformation = true; } if (rightSingleTablePredicateNode != null) { rightInputNode = command.CreateNode(command.CreateFilterOp(), rightInputNode, rightSingleTablePredicateNode); needsTransformation = true; } // Identify the new join predicate if (newJoinPredicateNode != null) { needsTransformation = true; if (joinOp.OpType == OpType.CrossJoin) { joinOp = command.CreateInnerJoinOp(); } else { PlanCompiler.Assert(joinOp.OpType == OpType.InnerJoin, "unexpected non-InnerJoin?"); newJoinPredicateNode = PlanCompilerUtil.CombinePredicates(joinNode.Child2, newJoinPredicateNode, command); } } else { newJoinPredicateNode = (joinOp.OpType == OpType.CrossJoin) ? null : joinNode.Child2; } // // If nothing has changed, then just return the current node. Otherwise, // we will loop forever // if (!needsTransformation) { return(false); } Node newJoinNode; // // Finally build up a new join node // if (joinOp.OpType == OpType.CrossJoin) { newJoinNode = command.CreateNode(joinOp, leftInputNode, rightInputNode); } else { newJoinNode = command.CreateNode(joinOp, leftInputNode, rightInputNode, newJoinPredicateNode); } // // Build up a new filterNode above this join node. But only if we have a filter left // var newFilterPredicateNode = predicate.BuildAndTree(); if (newFilterPredicateNode == null) { newNode = newJoinNode; } else { newNode = command.CreateNode(command.CreateFilterOp(), newJoinNode, newFilterPredicateNode); } return(true); }