public override System.Data.Entity.Core.Query.InternalTrees.Node Visit( GroupByIntoOp op, System.Data.Entity.Core.Query.InternalTrees.Node n) { System.Data.Entity.Core.Query.InternalTrees.Node node = this.VisitGroupByOp((GroupByBaseOp)op, n); if (node.Op.OpType == OpType.GroupByInto && n.Child3.Children.Count == 0) { GroupByIntoOp op1 = (GroupByIntoOp)node.Op; node = this.m_command.CreateNode((Op)this.m_command.CreateGroupByOp(op1.Keys, op1.Outputs), node.Child0, node.Child1, node.Child2); } return(node); }
public override void Visit(GroupByIntoOp op, System.Data.Entity.Core.Query.InternalTrees.Node n) { this.VisitGroupByOp((GroupByBaseOp)op, n); foreach (System.Data.Entity.Core.Query.InternalTrees.Node child in n.Child3.Children) { Var var = ((VarDefOp)child.Op).Var; GroupAggregateVarRefInfo groupAggregateVarRefInfo; if (!this._groupAggregateVarInfoManager.TryGetReferencedGroupAggregateVarInfo(var, out groupAggregateVarRefInfo)) { this._groupAggregateVarInfoManager.Add(var, new GroupAggregateVarInfo(n, var), this._command.CreateNode((Op)this._command.CreateVarRefOp(var)), false); } } }
/// <summary> /// First defer to default handling for groupby nodes /// If all group aggregate vars are prunned out turn it into a GroupBy. /// </summary> /// <param name="op"></param> /// <param name="n"></param> /// <returns></returns> public override Node Visit(GroupByIntoOp op, Node n) { Node result = VisitGroupByOp(op, n); //Transform the GroupByInto into a GroupBy if all group aggregate vars were prunned out if (result.Op.OpType == OpType.GroupByInto && n.Child3.Children.Count == 0) { GroupByIntoOp newOp = (GroupByIntoOp)result.Op; result = m_command.CreateNode(m_command.CreateGroupByOp(newOp.Keys, newOp.Outputs), result.Child0, result.Child1, result.Child2); } return(result); }
/// <summary> /// Registers the group aggregate var with the group aggregate var info manager /// </summary> /// <param name="op"></param> /// <param name="n"></param> public override void Visit(GroupByIntoOp op, Node n) { VisitGroupByOp(op, n); foreach (Node child in n.Child3.Children) { Var groupAggregateVar = ((VarDefOp)child.Op).Var; GroupAggregateVarRefInfo groupAggregateVarRefInfo; // If the group by is over a group, it may be already tracked as referencing a group var // An optimization would be to separately track this groupAggregateVar too, for the cases when the aggregate can // not be pushed to the group by node over which this one is defined but can be propagated to this group by node. if (!_groupAggregateVarInfoManager.TryGetReferencedGroupAggregateVarInfo(groupAggregateVar, out groupAggregateVarRefInfo)) { _groupAggregateVarInfoManager.Add(groupAggregateVar, new GroupAggregateVarInfo(n, groupAggregateVar), this._command.CreateNode(this._command.CreateVarRefOp(groupAggregateVar)), false); } } }
private void TryProcessCandidate( KeyValuePair <System.Data.Entity.Core.Query.InternalTrees.Node, System.Data.Entity.Core.Query.InternalTrees.Node> candidate, GroupAggregateVarInfo groupAggregateVarInfo) { System.Data.Entity.Core.Query.InternalTrees.Node definingGroupNode = groupAggregateVarInfo.DefiningGroupNode; IList <System.Data.Entity.Core.Query.InternalTrees.Node> ancestors1; IList <System.Data.Entity.Core.Query.InternalTrees.Node> ancestors2; this.FindPathsToLeastCommonAncestor(candidate.Key, definingGroupNode, out ancestors1, out ancestors2); if (!AggregatePushdown.AreAllNodesSupportedForPropagation(ancestors2)) { return; } GroupByIntoOp op1 = (GroupByIntoOp)definingGroupNode.Op; System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(op1.Inputs.Count == 1, "There should be one input var to GroupByInto at this stage"); Var first = op1.Inputs.First; FunctionOp op2 = (FunctionOp)candidate.Key.Op; System.Data.Entity.Core.Query.InternalTrees.Node subTree = OpCopier.Copy(this.m_command, candidate.Value); new VarRemapper(this.m_command, new Dictionary <Var, Var>(1) { { groupAggregateVarInfo.GroupAggregateVar, first } }).RemapSubtree(subTree); Var computedVar; System.Data.Entity.Core.Query.InternalTrees.Node varDefNode = this.m_command.CreateVarDefNode(this.m_command.CreateNode((Op)this.m_command.CreateAggregateOp(op2.Function, false), subTree), out computedVar); definingGroupNode.Child2.Children.Add(varDefNode); ((GroupByBaseOp)definingGroupNode.Op).Outputs.Set(computedVar); for (int index = 0; index < ancestors2.Count; ++index) { System.Data.Entity.Core.Query.InternalTrees.Node node = ancestors2[index]; if (node.Op.OpType == OpType.Project) { ((ProjectOp)node.Op).Outputs.Set(computedVar); } } candidate.Key.Op = (Op)this.m_command.CreateVarRefOp(computedVar); candidate.Key.Children.Clear(); }
public override Node Visit(GroupByIntoOp op, Node n) { PlanCompiler.Assert(n.HasChild3 && n.Child3.Children.Count > 0, "GroupByIntoOp with no group aggregates?"); var varDefListNode = n.Child3; var projectOpOutputs = Command.CreateVarVec(op.Outputs); var groupByOutputs = op.Outputs; // Local definitions foreach (var chi in varDefListNode.Children) { var varDefOp = chi.Op as VarDefOp; groupByOutputs.Clear(varDefOp.Var); } //Create the new groupByOp var groupByNode = Command.CreateNode( Command.CreateGroupByOp(op.Keys, groupByOutputs), n.Child0, n.Child1, n.Child2); var projectNode = Command.CreateNode( Command.CreateProjectOp(projectOpOutputs), groupByNode, varDefListNode); return VisitNode(projectNode); }
/// <summary> /// GroupByInto /// Again, VisitChildren - for the Keys and Properties VarDefList nodes - does /// the real work. /// The "Keys", "InputVars" and "OutputVars" varsets are updated to flatten out /// references to any structured Vars. /// </summary> /// <param name="op"> </param> /// <param name="n"> </param> /// <returns> </returns> public override Node Visit(GroupByIntoOp op, Node n) { VisitChildren(n); // update the output Vars and the key vars with the right sets var newKeys = FlattenVarSet(op.Keys); var newInputs = FlattenVarSet(op.Inputs); var newOutputs = FlattenVarSet(op.Outputs); if (newKeys != op.Keys || newInputs != op.Inputs || newOutputs != op.Outputs) { n.Op = m_command.CreateGroupByIntoOp(newKeys, newInputs, newOutputs); } return n; }
/// <summary> /// Mark AggregatePushdown as needed /// </summary> /// <param name="op">the groupByInto op</param> /// <param name="n">the node tree</param> /// <returns></returns> public override Node Visit(GroupByIntoOp op, Node n) { m_compilerState.MarkPhaseAsNeeded(PlanCompilerPhase.AggregatePushdown); return base.Visit(op, n); }
public override void Visit(GroupByIntoOp op, Node n) { VisitGroupByOp(op, n); Assert(n.Child3.Children.Count > 0, "GroupByInto with no group aggregate vars"); }
// <summary> // Registers the group aggregate var with the group aggregate var info manager // </summary> public override void Visit(GroupByIntoOp op, Node n) { VisitGroupByOp(op, n); foreach (var child in n.Child3.Children) { var groupAggregateVar = ((VarDefOp)child.Op).Var; GroupAggregateVarRefInfo groupAggregateVarRefInfo; // If the group by is over a group, it may be already tracked as referencing a group var // An optimization would be to separately track this groupAggregateVar too, for the cases when the aggregate can // not be pushed to the group by node over which this one is defined but can be propagated to this group by node. if (!_groupAggregateVarInfoManager.TryGetReferencedGroupAggregateVarInfo(groupAggregateVar, out groupAggregateVarRefInfo)) { _groupAggregateVarInfoManager.Add( groupAggregateVar, new GroupAggregateVarInfo(n, groupAggregateVar), _command.CreateNode(_command.CreateVarRefOp(groupAggregateVar)), false); } } }
/// <summary> /// Visitor pattern method for GroupByIntoOp /// </summary> /// <param name="op"> The GroupByIntoOp being visited </param> /// <param name="n"> The Node that references the Op </param> public virtual void Visit(GroupByIntoOp op, Node n) { VisitGroupByOp(op, n); }
public override void Visit(GroupByIntoOp op, Node n) { VisitGroupByOp(op, n); Map(op.Inputs); }
// <summary> // Copies a group by into node // </summary> // <param name="op"> The Op to Copy </param> // <param name="n"> The Node that references the Op </param> // <returns> A copy of the original Node that references a copy of the original Op </returns> public override Node Visit(GroupByIntoOp op, Node n) { // Visit the Node's children and map their Vars var children = ProcessChildren(n); // Create a new GroupByOp that uses copies of the Key and Output VarSets of the original GroupByOp var newGroupOp = m_destCmd.CreateGroupByIntoOp(Copy(op.Keys), Copy(op.Inputs), Copy(op.Outputs)); // Return a new Node that references the copied GroupByOp and has the copied child Nodes as its children return m_destCmd.CreateNode(newGroupOp, children); }
/// <summary> /// Try to push the given function aggregate candidate to the corresponding group into node. /// The candidate can be pushed if all ancestors of the group into node up to the least common /// ancestor between the group into node and the function aggregate have one of the following node op types: /// Project /// Filter /// ConstraintSortOp /// </summary> /// <param name="command"></param> /// <param name="candidate"></param> /// <param name="groupAggregateVarInfo"></param> /// <param name="m_childToParent"></param> private void TryProcessCandidate( KeyValuePair <Node, Node> candidate, GroupAggregateVarInfo groupAggregateVarInfo) { IList <Node> functionAncestors; IList <Node> groupByAncestors; Node definingGroupNode = groupAggregateVarInfo.DefiningGroupNode; FindPathsToLeastCommonAncestor(candidate.Key, definingGroupNode, out functionAncestors, out groupByAncestors); //Check whether all ancestors of the GroupByInto node are of type that we support propagating through if (!AreAllNodesSupportedForPropagation(groupByAncestors)) { return; } //Add the function to the group by node GroupByIntoOp definingGroupOp = (GroupByIntoOp)definingGroupNode.Op; PlanCompiler.Assert(definingGroupOp.Inputs.Count == 1, "There should be one input var to GroupByInto at this stage"); Var inputVar = definingGroupOp.Inputs.First; FunctionOp functionOp = (FunctionOp)candidate.Key.Op; // // Remap the template from referencing the groupAggregate var to reference the input to // the group by into // Node argumentNode = OpCopier.Copy(m_command, candidate.Value); Dictionary <Var, Var> dictionary = new Dictionary <Var, Var>(1); dictionary.Add(groupAggregateVarInfo.GroupAggregateVar, inputVar); VarRemapper remapper = new VarRemapper(m_command, dictionary); remapper.RemapSubtree(argumentNode); Node newFunctionDefiningNode = m_command.CreateNode( m_command.CreateAggregateOp(functionOp.Function, false), argumentNode); Var newFunctionVar; Node varDefNode = m_command.CreateVarDefNode(newFunctionDefiningNode, out newFunctionVar); // Add the new aggregate to the list of aggregates definingGroupNode.Child2.Children.Add(varDefNode); GroupByIntoOp groupByOp = (GroupByIntoOp)definingGroupNode.Op; groupByOp.Outputs.Set(newFunctionVar); //Propagate the new var throught the ancestors of the GroupByInto for (int i = 0; i < groupByAncestors.Count; i++) { Node groupByAncestor = groupByAncestors[i]; if (groupByAncestor.Op.OpType == OpType.Project) { ProjectOp ancestorProjectOp = (ProjectOp)groupByAncestor.Op; ancestorProjectOp.Outputs.Set(newFunctionVar); } } //Update the functionNode candidate.Key.Op = m_command.CreateVarRefOp(newFunctionVar); candidate.Key.Children.Clear(); }
public override void Visit(GroupByIntoOp op, System.Data.Entity.Core.Query.InternalTrees.Node n) { this.VisitGroupByOp((GroupByBaseOp)op, n); this.Map(op.Inputs); }