Esempio n. 1
0
 internal virtual SqlExpression VisitSimpleExpression(SqlSimpleExpression simple) {
     simple.Expression = this.VisitExpression(simple.Expression);
     return simple;
 }
 internal override SqlExpression VisitSimpleExpression(SqlSimpleExpression simple) {
     if (!this.isDebugMode) {
         throw Error.InvalidFormatNode("SIMPLE");
     }
     sb.Append("SIMPLE(");
     base.VisitSimpleExpression(simple);
     sb.Append(")");
     return simple;
 }
 internal override SqlExpression VisitSimpleExpression(SqlSimpleExpression simple) {
     SqlSimpleExpression n = new SqlSimpleExpression(this.VisitExpression(simple.Expression));
     return n;
 }
Esempio n. 4
0
        private SqlNode VisitAggregate(Expression sequence, LambdaExpression lambda, SqlNodeType aggType, Type returnType) {
            // Convert seq.Agg(exp) into 
            //
            // 1) SELECT Agg(exp) FROM seq
            // 2) SELECT Agg1 FROM (SELECT Agg(exp) as Agg1 FROM group-seq GROUP BY ...)
            // 3) SCALAR(SELECT Agg(exp) FROM seq)
            //
            bool isCount = aggType == SqlNodeType.Count || aggType == SqlNodeType.LongCount;

            SqlNode source = this.Visit(sequence);
            SqlSelect select = this.CoerceToSequence(source);
            SqlAlias alias = new SqlAlias(select);
            SqlAliasRef aref = new SqlAliasRef(alias);

            // If the sequence is of the form x.Select(expr).Agg() and the lambda for the aggregate is null,
            // or is a no-op parameter expression (like u=>u), clone the group by selection lambda 
            // expression, and use for the aggregate.
            // Final form should be x.Agg(expr)
            MethodCallExpression mce = sequence as MethodCallExpression;
            if (!outerNode && !isCount && (lambda == null || (lambda.Parameters.Count == 1 && lambda.Parameters[0] == lambda.Body)) &&
                (mce != null) && IsSequenceOperatorCall(mce, "Select") && select.From is SqlAlias) {
                LambdaExpression selectionLambda = GetLambda(mce.Arguments[1]);

                lambda = Expression.Lambda(selectionLambda.Type, selectionLambda.Body, selectionLambda.Parameters);

                alias = (SqlAlias)select.From;
                aref = new SqlAliasRef(alias);
            }

            if (lambda != null && !TypeSystem.IsSimpleType(lambda.Body.Type)) {
                throw Error.CannotAggregateType(lambda.Body.Type);
            }

            //Empty parameter aggregates are not allowed on anonymous types
            //i.e. db.Customers.Select(c=>new{c.Age}).Max() instead it should be
            //     db.Customers.Select(c=>new{c.Age}).Max(c=>c.Age)
            if (select.Selection.SqlType.IsRuntimeOnlyType && !IsGrouping(sequence.Type) && !isCount && lambda == null) {
                throw Error.NonCountAggregateFunctionsAreNotValidOnProjections(aggType);
            }
            if (lambda != null)
                this.map[lambda.Parameters[0]] = aref;

            if (this.outerNode) {
                // If this aggregate is basically the last/outer-most operator of the query
                // 
                // produce SELECT Agg(exp) FROM seq
                //
                SqlExpression exp = (lambda != null) ? this.VisitExpression(lambda.Body) : null;
                SqlExpression where = null;
                if (isCount && exp != null) {
                    where = exp;
                    exp = null;
                }
                else if (exp == null && !isCount) {
                    exp = aref;
                }
                if (exp != null) {
                    // in case this contains another aggregate
                    exp = new SqlSimpleExpression(exp);
                }
                SqlSelect sel = new SqlSelect(
                    this.GetAggregate(aggType, returnType, exp),
                    alias,
                    this.dominatingExpression
                    );
                sel.Where = where;
                sel.OrderingType = SqlOrderingType.Never;
                return sel;
            }
            else if (!isCount || lambda == null) {
                // Look to optimize aggregate by pushing its evaluation down to the select node that has the
                // actual group-by operator.
                //
                // Produce:  SELECT Agg1 FROM (SELECT Agg(exp) as Agg1 FROM seq GROUP BY ...)
                //
                GroupInfo info = this.FindGroupInfo(source);
                if (info != null) {
                    SqlExpression exp = null;
                    if (lambda != null) {
                        // evaluate expression relative to the group-by select node
                        this.map[lambda.Parameters[0]] = (SqlExpression)SqlDuplicator.Copy(info.ElementOnGroupSource);
                        exp = this.VisitExpression(lambda.Body);
                    } else if (!isCount) {
                        // support aggregates w/o an explicit selector specified
                        exp = info.ElementOnGroupSource;
                    }
                    if (exp != null) {
                        // in case this contains another aggregate
                        exp = new SqlSimpleExpression(exp);
                    }
                    SqlExpression agg = this.GetAggregate(aggType, returnType, exp);
                    SqlColumn c = new SqlColumn(agg.ClrType, agg.SqlType, null, null, agg, this.dominatingExpression);
                    info.SelectWithGroup.Row.Columns.Add(c);
                    return new SqlColumnRef(c);
                }
            }
            // Otherwise, if we cannot optimize then fall back to generating a nested aggregate in a correlated sub query
            //
            // SCALAR(SELECT Agg(exp) FROM seq)
            {
                SqlExpression exp = (lambda != null) ? this.VisitExpression(lambda.Body) : null;
                if (exp != null) {
                    // in case this contains another aggregate
                    exp = new SqlSimpleExpression(exp);
                }
                SqlSelect sel = new SqlSelect(
                    this.GetAggregate(aggType, returnType, isCount ? null : (lambda == null) ? aref : exp),
                    alias,
                    this.dominatingExpression
                    );
                sel.Where = isCount ? exp : null;
                return sql.SubSelect(SqlNodeType.ScalarSubSelect, sel);
            }
        }
Esempio n. 5
0
 internal override SqlExpression VisitSimpleExpression(SqlSimpleExpression simple) {
     simple.Expression = this.VisitExpression(simple.Expression);
     if (SimpleExpression.IsSimple(simple.Expression)) {
         return simple.Expression;
     }
     SqlExpression result = this.PushDownExpression(simple.Expression);
     // simple expressions must be scalar (such that they can be formed into a single column declaration)
     System.Diagnostics.Debug.Assert(result is SqlColumnRef);
     return result;
 }
Esempio n. 6
0
 internal virtual SqlExpression VisitSimpleExpression(SqlSimpleExpression simple) {
     simple.Expression = this.VisitExpression(simple.Expression);
     return simple;
 }
        internal override SqlExpression VisitSimpleExpression(SqlSimpleExpression simple)
        {
            SqlSimpleExpression n = new SqlSimpleExpression(this.VisitExpression(simple.Expression));

            return(n);
        }