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 == PseudoFunctions.CONVERT || func1.Name == "DateTime"))) { var left = PseudoFunctions.MakeConvert(new SqlDataType(leftType), new SqlDataType(leftType), exprExpr.Expr1); exprExpr = new SqlPredicate.ExprExpr(left, exprExpr.Operator, exprExpr.Expr2, null); } if (!(exprExpr.Expr2 is SqlFunction func2 && (func2.Name == PseudoFunctions.CONVERT || func2.Name == "DateTime"))) { var right = PseudoFunctions.MakeConvert(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); }
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( PseudoFunctions.MakeToLower(predicate.Expr1), predicate.IsNot, PseudoFunctions.MakeToLower(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 ? PseudoFunctions.MakeToLower(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 ? PseudoFunctions.MakeToLower(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)))); }