Exemple #1
0
        public override SqlStatement OptimizeStatement(SqlStatement statement, bool inlineParameters, bool withParameters, bool remoteContext)
        {
            statement = base.OptimizeStatement(statement, inlineParameters, withParameters, remoteContext);

            if (remoteContext)
            {
                return(statement);
            }

            // SAP HANA parameters are not just order-dependent but also name-dependent, so we cannot use
            // same parameter name
            var parameters = new HashSet <SqlParameter>(Utils.ObjectReferenceEqualityComparer <SqlParameter> .Default);

            statement.Parameters.Clear();

            // duplicate parameters
            statement = ConvertVisitor.ConvertAll(statement, (visitor, e) =>
            {
                if (e is ISqlExpression expr)
                {
                    if (HasParameters(expr))
                    {
                        // prevent skipping of duplicate elements
                        visitor.VisitedElements[e] = null;
                    }

                    if (e is SqlParameter p && !parameters.Add(p))
                    {
                        p = p.Clone();
                        parameters.Add(p);
                        statement.IsParameterDependent = true;
                        return(p);
                    }
                }
Exemple #2
0
            public void Build(Sql.ISqExtensionBuilder builder)
            {
                var expr    = builder.Arguments[0];
                var newExpr = expr.Transform(e =>
                {
                    if (e.NodeType == ExpressionType.Convert || e.NodeType == ExpressionType.ConvertChecked)
                    {
                        var unary  = (UnaryExpression)e;
                        var method = _method.MakeGenericMethod(unary.Operand.Type, unary.Type);
                        return(Expression.Call(null, method, unary.Operand));
                    }
                    return(e);
                });

                if (newExpr == expr)
                {
                    builder.ResultExpression = builder.GetExpression(0);
                    return;
                }

                var sqlExpr = builder.ConvertExpressionToSql(newExpr);

                sqlExpr = ConvertVisitor.Convert(sqlExpr, (v, e) =>
                {
                    if (e is SqlFunction func && func.Name == "$Convert_Remover$")
                    {
                        return(func.Parameters[0]);
                    }
                    return(e);
                });
Exemple #3
0
        public override ISqlPredicate ConvertPredicateImpl(ISqlPredicate predicate, ConvertVisitor <RunOptimizationContext> visitor)
        {
            if (predicate is SqlPredicate.ExprExpr exprExpr)
            {
                var leftType  = QueryHelper.GetDbDataType(exprExpr.Expr1);
                var rightType = QueryHelper.GetDbDataType(exprExpr.Expr2);

                if ((IsDateTime(leftType) || IsDateTime(rightType)) &&
                    !(exprExpr.Expr1.TryEvaluateExpression(visitor.Context.OptimizationContext.Context, out var value1) && value1 == null ||
                      exprExpr.Expr2.TryEvaluateExpression(visitor.Context.OptimizationContext.Context, out var value2) && value2 == null))
                {
                    if (!(exprExpr.Expr1 is SqlFunction func1 && (func1.Name == "$Convert$" || func1.Name == "DateTime")))
                    {
                        var left = new SqlFunction(leftType.SystemType, "$Convert$", SqlDataType.GetDataType(leftType.SystemType),
                                                   new SqlDataType(leftType), exprExpr.Expr1);
                        exprExpr = new SqlPredicate.ExprExpr(left, exprExpr.Operator, exprExpr.Expr2, null);
                    }

                    if (!(exprExpr.Expr2 is SqlFunction func2 && (func2.Name == "$Convert$" || func2.Name == "DateTime")))
                    {
                        var right = new SqlFunction(rightType.SystemType, "$Convert$", new SqlDataType(rightType),
                                                    new SqlDataType(rightType), exprExpr.Expr2);
                        exprExpr = new SqlPredicate.ExprExpr(exprExpr.Expr1, exprExpr.Operator, right, null);
                    }

                    predicate = exprExpr;
                }
            }

            predicate = base.ConvertPredicateImpl(predicate, visitor);
            return(predicate);
        }
Exemple #4
0
            protected override SqlStatement ProcessQuery(SqlStatement statement)
            {
                if (statement.IsInsert() && statement.RequireInsertClause().Into !.Name == "Parent")
                {
                    var expr =
                        new QueryVisitor().Find(statement.RequireInsertClause(), e =>
                    {
                        if (e.ElementType == QueryElementType.SetExpression)
                        {
                            var se = (SqlSetExpression)e;
                            return(((SqlField)se.Column).Name == "ParentID");
                        }

                        return(false);
                    }) as SqlSetExpression;

                    if (expr != null)
                    {
                        var value = ConvertTo <int> .From(((IValueContainer)expr.Expression !).Value);

                        if (value == 555)
                        {
                            var tableName = "Parent1";
                            var dic       = new Dictionary <IQueryElement, IQueryElement>();

                            statement = ConvertVisitor.Convert(statement, (v, e) =>
                            {
                                if (e.ElementType == QueryElementType.SqlTable)
                                {
                                    var oldTable = (SqlTable)e;

                                    if (oldTable.Name == "Parent")
                                    {
                                        var newTable = new SqlTable(oldTable)
                                        {
                                            Name = tableName, PhysicalName = tableName
                                        };

                                        foreach (var field in oldTable.Fields.Values)
                                        {
                                            dic.Add(field, newTable.Fields[field.Name]);
                                        }

                                        return(newTable);
                                    }
                                }

                                IQueryElement ex;
                                return(dic.TryGetValue(e, out ex) ? ex : e);
                            });
                        }
                    }

                    return(statement);
                }

                return(statement);
            }
Exemple #5
0
 /// <summary>
 /// Adds an ORDER BY clause to queries using OFFSET/FETCH, if none exists
 /// </summary>
 protected SqlStatement AddOrderByForSkip(SqlStatement statement)
 {
     ConvertVisitor.Convert(statement, (visitor, element) => {
         if (element is SelectQuery query && query.Select.SkipValue != null && query.OrderBy.IsEmpty)
         {
             query.OrderBy.ExprAsc(new SqlValue(typeof(int), 1));
         }
         return(element);
     });
Exemple #6
0
        private static SqlStatement NormalizeParameters(SqlStatement statement, List <ParameterAccessor> accessors)
        {
            // remember accessor indexes
            new QueryVisitor().VisitAll(statement, e =>
            {
                if (e.ElementType == QueryElementType.SqlParameter)
                {
                    var parameter = (SqlParameter)e;
                    if (parameter.IsQueryParameter)
                    {
                        var idx = accessors.FindIndex(a => object.ReferenceEquals(a.SqlParameter, parameter));
                        parameter.AccessorId = idx >= 0 ? (int?)idx : null;
                    }
                }
            });

            // correct expressions, we have to put expressions in correct order and duplicate them if they are reused
            statement = NormalizeExpressions(statement);

            var found             = new HashSet <ISqlExpression>();
            var columnExpressions = new HashSet <ISqlExpression>();

            statement = ConvertVisitor.Convert(statement, (visitor, e) =>
            {
                if (e.ElementType == QueryElementType.SqlParameter)
                {
                    var parameter = (SqlParameter)e;
                    if (parameter.IsQueryParameter)
                    {
                        var parentElement = visitor.ParentElement;
                        if (parentElement is SqlColumn)
                        {
                            columnExpressions.Add(parameter);
                        }
                        else if (parentElement !.ElementType == QueryElementType.SetExpression)
                        {
                            // consider that expression is already processed by SelectQuery and we do not need duplication.
                            // It is specific how InsertStatement is built
                            if (columnExpressions.Contains(parameter))
                            {
                                return(parameter);
                            }
                        }

                        if (!found.Add(parameter))
                        {
                            var newParameter =
                                (SqlParameter)parameter.Clone(new Dictionary <ICloneableElement, ICloneableElement>(),
                                                              c => true);
                            return(newParameter);
                        }

                        // notify visitor to process this parameter always
                        visitor.VisitedElements.Add(parameter, null);
                    }
Exemple #7
0
        private static T NormalizeExpressions <T>(T expression)
            where T : class, IQueryElement
        {
            var result = ConvertVisitor.Convert(expression, (visitor, e) =>
            {
                if (e.ElementType == QueryElementType.SqlExpression)
                {
                    var expr = (SqlExpression)e;

                    // we interested in modifying only expressions which have parameters
                    if (HasQueryParameters(expr))
                    {
                        if (expr.Expr.IsNullOrEmpty() || expr.Parameters.Length == 0)
                        {
                            return(expr);
                        }

                        var newExpressions = new List <ISqlExpression>();

                        var newExpr = QueryHelper.TransformExpressionIndexes(expr.Expr,
                                                                             idx =>
                        {
                            if (idx >= 0 && idx < expr.Parameters.Length)
                            {
                                var paramExpr  = expr.Parameters[idx];
                                var normalized = paramExpr;
                                var newIndex   = newExpressions.Count;

                                if (newExpressions.Contains(normalized) && HasQueryParameters(normalized))
                                {
                                    normalized = (ISqlExpression)normalized.Clone(
                                        new Dictionary <ICloneableElement, ICloneableElement>(),
                                        c => true);
                                }

                                newExpressions.Add(normalized);
                                return(newIndex);
                            }
                            return(idx);
                        });

                        // always create copy
                        var newExpression = new SqlExpression(expr.SystemType, newExpr, expr.Precedence, expr.IsAggregate, expr.IsPure, newExpressions.ToArray());
                        // force re-entrance
                        visitor.VisitedElements[expr] = null;
                        return(newExpression);
                    }
                }
                return(e);
            });

            return(result);
        }
        public override ISqlExpression ConvertExpressionImpl(ISqlExpression expr, ConvertVisitor visitor,
                                                             EvaluationContext context)
        {
            expr = base.ConvertExpressionImpl(expr, visitor, context);

            if (expr is SqlFunction func)
            {
                if (func.Name == "Convert")
                {
                    var ftype = func.SystemType.ToUnderlying();

                    if (ftype == typeof(bool))
                    {
                        var ex = AlternativeConvertToBoolean(func, 1);
                        if (ex != null)
                        {
                            return(ex);
                        }
                    }
                    return(new SqlExpression(func.SystemType, "Cast({0} as {1})", Precedence.Primary, FloorBeforeConvert(func), func.Parameters[0]));
                }
            }
            else if (expr is SqlBinaryExpression be)
            {
                switch (be.Operation)
                {
                case "%":
                    return(new SqlFunction(be.SystemType, "MOD", be.Expr1, be.Expr2));

                case "&":
                    return(new SqlFunction(be.SystemType, "BITAND", be.Expr1, be.Expr2));

                case "|":
                    return(Sub(
                               Add(be.Expr1, be.Expr2, be.SystemType),
                               new SqlFunction(be.SystemType, "BITAND", be.Expr1, be.Expr2),
                               be.SystemType));

                case "^":                         // (a + b) - BITAND(a, b) * 2
                    return(Sub(
                               Add(be.Expr1, be.Expr2, be.SystemType),
                               Mul(new SqlFunction(be.SystemType, "BITAND", be.Expr1, be.Expr2), 2),
                               be.SystemType));

                case "+":
                    return(be.SystemType == typeof(string) ?
                           new SqlBinaryExpression(be.SystemType, be.Expr1, "||", be.Expr2, be.Precedence) :
                           expr);
                }
            }

            return(expr);
        }
    public static Expression <Func <TTo, bool> > Converter <TFrom, TTo>(this Expression <Func <TFrom, bool> > expression, TTo type) where TTo : TFrom
    {
        // here we get the expression parameter the x from (x) => ....
        var parameterName = expression.Parameters.First().Name;
        // create the new parameter from the correct type
        ParameterExpression parameter = Expression.Parameter(typeof(TTo), parameterName);
        // asigne to allow the visit from or visitor
        Expression body = new ConvertVisitor(parameter).Visit(expression.Body);

        // recreate the expression
        return(Expression.Lambda <Func <TTo, bool> >(body, parameter));
    }
Exemple #10
0
        public override ISqlPredicate ConvertSearchStringPredicate(MappingSchema mappingSchema, SqlPredicate.SearchString predicate,
                                                                   ConvertVisitor visitor,
                                                                   OptimizationContext optimizationContext)
        {
            if (!predicate.IgnoreCase)
            {
                return(ConvertSearchStringPredicateViaLike(mappingSchema, predicate, visitor, optimizationContext));
            }

            ISqlExpression expr;

            switch (predicate.Kind)
            {
            case SqlPredicate.SearchString.SearchKind.EndsWith:
            {
                predicate = new SqlPredicate.SearchString(
                    new SqlFunction(typeof(string), "$ToLower$", predicate.Expr1),
                    predicate.IsNot,
                    new SqlFunction(typeof(string), "$ToLower$", predicate.Expr2), predicate.Kind,
                    predicate.IgnoreCase);

                return(ConvertSearchStringPredicateViaLike(mappingSchema, predicate, visitor, optimizationContext));
            }

            case SqlPredicate.SearchString.SearchKind.StartsWith:
            {
                expr = new SqlExpression(typeof(bool),
                                         predicate.IsNot ? "{0} NOT STARTING WITH {1}" : "{0} STARTING WITH {1}",
                                         Precedence.Comparison,
                                         TryConvertToValue(predicate.Expr1, optimizationContext.Context), TryConvertToValue(predicate.Expr2, optimizationContext.Context))
                {
                    CanBeNull = false
                };
                break;
            }

            case SqlPredicate.SearchString.SearchKind.Contains:
                expr = new SqlExpression(typeof(bool),
                                         predicate.IsNot ? "{0} NOT CONTAINING {1}" : "{0} CONTAINING {1}",
                                         Precedence.Comparison,
                                         TryConvertToValue(predicate.Expr1, optimizationContext.Context), TryConvertToValue(predicate.Expr2, optimizationContext.Context))
                {
                    CanBeNull = false
                };
                break;

            default:
                throw new InvalidOperationException($"Unexpected predicate: {predicate.Kind}");
            }

            return(new SqlSearchCondition(new SqlCondition(false, new SqlPredicate.Expr(expr))));
        }
Exemple #11
0
        public override ISqlExpression ConvertExpressionImpl(ISqlExpression expr, ConvertVisitor visitor,
                                                             EvaluationContext context)
        {
            expr = base.ConvertExpressionImpl(expr, visitor, context);

            if (expr is SqlBinaryExpression be)
            {
                switch (be.Operation)
                {
                case "+": return(be.SystemType == typeof(string)? new SqlBinaryExpression(be.SystemType, be.Expr1, "||", be.Expr2, be.Precedence) : expr);

                case "^":                         // (a + b) - (a & b) * 2
                    return(Sub(
                               Add(be.Expr1, be.Expr2, be.SystemType),
                               Mul(new SqlBinaryExpression(be.SystemType, be.Expr1, "&", be.Expr2), 2), be.SystemType));
                }
            }
            else if (expr is SqlFunction func)
            {
                switch (func.Name)
                {
                case "Space": return(new SqlFunction(func.SystemType, "PadR", new SqlValue(" "), func.Parameters[0]));

                case "Convert":
                {
                    var ftype = func.SystemType.ToUnderlying();

                    if (ftype == typeof(bool))
                    {
                        var ex = AlternativeConvertToBoolean(func, 1);
                        if (ex != null)
                        {
                            return(ex);
                        }
                    }

                    if (ftype == typeof(DateTime) || ftype == typeof(DateTimeOffset))
                    {
                        if (IsDateDataType(func.Parameters[0], "Date"))
                        {
                            return(new SqlFunction(func.SystemType, "Date", func.Parameters[1]));
                        }
                        return(new SqlFunction(func.SystemType, "DateTime", func.Parameters[1]));
                    }

                    return(new SqlExpression(func.SystemType, "Cast({0} as {1})", Precedence.Primary, func.Parameters[1], func.Parameters[0]));
                }
                }
            }

            return(expr);
        }
Exemple #12
0
        MemberAttributes ConvModifiers(TypeMember member)
        {
            bool strict = ConvertVisitor.IsStrictMode(pc);

            if (member is Field)
            {
                return(ConvModifiers(member.Modifiers, strict ? MemberAttributes.Private : MemberAttributes.Family));
            }
            else
            {
                return(ConvModifiers(member.Modifiers, strict ? MemberAttributes.Private : MemberAttributes.Public));
            }
        }
Exemple #13
0
        public override ISqlPredicate ConvertPredicateImpl(ISqlPredicate predicate, ConvertVisitor <RunOptimizationContext> visitor)
        {
            switch (predicate.ElementType)
            {
            case QueryElementType.ExprExprPredicate:
            {
                var expr = (SqlPredicate.ExprExpr)predicate;

                // Oracle saves empty string as null to database, so we need predicate modification before sending query
                //
                if (expr.WithNull == true &&
                    (expr.Operator == SqlPredicate.Operator.Equal ||
                     expr.Operator == SqlPredicate.Operator.NotEqual ||
                     expr.Operator == SqlPredicate.Operator.GreaterOrEqual ||
                     expr.Operator == SqlPredicate.Operator.LessOrEqual))
                {
                    if (expr.Expr1.SystemType == typeof(string) &&
                        expr.Expr1.TryEvaluateExpression(visitor.Context.OptimizationContext.Context, out var value1) && value1 is string string1)
                    {
                        if (string1 == "")
                        {
                            var sc = new SqlSearchCondition();
                            sc.Conditions.Add(new SqlCondition(false, new SqlPredicate.ExprExpr(expr.Expr1, expr.Operator, expr.Expr2, null), true));
                            sc.Conditions.Add(new SqlCondition(false, new SqlPredicate.IsNull(expr.Expr2, false), true));
                            return(sc);
                        }
                    }

                    if (expr.Expr2.SystemType == typeof(string) &&
                        expr.Expr2.TryEvaluateExpression(visitor.Context.OptimizationContext.Context, out var value2) && value2 is string string2)
                    {
                        if (string2 == "")
                        {
                            var sc = new SqlSearchCondition();
                            sc.Conditions.Add(new SqlCondition(false, new SqlPredicate.ExprExpr(expr.Expr1, expr.Operator, expr.Expr2, null), true));
                            sc.Conditions.Add(new SqlCondition(false, new SqlPredicate.IsNull(expr.Expr1, false), true));
                            return(sc);
                        }
                    }
                }
                break;
            }
            }

            predicate = base.ConvertPredicateImpl(predicate, visitor);

            return(predicate);
        }
Exemple #14
0
 /// <summary>
 /// Adds an ORDER BY clause to queries using OFFSET/FETCH, if none exists
 /// </summary>
 protected SqlStatement AddOrderByForSkip(SqlStatement statement)
 {
     statement = ConvertVisitor.Convert(statement, (visitor, element) =>
     {
         if (element.ElementType == QueryElementType.OrderByClause)
         {
             var orderByClause = (SqlOrderByClause)element;
             if (orderByClause.OrderBy.IsEmpty && orderByClause.SelectQuery.Select.SkipValue != null)
             {
                 return(new SqlOrderByClause(new[] { new SqlOrderByItem(new SqlValue(typeof(int), 1), false) }));
             }
         }
         return(element);
     });
     return(statement);
 }
Exemple #15
0
            /// <summary>
            /// We need to use same paremeters as for original query
            /// </summary>
            /// <param name="original"></param>
            SqlStatement Clone(SqlStatement original)
            {
                var clone = original.Clone();

                var pairs = from o in original.Parameters.Distinct()
                            join n in clone.Parameters.Distinct() on o.Name equals n.Name
                            select new { Old = o, New = n };

                var dic = pairs.ToDictionary(p => p.New, p => p.Old);

                clone = ConvertVisitor.Convert(clone, (v, e) =>
                                               e is SqlParameter param && dic.TryGetValue(param, out var newParam) ? newParam : e);

                clone.Parameters.Clear();
                clone.Parameters.AddRange(original.Parameters);

                return(clone);
            }
        /// <summary>
        ///
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        protected override Expression VisitUnary(UnaryExpression node)
        {
            IExpressionNodeVisitor <EntityType, UnaryExpression> visitor;

            switch (node.NodeType)
            {
            case ExpressionType.Not:
                visitor = new NotVisitor <EntityType>();
                break;

            case ExpressionType.Convert:
                visitor = new ConvertVisitor <EntityType>();
                break;

            default:
                throw new NotSupportedException();
            }

            visitor.Visit(this, node);
            return(null);
        }
        private SqlStatement WrapParameters(SqlStatement statement)
        {
            // ODBC cannot properly type result column, if it produced by parameter
            // To fix it we will wrap all parameters, used as select columns into type-cast
            // we use CVar, as other cast functions generate error for null-values parameters and CVar works

            // we are interested only in selects, because error generated by data reader, not by database itself
            if (statement.QueryType != QueryType.Select)
            {
                return(statement);
            }

            statement = ConvertVisitor.Convert(statement, (visitor, e) =>
            {
                if (e is SqlParameter p && p.IsQueryParameter && visitor.ParentElement is SqlColumn)
                {
                    return(new SqlExpression(p.Type.SystemType, "CVar({0})", Precedence.Primary, p));
                }

                return(e);
            });
Exemple #18
0
        static ISqlExpression ConvertParametersToValues(Query query, Expression expr, IDataContext?db, object?[]?ps, ISqlExpression sqlExpr)
        {
            var parameters = query.Queries[0].Parameters;

            var result = ConvertVisitor.Convert(sqlExpr, (v, e) =>
            {
                if (e.ElementType == QueryElementType.SqlParameter)
                {
                    var parameter = (SqlParameter)e;
                    var accessor  = GetParameterAccessor(parameters, parameter);
                    if (accessor != null)
                    {
                        return(new SqlValue(parameter.Type, accessor.ValueAccessor(expr, db, ps)));
                    }
                }

                return(e);
            });

            return(result);
        }
        public override ISqlPredicate ConvertSearchStringPredicate <TContext>(MappingSchema mappingSchema, SqlPredicate.SearchString predicate, ConvertVisitor <RunOptimizationContext <TContext> > visitor,
                                                                              OptimizationContext optimizationContext)
        {
            var like = ConvertSearchStringPredicateViaLike(mappingSchema, predicate, visitor,
                                                           optimizationContext);

            if (predicate.CaseSensitive.EvaluateBoolExpression(optimizationContext.Context) == true)
            {
                SqlPredicate.ExprExpr?subStrPredicate = null;

                switch (predicate.Kind)
                {
                case SqlPredicate.SearchString.SearchKind.StartsWith:
                {
                    subStrPredicate =
                        new SqlPredicate.ExprExpr(
                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary,
                                            new SqlFunction(typeof(string), "SUBSTRING",
                                                            predicate.Expr1,
                                                            new SqlValue(1),
                                                            new SqlFunction(typeof(int), "Length", predicate.Expr2))),
                            SqlPredicate.Operator.Equal,
                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary, predicate.Expr2),
                            null
                            );
                    break;
                }

                case SqlPredicate.SearchString.SearchKind.EndsWith:
                {
                    var indexExpression = new SqlBinaryExpression(typeof(int),
                                                                  new SqlBinaryExpression(typeof(int),
                                                                                          new SqlFunction(typeof(int), "Length", predicate.Expr1),
                                                                                          "-",
                                                                                          new SqlFunction(typeof(int), "Length", predicate.Expr2)),
                                                                  "+",
                                                                  new SqlValue(1));

                    subStrPredicate =
                        new SqlPredicate.ExprExpr(
                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary,
                                            new SqlFunction(typeof(string), "SUBSTRING",
                                                            predicate.Expr1,
                                                            indexExpression,
                                                            new SqlFunction(typeof(int), "Length", predicate.Expr2))),
                            SqlPredicate.Operator.Equal,
                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary, predicate.Expr2),
                            null
                            );

                    break;
                }

                case SqlPredicate.SearchString.SearchKind.Contains:
                {
                    subStrPredicate =
                        new SqlPredicate.ExprExpr(
                            new SqlFunction(typeof(int), "CHARINDEX",
                                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary,
                                                            predicate.Expr2),
                                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary,
                                                            predicate.Expr1)),
                            SqlPredicate.Operator.Greater,
                            new SqlValue(0), null);

                    break;
                }
                }

                if (subStrPredicate != null)
                {
                    var result = new SqlSearchCondition(
                        new SqlCondition(false, like, predicate.IsNot),
                        new SqlCondition(predicate.IsNot, subStrPredicate));

                    return(result);
                }
            }

            return(like);
        }
        public override ISqlPredicate ConvertSearchStringPredicate(SqlPredicate.SearchString predicate, ConvertVisitor <RunOptimizationContext> visitor)
        {
            ISqlExpression expr;

            var caseSensitive = predicate.CaseSensitive.EvaluateBoolExpression(visitor.Context.OptimizationContext.Context);

            // for explicit case-sensitive search we apply "CAST({0} AS BLOB)" to searched string as COLLATE's collation is character set-dependent
            switch (predicate.Kind)
            {
            case SqlPredicate.SearchString.SearchKind.EndsWith:
            {
                if (caseSensitive == false)
                {
                    predicate = new SqlPredicate.SearchString(
                        new SqlFunction(typeof(string), "$ToLower$", predicate.Expr1),
                        predicate.IsNot,
                        new SqlFunction(typeof(string), "$ToLower$", predicate.Expr2), predicate.Kind,
                        predicate.CaseSensitive);
                }
                else if (caseSensitive == true)
                {
                    predicate = new SqlPredicate.SearchString(
                        new SqlExpression(typeof(string), "CAST({0} AS BLOB)", Precedence.Primary, predicate.Expr1),
                        predicate.IsNot,
                        predicate.Expr2,
                        predicate.Kind,
                        predicate.CaseSensitive);
                }

                return(ConvertSearchStringPredicateViaLike(predicate, visitor));
            }

            case SqlPredicate.SearchString.SearchKind.StartsWith:
            {
                expr = new SqlExpression(typeof(bool),
                                         predicate.IsNot ? "{0} NOT STARTING WITH {1}" : "{0} STARTING WITH {1}",
                                         Precedence.Comparison,
                                         TryConvertToValue(
                                             caseSensitive == false
                                                                ? new SqlFunction(typeof(string), "$ToLower$", predicate.Expr1)
                                                                : caseSensitive == true
                                                                        ? new SqlExpression(typeof(string), "CAST({0} AS BLOB)", Precedence.Primary, predicate.Expr1)
                                                                        : predicate.Expr1,
                                             visitor.Context.OptimizationContext.Context),
                                         TryConvertToValue(
                                             caseSensitive == false
                                                                ? new SqlFunction(typeof(string), "$ToLower$", predicate.Expr2)
                                                                : predicate.Expr2, visitor.Context.OptimizationContext.Context))
                {
                    CanBeNull = false
                };
                break;
            }

            case SqlPredicate.SearchString.SearchKind.Contains:
            {
                if (caseSensitive == false)
                {
                    expr = new SqlExpression(typeof(bool),
                                             predicate.IsNot ? "{0} NOT CONTAINING {1}" : "{0} CONTAINING {1}",
                                             Precedence.Comparison,
                                             TryConvertToValue(predicate.Expr1, visitor.Context.OptimizationContext.Context),
                                             TryConvertToValue(predicate.Expr2, visitor.Context.OptimizationContext.Context))
                    {
                        CanBeNull = false
                    };
                }
                else
                {
                    if (caseSensitive == true)
                    {
                        predicate = new SqlPredicate.SearchString(
                            new SqlExpression(typeof(string), "CAST({0} AS BLOB)", Precedence.Primary, predicate.Expr1),
                            predicate.IsNot,
                            predicate.Expr2,
                            predicate.Kind,
                            new SqlValue(false));
                    }

                    return(ConvertSearchStringPredicateViaLike(predicate, visitor));
                }
                break;
            }

            default:
                throw new InvalidOperationException($"Unexpected predicate: {predicate.Kind}");
            }

            return(new SqlSearchCondition(new SqlCondition(false, new SqlPredicate.Expr(expr))));
        }
Exemple #21
0
        public override ISqlExpression ConvertExpressionImpl(ISqlExpression expression, ConvertVisitor visitor, EvaluationContext context)
        {
            expression = base.ConvertExpressionImpl(expression, visitor, context);
            if (expression is SqlBinaryExpression be)
            {
                switch (be.Operation)
                {
                case "%": {
                    var expr2 = (!ReflectionExtensions.IsIntegerType(be.Expr1.SystemType)) ? new SqlFunction(typeof(int), "Int", be.Expr1) : be.Expr1;
                    return(new SqlFunction(be.SystemType, "Mod", expr2, be.Expr2));
                }

                case "&": return(new SqlFunction(be.SystemType, "BitAnd", be.Expr1, be.Expr2));

                case "|": return(new SqlFunction(be.SystemType, "BitOr", be.Expr1, be.Expr2));

                case "^": return(new SqlFunction(be.SystemType, "BitXor", be.Expr1, be.Expr2));

                case "+": return((be.SystemType == typeof(string)) ? new SqlBinaryExpression(be.SystemType, be.Expr1, "||", be.Expr2, be.Precedence) : expression);
                }
            }
            else if (expression is SqlFunction func)
            {
                switch (func.Name.ToLower())
                {
                case "convert": {
                    if (ReflectionExtensions.ToUnderlying(func.SystemType) == typeof(bool))
                    {
                        var ex = AlternativeConvertToBoolean(func, 1);
                        if (ex != null)
                        {
                            return(ex);
                        }
                    }
                    if (func.Parameters[0] is SqlDataType)
                    {
                        var type = (SqlDataType)func.Parameters[0];
                        if (type.Type.SystemType == typeof(string) && func.Parameters[1].SystemType != typeof(string))
                        {
                            return(new SqlFunction(func.SystemType, "RTrim", new SqlFunction(typeof(string), "Char", func.Parameters[1])));
                        }
                        var length = type.Type.Length;
                        if ((length.HasValue ? new bool?(length.GetValueOrDefault() > 0) : null).GetValueOrDefault())
                        {
                            return(new SqlFunction(func.SystemType, type.Type.DataType.ToString(), func.Parameters[1], new SqlValue(type.Type.Length)));
                        }
                        length = type.Type.Precision;
                        if ((length.HasValue ? new bool?(length.GetValueOrDefault() > 0) : null).GetValueOrDefault())
                        {
                            return(new SqlFunction(func.SystemType, type.Type.DataType.ToString(), func.Parameters[1], new SqlValue(type.Type.Precision), new SqlValue(type.Type.Scale)));
                        }
                        return(new SqlFunction(func.SystemType, type.Type.DataType.ToString(), func.Parameters[1]));
                    }
                    if (func.Parameters[0] is SqlFunction)
                    {
                        var f = (SqlFunction)func.Parameters[0];
                        return((f.Name.ToLower() == "char")
                  ? new SqlFunction(func.SystemType, f.Name, func.Parameters[1])
                  : ((f.Parameters.Length == 1)
                  ? new SqlFunction(func.SystemType, f.Name, func.Parameters[1], f.Parameters[0])
                  : new SqlFunction(func.SystemType, f.Name, func.Parameters[1], f.Parameters[0], f.Parameters[1])));
                    }
                    var e = (SqlExpression)func.Parameters[0];
                    return(new SqlFunction(func.SystemType, e.Expr, func.Parameters[1]));
                }

                case "millisecond": return(Div(new SqlFunction(func.SystemType, "Microsecond", func.Parameters), 1000));

                case "smallDateTime":
                case "dateTime":
                case "dateTime2": return(new SqlFunction(func.SystemType, "TimeStamp", func.Parameters));

                case "uint16": return(new SqlFunction(func.SystemType, "Int", func.Parameters));

                case "uint32": return(new SqlFunction(func.SystemType, "BigInt", func.Parameters));

                case "uint64": return(new SqlFunction(func.SystemType, "Decimal", func.Parameters));

                case "byte":
                case "sbyte":
                case "int16": return(new SqlFunction(func.SystemType, "SmallInt", func.Parameters));

                case "int32": return(new SqlFunction(func.SystemType, "Int", func.Parameters));

                case "int64": return(new SqlFunction(func.SystemType, "BigInt", func.Parameters));

                case "double": return(new SqlFunction(func.SystemType, "Float", func.Parameters));

                case "single": return(new SqlFunction(func.SystemType, "Real", func.Parameters));

                case "money": return(new SqlFunction(func.SystemType, "Decimal", func.Parameters[0], new SqlValue(19), new SqlValue(4)));

                case "smallmoney": return(new SqlFunction(func.SystemType, "Decimal", func.Parameters[0], new SqlValue(10), new SqlValue(4)));

                case "varchar":
                    if (ReflectionExtensions.ToUnderlying(func.Parameters[0].SystemType) == typeof(decimal))
                    {
                        return(new SqlFunction(func.SystemType, "Char", func.Parameters[0]));
                    }
                    break;

                case "nchar":
                case "nvarchar": return(new SqlFunction(func.SystemType, "Char", func.Parameters));

                case "datediff":
                    switch ((Sql.DateParts)((SqlValue)func.Parameters[0]).Value)
                    {
                    case Sql.DateParts.Day: return(new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) / 86400", 80, func.Parameters[2], func.Parameters[1]));

                    case Sql.DateParts.Hour: return(new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) / 3600", 80, func.Parameters[2], func.Parameters[1]));

                    case Sql.DateParts.Minute: return(new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) / 60", 80, func.Parameters[2], func.Parameters[1]));

                    case Sql.DateParts.Second: return(new SqlExpression(typeof(int), "(Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))", 60, func.Parameters[2], func.Parameters[1]));

                    case Sql.DateParts.Millisecond: return(new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) * 1000 + (MICROSECOND({0}) - MICROSECOND({1})) / 1000", 60, func.Parameters[2], func.Parameters[1]));
                    }
                    break;
                    //case "ltrim":            throw new NotImplementedException("ConvertExpression.ltrim");
                    //case "rtrim":            throw new NotImplementedException("ConvertExpression.rtrim");
                }
            }
            return(expression);
        }
Exemple #22
0
 public override ISqlExpression ConvertExpressionImpl(ISqlExpression expression, ConvertVisitor visitor, EvaluationContext context)
 {
     //    public override ISqlExpression ConvertExpression(ISqlExpression expr, bool withParameters) {
     expression = base.ConvertExpressionImpl(expression, visitor, context);
     if (expression is SqlFunction func)
     {
         switch (func.Name.ToLower())
         {
         case "exists": return(AlternativeExists(func));
         }
     }
     return(expression);
 }
        public override ISqlPredicate ConvertSearchStringPredicate(SqlPredicate.SearchString predicate, ConvertVisitor <RunOptimizationContext> visitor)
        {
            var like = base.ConvertSearchStringPredicate(predicate, visitor);

            if (predicate.CaseSensitive.EvaluateBoolExpression(visitor.Context.OptimizationContext.Context) == true)
            {
                SqlPredicate.ExprExpr?subStrPredicate = null;

                switch (predicate.Kind)
                {
                case SqlPredicate.SearchString.SearchKind.StartsWith:
                {
                    subStrPredicate =
                        new SqlPredicate.ExprExpr(
                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary, new SqlFunction(
                                                typeof(string), "LEFT", predicate.Expr1,
                                                new SqlFunction(typeof(int), "Length", predicate.Expr2))),
                            SqlPredicate.Operator.Equal,
                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary, predicate.Expr2),
                            null
                            );

                    break;
                }

                case SqlPredicate.SearchString.SearchKind.EndsWith:
                {
                    subStrPredicate =
                        new SqlPredicate.ExprExpr(
                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary, new SqlFunction(
                                                typeof(string), "RIGHT", predicate.Expr1,
                                                new SqlFunction(typeof(int), "Length", predicate.Expr2))),
                            SqlPredicate.Operator.Equal,
                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary, predicate.Expr2),
                            null
                            );

                    break;
                }

                case SqlPredicate.SearchString.SearchKind.Contains:
                {
                    subStrPredicate =
                        new SqlPredicate.ExprExpr(
                            new SqlFunction(typeof(int), "CHARINDEX",
                                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary,
                                                            predicate.Expr2),
                                            new SqlFunction(typeof(byte[]), "Convert", SqlDataType.DbVarBinary,
                                                            predicate.Expr1)),
                            SqlPredicate.Operator.Greater,
                            new SqlValue(0), null);

                    break;
                }
                }

                if (subStrPredicate != null)
                {
                    var result = new SqlSearchCondition(
                        new SqlCondition(false, like, predicate.IsNot),
                        new SqlCondition(predicate.IsNot, subStrPredicate));

                    return(result);
                }
            }

            return(like);
        }
Exemple #24
0
        public override ISqlExpression ConvertExpressionImpl(ISqlExpression expression, ConvertVisitor visitor,
                                                             EvaluationContext context)
        {
            expression = base.ConvertExpressionImpl(expression, visitor, context);

            switch (expression)
            {
            case SqlBinaryExpression be:
                switch (be.Operation)
                {
                case "%":
                    return(be.Expr1.SystemType !.IsIntegerType()?
                           be :
                           new SqlBinaryExpression(
                               typeof(int),
                               new SqlFunction(typeof(int), "Convert", SqlDataType.Int32, be.Expr1),
                               be.Operation,
                               be.Expr2,
                               be.Precedence));
                }

                break;

            case SqlFunction func:
                switch (func.Name)
                {
                case "Convert":
                    switch (Type.GetTypeCode(func.SystemType.ToUnderlying()))
                    {
                    case TypeCode.UInt64:
                        if (func.Parameters[1].SystemType !.IsFloatType())
                        {
                            return(new SqlFunction(
                                       func.SystemType,
                                       func.Name,
                                       false,
                                       func.Precedence,
                                       func.Parameters[0],
                                       new SqlFunction(func.SystemType, "Floor", func.Parameters[1])));
                        }

                        break;

                    case TypeCode.DateTime:
                        var type1 = func.Parameters[1].SystemType !.ToUnderlying();

                        if (IsTimeDataType(func.Parameters[0]))
                        {
                            if (type1 == typeof(DateTime) || type1 == typeof(DateTimeOffset))
                            {
                                return(new SqlExpression(
                                           func.SystemType, "Cast(Convert(NChar, {0}, 114) as DateTime)", Precedence.Primary, func.Parameters[1]));
                            }

                            if (func.Parameters[1].SystemType == typeof(string))
                            {
                                return(func.Parameters[1]);
                            }

                            return(new SqlExpression(
                                       func.SystemType, "Convert(NChar, {0}, 114)", Precedence.Primary, func.Parameters[1]));
                        }

                        if (type1 == typeof(DateTime) || type1 == typeof(DateTimeOffset))
                        {
                            if (IsDateDataType(func.Parameters[0], "Datetime"))
                            {
                                return(new SqlExpression(
                                           func.SystemType, "Cast(Floor(Cast({0} as Float)) as DateTime)", Precedence.Primary, func.Parameters[1]));
                            }
                        }

                        break;
                    }

                    break;
                }

                break;
            }

            return(expression);
        }
Exemple #25
0
 public override ISqlExpression ConvertExpressionImpl <TContext>(ISqlExpression expression, ConvertVisitor <TContext> visitor, EvaluationContext context)
 {
     expression = base.ConvertExpressionImpl(expression, visitor, context);
     return(dataSourceInformationRow.DataSourceProduct?.DbSystem?.Name switch {
         DbSystem.Names.DB2iSeries => ConvertExpressionImpl_DB2iSeries(expression),
         _ => expression
     });
        public override ISqlExpression ConvertExpressionImpl(ISqlExpression expr, ConvertVisitor visitor,
                                                             EvaluationContext context)
        {
            expr = base.ConvertExpressionImpl(expr, visitor, context);

            if (expr is SqlBinaryExpression be)
            {
                switch (be.Operation)
                {
                case "%": return(new SqlFunction(be.SystemType, "Mod", be.Expr1, be.Expr2));

                case "&": return(new SqlFunction(be.SystemType, "BitAnd", be.Expr1, be.Expr2));

                case "|": return(new SqlFunction(be.SystemType, "BitOr", be.Expr1, be.Expr2));

                case "^": return(new SqlFunction(be.SystemType, "BitXor", be.Expr1, be.Expr2));

                case "+": return(be.SystemType == typeof(string) ? new SqlBinaryExpression(be.SystemType, be.Expr1, "||", be.Expr2, be.Precedence) : expr);
                }
            }
            else if (expr is SqlFunction func)
            {
                switch (func.Name)
                {
                case "Coalesce": return(ConvertCoalesceToBinaryFunc(func, "Nvl"));

                case "Convert":
                {
                    var par0 = func.Parameters[0];
                    var par1 = func.Parameters[1];

                    switch (Type.GetTypeCode(func.SystemType.ToUnderlying()))
                    {
                    case TypeCode.String   : return(new SqlFunction(func.SystemType, "To_Char", func.Parameters[1]));

                    case TypeCode.Boolean:
                    {
                        var ex = AlternativeConvertToBoolean(func, 1);
                        if (ex != null)
                        {
                            return(ex);
                        }
                        break;
                    }

                    case TypeCode.UInt64:
                        if (func.Parameters[1].SystemType !.IsFloatType())
                        {
                            par1 = new SqlFunction(func.SystemType, "Floor", func.Parameters[1]);
                        }
                        break;

                    case TypeCode.DateTime:
                        if (IsDateDataType(func.Parameters[0], "Date"))
                        {
                            if (func.Parameters[1].SystemType == typeof(string))
                            {
                                return(new SqlFunction(
                                           func.SystemType,
                                           "Date",
                                           new SqlFunction(func.SystemType, "To_Date", func.Parameters[1], new SqlValue("%Y-%m-%d"))));
                            }

                            return(new SqlFunction(func.SystemType, "Date", func.Parameters[1]));
                        }

                        if (IsTimeDataType(func.Parameters[0]))
                        {
                            return(new SqlExpression(func.SystemType, "Cast(Extend({0}, hour to second) as Char(8))", Precedence.Primary, func.Parameters[1]));
                        }

                        return(new SqlFunction(func.SystemType, "To_Date", func.Parameters[1]));

                    default:
                        if (func.SystemType.ToUnderlying() == typeof(DateTimeOffset))
                        {
                            goto case TypeCode.DateTime;
                        }
                        break;
                    }

                    return(new SqlExpression(func.SystemType, "Cast({0} as {1})", Precedence.Primary, par1, par0));
                }
                }
            }

            return(expr);
        }
Exemple #27
0
        public override ISqlExpression ConvertExpressionImpl(ISqlExpression expression, ConvertVisitor <RunOptimizationContext> visitor)
        {
            expression = base.ConvertExpressionImpl(expression, visitor);

            if (expression is SqlBinaryExpression be)
            {
                switch (be.Operation)
                {
                case "%": return(new SqlFunction(be.SystemType, "MOD", be.Expr1, be.Expr2));

                case "&": return(new SqlFunction(be.SystemType, "BITAND", be.Expr1, be.Expr2));

                case "|":                         // (a + b) - BITAND(a, b)
                    return(Sub(
                               Add(be.Expr1, be.Expr2, be.SystemType),
                               new SqlFunction(be.SystemType, "BITAND", be.Expr1, be.Expr2),
                               be.SystemType));

                case "^":                         // (a + b) - BITAND(a, b) * 2
                    return(Sub(
                               Add(be.Expr1, be.Expr2, be.SystemType),
                               Mul(new SqlFunction(be.SystemType, "BITAND", be.Expr1, be.Expr2), 2),
                               be.SystemType));

                case "+": return(be.SystemType == typeof(string) ? new SqlBinaryExpression(be.SystemType, be.Expr1, "||", be.Expr2, be.Precedence) : expression);
                }
            }
            else if (expression is SqlFunction func)
            {
                switch (func.Name)
                {
                case "Coalesce":
                {
                    return(ConvertCoalesceToBinaryFunc(func, "Nvl"));
                }

                case "Convert":
                {
                    var ftype = func.SystemType.ToUnderlying();

                    if (ftype == typeof(bool))
                    {
                        var ex = AlternativeConvertToBoolean(func, 1);
                        if (ex != null)
                        {
                            return(ex);
                        }
                    }

                    if (ftype == typeof(DateTime) || ftype == typeof(DateTimeOffset)
#if NET6_0_OR_GREATER
                        || ftype == typeof(DateOnly)
#endif
                        )
                    {
                        if (IsTimeDataType(func.Parameters[0]))
                        {
                            if (func.Parameters[1].SystemType == typeof(string))
                            {
                                return(func.Parameters[1]);
                            }

                            return(new SqlFunction(func.SystemType, "To_Char", func.Parameters[1], new SqlValue("HH24:MI:SS")));
                        }

                        if (IsDateDataType(func.Parameters[0], "Date"))
                        {
                            if (func.Parameters[1].SystemType !.ToUnderlying() == typeof(DateTime) ||
                                func.Parameters[1].SystemType !.ToUnderlying() == typeof(DateTimeOffset))
                            {
                                return(new SqlFunction(func.SystemType, "Trunc", func.Parameters[1], new SqlValue("DD")));
                            }

                            return(new SqlFunction(func.SystemType, "TO_DATE", func.Parameters[1], new SqlValue("YYYY-MM-DD")));
                        }
                        else if (IsDateDataOffsetType(func.Parameters[0]))
                        {
                            if (ftype == typeof(DateTimeOffset))
                            {
                                return(func.Parameters[1]);
                            }

                            return(new SqlFunction(func.SystemType, "TO_TIMESTAMP_TZ", func.Parameters[1], new SqlValue("YYYY-MM-DD HH24:MI:SS")));
                        }

                        return(new SqlFunction(func.SystemType, "TO_TIMESTAMP", func.Parameters[1], new SqlValue("YYYY-MM-DD HH24:MI:SS")));
                    }
                    else if (ftype == typeof(string))
                    {
                        var stype = func.Parameters[1].SystemType !.ToUnderlying();

                        if (stype == typeof(DateTimeOffset))
                        {
                            return(new SqlFunction(func.SystemType, "To_Char", func.Parameters[1], new SqlValue("YYYY-MM-DD HH24:MI:SS TZH:TZM")));
                        }
                        else if (stype == typeof(DateTime))
                        {
                            return(new SqlFunction(func.SystemType, "To_Char", func.Parameters[1], new SqlValue("YYYY-MM-DD HH24:MI:SS")));
                        }
#if NET6_0_OR_GREATER
                        else if (stype == typeof(DateOnly))
                        {
                            return(new SqlFunction(func.SystemType, "To_Char", func.Parameters[1], new SqlValue("YYYY-MM-DD")));
                        }
#endif
                    }

                    return(new SqlExpression(func.SystemType, "Cast({0} as {1})", Precedence.Primary, FloorBeforeConvert(func), func.Parameters[0]));
                }

                case "CharIndex":
                    return(func.Parameters.Length == 2?
                           new SqlFunction(func.SystemType, "InStr", func.Parameters[1], func.Parameters[0]):
                           new SqlFunction(func.SystemType, "InStr", func.Parameters[1], func.Parameters[0], func.Parameters[2]));

                case "Avg":
                    return(new SqlFunction(
                               func.SystemType,
                               "Round",
                               new SqlFunction(func.SystemType, "AVG", func.Parameters[0]),
                               new SqlValue(27)));
                }
            }
            else if (expression is SqlExpression e)
            {
                if (e.Expr.StartsWith("To_Number(To_Char(") && e.Expr.EndsWith(", 'FF'))"))
                {
                    return(Div(new SqlExpression(e.SystemType, e.Expr.Replace("To_Number(To_Char(", "to_Number(To_Char("), e.Parameters), 1000));
                }
            }

            return(expression);
        }
Exemple #28
0
        public override ISqlExpression ConvertExpressionImpl(ISqlExpression expression, ConvertVisitor visitor,
                                                             EvaluationContext context)
        {
            expression = base.ConvertExpressionImpl(expression, visitor, context);

            switch (expression.ElementType)
            {
            case QueryElementType.SqlBinaryExpression:
            {
                var be = (SqlBinaryExpression)expression;

                switch (be.Operation)
                {
                case "%":
                {
                    var type1 = be.Expr1.SystemType !.ToUnderlying();

                    if (type1 == typeof(double) || type1 == typeof(float))
                    {
                        return(new SqlBinaryExpression(
                                   be.Expr2.SystemType !,
                                   new SqlFunction(typeof(int), "Convert", SqlDataType.Int32, be.Expr1),
                                   be.Operation,
                                   be.Expr2));
                    }

                    break;
                }
                }

                break;
            }

            case QueryElementType.SqlFunction:
            {
                var func = (SqlFunction)expression;

                switch (func.Name)
                {
                case "Convert":
                {
                    if (func.SystemType.ToUnderlying() == typeof(ulong) &&
                        func.Parameters[1].SystemType !.IsFloatType())
                    {
                        return(new SqlFunction(
                                   func.SystemType,
                                   func.Name,
                                   false,
                                   func.Precedence,
                                   func.Parameters[0],
                                   new SqlFunction(func.SystemType, "Floor", func.Parameters[1])));
                    }

                    if (Type.GetTypeCode(func.SystemType.ToUnderlying()) == TypeCode.DateTime)
                    {
                        var type1 = func.Parameters[1].SystemType !.ToUnderlying();

                        if (IsTimeDataType(func.Parameters[0]))
                        {
                            if (type1 == typeof(DateTimeOffset) || type1 == typeof(DateTime))
                            {
                                if (_sqlVersion >= SqlServerVersion.v2008)
                                {
                                    return(new SqlExpression(
                                               func.SystemType, "CAST({0} AS TIME)", Precedence.Primary, func.Parameters[1]));
                                }
                                else
                                {
                                    return(new SqlExpression(
                                               func.SystemType, "Cast(Convert(Char, {0}, 114) as DateTime)", Precedence.Primary, func.Parameters[1]));
                                }
                            }

                            if (func.Parameters[1].SystemType == typeof(string))
                            {
                                return(func.Parameters[1]);
                            }

                            return(new SqlExpression(
                                       func.SystemType, "Convert(Char, {0}, 114)", Precedence.Primary, func.Parameters[1]));
                        }

                        if (type1 == typeof(DateTime) || type1 == typeof(DateTimeOffset))
                        {
                            if (IsDateDataType(func.Parameters[0], "Datetime"))
                            {
                                return(new SqlExpression(
                                           func.SystemType, "Cast(Floor(Cast({0} as Float)) as DateTime)", Precedence.Primary, func.Parameters[1]));
                            }
                        }

                        if (func.Parameters.Length == 2 && func.Parameters[0] is SqlDataType && func.Parameters[0] == SqlDataType.DateTime)
                        {
                            return(new SqlFunction(func.SystemType, func.Name, func.IsAggregate, func.Precedence, func.Parameters[0], func.Parameters[1], new SqlValue(120)));
                        }
                    }


                    break;
                }
                }

                break;
            }
            }

            return(expression);
        }
Exemple #29
0
        public override ISqlPredicate ConvertSearchStringPredicate <TContext>(MappingSchema mappingSchema, SqlPredicate.SearchString predicate, ConvertVisitor <RunOptimizationContext <TContext> > visitor,
                                                                              OptimizationContext optimizationContext)
        {
            var like = ConvertSearchStringPredicateViaLike(mappingSchema, predicate, visitor,
                                                           optimizationContext);

            if (predicate.CaseSensitive.EvaluateBoolExpression(optimizationContext.Context) == true)
            {
                SqlPredicate.ExprExpr?subStrPredicate = null;

                switch (predicate.Kind)
                {
                case SqlPredicate.SearchString.SearchKind.StartsWith:
                {
                    subStrPredicate =
                        new SqlPredicate.ExprExpr(
                            new SqlFunction(typeof(string), "Substr", predicate.Expr1, new SqlValue(1),
                                            new SqlFunction(typeof(int), "Length", predicate.Expr2)),
                            SqlPredicate.Operator.Equal,
                            predicate.Expr2, null);

                    break;
                }

                case SqlPredicate.SearchString.SearchKind.EndsWith:
                {
                    subStrPredicate =
                        new SqlPredicate.ExprExpr(
                            new SqlFunction(typeof(string), "Substr", predicate.Expr1,
                                            new SqlBinaryExpression(typeof(int),
                                                                    new SqlFunction(typeof(int), "Length", predicate.Expr2), "*", new SqlValue(-1),
                                                                    Precedence.Multiplicative)
                                            ),
                            SqlPredicate.Operator.Equal,
                            predicate.Expr2, null);

                    break;
                }

                case SqlPredicate.SearchString.SearchKind.Contains:
                {
                    subStrPredicate =
                        new SqlPredicate.ExprExpr(
                            new SqlFunction(typeof(int), "InStr", predicate.Expr1, predicate.Expr2),
                            SqlPredicate.Operator.Greater,
                            new SqlValue(0), null);

                    break;
                }
                }

                if (subStrPredicate != null)
                {
                    var result = new SqlSearchCondition(
                        new SqlCondition(false, like, predicate.IsNot),
                        new SqlCondition(predicate.IsNot, subStrPredicate));

                    return(result);
                }
            }

            return(like);
        }
Exemple #30
0
        public override ISqlExpression ConvertExpressionImpl(ISqlExpression expr, ConvertVisitor visitor, EvaluationContext context)
        {
            expr = base.ConvertExpressionImpl(expr, visitor, context);
            if (expr is SqlBinaryExpression)
            {
                var sqlBinaryExpression = (SqlBinaryExpression)expr;
                switch (sqlBinaryExpression.Operation)
                {
                case "%": {
                    object sqlExpression;
                    if (sqlBinaryExpression.Expr1.SystemType.IsInteger())
                    {
                        sqlExpression = sqlBinaryExpression.Expr1;
                    }
                    else
                    {
                        sqlExpression = new SqlFunction(typeof(int), "Int", sqlBinaryExpression.Expr1);
                    }
                    var sqlExpression3 = (ISqlExpression)sqlExpression;
                    return(new SqlFunction(sqlBinaryExpression.SystemType, "Mod", sqlExpression3, sqlBinaryExpression.Expr2));
                }

                case "&":
                    return(new SqlFunction(sqlBinaryExpression.SystemType, "BitAnd", sqlBinaryExpression.Expr1, sqlBinaryExpression.Expr2));

                case "|":
                    return(new SqlFunction(sqlBinaryExpression.SystemType, "BitOr", sqlBinaryExpression.Expr1, sqlBinaryExpression.Expr2));

                case "^":
                    return(new SqlFunction(sqlBinaryExpression.SystemType, "BitXor", sqlBinaryExpression.Expr1, sqlBinaryExpression.Expr2));

                case "+":
                    if (!(sqlBinaryExpression.SystemType == typeof(string)))
                    {
                        return(expr);
                    }
                    return(new SqlBinaryExpression(sqlBinaryExpression.SystemType, sqlBinaryExpression.Expr1, "||", sqlBinaryExpression.Expr2, sqlBinaryExpression.Precedence));
                }
            }
            else if (expr is SqlFunction)
            {
                var sqlFunction = (SqlFunction)expr;
                switch (sqlFunction.Name)
                {
                case "Convert": {
                    if (sqlFunction.SystemType.ToUnderlying() == typeof(bool))
                    {
                        var sqlExpression4 = base.AlternativeConvertToBoolean(sqlFunction, 1);
                        if (sqlExpression4 != null)
                        {
                            return(sqlExpression4);
                        }
                    }
                    if (sqlFunction.Parameters[0] is SqlDataType)
                    {
                        var sqlDataType = (SqlDataType)sqlFunction.Parameters[0];
                        if (sqlDataType.Type.SystemType == typeof(string) && sqlFunction.Parameters[1].SystemType != typeof(string))
                        {
                            return(new SqlFunction(sqlFunction.SystemType, "RTrim", new SqlFunction(typeof(string), "Char", sqlFunction.Parameters[1])));
                        }
                        DataType dataType;
                        if (sqlDataType.Type.Length > 0)
                        {
                            var systemType = sqlFunction.SystemType;
                            dataType = sqlDataType.Type.DataType;
                            return(new SqlFunction(systemType, dataType.ToString(), sqlFunction.Parameters[1], new SqlValue(sqlDataType.Type.Length)));
                        }
                        if (sqlDataType.Type.Precision > 0)
                        {
                            var systemType2 = sqlFunction.SystemType;
                            dataType = sqlDataType.Type.DataType;
                            return(new SqlFunction(systemType2, dataType.ToString(), sqlFunction.Parameters[1], new SqlValue(sqlDataType.Type.Precision), new SqlValue(sqlDataType.Type.Scale)));
                        }
                        var systemType3 = sqlFunction.SystemType;
                        dataType = sqlDataType.Type.DataType;
                        return(new SqlFunction(systemType3, dataType.ToString(), sqlFunction.Parameters[1]));
                    }
                    if (sqlFunction.Parameters[0] is SqlFunction)
                    {
                        var sqlFunction2 = (SqlFunction)sqlFunction.Parameters[0];
                        if (!(sqlFunction2.Name == "Char"))
                        {
                            if (sqlFunction2.Parameters.Length != 1)
                            {
                                return(new SqlFunction(sqlFunction.SystemType, sqlFunction2.Name, sqlFunction.Parameters[1], sqlFunction2.Parameters[0], sqlFunction2.Parameters[1]));
                            }
                            return(new SqlFunction(sqlFunction.SystemType, sqlFunction2.Name, sqlFunction.Parameters[1], sqlFunction2.Parameters[0]));
                        }
                        return(new SqlFunction(sqlFunction.SystemType, sqlFunction2.Name, sqlFunction.Parameters[1]));
                    }
                    var sqlExpression5 = (SqlExpression)sqlFunction.Parameters[0];
                    return(new SqlFunction(sqlFunction.SystemType, sqlExpression5.Expr, sqlFunction.Parameters[1]));
                }

                case "Millisecond":
                    return(base.Div(new SqlFunction(sqlFunction.SystemType, "Microsecond", sqlFunction.Parameters), 1000));

                case "SmallDateTime":
                case "DateTime":
                case "DateTime2":
                    return(new SqlFunction(sqlFunction.SystemType, "TimeStamp", sqlFunction.Parameters));

                case "UInt16":
                    return(new SqlFunction(sqlFunction.SystemType, "Int", sqlFunction.Parameters));

                case "UInt32":
                    return(new SqlFunction(sqlFunction.SystemType, "BigInt", sqlFunction.Parameters));

                case "UInt64":
                    return(new SqlFunction(sqlFunction.SystemType, "Decimal", sqlFunction.Parameters));

                case "Byte":
                case "SByte":
                case "Int16":
                    return(new SqlFunction(sqlFunction.SystemType, "SmallInt", sqlFunction.Parameters));

                case "Int32":
                    return(new SqlFunction(sqlFunction.SystemType, "Int", sqlFunction.Parameters));

                case "Int64":
                    return(new SqlFunction(sqlFunction.SystemType, "BigInt", sqlFunction.Parameters));

                case "Double":
                    return(new SqlFunction(sqlFunction.SystemType, "Float", sqlFunction.Parameters));

                case "Single":
                    return(new SqlFunction(sqlFunction.SystemType, "Real", sqlFunction.Parameters));

                case "Money":
                    return(new SqlFunction(sqlFunction.SystemType, "Decimal", sqlFunction.Parameters[0], new SqlValue(19), new SqlValue(4)));

                case "SmallMoney":
                    return(new SqlFunction(sqlFunction.SystemType, "Decimal", sqlFunction.Parameters[0], new SqlValue(10), new SqlValue(4)));

                case "VarChar":
                    if (!(sqlFunction.Parameters[0].SystemType.ToUnderlying() == typeof(decimal)))
                    {
                        break;
                    }
                    return(new SqlFunction(sqlFunction.SystemType, "Char", sqlFunction.Parameters[0]));

                case "NChar":
                case "NVarChar":
                    return(new SqlFunction(sqlFunction.SystemType, "Char", sqlFunction.Parameters));

                case "DateDiff":
                    switch ((Sql.DateParts)((SqlValue)sqlFunction.Parameters[0]).Value)
                    {
                    case Sql.DateParts.Day:
                        return(new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) / 86400", 80, sqlFunction.Parameters[2], sqlFunction.Parameters[1]));

                    case Sql.DateParts.Hour:
                        return(new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) / 3600", 80, sqlFunction.Parameters[2], sqlFunction.Parameters[1]));

                    case Sql.DateParts.Minute:
                        return(new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) / 60", 80, sqlFunction.Parameters[2], sqlFunction.Parameters[1]));

                    case Sql.DateParts.Second:
                        return(new SqlExpression(typeof(int), "(Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))", 60, sqlFunction.Parameters[2], sqlFunction.Parameters[1]));

                    case Sql.DateParts.Millisecond:
                        return(new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) * 1000 + (MICROSECOND({0}) - MICROSECOND({1})) / 1000", 60, sqlFunction.Parameters[2], sqlFunction.Parameters[1]));
                    }
                    break;
                }
            }
            return(expr);
        }