Esempio n. 1
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.Method.DeclaringType == typeof(QueryableExtensions) &&
                node.Method.Name == nameof(QueryableExtensions.SelectOnly))
            {
                // use last operator call only
                FieldNames = FieldNames
                             ?? (string[])ExpressionsInternalToolkit.GetConstant(node.Arguments[1]);
            }

            return(base.VisitMethodCall(node));
        }
Esempio n. 2
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.Object is ParameterExpression)
            {
                var arg = node.Arguments.FirstOrDefault()
                          ?? throw new ArgumentException("Invalid argument.");
                var memberName = ExpressionsInternalToolkit.GetConstant(arg);

                _sb.Append(memberName);
            }

            return(node);
        }
Esempio n. 3
0
        protected override Expression VisitConstant(ConstantExpression node)
        {
            var value     = ExpressionsInternalToolkit.GetConstant(node);
            var valueType = value?.GetType();

            var isCollection = (valueType?.GetInterfaces()
                                .Any(x =>
                                     (
                                         x == typeof(ICollection) ||
                                         (
                                             x.IsGenericType &&
                                             x.GetGenericTypeDefinition() == typeof(ICollection <>)
                                         )
                                     )
                                     ) ?? false);

            if (isCollection)
            {
                var inSb = new StringBuilder();
                inSb.Append("(");

                var valuesCollection = value as IEnumerable;
                var enumerator       = valuesCollection.GetEnumerator();

                var hasItems = enumerator.MoveNext();
                while (hasItems)
                {
                    var pName = _queryParamsStore.Append(enumerator.Current);
                    inSb.Append(pName);

                    var isLast = !enumerator.MoveNext();
                    if (isLast)
                    {
                        break;
                    }

                    inSb.Append(", ");
                }

                inSb.Append(")");

                _sb.Append(inSb);
            }
            else
            {
                var paramName = _queryParamsStore.Append(value);
                _sb.Append(paramName);
            }

            return(node);
        }
Esempio n. 4
0
        protected override Expression VisitBinary(BinaryExpression node)
        {
            switch (node.NodeType)
            {
            case ExpressionType.Or:
            case ExpressionType.OrElse:
                _sb.Append("(");
                Visit(node.Left);
                _sb.Append(" OR ");
                Visit(node.Right);
                _sb.Append(")");
                break;

            case ExpressionType.And:
            case ExpressionType.AndAlso:
                _sb.Append("(");
                Visit(node.Left);
                _sb.Append(" AND ");
                Visit(node.Right);
                _sb.Append(")");
                break;

            case ExpressionType.GreaterThan:
                Visit(node.Left);
                _sb.Append(" > ");
                Visit(node.Right);
                break;

            case ExpressionType.GreaterThanOrEqual:
                Visit(node.Left);
                _sb.Append(" >= ");
                Visit(node.Right);
                break;

            case ExpressionType.LessThan:
                Visit(node.Left);
                _sb.Append(" < ");
                Visit(node.Right);
                break;

            case ExpressionType.LessThanOrEqual:
                Visit(node.Left);
                _sb.Append(" <= ");
                Visit(node.Right);
                break;

            case ExpressionType.Equal:
            {
                if (ExpressionsInternalToolkit.TryGetConstant(node.Left, out var resValueLeft) &&
                    resValueLeft == null)
                {
                    Visit(node.Right);
                    if (_notUnary)
                    {
                        _sb.Append(" IS NULL");
                    }
                }
                else if (ExpressionsInternalToolkit.TryGetConstant(node.Right, out var resValueRight) &&
                         resValueRight == null)
                {
                    Visit(node.Left);
                    _sb.Append(" IS NULL");
                }
                else
                {
                    Visit(node.Left);
                    _sb.Append(" = ");
                    Visit(node.Right);
                }
            }
            break;

            case ExpressionType.NotEqual:
            {
                object resValueLeft;
                if (ExpressionsInternalToolkit.TryGetConstant(node.Left, out resValueLeft) &&
                    resValueLeft == null)
                {
                    Visit(node.Right);
                    if (_notUnary)
                    {
                        _sb.Append(" IS NOT NULL");
                    }
                }
                else if (ExpressionsInternalToolkit.TryGetConstant(node.Right, out var resValueRight) &&
                         resValueRight == null)
                {
                    Visit(node.Left);
                    _sb.Append(" IS NOT NULL");
                }
                else
                {
                    Visit(node.Left);
                    _sb.Append(" <> ");
                    Visit(node.Right);
                }
            }
            break;
            }

            return(node);
        }
Esempio n. 5
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            // it is a Enumerable.Contains extension
            if (node.Method.DeclaringType == typeof(Enumerable) &&
                node.Method.Name == nameof(Enumerable.Contains))
            {
                if (node.Arguments.Count != 2)
                {
                    throw new InvalidOperationException("Constains call should be with 2 parameter.");
                }

                Visit(node.Arguments[1]);
                _sb.Append(_notUnary ? " NOT IN " : " IN ");
                var collection = ExpressionsInternalToolkit.GetConstant(node.Arguments[0]);
                Visit(Expression.Constant(collection));

                return(node);
            }

            // it is row indexer
            if (node.Method.DeclaringType == typeof(ShadowRow) && node.Method.Name == "get_Item")
            {
                if (node.Arguments.Count != 1)
                {
                    throw new InvalidOperationException("Only 1 indexer are supported.");
                }

                var member = ExpressionsInternalToolkit.GetConstant(node.Arguments[0]);
                _sb.Append(" ");
                _sb.Append(member);
                _sb.Append(" ");

                return(node);
            }

            // it is a string manipulation methods
            if (node.Method.DeclaringType == typeof(string))
            {
                Visit(node.Object);

                if (node.Arguments.Count() != 1)
                {
                    throw new InvalidOperationException("Argument count is invalid.");
                }

                var value = ExpressionsInternalToolkit.GetConstant(node.Arguments[0]);

                if (value?.GetType() != typeof(string))
                {
                    throw new InvalidOperationException("Invalid value type.");
                }

                if (_notUnary)
                {
                    _sb.Append(" NOT");
                }

                if (node.Method.Name == nameof(String.Contains))
                {
                    var paramName = _queryParamsStore.Append($"%{value}%");
                    _sb.Append($" LIKE {paramName}");
                }
                else if (node.Method.Name == nameof(String.EndsWith))
                {
                    var paramName = _queryParamsStore.Append($"%{value}");
                    _sb.Append($" LIKE {paramName}");
                }
                else if (node.Method.Name == nameof(String.StartsWith))
                {
                    var paramName = _queryParamsStore.Append($"{value}%");
                    _sb.Append($" LIKE {paramName}");
                }
                else
                {
                    throw new Exception();
                }

                return(node);
            }

            if (node.Method.Name == nameof(Boolean.Equals))
            {
                Visit(node.Object);

                var value = ExpressionsInternalToolkit.GetConstant(node.Arguments[0]);

                if (value?.GetType() == null)
                {
                    _sb.Append(_notUnary ? " IS NOT NULL" : " IS NULL ");
                }
                else if (value.GetType() == typeof(bool))
                {
                    var boolSqlValue = (bool)value ? 1 : 0;

                    _sb.Append(_notUnary ? " != " : " = ");
                    _sb.Append(_queryParamsStore.Append(boolSqlValue));
                }
                else
                {
                    _sb.Append(_notUnary ? " != " : " = ");
                    _sb.Append(_queryParamsStore.Append(value));
                }
            }

            return(node);
        }
Esempio n. 6
0
        /// <summary>
        /// Executes the specified query.
        /// </summary>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="expression">The expression.</param>
        /// <returns></returns>
        public override TResult Execute <TResult>(Expression expression)
        {
            // it is a Count aggregation call
            if (ExpressionsInternalToolkit.IsCountQueryableCall(expression))
            {
                using (var cmd = PrepareSqlAndParams(expression))
                {
                    var val = cmd.ExecuteScalar();

                    var skipCount            = ExpressionsInternalToolkit.GetSkipCount(expression);
                    var countViaSkipAdjusted = Math.Max((int)val - skipCount, 0);
                    if (ExpressionsInternalToolkit.TakeIsUsed(expression))
                    {
                        var takeCount            = ExpressionsInternalToolkit.GetTakeCount(expression);
                        var countViaTakeAdjusted = Math.Min(countViaSkipAdjusted, takeCount);
                        return((TResult)(object)countViaTakeAdjusted);
                    }

                    return((TResult)(object)Math.Max((int)val - skipCount, 0));
                }
            }

            // otherwise is applied a Query
            using (var cmd = PrepareSqlAndParams(expression))
            {
                if (ExpressionsInternalToolkit.IsListAsyncCall(expression))
                {
                    var ct = ExpressionsInternalToolkit.GetCancellationTokenForToList(expression);
                    return((TResult)(object)cmd.ReadAllAsync(ct));
                }
                else
                {
                    var collection = new List <ShadowRow>();
                    using (var enumerator = GetEnumerator <ShadowRow>(expression))
                    {
                        while (enumerator.MoveNext())
                        {
                            collection.Add(enumerator.Current);
                        }
                    }

                    var firstAggregationCalled          = ExpressionsInternalToolkit.IsFirstQueryableCall(expression);
                    var firstOrDefaultAggregationCalled = ExpressionsInternalToolkit.IsFirstOrDefaultQueryableCall(expression);
                    if (firstAggregationCalled || firstOrDefaultAggregationCalled)
                    {
                        if (collection.Count > 1)
                        {
                            throw new InvalidOperationException("Unexpected collection length.");
                        }

                        if (firstAggregationCalled)
                        {
                            var first = collection.FirstOrDefault();
                            if (first == null)
                            {
                                throw new InvalidOperationException("Data not found.");
                            }
                            return((TResult)(object)first);
                        }

                        if (firstOrDefaultAggregationCalled)
                        {
                            return((TResult)(object)collection.FirstOrDefault());
                        }
                    }

                    return((TResult)(object)collection);
                }
            }
        }
        public override string TranslateToSql(Expression expr)
        {
            var externalPredicates = new List <Expression <Func <ShadowRow, bool> > >();

            var itIsCount = false;
            var itIsFirst = false;
            var skipUsed  = ExpressionsInternalToolkit.SkipIsUsed(expr);
            var takeUsed  = ExpressionsInternalToolkit.TakeIsUsed(expr);

#pragma warning disable CS0642

            if (itIsCount = ExpressionsInternalToolkit.IsCountQueryableCall(expr))
            {
                ;
            }
            else if (itIsFirst = ExpressionsInternalToolkit.IsFirstQueryableCall(expr) ||
                                 ExpressionsInternalToolkit.IsFirstOrDefaultQueryableCall(expr))
            {
                ;
            }
#pragma warning restore CS0642


            var selectOnlyTranslator = new SelectOnlyTranslator();

            if (itIsCount)
            {
                _sb.Append("SELECT COUNT (");
                _sb.Append(selectOnlyTranslator.TranslateToSql(expr));
                _sb.Append(") FROM ");
                var mCall = expr as MethodCallExpression;
                if (mCall.Arguments.Count == 2)
                {
                    var lambda      = ExpressionsInternalToolkit.SkipUnary(mCall.Arguments[1]) as LambdaExpression; // skip Quote
                    var lambdaTyped =
                        Expression.Lambda <Func <ShadowRow, bool> >(lambda.Body, ExpressionBuilders.DefaultRowParameter);
                    externalPredicates.Add(lambdaTyped);
                }
            }
            else if (itIsFirst && !skipUsed)
            {
                _sb.Append("SELECT TOP 1 ");
                _sb.Append(selectOnlyTranslator.TranslateToSql(expr));
                _sb.Append(" FROM ");
                var mCall = expr as MethodCallExpression;
                if (mCall.Arguments.Count == 2)
                {
                    var lambda      = ExpressionsInternalToolkit.SkipUnary(mCall.Arguments[1]) as LambdaExpression; // skip Quote
                    var lambdaTyped =
                        Expression.Lambda <Func <ShadowRow, bool> >(lambda.Body, ExpressionBuilders.DefaultRowParameter);
                    externalPredicates.Add(lambdaTyped);
                }
            }
            else
            {
                _sb.Append("SELECT ");
                _sb.Append(selectOnlyTranslator.TranslateToSql(expr));
                _sb.Append(" FROM ");
            }

            _sb.Append(_sourceName);

            var whereLine = new WhereQueryTranslator(_queryParamsStore,
                                                     externalPredicates.Any() ? externalPredicates.ToArray() : null)
                            .TranslateToSql(expr);
            if (!string.IsNullOrWhiteSpace(whereLine))
            {
                _sb.Append(" WHERE ");
                _sb.Append(whereLine);
            }

            if (!itIsCount)
            {
                var orderByLine = new OrderByQueryTranslator(_queryParamsStore)
                                  .TranslateToSql(expr);
                var orderByUsed = !string.IsNullOrWhiteSpace(orderByLine);
                if (orderByUsed)
                {
                    _sb.Append(" ORDER BY ");
                    _sb.Append(orderByLine);
                }

                if (skipUsed)
                {
                    if (!orderByUsed)
                    {
                        _sb.Append(" ORDER BY (SELECT NULL)");
                    }

                    _sb.Append(" OFFSET ");
                    var skipCount = ExpressionsInternalToolkit.GetSkipCount(expr);
                    _sb.Append(_queryParamsStore.Append(skipCount));
                    _sb.Append(" ROWS");
                }

                if (takeUsed)
                {
                    if (!skipUsed)
                    {
                        if (!orderByUsed)
                        {
                            _sb.Append(" ORDER BY (SELECT NULL)");
                        }

                        _sb.Append(" OFFSET 0 ROWS");
                    }

                    _sb.Append(" FETCH NEXT ");
                    var takeCount = ExpressionsInternalToolkit.GetTakeCount(expr);
                    _sb.Append(_queryParamsStore.Append(takeCount));
                    _sb.Append(" ROW ONLY");
                }
            }

            if (itIsFirst && skipUsed)
            {
                _sb.Append(" FETCH NEXT 1 ROW ONLY");
            }

            return(_sb.ToString());
        }