Exemplo n.º 1
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(')');
 }
        private SqlFragment HandleFunction(DbFunctionAggregate fa, SqlFragment arg)
        {
            Debug.Assert(fa.Arguments.Count == 1);

            if (fa.Function.NamespaceName != "Edm")
            {
                throw new NotSupportedException();
            }

            FunctionFragment fragment = new FunctionFragment();

            fragment.Name = fa.Function.Name;
            if (fa.Function.Name == "BigCount")
            {
                fragment.Name = "COUNT";
            }
            else
            {
                fragment.Name = fa.Function.Name.ToUpperInvariant();
            }

            fragment.Distinct  = fa.Distinct;
            fragment.Argmument = arg;
            return(fragment);
            //return new CastExpression(aggregate, GetDbType(functionAggregate.ResultType.EdmType));
        }
Exemplo n.º 3
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);
 }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
            public override TreeNode Visit(DbGroupByExpression e)
            {
                List <TreeNode> keys = new List <TreeNode>();
                List <TreeNode> aggs = new List <TreeNode>();

                RowType outputType = TypeHelpers.GetEdmType <RowType>(TypeHelpers.GetEdmType <CollectionType>(e.ResultType).TypeUsage);
                int     keyIdx     = 0;

                for (int idx = 0; idx < e.Keys.Count; idx++)
                {
                    keys.Add(this.VisitWithLabel("Key", outputType.Properties[idx].Name, e.Keys[keyIdx]));
                    keyIdx++;
                }

                int aggIdx = 0;

                for (int idx = e.Keys.Count; idx < outputType.Properties.Count; idx++)
                {
                    TreeNode aggInfo = new TreeNode("Aggregate : '");
                    aggInfo.Text.Append(outputType.Properties[idx].Name);
                    aggInfo.Text.Append("'");

                    DbFunctionAggregate funcAgg = e.Aggregates[aggIdx] as DbFunctionAggregate;
                    if (funcAgg != null)
                    {
                        TreeNode funcInfo = this.VisitFunction(funcAgg.Function, funcAgg.Arguments);
                        if (funcAgg.Distinct)
                        {
                            funcInfo = new TreeNode("Distinct", funcInfo);
                        }
                        aggInfo.Children.Add(funcInfo);
                    }
                    else
                    {
                        DbGroupAggregate groupAgg = e.Aggregates[aggIdx] as DbGroupAggregate;
                        Debug.Assert(groupAgg != null, "Invalid DbAggregate");
                        aggInfo.Children.Add(this.Visit("GroupAggregate", groupAgg.Arguments[0]));
                    }

                    aggs.Add(aggInfo);
                    aggIdx++;
                }

                TreeNode retInfo = NodeFromExpression(e);

                retInfo.Children.Add(this.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);
            }
Exemplo n.º 6
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);
            }
        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);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Aggregates are not visited by the normal visitor walk.
        /// </summary>
        /// <param name="aggregate">The aggreate go be translated</param>
        /// <param name="aggregateArgument">The translated aggregate argument</param>
        /// <returns></returns>
        private SqlBuilder VisitAggregate(DbAggregate aggregate, ISqlFragment aggregateArgument)
        {
            SqlBuilder          aggregateResult   = new SqlBuilder();
            DbFunctionAggregate functionAggregate = aggregate as DbFunctionAggregate;

            if (functionAggregate == null)
            {
                throw new NotSupportedException();
            }

            //The only aggregate function with different name is Big_Count
            //Note: If another such function is to be added, a dictionary should be created
            if (MetadataHelpers.IsCanonicalFunction(functionAggregate.Function) &&
                String.Equals(functionAggregate.Function.Name, "BigCount", StringComparison.Ordinal))
            {
                aggregateResult.Append("COUNT_BIG");
            }
            else
            {
                WriteFunctionName(aggregateResult, functionAggregate.Function);
            }

            aggregateResult.Append("(");

            DbFunctionAggregate fnAggr = functionAggregate;

            if ((null != fnAggr) && (fnAggr.Distinct))
            {
                aggregateResult.Append("DISTINCT ");
            }

            aggregateResult.Append(aggregateArgument);

            aggregateResult.Append(")");
            return(aggregateResult);
        }
        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);
        }
Exemplo n.º 10
0
    private SqlFragment HandleFunction(DbFunctionAggregate fa, SqlFragment arg)
    {
      Debug.Assert(fa.Arguments.Count == 1);

      if (fa.Function.NamespaceName != "Edm")
        throw new NotSupportedException();

      FunctionFragment fragment = new FunctionFragment();
      fragment.Name = fa.Function.Name;
      if (fa.Function.Name == "BigCount")
        fragment.Name = "COUNT";
      else
        fragment.Name = fa.Function.Name.ToUpperInvariant();

      fragment.Distinct = fa.Distinct;
      fragment.Argument = arg;
      return fragment;
      //return new CastExpression(aggregate, GetDbType(functionAggregate.ResultType.EdmType));
    }
Exemplo n.º 11
0
        private Expression CreateAggregateFunction(DbFunctionAggregate functionAggregate, string sourceVariableName, Type sourceType, Expression sourceGroup, Type resultType)
        {
            Expression result = null;

            //More the one aggregate argument is not supported
            if (functionAggregate.Arguments.Count > 1)
            {
                throw new InvalidOperationException("DbFunctionAggreate contains more than one argument");
            }


            LambdaExpression aggregateSelector = null;

            // Count does not have selector
            if (functionAggregate.Arguments.Count == 1)
            {
                // Build the selector of the current aggregate

                ParameterExpression aggregateContext = Expression.Parameter(sourceType, sourceVariableName);
                using (this.CreateVariable(aggregateContext, sourceVariableName))
                {
                    aggregateSelector =
                        Expression.Lambda(
                            this.Visit(functionAggregate.Arguments[0]),
                            aggregateContext);
                }
            }

            //Create Expression Call
            switch (functionAggregate.Function.Name)
            {
            case "Count":
                result = queryMethodExpressionBuilder.Count(sourceGroup);
                break;

            case "Max":
                result = queryMethodExpressionBuilder.Max(sourceGroup, aggregateSelector);
                break;

            case "Min":
                result = queryMethodExpressionBuilder.Min(sourceGroup, aggregateSelector);
                break;

            case "Avg":
                result = queryMethodExpressionBuilder.Average(sourceGroup, aggregateSelector);
                break;

            case "Sum":
                result = queryMethodExpressionBuilder.Sum(sourceGroup, aggregateSelector);
                break;

            default:
                throw new NotSupportedException(functionAggregate.Function.Name + " is not a not supported DbFunctionAggregate");
            }

            //Type unify
            if (resultType != null && result.Type != resultType)
            {
                result = Expression.Convert(result, resultType);
            }

            return(result);
        }