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()); }
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); }