From 0816810d3b0718bc7df88da3d2b39d155455bbcc Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Thu, 7 Mar 2024 22:45:21 +1300 Subject: [PATCH] Refactor extract DbExpressionRequest interface for db platform specific expressions This provides a simpler DbExpressionRequest interface for db platform specific expression adapters (rather than the SpiExpressionRequest which has more features that we don't wish to expose to those expression adapters. --- .../api/SpiExpressionRequest.java | 6 ++++- .../expression/platform/BaseDbExpression.java | 5 ++--- .../platform/BasicDbExpression.java | 7 +++--- .../platform/DbExpressionHandler.java | 9 ++++---- .../platform/DbExpressionRequest.java | 22 +++++++++++++++++++ .../expression/platform/H2DbExpression.java | 3 +-- .../expression/platform/HanaDbExpression.java | 9 ++++---- .../platform/MariaDbExpression.java | 3 +-- .../platform/MySqlDbExpression.java | 3 +-- .../platform/OracleDbExpression.java | 9 ++++---- .../platform/PostgresDbExpression.java | 7 +++--- .../platform/SqlServerDbExpression.java | 7 +++--- 12 files changed, 53 insertions(+), 37 deletions(-) create mode 100644 ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionRequest.java diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java b/ebean-core/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java index 1b90140ee..b96317547 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java +++ b/ebean-core/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java @@ -3,13 +3,14 @@ package io.ebeaninternal.api; import io.ebeaninternal.server.core.SpiOrmQueryRequest; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.expression.platform.DbExpressionHandler; +import io.ebeaninternal.server.expression.platform.DbExpressionRequest; import java.util.List; /** * Request object used for gathering expression sql and bind values. */ -public interface SpiExpressionRequest { +public interface SpiExpressionRequest extends DbExpressionRequest { /** * Return the DB specific handler for JSON and ARRAY expressions. @@ -34,11 +35,13 @@ public interface SpiExpressionRequest { /** * Append to the expression sql without any parsing. */ + @Override SpiExpressionRequest append(String expression); /** * Append to the expression sql without any parsing. */ + @Override SpiExpressionRequest append(char c); /** @@ -47,6 +50,7 @@ public interface SpiExpressionRequest { * This is a fast path case when expression is a bean property path and falls back to using parse() * when that isn't the case. */ + @Override SpiExpressionRequest property(String expression); /** diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java index a91131d53..e2007715d 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.BitwiseOp; /** @@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.BitwiseOp; abstract class BaseDbExpression implements DbExpressionHandler { @Override - public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { + public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { final String bitOp = bitOp(operator); request.append('(').property(propName).append(' ').append(bitOp).append(" ? ").append(compare).append(" ?)"); } @@ -28,7 +27,7 @@ abstract class BaseDbExpression implements DbExpressionHandler { /** * Common alternative where the bitwise operation is a function (specifically bitand is used - H2 and Oracle). */ - protected void bitwiseFunction(SpiExpressionRequest request, String propName, BitwiseOp operator, String compare) { + protected void bitwiseFunction(DbExpressionRequest request, String propName, BitwiseOp operator, String compare) { final String funcName = functionName(operator); request.append(funcName).append('(').property(propName).append(", ?) ").append(compare).append(" ?"); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/BasicDbExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/BasicDbExpression.java index edecf8230..4f64e58fd 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/BasicDbExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/BasicDbExpression.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.Op; /** @@ -9,17 +8,17 @@ import io.ebeaninternal.server.expression.Op; class BasicDbExpression extends BaseDbExpression { @Override - public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { + public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) { throw new RuntimeException("JSON expressions only supported on Postgres and Oracle"); } @Override - public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) { + public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) { throw new RuntimeException("ARRAY expressions only supported on Postgres"); } @Override - public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) { + public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) { throw new RuntimeException("ARRAY expressions only supported on Postgres"); } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandler.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandler.java index 93c9dc18a..a376eb4e3 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandler.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandler.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.BitwiseOp; import io.ebeaninternal.server.expression.Op; @@ -12,22 +11,22 @@ public interface DbExpressionHandler { /** * Write the db platform specific json expression. */ - void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value); + void json(DbExpressionRequest request, String propName, String path, Op operator, Object value); /** * Add SQL for ARRAY CONTAINS expression. */ - void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values); + void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values); /** * Add SQL for ARRAY IS EMPTY expression. */ - void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty); + void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty); /** * Add the bitwise expression. */ - void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match); + void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match); /** * Performs a "CONCAT" operation for that platform. diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionRequest.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionRequest.java new file mode 100644 index 000000000..9b14fd33d --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionRequest.java @@ -0,0 +1,22 @@ +package io.ebeaninternal.server.expression.platform; + +/** + * Request building the expression sql. + */ +public interface DbExpressionRequest { + + /** + * Append to the expression sql without any parsing. + */ + DbExpressionRequest append(String expression); + + /** + * Append to the expression sql without any parsing. + */ + DbExpressionRequest append(char c); + + /** + * Append to the expression sql with logical property parsing to db columns with logical path prefix. + */ + DbExpressionRequest property(String expression); +} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java index 8791cfa07..c72f89a66 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.BitwiseOp; /** @@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.BitwiseOp; final class H2DbExpression extends BasicDbExpression { @Override - public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { + public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { final String funcName = functionName(operator); request.append(funcName).append('(').property(propName).append(", cast(? as long)) ").append(compare).append(" cast(? as long)"); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/HanaDbExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/HanaDbExpression.java index 9c8910fca..282500da6 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/HanaDbExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/HanaDbExpression.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.BitwiseOp; import io.ebeaninternal.server.expression.Op; @@ -10,17 +9,17 @@ import io.ebeaninternal.server.expression.Op; final class HanaDbExpression extends BaseDbExpression { @Override - public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { + public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { bitwiseFunction(request, propName, operator, compare); } @Override - public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { + public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) { request.append("json_value(").property(propName).append(", '$.").append(path).append("')").append(operator.bind()); } @Override - public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) { + public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) { request.append("cardinality(").property(propName).append(')'); if (empty) { request.append(" = 0"); @@ -41,7 +40,7 @@ final class HanaDbExpression extends BaseDbExpression { } @Override - public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) { + public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) { for (int i = 0; i < values.length; i++) { if (i > 0) { request.append(" and "); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/MariaDbExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/MariaDbExpression.java index 6e336e642..2622cc2fe 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/MariaDbExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/MariaDbExpression.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.Op; /** @@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.Op; final class MariaDbExpression extends BasicDbExpression { @Override - public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { + public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) { request.append('(').property(propName).append(" ->> '$.").append(path).append("')").append(operator.bind()); } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/MySqlDbExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/MySqlDbExpression.java index 59965abba..0c39856c3 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/MySqlDbExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/MySqlDbExpression.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.Op; /** @@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.Op; final class MySqlDbExpression extends BasicDbExpression { @Override - public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { + public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) { request.append('(').property(propName).append(" ->> '$.").append(path).append("')").append(operator.bind()); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java index d51fbc23a..229aff32a 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.BitwiseOp; import io.ebeaninternal.server.expression.Op; @@ -15,7 +14,7 @@ final class OracleDbExpression extends BaseDbExpression { } @Override - public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { + public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) { if (operator == Op.EXISTS) { request.append("json_exists(").property(propName).append(", '$.").append(path).append("')"); } else if (operator == Op.NOT_EXISTS) { @@ -26,17 +25,17 @@ final class OracleDbExpression extends BaseDbExpression { } @Override - public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { + public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { bitwiseFunction(request, propName, operator, compare); } @Override - public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) { + public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) { throw new IllegalStateException("ARRAY expressions not supported on Oracle"); } @Override - public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) { + public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) { throw new IllegalStateException("ARRAY expressions not supported on Oracle"); } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java index ab036d175..c3c71ae0e 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.Op; /** @@ -14,7 +13,7 @@ final class PostgresDbExpression extends BaseDbExpression { } @Override - public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { + public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) { String[] paths = path.split("\\."); if (paths.length == 1) { // (t0.content ->> 'title') = 'Some value' @@ -34,7 +33,7 @@ final class PostgresDbExpression extends BaseDbExpression { } @Override - public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) { + public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) { if (!contains) { request.append("not ("); } @@ -49,7 +48,7 @@ final class PostgresDbExpression extends BaseDbExpression { } @Override - public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) { + public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) { request.append("coalesce(cardinality(").property(propName).append("),0)"); if (empty) { request.append(" = 0"); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/SqlServerDbExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/SqlServerDbExpression.java index c84482374..bc1d80e1f 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/SqlServerDbExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/platform/SqlServerDbExpression.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.expression.platform; -import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.expression.Op; /** @@ -9,19 +8,19 @@ import io.ebeaninternal.server.expression.Op; final class SqlServerDbExpression extends BaseDbExpression { @Override - public void json(final SpiExpressionRequest request, final String propName, + public void json(final DbExpressionRequest request, final String propName, final String path, final Op operator, final Object value) { request.append("json_value(").property(propName).append(", '$.").append(path).append("')").append(operator.bind()); } @Override - public void arrayContains(final SpiExpressionRequest request, final String propName, + public void arrayContains(final DbExpressionRequest request, final String propName, final boolean contains, final Object... values) { throw new RuntimeException("ARRAY expressions not supported on Microsoft SQL Server"); } @Override - public void arrayIsEmpty(final SpiExpressionRequest request, final String propName, final boolean empty) { + public void arrayIsEmpty(final DbExpressionRequest request, final String propName, final boolean empty) { throw new RuntimeException("ARRAY expressions not supported on Microsoft SQL Server"); } }