public override void Visit(DbGroupByExpression e) { VisitExprKind(e.ExpressionKind); _key.Append('('); VisitGroupBinding(e.Input); foreach (var k in e.Keys) { _key.Append("K("); k.Accept(this); _key.Append(')'); } foreach (var a in e.Aggregates) { var ga = a as DbGroupAggregate; if (ga != null) { _key.Append("GA("); Debug.Assert(ga.Arguments.Count == 1, "Group aggregate must have one argument."); ga.Arguments[0].Accept(this); _key.Append(')'); } else { _key.Append("A:"); var fa = (DbFunctionAggregate)a; if (fa.Distinct) { _key.Append("D:"); } VisitFunction(fa.Function, fa.Arguments); } } _key.Append(')'); }
public override SqlFragment Visit(DbGroupByExpression expression) { // first process the input DbGroupExpressionBinding e = expression.Input; SelectStatement innerSelect = VisitInputExpressionEnsureSelect(e.Expression, e.VariableName, e.VariableType); SelectStatement select = WrapIfNotCompatible(innerSelect, expression.ExpressionKind); CollectionType ct = (CollectionType)expression.ResultType.EdmType; RowType rt = (RowType)ct.TypeUsage.EdmType; int propIndex = 0; foreach (DbExpression key in expression.Keys) { select.AddGroupBy(key.Accept(this)); propIndex++; } for (int agg = 0; agg < expression.Aggregates.Count; agg++) { DbAggregate a = expression.Aggregates[agg]; DbFunctionAggregate fa = a as DbFunctionAggregate; if (fa == null) throw new NotSupportedException(); string alias = rt.Properties[propIndex++].Name; ColumnFragment functionCol = new ColumnFragment(null, null); functionCol.Literal = HandleFunction(fa, a.Arguments[0].Accept(this)); functionCol.ColumnAlias = alias; select.Columns.Add(functionCol); } return select; }
public override void Visit(DbGroupByExpression e) { Check.NotNull <DbGroupByExpression>(e, nameof(e)); this.VisitExprKind(e.ExpressionKind); this._key.Append('('); this.VisitGroupBinding(e.Input); foreach (DbExpression key in (IEnumerable <DbExpression>)e.Keys) { this._key.Append("K("); key.Accept((DbExpressionVisitor)this); this._key.Append(')'); } foreach (DbAggregate aggregate in (IEnumerable <DbAggregate>)e.Aggregates) { DbGroupAggregate dbGroupAggregate = aggregate as DbGroupAggregate; if (dbGroupAggregate != null) { this._key.Append("GA("); dbGroupAggregate.Arguments[0].Accept((DbExpressionVisitor)this); this._key.Append(')'); } else { this._key.Append("A:"); DbFunctionAggregate functionAggregate = (DbFunctionAggregate)aggregate; if (functionAggregate.Distinct) { this._key.Append("D:"); } this.VisitFunction(functionAggregate.Function, functionAggregate.Arguments); } } this._key.Append(')'); }
public override void Visit(DbGroupByExpression e) { Check.NotNull(e, "e"); Begin(e); Dump(e.Input, "Input"); Dump(e.Keys, "Keys", "Key"); Begin("Aggregates"); foreach (var agg in e.Aggregates) { var funcAgg = agg as DbFunctionAggregate; if (funcAgg != null) { Begin("DbFunctionAggregate"); Dump(funcAgg.Function); Dump(funcAgg.Arguments, "Arguments", "Argument"); End("DbFunctionAggregate"); } else { var groupAgg = agg as DbGroupAggregate; Debug.Assert(groupAgg != null, "Invalid DbAggregate"); Begin("DbGroupAggregate"); Dump(groupAgg.Arguments, "Arguments", "Argument"); End("DbGroupAggregate"); } } End("Aggregates"); End(e); }
public override void Visit(DbGroupByExpression e) { Check.NotNull <DbGroupByExpression>(e, nameof(e)); this.Begin((DbExpression)e); this.Dump(e.Input, "Input"); this.Dump((IEnumerable <DbExpression>)e.Keys, "Keys", "Key"); this.Begin("Aggregates"); foreach (DbAggregate aggregate in (IEnumerable <DbAggregate>)e.Aggregates) { DbFunctionAggregate functionAggregate = aggregate as DbFunctionAggregate; if (functionAggregate != null) { this.Begin("DbFunctionAggregate"); this.Dump(functionAggregate.Function); this.Dump((IEnumerable <DbExpression>)functionAggregate.Arguments, "Arguments", "Argument"); this.End("DbFunctionAggregate"); } else { DbGroupAggregate dbGroupAggregate = aggregate as DbGroupAggregate; this.Begin("DbGroupAggregate"); this.Dump((IEnumerable <DbExpression>)dbGroupAggregate.Arguments, "Arguments", "Argument"); this.End("DbGroupAggregate"); } } this.End("Aggregates"); this.End((DbExpression)e); }
public override TreeNode Visit(DbGroupByExpression e) { Check.NotNull(e, "e"); var keys = new List <TreeNode>(); var aggs = new List <TreeNode>(); var outputType = TypeHelpers.GetEdmType <RowType>(TypeHelpers.GetEdmType <CollectionType>(e.ResultType).TypeUsage); var keyIdx = 0; for (var idx = 0; idx < e.Keys.Count; idx++) { keys.Add(VisitWithLabel("Key", outputType.Properties[idx].Name, e.Keys[keyIdx])); keyIdx++; } var aggIdx = 0; for (var idx = e.Keys.Count; idx < outputType.Properties.Count; idx++) { var aggInfo = new TreeNode("Aggregate : '"); aggInfo.Text.Append(outputType.Properties[idx].Name); aggInfo.Text.Append("'"); var funcAgg = e.Aggregates[aggIdx] as DbFunctionAggregate; if (funcAgg != null) { var funcInfo = VisitFunction(funcAgg.Function, funcAgg.Arguments); if (funcAgg.Distinct) { funcInfo = new TreeNode("Distinct", funcInfo); } aggInfo.Children.Add(funcInfo); } else { var groupAgg = e.Aggregates[aggIdx] as DbGroupAggregate; Debug.Assert(groupAgg != null, "Invalid DbAggregate"); aggInfo.Children.Add(Visit("GroupAggregate", groupAgg.Arguments[0])); } aggs.Add(aggInfo); aggIdx++; } var retInfo = NodeFromExpression(e); retInfo.Children.Add(VisitGroupBinding(e.Input)); if (keys.Count > 0) { retInfo.Children.Add(new TreeNode("Keys", keys)); } if (aggs.Count > 0) { retInfo.Children.Add(new TreeNode("Aggregates", aggs)); } return(retInfo); }
/// <summary> /// Walks the structure /// </summary> /// <param name="expression">The DbExpression that is being visited.</param> /// <returns></returns> public override bool Visit(DbGroupByExpression expression) { bool inputNeedsRewrite = VisitExpression(expression.Input.Expression); bool keysNeedRewrite = VisitExpressionList(expression.Keys); bool aggregatesNeedRewrite = VisitAggregateList(expression.Aggregates); return(inputNeedsRewrite || keysNeedRewrite || aggregatesNeedRewrite); }
public override bool Visit(DbGroupByExpression expression) { bool flag1 = VisitExpression(expression.Input.Expression); bool flag2 = VisitExpressionList(expression.Keys); bool flag3 = VisitAggregateList(expression.Aggregates); return(flag1 || flag2 || flag3); }
public override void Visit(DbGroupByExpression expression) { EntityUtils.CheckArgumentNull <DbGroupByExpression>(expression, nameof(expression)); this.VisitGroupExpressionBindingPre(expression.Input); this.VisitExpressionList(expression.Keys); this.VisitGroupExpressionBindingMid(expression.Input); this.VisitAggregateList(expression.Aggregates); this.VisitGroupExpressionBindingPost(expression.Input); }
public override void Visit(DbGroupByExpression expression) { Write(expression); _depth++; Write("Input", expression.Input); Write("Aggregates", expression.Aggregates); Write("Keys", expression.Keys); _depth--; }
/// <summary> /// Walks the structure /// </summary> /// <param name="expression"> The DbExpression that is being visited. </param> /// <returns> </returns> public override bool Visit(DbGroupByExpression expression) { Check.NotNull(expression, "expression"); var inputNeedsRewrite = VisitExpression(expression.Input.Expression); var keysNeedRewrite = VisitExpressionList(expression.Keys); var aggregatesNeedRewrite = VisitAggregateList(expression.Aggregates); return(inputNeedsRewrite || keysNeedRewrite || aggregatesNeedRewrite); }
public override TreeNode Visit(DbGroupByExpression e) { Check.NotNull <DbGroupByExpression>(e, nameof(e)); List <TreeNode> children1 = new List <TreeNode>(); List <TreeNode> children2 = new List <TreeNode>(); RowType edmType = TypeHelpers.GetEdmType <RowType>(TypeHelpers.GetEdmType <CollectionType>(e.ResultType).TypeUsage); int index1 = 0; for (int index2 = 0; index2 < e.Keys.Count; ++index2) { children1.Add(this.VisitWithLabel("Key", edmType.Properties[index2].Name, e.Keys[index1])); ++index1; } int index3 = 0; for (int count = e.Keys.Count; count < edmType.Properties.Count; ++count) { TreeNode treeNode1 = new TreeNode("Aggregate : '", new TreeNode[0]); treeNode1.Text.Append(edmType.Properties[count].Name); treeNode1.Text.Append("'"); DbFunctionAggregate aggregate1 = e.Aggregates[index3] as DbFunctionAggregate; if (aggregate1 != null) { TreeNode treeNode2 = this.VisitFunction(aggregate1.Function, aggregate1.Arguments); if (aggregate1.Distinct) { treeNode2 = new TreeNode("Distinct", new TreeNode[1] { treeNode2 }); } treeNode1.Children.Add(treeNode2); } else { DbGroupAggregate aggregate2 = e.Aggregates[index3] as DbGroupAggregate; treeNode1.Children.Add(this.Visit("GroupAggregate", aggregate2.Arguments[0])); } children2.Add(treeNode1); ++index3; } TreeNode treeNode = ExpressionPrinter.PrinterVisitor.NodeFromExpression((DbExpression)e); treeNode.Children.Add(this.VisitGroupBinding(e.Input)); if (children1.Count > 0) { treeNode.Children.Add(new TreeNode("Keys", children1)); } if (children2.Count > 0) { treeNode.Children.Add(new TreeNode("Aggregates", children2)); } return(treeNode); }
/// <summary> /// Visitor pattern method for <see cref="DbGroupByExpression" />. /// </summary> /// <param name="expression"> The DbExpression that is being visited. </param> /// <exception cref="ArgumentNullException"> /// <paramref name="expression" /> /// is null /// </exception> public override void Visit(DbGroupByExpression expression) { // #433613: PreSharp warning 56506: Parameter 'expression' to this public method must be validated: A null-dereference can occur here. Check.NotNull(expression, "expression"); VisitGroupExpressionBindingPre(expression.Input); VisitExpressionList(expression.Keys); VisitGroupExpressionBindingMid(expression.Input); VisitAggregateList(expression.Aggregates); VisitGroupExpressionBindingPost(expression.Input); }
public override object Visit(DbGroupByExpression expression) { this.Visit(expression.Input.Expression); foreach (var arg in expression.Keys) { this.Visit(arg); } return(null); }
public override void Visit(DbGroupByExpression expression) { if (expression == null) { throw new ArgumentException("expression"); } VisitGroupExpressionBindingPre(expression.Input); VisitExpressionList(expression.Keys); VisitGroupExpressionBindingMid(expression.Input); VisitAggregateList(expression.Aggregates); VisitGroupExpressionBindingPost(expression.Input); }
public override bool Visit(DbGroupByExpression expression) { Check.NotNull <DbGroupByExpression>(expression, nameof(expression)); bool flag1 = this.VisitExpression(expression.Input.Expression); bool flag2 = this.VisitExpressionList(expression.Keys); bool flag3 = this.VisitAggregateList(expression.Aggregates); if (!flag1 && !flag2) { return(flag3); } return(true); }
public override SqlFragment Visit(DbGroupByExpression expression) { // first process the input DbGroupExpressionBinding e = expression.Input; SelectStatement innerSelect = VisitInputExpressionEnsureSelect(e.Expression, e.VariableName, e.VariableType); scope.Add(e.GroupVariableName, innerSelect); SelectStatement select = WrapIfNotCompatible(innerSelect, expression.ExpressionKind); CollectionType ct = (CollectionType)expression.ResultType.EdmType; RowType rt = (RowType)ct.TypeUsage.EdmType; int propIndex = 0; foreach (DbExpression key in expression.Keys) { var fragment = key.Accept(this); select.AddGroupBy(fragment); propIndex++; var colFragment = fragment as ColumnFragment; if (colFragment != null) { colFragment = colFragment.Clone(); colFragment.ColumnAlias = String.Format("K{0}", propIndex); select.Columns.Add(colFragment); } } for (int agg = 0; agg < expression.Aggregates.Count; agg++) { DbAggregate a = expression.Aggregates[agg]; DbFunctionAggregate fa = a as DbFunctionAggregate; if (fa == null) { throw new NotSupportedException(); } string alias = rt.Properties[propIndex++].Name; ColumnFragment functionCol = new ColumnFragment(null, null); functionCol.Literal = HandleFunction(fa, a.Arguments[0].Accept(this)); functionCol.ColumnAlias = alias; select.Columns.Add(functionCol); } return(select); }
/// <summary> /// Implements the visitor pattern for <see cref="T:System.Data.Common.CommandTrees.DbGroupByExpression"/>. /// </summary> /// <param name="expression">The <see cref="T:System.Data.Common.CommandTrees.DbGroupByExpression"/> that is visited.</param> public override void Visit(DbGroupByExpression expression) { expression.Input.Expression.Accept(this); foreach (DbExpression ex in expression.Keys) { ex.Accept(this); } foreach (DbAggregate agg in expression.Aggregates) { foreach (DbExpression ex in agg.Arguments) { ex.Accept(this); } } }
/// <summary> /// Implements the visitor pattern for <see cref="T:System.Data.Common.CommandTrees.DbGroupByExpression"/>. /// </summary> /// <param name="expression">The <see cref="T:System.Data.Common.CommandTrees.DbGroupByExpression"/> that is visited.</param> public override void Visit(DbGroupByExpression expression) { if (expression == null) { throw new ArgumentNullException("expression"); } expression.Input.Expression.Accept(this); foreach (DbExpression ex in expression.Keys) { ex.Accept(this); } foreach (DbAggregate agg in expression.Aggregates) { foreach (DbExpression ex in agg.Arguments) { ex.Accept(this); } } }
public override void Visit(DbGroupByExpression expression) { throw new NotSupportedException("Visit(\"GroupByExpression\") is not supported."); }
public override SqlFragment Visit(DbGroupByExpression expression) { throw new NotImplementedException(); }
/// <summary> /// Visitor pattern method for <see cref="DbGroupByExpression" />. /// </summary> /// <param name="expression"> The DbExpression that is being visited. </param> /// <exception cref="ArgumentNullException"> /// <paramref name="expression" /> /// is null /// </exception> public override void Visit(DbGroupByExpression expression) { Check.NotNull(expression, "expression"); VisitGroupExpressionBindingPre(expression.Input); VisitExpressionList(expression.Keys); VisitGroupExpressionBindingMid(expression.Input); VisitAggregateList(expression.Aggregates); VisitGroupExpressionBindingPost(expression.Input); }
public override Expression Visit(DbGroupByExpression expression) { Expression source = this.Visit(expression.Input.Expression); Type elementType = TypeHelper.GetElementType(source.Type); Type resultType = edmTypeConverter.GetElementType(expression.ResultType); Expression result = source; if (expression.Keys.Count == 0) { // This is a special case // The DbGroupByExpression does not contain any Key element // There is no GroupByClause List <Expression> constructorArguments = new List <Expression>(); for (int i = 0; i < expression.Aggregates.Count; i++) { DbFunctionAggregate aggregation = expression.Aggregates[i] as DbFunctionAggregate; if (aggregation == null) { throw new InvalidOperationException(expression.Aggregates[i].GetType().ToString() + "is not supported"); } Expression arg = this.CreateAggregateFunction( aggregation, //Aggregation is executed on the source expression.Input.GroupVariableName, elementType, source, resultType.GetProperties()[0].PropertyType); constructorArguments.Add(arg); } Expression aggregationResults = Expression.New( resultType.GetConstructors().Single(), constructorArguments.ToArray(), resultType.GetProperties()); // Wrap by a SingleResult collection object result = Expression.New( typeof(SingleResult <>).MakeGenericType(resultType).GetConstructors().Single(), aggregationResults); // Make it queryable result = queryMethodExpressionBuilder.AsQueryable(result); } else { // The properties of the selector form a subset of the properties of the result type // These properties defined first in the edm type PropertyInfo[] props = resultType.GetProperties(); Dictionary <string, Type> selectorProperties = new Dictionary <string, Type>(); // Collect the properties for (int i = 0; i < expression.Keys.Count; i++) { selectorProperties.Add(props[i].Name, props[i].PropertyType); } Type selectorType = DataRowFactory.Create(selectorProperties); LambdaExpression selector = null; ParameterExpression groupParam = Expression.Parameter(elementType, expression.Input.VariableName); using (this.CreateVariable(groupParam, expression.Input.VariableName)) { Expression[] keys = this.VisitExpressions(expression.Keys); selector = Expression.Lambda( this.CreateSelector(keys, selectorType), groupParam); } // Build the GroupBy call expression result = queryMethodExpressionBuilder.GroupBy(result, selector); // Get IGrouping<> type Type groupingType = TypeHelper.GetElementType(result.Type); // Collect argument initiators in an array Expression[] groupInit = new Expression[expression.Keys.Count + expression.Aggregates.Count]; ParameterExpression selectParam = Expression.Parameter(groupingType, "group"); Expression keyParam = Expression.Property(selectParam, "Key"); // Collect the Key arguments for (int i = 0; i < expression.Keys.Count; i++) { groupInit[i] = Expression.Property(keyParam, props[i].Name); } // Collect the aggregate arguments for (int i = 0; i < expression.Aggregates.Count; i++) { DbFunctionAggregate aggregate = expression.Aggregates[i] as DbFunctionAggregate; if (aggregate == null) { throw new InvalidOperationException(expression.Aggregates[i].GetType().ToString() + "is not supported"); } groupInit[expression.Keys.Count + i] = this.CreateAggregateFunction( aggregate, // Aggregation is executed on the group expression.Input.GroupVariableName, elementType, selectParam, props[expression.Keys.Count + i].PropertyType); } selector = Expression.Lambda( Expression.New( resultType.GetConstructors().Single(), groupInit, resultType.GetProperties()), selectParam); result = queryMethodExpressionBuilder.Select(result, selector); } return(result); }
public override LegacyCommandTrees.DbExpression Visit(DbGroupByExpression expression) { throw new NotImplementedException(); }
/// <summary> /// Typed visitor pattern method for DbGroupByExpression. /// </summary> /// <param name="expression"> The DbGroupByExpression that is being visited. </param> /// <returns> An instance of TResultType. </returns> public abstract TResultType Visit(DbGroupByExpression expression);
public override ViewValidator.DbExpressionEntitySetInfo Visit( DbGroupByExpression expression) { Check.NotNull <DbGroupByExpression>(expression, nameof(expression)); return((ViewValidator.DbExpressionEntitySetInfo)null); }
public override TReturn Visit(DbGroupByExpression expression) { Check.NotNull <DbGroupByExpression>(expression, nameof(expression)); throw this.ConstructNotSupportedException((DbExpression)expression); }
public override void Visit(DbGroupByExpression expression) { Contract.Requires(expression != null); }
/// <summary> /// Visitor pattern method for DbGroupByExpression. /// </summary> /// <param name="expression"> The DbGroupByExpression that is being visited. </param> public abstract void Visit(DbGroupByExpression expression);
public override void Visit(DbGroupByExpression expression) { }
public override Expression Visit(DbGroupByExpression expression) { Expression source = this.Visit(expression.Input.Expression); Type elementType = TypeHelper.GetElementType(source.Type); Type resultType = edmTypeConverter.GetElementType(expression.ResultType); Expression result = source; if (expression.Keys.Count == 0) { // This is a special case // The DbGroupByExpression does not contain any Key element // There is no GroupByClause List<Expression> constructorArguments = new List<Expression>(); for (int i = 0; i < expression.Aggregates.Count; i++) { DbFunctionAggregate aggregation = expression.Aggregates[i] as DbFunctionAggregate; if (aggregation == null) { throw new InvalidOperationException(expression.Aggregates[i].GetType().ToString() + "is not supported"); } Expression arg = this.CreateAggregateFunction( aggregation, //Aggregation is executed on the source expression.Input.GroupVariableName, elementType, source, resultType.GetProperties()[0].PropertyType); constructorArguments.Add(arg); } Expression aggregationResults = Expression.New( resultType.GetConstructors().Single(), constructorArguments.ToArray(), resultType.GetProperties()); // Wrap by a SingleResult collection object result = Expression.New( typeof(SingleResult<>).MakeGenericType(resultType).GetConstructors().Single(), aggregationResults); // Make it queryable result = queryMethodExpressionBuilder.AsQueryable(result); } else { // The properties of the selector form a subset of the properties of the result type // These properties defined first in the edm type PropertyInfo[] props = resultType.GetProperties(); Dictionary<string, Type> selectorProperties = new Dictionary<string, Type>(); // Collect the properties for (int i = 0; i < expression.Keys.Count; i++) { selectorProperties.Add(props[i].Name, props[i].PropertyType); } Type selectorType = DataRowFactory.Create(selectorProperties); LambdaExpression selector = null; ParameterExpression groupParam = Expression.Parameter(elementType, expression.Input.VariableName); using (this.CreateVariable(groupParam, expression.Input.VariableName)) { Expression[] keys = this.VisitExpressions(expression.Keys); selector = Expression.Lambda( this.CreateSelector(keys, selectorType), groupParam); } // Build the GroupBy call expression result = queryMethodExpressionBuilder.GroupBy(result, selector); // Get IGrouping<> type Type groupingType = TypeHelper.GetElementType(result.Type); // Collect argument initiators in an array Expression[] groupInit = new Expression[expression.Keys.Count + expression.Aggregates.Count]; ParameterExpression selectParam = Expression.Parameter(groupingType, "group"); Expression keyParam = Expression.Property(selectParam, "Key"); // Collect the Key arguments for (int i = 0; i < expression.Keys.Count; i++) { groupInit[i] = Expression.Property(keyParam, props[i].Name); } // Collect the aggregate arguments for (int i = 0; i < expression.Aggregates.Count; i++) { DbFunctionAggregate aggregate = expression.Aggregates[i] as DbFunctionAggregate; if (aggregate == null) { throw new InvalidOperationException(expression.Aggregates[i].GetType().ToString() + "is not supported"); } groupInit[expression.Keys.Count + i] = this.CreateAggregateFunction( aggregate, // Aggregation is executed on the group expression.Input.GroupVariableName, elementType, selectParam, props[expression.Keys.Count + i].PropertyType); } selector = Expression.Lambda( Expression.New( resultType.GetConstructors().Single(), groupInit, resultType.GetProperties()), selectParam); result = queryMethodExpressionBuilder.Select(result, selector); } return result; }
public override void Visit(DbGroupByExpression expression) { throw new NotSupportedException("Visit(\"DbGroupByExpression\") is not supported."); }
public override DbExpressionEntitySetInfo Visit(DbGroupByExpression expression) { Check.NotNull(expression, "expression"); return(null); }
/// <summary> /// <see cref="Visit(DbFilterExpression)"/> for general details. /// We modify both the GroupBy and the Select fields of the SqlSelectStatement. /// GroupBy gets just the keys without aliases, /// and Select gets the keys and the aggregates with aliases. /// /// Whenever there exists at least one aggregate with an argument that is not is not a simple /// <see cref="DbPropertyExpression"/> over <see cref="DbVariableReferenceExpression"/>, /// we create a nested query in which we alias the arguments to the aggregates. /// That is due to the following two limitations of Sql Server: /// <list type="number"> /// <item>If an expression being aggregated contains an outer reference, then that outer /// reference must be the only column referenced in the expression </item> /// <item>Sql Server cannot perform an aggregate function on an expression containing /// an aggregate or a subquery. </item> /// </list> /// /// The default translation, without inner query is: /// /// SELECT /// kexp1 AS key1, kexp2 AS key2,... kexpn AS keyn, /// aggf1(aexpr1) AS agg1, .. aggfn(aexprn) AS aggn /// FROM input AS a /// GROUP BY kexp1, kexp2, .. kexpn /// /// When we inject an innner query, the equivalent translation is: /// /// SELECT /// key1 AS key1, key2 AS key2, .. keyn AS keys, /// aggf1(agg1) AS agg1, aggfn(aggn) AS aggn /// FROM ( /// SELECT /// kexp1 AS key1, kexp2 AS key2,... kexpn AS keyn, /// aexpr1 AS agg1, .. aexprn AS aggn /// FROM input AS a /// ) as a /// GROUP BY key1, key2, keyn /// /// </summary> /// <param name="e"></param> /// <returns>A <see cref="SqlSelectStatement"/></returns> public override ISqlFragment Visit(DbGroupByExpression e) { Symbol fromSymbol; SqlSelectStatement innerQuery = VisitInputExpression(e.Input.Expression, e.Input.VariableName, e.Input.VariableType, out fromSymbol); // GroupBy is compatible with Filter and OrderBy // but not with Project, GroupBy if (!IsCompatible(innerQuery, e.ExpressionKind)) { innerQuery = CreateNewSelectStatement(innerQuery, e.Input.VariableName, e.Input.VariableType, out fromSymbol); } selectStatementStack.Push(innerQuery); symbolTable.EnterScope(); AddFromSymbol(innerQuery, e.Input.VariableName, fromSymbol); // This line is not present for other relational nodes. symbolTable.Add(e.Input.GroupVariableName, fromSymbol); // The enumerator is shared by both the keys and the aggregates, // so, we do not close it in between. RowType groupByType = MetadataHelpers.GetEdmType <RowType>(MetadataHelpers.GetEdmType <CollectionType>(e.ResultType).TypeUsage); //Whenever there exists at least one aggregate with an argument that is not simply a PropertyExpression // over a VarRefExpression, we need a nested query in which we alias the arguments to the aggregates. bool needsInnerQuery = NeedsInnerQuery(e.Aggregates); SqlSelectStatement result; if (needsInnerQuery) { //Create the inner query result = CreateNewSelectStatement(innerQuery, e.Input.VariableName, e.Input.VariableType, false, out fromSymbol); AddFromSymbol(result, e.Input.VariableName, fromSymbol, false); } else { result = innerQuery; } using (IEnumerator <EdmProperty> members = groupByType.Properties.GetEnumerator()) { members.MoveNext(); Debug.Assert(result.Select.IsEmpty); string separator = ""; foreach (DbExpression key in e.Keys) { EdmProperty member = members.Current; var alias = new Symbol(member.Name); result.GroupBy.Append(separator); ISqlFragment keySql = key.Accept(this); if (!needsInnerQuery) { //Default translation: Alias = Key result.Select.Append(new SelectColumn(alias, keySql)); result.GroupBy.Append(keySql); } else { // The inner query contains the default translation Alias = Key result.Select.Append(new SelectColumn(alias, keySql)); //The outer resulting query projects over the key aliased in the inner query: // fromSymbol.Alias AS Alias result.Select.Append(new SelectColumn(alias, fromSymbol, alias)); result.GroupBy.Append(alias); } separator = ", "; members.MoveNext(); } foreach (DbAggregate aggregate in e.Aggregates) { EdmProperty member = members.Current; var alias = new Symbol(member.Name); Debug.Assert(aggregate.Arguments.Count == 1); ISqlFragment translatedAggregateArgument = aggregate.Arguments[0].Accept(this); ISqlFragment aggregateArgument; if (needsInnerQuery) { //In this case the argument to the aggratete is reference to the one projected out by the // inner query SqlBuilder wrappingAggregateArgument = new SqlBuilder(); wrappingAggregateArgument.Append(fromSymbol); wrappingAggregateArgument.Append("."); wrappingAggregateArgument.Append(SqlGenerator.QuoteIdentifier(alias.Name)); aggregateArgument = wrappingAggregateArgument; innerQuery.Select.Append(new SelectColumn(alias, translatedAggregateArgument)); } else { aggregateArgument = translatedAggregateArgument; } ISqlFragment aggregateResult = VisitAggregate(aggregate, aggregateArgument); result.Select.Append(new SelectColumn(alias, aggregateResult)); separator = ", "; members.MoveNext(); } } symbolTable.ExitScope(); selectStatementStack.Pop(); return(result); }
public override void Visit(DbGroupByExpression expression) { if (expression == null) throw new ArgumentException("expression"); VisitGroupExpressionBindingPre(expression.Input); VisitExpressionList(expression.Keys); VisitGroupExpressionBindingMid(expression.Input); VisitAggregateList(expression.Aggregates); VisitGroupExpressionBindingPost(expression.Input); }
public override void Visit(DbGroupByExpression e) { Begin(e); Dump(e.Input, "Input"); Dump(e.Keys, "Keys", "Key"); Begin("Aggregates"); foreach (DbAggregate agg in e.Aggregates) { DbFunctionAggregate funcAgg = agg as DbFunctionAggregate; if (funcAgg != null) { Begin("DbFunctionAggregate"); Dump(funcAgg.Function); Dump(funcAgg.Arguments, "Arguments", "Argument"); End("DbFunctionAggregate"); } else { DbGroupAggregate groupAgg = agg as DbGroupAggregate; Debug.Assert(groupAgg != null, "Invalid DbAggregate"); Begin("DbGroupAggregate"); Dump(groupAgg.Arguments, "Arguments", "Argument"); End("DbGroupAggregate"); } } End("Aggregates"); End(e); }
public override DbExpressionEntitySetInfo Visit(DbGroupByExpression expression) { return(null); }
public override TReturn Visit(DbGroupByExpression expression) { throw ConstructNotSupportedException(expression); }