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); }
private static bool ProcessGroupByOverProject( RuleProcessingContext context, System.Data.Entity.Core.Query.InternalTrees.Node n, out System.Data.Entity.Core.Query.InternalTrees.Node newNode) { newNode = n; GroupByOp op = (GroupByOp)n.Op; Command command = context.Command; System.Data.Entity.Core.Query.InternalTrees.Node child0 = n.Child0; System.Data.Entity.Core.Query.InternalTrees.Node child1_1 = child0.Child1; System.Data.Entity.Core.Query.InternalTrees.Node child1_2 = n.Child1; System.Data.Entity.Core.Query.InternalTrees.Node child2 = n.Child2; if (child1_2.Children.Count > 0) { return(false); } VarVec varVec = command.GetExtendedNodeInfo(child0).LocalDefinitions; if (op.Outputs.Overlaps(varVec)) { return(false); } bool flag = false; for (int index = 0; index < child1_1.Children.Count; ++index) { System.Data.Entity.Core.Query.InternalTrees.Node child = child1_1.Children[index]; if (child.Child0.Op.OpType == OpType.Constant || child.Child0.Op.OpType == OpType.InternalConstant || child.Child0.Op.OpType == OpType.NullSentinel) { if (!flag) { varVec = command.CreateVarVec(varVec); flag = true; } varVec.Clear(((VarDefOp)child.Op).Var); } } if (GroupByOpRules.VarRefUsageFinder.AnyVarUsedMoreThanOnce(varVec, child2, command)) { return(false); } Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node> varReplacementTable = new Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node>(child1_1.Children.Count); for (int index = 0; index < child1_1.Children.Count; ++index) { System.Data.Entity.Core.Query.InternalTrees.Node child = child1_1.Children[index]; Var var = ((VarDefOp)child.Op).Var; varReplacementTable.Add(var, child.Child0); } newNode.Child2 = GroupByOpRules.VarRefReplacer.Replace(varReplacementTable, child2, command); newNode.Child0 = child0.Child0; return(true); }
private static bool ProcessGroupByOpOnAllInputColumnsWithAggregateOperation( RuleProcessingContext context, System.Data.Entity.Core.Query.InternalTrees.Node n, out System.Data.Entity.Core.Query.InternalTrees.Node newNode) { newNode = n; PhysicalProjectOp op1 = context.Command.Root.Op as PhysicalProjectOp; if (op1 == null || op1.Outputs.Count > 1 || (n.Child0.Op.OpType != OpType.ScanTable || n.Child2 == null) || (n.Child2.Child0 == null || n.Child2.Child0.Child0 == null || n.Child2.Child0.Child0.Op.OpType != OpType.Aggregate)) { return(false); } GroupByOp op2 = (GroupByOp)n.Op; Table table = ((ScanTableBaseOp)n.Child0.Op).Table; VarList columns = table.Columns; foreach (Var v in (List <Var>)columns) { if (!op2.Keys.IsSet(v)) { return(false); } } foreach (Var v in (List <Var>)columns) { op2.Outputs.Clear(v); op2.Keys.Clear(v); } Command command = context.Command; ScanTableOp scanTableOp = command.CreateScanTableOp(table.TableMetadata); System.Data.Entity.Core.Query.InternalTrees.Node node1 = command.CreateNode((Op)scanTableOp); System.Data.Entity.Core.Query.InternalTrees.Node node2 = command.CreateNode((Op)command.CreateOuterApplyOp(), node1, n); Var computedVar; System.Data.Entity.Core.Query.InternalTrees.Node varDefListNode = command.CreateVarDefListNode(command.CreateNode((Op)command.CreateVarRefOp(op2.Outputs.First)), out computedVar); newNode = command.CreateNode((Op)command.CreateProjectOp(computedVar), node2, varDefListNode); System.Data.Entity.Core.Query.InternalTrees.Node node3 = (System.Data.Entity.Core.Query.InternalTrees.Node)null; IEnumerator <Var> enumerator1 = scanTableOp.Table.Keys.GetEnumerator(); IEnumerator <Var> enumerator2 = table.Keys.GetEnumerator(); for (int index = 0; index < table.Keys.Count; ++index) { enumerator1.MoveNext(); enumerator2.MoveNext(); System.Data.Entity.Core.Query.InternalTrees.Node node4 = command.CreateNode((Op)command.CreateComparisonOp(OpType.EQ, false), command.CreateNode((Op)command.CreateVarRefOp(enumerator1.Current)), command.CreateNode((Op)command.CreateVarRefOp(enumerator2.Current))); node3 = node3 == null ? node4 : command.CreateNode((Op)command.CreateConditionalOp(OpType.And), node3, node4); } System.Data.Entity.Core.Query.InternalTrees.Node node5 = command.CreateNode((Op)command.CreateFilterOp(), n.Child0, node3); n.Child0 = node5; return(true); }
/// <summary> /// Converts a collection aggregate function count(X), where X is a collection into /// two parts. Part A is a groupby subquery that looks like /// GroupBy(Unnest(X), empty, count(y)) /// where "empty" describes the fact that the groupby has no keys, and y is an /// element var of the Unnest /// /// Part 2 is a VarRef that refers to the aggregate var for count(y) described above. /// /// Logically, we would replace the entire functionOp by element(GroupBy...). However, /// since we also want to translate element() into single-row-subqueries, we do this /// here as well. /// /// The function itself is replaced by the VarRef, and the GroupBy is added to the list /// of scalar subqueries for the current relOp node on the stack /// /// </summary> /// <param name="op">the functionOp for the collection agg</param> /// <param name="n">current subtree</param> /// <returns>the VarRef node that should replace the function</returns> private Node VisitCollectionAggregateFunction(FunctionOp op, Node n) { TypeUsage softCastType = null; Node argNode = n.Child0; if (OpType.SoftCast == argNode.Op.OpType) { softCastType = TypeHelpers.GetEdmType <CollectionType>(argNode.Op.Type).TypeUsage; argNode = argNode.Child0; while (OpType.SoftCast == argNode.Op.OpType) { argNode = argNode.Child0; } } Node unnestNode = BuildUnnest(argNode); UnnestOp unnestOp = unnestNode.Op as UnnestOp; Var unnestOutputVar = unnestOp.Table.Columns[0]; AggregateOp aggregateOp = m_command.CreateAggregateOp(op.Function, false); VarRefOp unnestVarRefOp = m_command.CreateVarRefOp(unnestOutputVar); Node unnestVarRefNode = m_command.CreateNode(unnestVarRefOp); if (softCastType != null) { unnestVarRefNode = m_command.CreateNode(m_command.CreateSoftCastOp(softCastType), unnestVarRefNode); } Node aggExprNode = m_command.CreateNode(aggregateOp, unnestVarRefNode); VarVec keyVars = m_command.CreateVarVec(); // empty keys Node keyVarDefListNode = m_command.CreateNode(m_command.CreateVarDefListOp()); VarVec gbyOutputVars = m_command.CreateVarVec(); Var aggVar; Node aggVarDefListNode = m_command.CreateVarDefListNode(aggExprNode, out aggVar); gbyOutputVars.Set(aggVar); GroupByOp gbyOp = m_command.CreateGroupByOp(keyVars, gbyOutputVars); Node gbySubqueryNode = m_command.CreateNode(gbyOp, unnestNode, keyVarDefListNode, aggVarDefListNode); // "Move" this subquery to my parent relop Node ret = AddSubqueryToParentRelOp(aggVar, gbySubqueryNode); return(ret); }
private static bool ProcessGroupByOpWithNoAggregates( RuleProcessingContext context, System.Data.Entity.Core.Query.InternalTrees.Node n, out System.Data.Entity.Core.Query.InternalTrees.Node newNode) { Command command = context.Command; GroupByOp op = (GroupByOp)n.Op; ExtendedNodeInfo extendedNodeInfo = command.GetExtendedNodeInfo(n.Child0); ProjectOp projectOp = command.CreateProjectOp(op.Keys); VarDefListOp varDefListOp = command.CreateVarDefListOp(); command.CreateNode((Op)varDefListOp); newNode = command.CreateNode((Op)projectOp, n.Child0, n.Child1); if (extendedNodeInfo.Keys.NoKeys || !op.Keys.Subsumes(extendedNodeInfo.Keys.KeyVars)) { newNode = command.CreateNode((Op)command.CreateDistinctOp(command.CreateVarVec(op.Keys)), newNode); } return(true); }
// <summary> // GroupByOp // </summary> // <remarks> // At this point in the process, there really isn't a way we should actually // have a NestOp as an input to the GroupByOp, and we currently aren't allowing // you to specify a collection as an aggregation Var or key, so if we find a // NestOp anywhere on the inputs, it's a NotSupported situation. // </remarks> public override Node Visit(GroupByOp op, Node n) { return NestingNotSupported(op, n); }
/// <summary> /// GroupBy /// Again, VisitChildren - for the Keys and Properties VarDefList nodes - does /// the real work. /// The "Keys" and the "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(GroupByOp op, Node n) { VisitChildren(n); // update the output Vars and the key vars with the right sets var newKeys = FlattenVarSet(op.Keys); var newOutputs = FlattenVarSet(op.Outputs); if (newKeys != op.Keys || newOutputs != op.Outputs) { n.Op = m_command.CreateGroupByOp(newKeys, newOutputs); } return n; }
/// <summary> /// Visitor pattern method for GroupByOp /// </summary> /// <param name="op"> The GroupByOp being visited </param> /// <param name="n"> The Node that references the Op </param> public virtual void Visit(GroupByOp op, Node n) { VisitGroupByOp(op, n); }
// <summary> // GroupByOp // </summary> public override int Visit(GroupByOp op, Node n) { return(op.Outputs.Count); }
public override int Visit(GroupByOp op, System.Data.Entity.Core.Query.InternalTrees.Node n) { return(op.Outputs.Count); }
// <summary> // Copies a group-by 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(GroupByOp 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.CreateGroupByOp(Copy(op.Keys), 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); }