public void SqlAggregateReplacingTest()
        {
            SqlAggregate a          = SqlDml.Count();
            SqlAggregate aReplacing = SqlDml.Avg(1, true);

            a.ReplaceWith(aReplacing);

            bool passed = false;

            try {
                a.ReplaceWith(1);
            }
            catch {
                passed = true;
            }

            Assert.IsTrue(passed);
            Assert.AreNotEqual(a, aReplacing);
            Assert.AreEqual(a.NodeType, aReplacing.NodeType);
            Assert.AreEqual(a.Distinct, aReplacing.Distinct);
            Assert.AreEqual(a.Expression, aReplacing.Expression);
        }
        /// <summary>
        /// Translates <see cref="AggregateColumn"/> to corresponding <see cref="SqlExpression"/>.
        /// </summary>
        /// <param name="source">The source <see cref="SqlProvider"/>.</param>
        /// <param name="sourceColumns">The source columns.</param>
        /// <param name="aggregateColumn">The aggregate column.</param>
        /// <returns>Aggregate processing result (expression).</returns>
        protected virtual SqlExpression ProcessAggregate(SqlProvider source, List <SqlExpression> sourceColumns, AggregateColumn aggregateColumn)
        {
            switch (aggregateColumn.AggregateType)
            {
            case AggregateType.Avg:
                return(SqlDml.Avg(sourceColumns[aggregateColumn.SourceIndex]));

            case AggregateType.Count:
                return(SqlDml.Count(SqlDml.Asterisk));

            case AggregateType.Max:
                return(SqlDml.Max(sourceColumns[aggregateColumn.SourceIndex]));

            case AggregateType.Min:
                return(SqlDml.Min(sourceColumns[aggregateColumn.SourceIndex]));

            case AggregateType.Sum:
                return(SqlDml.Sum(sourceColumns[aggregateColumn.SourceIndex]));

            default:
                throw new ArgumentException();
            }
        }
        protected override SqlExpression ProcessAggregate(
            SqlProvider source, List <SqlExpression> sourceColumns, AggregateColumn aggregateColumn)
        {
            var aggregateType = aggregateColumn.Type;
            var result        = base.ProcessAggregate(source, sourceColumns, aggregateColumn);

            if (aggregateColumn.AggregateType == AggregateType.Avg)
            {
                var originType = source.Origin.Header.Columns[aggregateColumn.SourceIndex].Type;
                // floats are promoted to doubles, but we need the same type
                if (originType == aggregateType && originType != typeof(float))
                {
                    return(result);
                }
                var sqlType = Driver.MapValueType(aggregateType);
                return(SqlDml.Cast(SqlDml.Avg(SqlDml.Cast(sourceColumns[aggregateColumn.SourceIndex], sqlType)), sqlType));
            }
            // cast to decimal is dangerous, because 'decimal' defaults to integer type
            if (aggregateColumn.AggregateType == AggregateType.Sum && aggregateType != typeof(decimal))
            {
                return(SqlDml.Cast(result, Driver.MapValueType(aggregateType)));
            }
            return(result);
        }
        protected override SqlExpression ProcessAggregate(
            SqlProvider source, List <SqlExpression> sourceColumns, AggregateColumn aggregateColumn)
        {
            var result = base.ProcessAggregate(source, sourceColumns, aggregateColumn);
            var aggregateReturnType   = aggregateColumn.Type;
            var originCalculateColumn = source.Origin.Header.Columns[aggregateColumn.SourceIndex];
            var sqlType = Driver.MapValueType(aggregateReturnType);

            if (aggregateColumn.AggregateType == AggregateType.Min ||
                aggregateColumn.AggregateType == AggregateType.Max ||
                aggregateColumn.AggregateType == AggregateType.Sum)
            {
                if (!IsCalculatedColumn(originCalculateColumn))
                {
                    if (aggregateReturnType == DecimalType)
                    {
                        return(result);
                    }
                    else if (ShouldCastDueType(aggregateReturnType))
                    {
                        return(SqlDml.Cast(result, Driver.MapValueType(aggregateReturnType)));
                    }
                }
                else if (ShouldCastDueType(aggregateReturnType))
                {
                    return(SqlDml.Cast(result, Driver.MapValueType(aggregateReturnType)));
                }
                return(result);
            }
            if (aggregateColumn.AggregateType == AggregateType.Avg)
            {
                //var sqlType = Driver.MapValueType(aggregateReturnType);
                if (aggregateReturnType != originCalculateColumn.Type)
                {
                    return(SqlDml.Cast(SqlDml.Avg(SqlDml.Cast(sourceColumns[aggregateColumn.SourceIndex], sqlType)), sqlType));
                }
                if (!IsCalculatedColumn(originCalculateColumn))
                {
                    if (aggregateReturnType == DecimalType)
                    {
                        return(result);
                    }
                    else if (ShouldCastDueType(aggregateReturnType))
                    {
                        return(SqlDml.Cast(SqlDml.Avg(SqlDml.Cast(sourceColumns[aggregateColumn.SourceIndex], sqlType)), sqlType));
                    }
                    else if (aggregateReturnType != originCalculateColumn.Type)
                    {
                        return(SqlDml.Cast(SqlDml.Avg(SqlDml.Cast(sourceColumns[aggregateColumn.SourceIndex], sqlType)), sqlType));
                    }
                }
                else
                {
                    if (ShouldCastDueType(aggregateReturnType))
                    {
                        return(SqlDml.Cast(SqlDml.Avg(SqlDml.Cast(sourceColumns[aggregateColumn.SourceIndex], sqlType)), sqlType));
                    }
                    else if (aggregateReturnType != originCalculateColumn.Type)
                    {
                        return(SqlDml.Cast(SqlDml.Avg(SqlDml.Cast(sourceColumns[aggregateColumn.SourceIndex], sqlType)), sqlType));
                    }
                    return(result);
                }
            }
            return(result);
        }