From f26669a60d2b38605d129b89b87e6ba181d88975 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 18 Dec 2024 13:38:01 +0100 Subject: [PATCH] [jOOQ/jOOQ#17785] Field::contains should be emulated using DSL::position instead of Field::like, if available --- .../src/main/java/org/jooq/impl/Contains.java | 78 ++++++++++++++++-- .../org/jooq/impl/ContainsIgnoreCase.java | 10 ++- .../src/main/java/org/jooq/impl/EndsWith.java | 80 ++++++++++++++++++- .../org/jooq/impl/EndsWithIgnoreCase.java | 11 +-- jOOQ/src/main/java/org/jooq/impl/Like.java | 28 ++++--- jOOQ/src/main/java/org/jooq/impl/Names.java | 1 + .../main/java/org/jooq/impl/StartsWith.java | 9 ++- .../org/jooq/impl/StartsWithIgnoreCase.java | 12 +-- 8 files changed, 194 insertions(+), 35 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Contains.java b/jOOQ/src/main/java/org/jooq/impl/Contains.java index d5a700e78d..24f06f50c0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Contains.java +++ b/jOOQ/src/main/java/org/jooq/impl/Contains.java @@ -100,11 +100,42 @@ implements case YUGABYTEDB: return false; - case DUCKDB: - return true; + + + + + + + + + + + + + + + + + + + + + + case CLICKHOUSE: + case CUBRID: + case DERBY: + case FIREBIRD: + case H2: + case HSQLDB: + case IGNITE: + case MARIADB: + case MYSQL: + case SQLITE: + case TRINO: + return false; default: - return false; + return true; } } @@ -132,12 +163,45 @@ implements break; } - case DUCKDB: - ctx.visit(function(N_CONTAINS, BOOLEAN, value, content)); + + + + + + + + + + + + + + + + + + + + + + + case CLICKHOUSE: + case CUBRID: + case DERBY: + case FIREBIRD: + case H2: + case HSQLDB: + case IGNITE: + case MARIADB: + case MYSQL: + case SQLITE: + case TRINO: { + acceptDefault(ctx); break; + } default: - acceptDefault(ctx); + ctx.visit(function(N_CONTAINS, BOOLEAN, value, content)); break; } } @@ -152,7 +216,7 @@ implements private final void acceptDefault(Context ctx) { - ctx.visit(value.like(DSL.concat(inline("%"), Tools.escapeForLike(content, ctx.configuration()), inline("%")), Tools.ESCAPE)); + ctx.visit(DSL.position(Like.requiresStringCast(value), Like.requiresStringCast(content)).gt(inline(0))); } // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java b/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java index 9b3d4738f9..747cc0b52b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java +++ b/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java @@ -100,12 +100,14 @@ implements - case DUCKDB: - ctx.visit(value.lower().contains(content.lower())); - break; + + + + + default: - ctx.visit(value.likeIgnoreCase(DSL.concat(inline("%"), Tools.escapeForLike(content, ctx.configuration()), inline("%")), Tools.ESCAPE)); + ctx.visit(value.lower().contains(content.lower())); break; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/EndsWith.java b/jOOQ/src/main/java/org/jooq/impl/EndsWith.java index 9714143033..95d1b1d52b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/EndsWith.java +++ b/jOOQ/src/main/java/org/jooq/impl/EndsWith.java @@ -94,6 +94,43 @@ implements @Override final boolean parenthesised(Context ctx) { switch (ctx.family()) { + + + + + + + + + + + + + + + + + + + + + + + + case CUBRID: + case DERBY: + case FIREBIRD: + case H2: + case HSQLDB: + case IGNITE: + case MARIADB: + case MYSQL: + case POSTGRES: + case SQLITE: + case TRINO: + case YUGABYTEDB: + return false; + case DUCKDB: return true; @@ -101,7 +138,7 @@ implements return true; default: - return false; + return true; } } @@ -114,6 +151,45 @@ implements + + + + + + + + + + + + + + + + + + + + + + + + + case CUBRID: + case DERBY: + case FIREBIRD: + case H2: + case HSQLDB: + case IGNITE: + case MARIADB: + case MYSQL: + case POSTGRES: + case SQLITE: + case TRINO: + case YUGABYTEDB: + ctx.visit(DSL.position(Like.requiresStringCast(string), Like.requiresStringCast(suffix)).eq(iadd(isub(Like.requiresStringCast(string).length(), Like.requiresStringCast(suffix).length()), inline(1)))); + break; + case DUCKDB: ctx.visit(function(N_SUFFIX, BOOLEAN, string, suffix)); break; @@ -123,7 +199,7 @@ implements break; default: - ctx.visit(string.like(DSL.concat(inline("%"), Tools.escapeForLike(suffix, ctx.configuration())), Tools.ESCAPE)); + ctx.visit(function(N_ENDS_WITH, BOOLEAN, string, suffix)); break; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/EndsWithIgnoreCase.java b/jOOQ/src/main/java/org/jooq/impl/EndsWithIgnoreCase.java index 4ed70a703b..e901358915 100644 --- a/jOOQ/src/main/java/org/jooq/impl/EndsWithIgnoreCase.java +++ b/jOOQ/src/main/java/org/jooq/impl/EndsWithIgnoreCase.java @@ -100,13 +100,14 @@ implements - case CLICKHOUSE: - case DUCKDB: - ctx.visit(string.lower().endsWith(suffix.lower())); - break; + + + + + default: - ctx.visit(string.likeIgnoreCase(DSL.concat(inline("%"), Tools.escapeForLike(suffix, ctx.configuration())), Tools.ESCAPE)); + ctx.visit(string.lower().endsWith(suffix.lower())); break; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Like.java b/jOOQ/src/main/java/org/jooq/impl/Like.java index 399b969140..2cc53eeb13 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Like.java +++ b/jOOQ/src/main/java/org/jooq/impl/Like.java @@ -178,20 +178,14 @@ implements case SIMILAR_TO: case NOT_LIKE: case NOT_SIMILAR_TO: - if (!arg1.getDataType().isString() && REQUIRES_CAST_ON_LIKE.contains(ctx.dialect())) - arg1 = castIfNeeded(arg1, String.class); - if (!arg2.getDataType().isString() && REQUIRES_CAST_ON_LIKE.contains(ctx.dialect())) - arg2 = castIfNeeded(arg2, String.class); - + arg1 = requiresStringCastOnLike(ctx, arg1); + arg2 = requiresStringCastOnLike(ctx, arg2); break; case LIKE_IGNORE_CASE: case NOT_LIKE_IGNORE_CASE: - if (!arg1.getDataType().isString()) - arg1 = castIfNeeded(arg1, String.class); - if (!arg2.getDataType().isString()) - arg2 = castIfNeeded(arg2, String.class); - + arg1 = requiresStringCast(arg1); + arg2 = requiresStringCast(arg2); break; } @@ -226,6 +220,20 @@ implements } } + static final Field requiresStringCastOnLike(Context ctx, Field arg1) { + if (!arg1.getDataType().isString() && REQUIRES_CAST_ON_LIKE.contains(ctx.dialect())) + arg1 = castIfNeeded(arg1, String.class); + + return (Field) arg1; + } + + static final Field requiresStringCast(Field arg1) { + if (!arg1.getDataType().isString()) + arg1 = castIfNeeded(arg1, String.class); + + return (Field) arg1; + } + diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index d9f1cdaa65..4d2fcded2b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -458,6 +458,7 @@ final class Names { static final Name N_DENSE_RANK = systemName("dense_rank"); static final Name N_DIGITS = systemName("digits"); static final Name N_E = systemName("e"); + static final Name N_ENDS_WITH = systemName("ends_with"); static final Name N_EXCLUDED = systemName("excluded"); static final Name N_EXECUTE = systemName("execute"); static final Name N_EXISTS = systemName("exists"); diff --git a/jOOQ/src/main/java/org/jooq/impl/StartsWith.java b/jOOQ/src/main/java/org/jooq/impl/StartsWith.java index b7c1892c31..7883c4275b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/StartsWith.java +++ b/jOOQ/src/main/java/org/jooq/impl/StartsWith.java @@ -111,6 +111,9 @@ implements + + + @@ -163,6 +166,10 @@ implements + + + + @@ -179,7 +186,7 @@ implements case POSTGRES: case SQLITE: case YUGABYTEDB: - ctx.visit(string.like(DSL.concat(Tools.escapeForLike(prefix, ctx.configuration()), inline("%")), Tools.ESCAPE)); + ctx.visit(DSL.position(Like.requiresStringCast(string), Like.requiresStringCast(prefix)).eq(inline(1))); break; case DUCKDB: diff --git a/jOOQ/src/main/java/org/jooq/impl/StartsWithIgnoreCase.java b/jOOQ/src/main/java/org/jooq/impl/StartsWithIgnoreCase.java index 8806dc2663..0c317bb8e3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/StartsWithIgnoreCase.java +++ b/jOOQ/src/main/java/org/jooq/impl/StartsWithIgnoreCase.java @@ -100,14 +100,14 @@ implements - case CLICKHOUSE: - case DUCKDB: - case TRINO: - ctx.visit(string.lower().startsWith(prefix.lower())); - break; + + + + + default: - ctx.visit(string.likeIgnoreCase(DSL.concat(Tools.escapeForLike(prefix, ctx.configuration()), inline("%")), Tools.ESCAPE)); + ctx.visit(string.lower().startsWith(prefix.lower())); break; } }