Пример #1
0
            private MethodCallExpression ParseAggregate(ParameterExpression it, Expression query, out bool isSubQuery)
            {
                var        isGroupQuery = E.IsGroupQuery(query);
                Expression source       = isGroupQuery ? it : query;

                Debug.Assert(this.IsAggregateFunction(Token.Function));
                var errorToken = Token;
                var function   = Token.Function;

                NextToken();
                var args       = this.ParseArgumentList();
                var methodName = function == Function.BigCount ? "LongCount" : function.ToString();

                if (function == Function.Count || function == Function.BigCount)
                {
                    if (args.Length == 0)
                    {
                        //===================================================================
                        // 解释如下例句:
                        // select value count() from products as p
                        //===================================================================

                        var t   = E.ElementType(source);
                        var exp = E.GenerateMethodCall(function, new[] { source }, new[] { t });
                        isSubQuery = false;
                        return(exp);
                    }

                    if (args.Length == 1)
                    {
                        if (typeof(IEnumerable).IsAssignableFrom(args[0].Type) && args[0].Type != typeof(string))
                        {
                            //===================================================================
                            // 解释如下例句:
                            // 1、select value count(c.Products) from category as c
                            // 2、select c.CategoryId, count(select p from c.Products as p) as ProductsCount from category as c
                            // 注:只解释 count(c.Products),count(select p from c.Products as p) 部份
                            //===================================================================

                            var t   = E.ElementType(args[0]);
                            var exp = E.GenerateMethodCall(function, new[] { args[0] }, new[] { t });

                            isSubQuery = true;
                            return(exp);
                        }
                        else
                        {
                            if (isGroupQuery)
                            {
                                //===================================================================
                                // 解释如下例句:
                                // 2、select value count(p.CategoryId) from products as p group by p.CategoryId
                                //===================================================================

                                Debug.Assert(args[0].NodeType == ExpressionType.MemberAccess);

                                var m = (MemberExpression)args[0];
                                var t = ExpressionUtility.ElementType(it);

                                var exp = ExpressionUtility.GenerateMethodCall(function, new[] { it }, new Type[] { t });
                                isSubQuery = true;
                                return(exp);
                            }
                            else
                            {
                                //===================================================================
                                // 解释如下例句:
                                // 1、select value count(p.CategoryId) from products as p
                                //===================================================================

                                Debug.Assert(args[0].NodeType == ExpressionType.MemberAccess);

                                var m = (MemberExpression)args[0];
                                var t = ExpressionUtility.ElementType(query);

                                var exp = ExpressionUtility.GenerateMethodCall(function, new[] { query }, new Type[] { t });
                                isSubQuery = false;
                                return(exp);
                            }
                        }
                    }

                    throw Error.NoCanonicalAggrFunctionOverloadMatch(errorToken, methodName, args.Select(o => o.Type));
                }

                if (function == Function.Min || function == Function.Max)
                {
                    if (args.Length == 1)
                    {
                        if (typeof(IEnumerable).IsAssignableFrom(args[0].Type) && args[0].Type != typeof(string))
                        {
                            //=====================================================================
                            // 解释如下例句:
                            // select min(select value p.UnitPrice from c.Products as p) from Categories as c
                            // 注:只解释 min(select value p.UnitPrice from c.Products as p)
                            //=====================================================================
                            var t   = E.ElementType(args[0]);
                            var exp = E.GenerateMethodCall(function, new[] { args[0] }, new[] { t });
                            isSubQuery = true;
                            return(exp);
                        }
                        else
                        {
                            if (isGroupQuery)
                            {
                                //===================================================================
                                // 解释如下例句:
                                // select value min(p.UnitPrice) from Products as p group by p.CategoryId
                                // 注:只解释 min(p.UnitPrice) 部份
                                //===================================================================

                                var t = E.ElementType(source);
                                var p = E.FindParameter(args[0]);
                                Debug.Assert(p != null);
                                var l = Expression.Lambda(args[0], p);

                                var exp = E.GenerateMethodCall(function, new[] { source, l }, new[] { t, args[0].Type });
                                isSubQuery = true;
                                return(exp);
                            }
                            else
                            {
                                //===================================================================
                                // 解释如下例句:
                                // select value min(p.UnitPrice) from Products as p
                                //===================================================================

                                var t = ExpressionUtility.ElementType(source);
                                var p = E.FindParameter(args[0]);
                                Debug.Assert(p != null);
                                var l = Expression.Lambda(args[0], p);

                                var exp = E.GenerateMethodCall(function, new[] { source, l }, new[] { t, args[0].Type });

                                isSubQuery = false;
                                return(exp);
                            }
                        }
                    }

                    throw Error.NoCanonicalAggrFunctionOverloadMatch(errorToken, methodName, args.Select(o => o.Type));
                }

                if (function == Function.Sum || function == Function.Average)
                {
                    if (args.Length == 1)
                    {
                        if (typeof(IEnumerable).IsAssignableFrom(args[0].Type) && args[0].Type != typeof(string))
                        {
                            //===================================================================
                            // 解释如下例句:
                            // select sum(select value p.UnitPrice from c.Products as p) from Categories as c
                            // 注:只解释 sum(select value p.UnitPrice from c.Products as p)
                            //===================================================================

                            var t = E.ElementType(args[0]);
                            Debug.Assert(t.IsValueType);

                            var exp = E.GenerateMethodCall(function, new[] { args[0] }, new Type[0]);
                            isSubQuery = true;
                            return(exp);
                        }
                        else
                        {
                            if (isGroupQuery)
                            {
                                //===================================================================
                                // 解释如下例句:
                                // select key, sum(o.Quantity) as SumQuantity
                                // from OrderDetails as o group by o.Product as key
                                // 注:只解释 sum(o.Quantity)
                                //===================================================================

                                var t = E.ElementType(source);
                                var p = E.FindParameter(args[0]);
                                Debug.Assert(p != null);

                                E.CheckAndPromoteArgument(typeof(IEnumerableSignatures), function, ref args[0], errorToken);
                                var l   = Expression.Lambda(args[0], p);
                                var exp = E.GenerateMethodCall(function, new[] { source, l }, new[] { t });

                                isSubQuery = true;
                                return(exp);
                            }
                            else
                            {
                                //===================================================================
                                // 解释如下例句:
                                // select sum(o.UnitPrice) from OrderDetails as o
                                //===================================================================

                                var t = E.ElementType(source);
                                var p = E.FindParameter(args[0]);
                                Debug.Assert(p != null);

                                E.CheckAndPromoteArgument(typeof(IEnumerableSignatures), function, ref args[0], errorToken);
                                var l   = Expression.Lambda(args[0], p);
                                var exp = E.GenerateMethodCall(function, new[] { source, l }, new[] { t });

                                isSubQuery = false;
                                return(exp);
                            }
                        }
                    }

                    throw Error.NoCanonicalAggrFunctionOverloadMatch(errorToken, methodName, args.Select(o => o.Type));
                }

                throw new NotSupportedException(function.ToString());
            }
Пример #2
0
            private Expression ParseSelection()
            {
                var query = this.source;

                ParameterExpression p = it;

                Expression expr;

                switch (Token.Keyword)
                {
                case Keyword.Value:
                    bool isGroupQuery = ExpressionUtility.IsGroupQuery(query);
                    NextToken();


                    if (IsAggregateFunction(Token.Function))
                    {
                        bool isSubQuery;
                        var  agg = this.ParseAggregate(p, query, out isSubQuery);
                        expr = agg;
                        if (!isSubQuery)
                        {
                            return(agg);
                        }
                    }
                    else
                    {
                        expr = ((IParser)this).ParseExpression();
                        if (expr == null)
                        {
                            expr = ParseSelectionIdentifier();
                        }

                        if (expr == null)
                        {
                            return(null);
                        }

                        if (isGroupQuery && expr.NodeType == ExpressionType.MemberAccess)
                        {
                            expr = this.parser.TranslateInnerGroupKey(expr, Token);
                        }

                        //==========================================================
                        // 例句:
                        // select value row(p.CategoryId, p.UnitPrice) from Products as p
                        // group by p.CategoryId, p.UnitPrice
                        // having max(p.UnitPrice) > 1000
                        // ---------------------------------------------------------
                        // 如果解釋生成的 Expression 已經是一個非字符串對象,進接返回即可
                        if (typeof(IQueryable).IsAssignableFrom(expr.Type))
                        {
                            var t = ExpressionUtility.ElementType(expr);
                            if (!t.IsValueType && t != typeof(string))
                            {
                                return(expr);
                            }
                        }
                        //==========================================================
                    }

                    Debug.Assert(p != null);

                    var elementType = ExpressionUtility.ElementType(query);
                    var lambda      = Expression.Lambda(expr, new[] { p });

                    query = E.GenerateSelect(new[] { query, lambda }, new[] { elementType, lambda.Body.Type });

                    if (this.Token.Identity != TokenId.End && Token.Keyword == Keyword.None)
                    {
                        throw Error.InvalidSelectValueList(Token);
                    }

                    break;

                case Keyword.Row:
                case Keyword.None:
                    query = this.ParseRow(p, query);
                    break;

                default:
                    throw Error.GenericSyntaxError(Token);
                }

                return(query);
            }