Example #1
0
        /// <summary>
        /// Creates an <see cref="ImperativeQueryable{T}"/> from an enumerable expression.
        /// </summary>
        /// <typeparam name="T">The element type.</typeparam>
        /// <param name="expression">The enumerable expression.</param>
        /// <returns>The queryable object.</returns>
        private static ImperativeQueryable <T> Create <T>(EnumerableExpression expression)
        {
            var executor = new QueryExecutor();
            var provider = new ImperativeQueryProvider(executor);

            return(new ImperativeQueryable <T>(provider, expression));
        }
        public void CompileShouldReturnEnumerableOfCompiledChildExpressions()
        {
            var expression = new EnumerableExpression();

            expression.AddChild(new IntegerExpression("2"));
            expression.AddChild(new IntegerExpression("3"));
            var result = expression.Compile();

            Assert.IsInstanceOfType(result.Result, typeof(IEnumerable <object>));
            var resultList = (IEnumerable <object>)result.Result;

            Assert.AreEqual(2d, resultList.ElementAt(0));
            Assert.AreEqual(3d, resultList.ElementAt(1));
        }
Example #3
0
    public virtual SqlExpression?Translate(
        MethodInfo method,
        EnumerableExpression source,
        IReadOnlyList <SqlExpression> arguments,
        IDiagnosticsLogger <DbLoggerCategory.Query> logger)
    {
        if (method.DeclaringType == typeof(Queryable))
        {
            var methodInfo = method.IsGenericMethod
                ? method.GetGenericMethodDefinition()
                : method;
            switch (methodInfo.Name)
            {
            case nameof(Queryable.Average)
                when(QueryableMethods.IsAverageWithoutSelector(methodInfo) ||
                     QueryableMethods.IsAverageWithSelector(methodInfo)) &&
                source.Selector is SqlExpression averageSqlExpression:
                var averageInputType = averageSqlExpression.Type;
                if (averageInputType == typeof(int) ||
                    averageInputType == typeof(long))
                {
                    averageSqlExpression = _sqlExpressionFactory.ApplyDefaultTypeMapping(
                        _sqlExpressionFactory.Convert(averageSqlExpression, typeof(double)));
                }

                return(averageInputType == typeof(float)
                        ? _sqlExpressionFactory.Convert(
                           _sqlExpressionFactory.AggregateFunction(
                               "avg",
                               new[] { averageSqlExpression },
                               nullable: true,
                               argumentsPropagateNullability: FalseArrays[1],
                               source,
                               typeof(double)),
                           averageSqlExpression.Type,
                           averageSqlExpression.TypeMapping)
                        : _sqlExpressionFactory.AggregateFunction(
                           "avg",
                           new[] { averageSqlExpression },
                           nullable: true,
                           argumentsPropagateNullability: FalseArrays[1],
                           source,
                           averageSqlExpression.Type,
                           averageSqlExpression.TypeMapping));

            // PostgreSQL COUNT() always returns bigint, so we need to downcast to int
            case nameof(Queryable.Count)
                when methodInfo == QueryableMethods.CountWithoutPredicate ||
                methodInfo == QueryableMethods.CountWithPredicate:
                var countSqlExpression = (source.Selector as SqlExpression) ?? _sqlExpressionFactory.Fragment("*");
                return(_sqlExpressionFactory.Convert(
                           _sqlExpressionFactory.AggregateFunction(
                               "count",
                               new[] { countSqlExpression },
                               nullable: false,
                               argumentsPropagateNullability: FalseArrays[1],
                               source,
                               typeof(long)),
                           typeof(int), _typeMappingSource.FindMapping(typeof(int))));

            case nameof(Queryable.LongCount)
                when methodInfo == QueryableMethods.LongCountWithoutPredicate ||
                methodInfo == QueryableMethods.LongCountWithPredicate:
                var longCountSqlExpression = (source.Selector as SqlExpression) ?? _sqlExpressionFactory.Fragment("*");
                return(_sqlExpressionFactory.AggregateFunction(
                           "count",
                           new[] { longCountSqlExpression },
                           nullable: false,
                           argumentsPropagateNullability: FalseArrays[1],
                           source,
                           typeof(long)));

            case nameof(Queryable.Max)
                when(methodInfo == QueryableMethods.MaxWithoutSelector ||
                     methodInfo == QueryableMethods.MaxWithSelector) &&
                source.Selector is SqlExpression maxSqlExpression:
                return(_sqlExpressionFactory.AggregateFunction(
                           "max",
                           new[] { maxSqlExpression },
                           nullable: true,
                           argumentsPropagateNullability: FalseArrays[1],
                           source,
                           maxSqlExpression.Type,
                           maxSqlExpression.TypeMapping));

            case nameof(Queryable.Min)
                when(methodInfo == QueryableMethods.MinWithoutSelector ||
                     methodInfo == QueryableMethods.MinWithSelector) &&
                source.Selector is SqlExpression minSqlExpression:
                return(_sqlExpressionFactory.AggregateFunction(
                           "min",
                           new[] { minSqlExpression },
                           nullable: true,
                           argumentsPropagateNullability: FalseArrays[1],
                           source,
                           minSqlExpression.Type,
                           minSqlExpression.TypeMapping));

            // In PostgreSQL SUM() doesn't return the same type as its argument for smallint, int and bigint.
            // Cast to get the same type.
            // http://www.postgresql.org/docs/current/static/functions-aggregate.html
            case nameof(Queryable.Sum)
                when(QueryableMethods.IsSumWithoutSelector(methodInfo) ||
                     QueryableMethods.IsSumWithSelector(methodInfo)) &&
                source.Selector is SqlExpression sumSqlExpression:
                var sumInputType = sumSqlExpression.Type;

                // Note that there is no Sum over short in LINQ
                if (sumInputType == typeof(int))
                {
                    return(_sqlExpressionFactory.Convert(
                               _sqlExpressionFactory.AggregateFunction(
                                   "sum",
                                   new[] { sumSqlExpression },
                                   nullable: true,
                                   argumentsPropagateNullability: FalseArrays[1],
                                   source,
                                   typeof(long)),
                               sumInputType,
                               sumSqlExpression.TypeMapping));
                }

                if (sumInputType == typeof(long))
                {
                    return(_sqlExpressionFactory.Convert(
                               _sqlExpressionFactory.AggregateFunction(
                                   "sum",
                                   new[] { sumSqlExpression },
                                   nullable: true,
                                   argumentsPropagateNullability: FalseArrays[1],
                                   source,
                                   typeof(decimal)),
                               sumInputType,
                               sumSqlExpression.TypeMapping));
                }

                return(_sqlExpressionFactory.AggregateFunction(
                           "sum",
                           new[] { sumSqlExpression },
                           nullable: true,
                           argumentsPropagateNullability: FalseArrays[1],
                           source,
                           sumInputType,
                           sumSqlExpression.TypeMapping));
            }
        }

        return(null);
    }