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;
        }
Exemple #3
0
 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);
        }
Exemple #5
0
 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);
            }
Exemple #7
0
        /// <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);
        }
Exemple #8
0
        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);
        }
Exemple #9
0
 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);
 }
Exemple #10
0
 public override void Visit(DbGroupByExpression expression)
 {
     Write(expression);
     _depth++;
     Write("Input", expression.Input);
     Write("Aggregates", expression.Aggregates);
     Write("Keys", expression.Keys);
     _depth--;
 }
Exemple #11
0
        /// <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);
        }
Exemple #12
0
            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);
        }
Exemple #14
0
        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);
 }
Exemple #16
0
        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);
        }
Exemple #18
0
        /// <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);
                }
            }
        }
Exemple #19
0
        /// <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.");
		}
Exemple #21
0
 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);
        }
        /// <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);
        }
Exemple #25
0
 public override LegacyCommandTrees.DbExpression Visit(DbGroupByExpression expression)
 {
     throw new NotImplementedException();
 }
Exemple #26
0
 /// <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);
 }
Exemple #28
0
 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;
        }
        /// <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);
                }
            }
        }
Exemple #34
0
 public override void Visit(DbGroupByExpression expression)
 {
     throw new NotSupportedException("Visit(\"DbGroupByExpression\") is not supported.");
 }
Exemple #35
0
            public override DbExpressionEntitySetInfo Visit(DbGroupByExpression expression)
            {
                Check.NotNull(expression, "expression");

                return(null);
            }
 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(')');
 }
Exemple #37
0
        /// <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);
        }
 /// <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)
 {
   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);
        }
Exemple #41
0
 public override DbExpressionEntitySetInfo Visit(DbGroupByExpression expression)
 {
     return(null);
 }
 public override TReturn Visit(DbGroupByExpression expression)
 {
     throw ConstructNotSupportedException(expression);
 }