From 9982fa3682a9452383bab436b2057afac41fcea6 Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Fri, 24 Mar 2023 17:37:34 +1300 Subject: [PATCH] Refactor SpiExpressionRequest split append() into append() and parse() - append() adds to the sql with NO parsing - parse() adds to the sql with parsing to replace logical bean paths into table alias placeholder + db column --- .../api/SpiExpressionRequest.java | 5 ++ .../server/deploy/BeanPropertyAssocMany.java | 2 +- .../expression/AllEqualsExpression.java | 8 +- .../server/expression/BetweenExpression.java | 2 +- .../expression/BetweenPropertyExpression.java | 8 +- .../CaseInsensitiveEqualExpression.java | 4 +- .../expression/DefaultExpressionRequest.java | 13 ++- .../expression/ExistsQueryExpression.java | 4 +- .../server/expression/IdExpression.java | 10 +-- .../server/expression/IdInExpression.java | 20 ++--- .../server/expression/InExpression.java | 7 +- .../server/expression/InPairsExpression.java | 7 +- .../server/expression/InRangeExpression.java | 2 +- .../server/expression/IsEmptyExpression.java | 7 +- .../server/expression/LikeExpression.java | 4 +- .../expression/NativeILikeExpression.java | 4 +- .../server/expression/NullExpression.java | 8 +- .../server/expression/RawExpression.java | 8 +- .../server/expression/SimpleExpression.java | 11 ++- .../server/expression/SubQueryExpression.java | 2 +- .../expression/platform/BaseDbExpression.java | 4 +- .../expression/platform/H2DbExpression.java | 2 +- .../expression/platform/HanaDbExpression.java | 8 +- .../platform/MariaDbExpression.java | 3 +- .../platform/MySqlDbExpression.java | 3 +- .../platform/OracleDbExpression.java | 7 +- .../platform/PostgresDbExpression.java | 24 +++--- .../platform/SqlServerDbExpression.java | 3 +- .../server/query/CQueryPredicates.java | 80 ++++--------------- .../expression/TDSpiExpressionRequest.java | 6 ++ 30 files changed, 97 insertions(+), 179 deletions(-) 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 e61c9479e..cd68c4a5c 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java +++ b/ebean-core/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java @@ -36,6 +36,11 @@ public interface SpiExpressionRequest { */ SpiExpressionRequest append(String sql); + /** + * Append to the expression sql with logical property parsing to db columns with logical path prefix. + */ + SpiExpressionRequest parse(String sql); + /** * Add an encryption key to bind to this request. */ diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java index 0cd13f64b..bd80bc795 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java @@ -416,7 +416,7 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc implements ST public String assocIsEmpty(SpiExpressionRequest request, String path) { boolean softDelete = targetDescriptor.isSoftDelete(); boolean needsX2Table = softDelete || extraWhere() != null; - StringBuilder sb = new StringBuilder(50); + StringBuilder sb = new StringBuilder(50).append("from "); // use from to stop parsing on table name SpiQuery query = request.getQueryRequest().query(); if (hasJoinTable()) { sb.append(query.isAsDraft() ? intersectionDraftTable : intersectionPublishTable); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/AllEqualsExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/AllEqualsExpression.java index 52d31c6dc..944e3375b 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/AllEqualsExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/AllEqualsExpression.java @@ -1,10 +1,6 @@ package io.ebeaninternal.server.expression; -import io.ebeaninternal.api.BindValuesKey; -import io.ebeaninternal.api.ManyWhereJoins; -import io.ebeaninternal.api.SpiExpression; -import io.ebeaninternal.api.SpiExpressionRequest; -import io.ebeaninternal.api.SpiExpressionValidation; +import io.ebeaninternal.api.*; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.el.ElPropertyDeploy; @@ -80,7 +76,7 @@ final class AllEqualsExpression extends NonPrepareExpression { if (count > 0) { request.append("and "); } - request.append(name(propName)); + request.parse(name(propName)); if (value == null) { request.append(" is null "); } else { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/BetweenExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/BetweenExpression.java index 36b0260d0..e7f480cb7 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/BetweenExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/BetweenExpression.java @@ -52,7 +52,7 @@ final class BetweenExpression extends AbstractExpression { if (prop != null && prop.isDbEncrypted()) { pname = prop.beanProperty().decryptProperty(propName); } - request.append(pname).append(_BETWEEN); + request.parse(pname).append(_BETWEEN); } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/BetweenPropertyExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/BetweenPropertyExpression.java index 0dfa1fc33..40f38428d 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/BetweenPropertyExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/BetweenPropertyExpression.java @@ -1,11 +1,7 @@ package io.ebeaninternal.server.expression; import io.ebean.util.SplitName; -import io.ebeaninternal.api.BindValuesKey; -import io.ebeaninternal.api.ManyWhereJoins; -import io.ebeaninternal.api.SpiExpression; -import io.ebeaninternal.api.SpiExpressionRequest; -import io.ebeaninternal.api.SpiExpressionValidation; +import io.ebeaninternal.api.*; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.el.ElPropertyDeploy; @@ -85,7 +81,7 @@ final class BetweenPropertyExpression extends NonPrepareExpression { @Override public void addSql(SpiExpressionRequest request) { - request.append(" ?").append(BETWEEN).append(name(lowProperty)).append(" and ").append(name(highProperty)); + request.append(" ?").append(BETWEEN).parse(name(lowProperty)).append(" and ").parse(name(highProperty)); } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/CaseInsensitiveEqualExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/CaseInsensitiveEqualExpression.java index 0d9f39fc5..d1010f501 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/CaseInsensitiveEqualExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/CaseInsensitiveEqualExpression.java @@ -52,9 +52,9 @@ final class CaseInsensitiveEqualExpression extends AbstractValueExpression { pname = prop.beanProperty().decryptProperty(propName); } if (not) { - request.append("lower(").append(pname).append(") != ?"); + request.append("lower(").parse(pname).append(") != ?"); } else { - request.append("lower(").append(pname).append(") = ?"); + request.append("lower(").parse(pname).append(") = ?"); } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java index d1b1f4040..8ce43712d 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java @@ -2,12 +2,12 @@ package io.ebeaninternal.server.expression; import io.ebeaninternal.api.SpiExpressionList; import io.ebeaninternal.api.SpiExpressionRequest; +import io.ebeaninternal.server.bind.DataBind; import io.ebeaninternal.server.core.SpiOrmQueryRequest; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.deploy.DeployParser; import io.ebeaninternal.server.expression.platform.DbExpressionHandler; import io.ebeaninternal.server.persist.Binder; -import io.ebeaninternal.server.bind.DataBind; import java.sql.SQLException; import java.util.ArrayList; @@ -73,7 +73,6 @@ public final class DefaultExpressionRequest implements SpiExpressionRequest { @Override public String parseDeploy(String logicalProp) { - String s = deployParser.getDeployWord(logicalProp); return s == null ? logicalProp : s; } @@ -120,6 +119,16 @@ public final class DefaultExpressionRequest implements SpiExpressionRequest { return this; } + @Override + public SpiExpressionRequest parse(String expression) { + if (deployParser == null) { + sql.append(expression); + } else { + sql.append(deployParser.parse(expression)); + } + return this; + } + @Override public void addBindEncryptKey(Object bindValue) { bindValues.add(bindValue); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/ExistsQueryExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/ExistsQueryExpression.java index 4a8717e4c..30b40d53f 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/ExistsQueryExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/ExistsQueryExpression.java @@ -95,9 +95,7 @@ final class ExistsQueryExpression implements SpiExpression, UnsupportedDocStoreE if (not) { request.append(" not"); } - request.append(" exists ("); - request.append(sql); - request.append(")"); + request.append(" exists (").parse(sql).append(")"); } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/IdExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/IdExpression.java index 34e49bcc1..012cafad0 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/IdExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/IdExpression.java @@ -1,10 +1,6 @@ package io.ebeaninternal.server.expression; -import io.ebeaninternal.api.BindValuesKey; -import io.ebeaninternal.api.ManyWhereJoins; -import io.ebeaninternal.api.SpiExpression; -import io.ebeaninternal.api.SpiExpressionRequest; -import io.ebeaninternal.api.SpiExpressionValidation; +import io.ebeaninternal.api.*; import io.ebeaninternal.server.deploy.BeanDescriptor; import java.io.IOException; @@ -62,11 +58,9 @@ final class IdExpression extends NonPrepareExpression implements SpiExpression { @Override public void addSql(SpiExpressionRequest request) { - DefaultExpressionRequest r = (DefaultExpressionRequest) request; String idSql = r.getBeanDescriptor().idBinderIdSql(null); - - request.append(idSql); + request.parse(idSql); } /** diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/IdInExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/IdInExpression.java index 6e5b5a62a..b3ad3c75a 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/IdInExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/IdInExpression.java @@ -1,21 +1,13 @@ package io.ebeaninternal.server.expression; import io.ebean.event.BeanQueryRequest; -import io.ebeaninternal.api.BindValuesKey; -import io.ebeaninternal.api.ManyWhereJoins; -import io.ebeaninternal.api.SpiExpression; -import io.ebeaninternal.api.SpiExpressionRequest; -import io.ebeaninternal.api.SpiExpressionValidation; +import io.ebeaninternal.api.*; import io.ebeaninternal.server.core.BindPadding; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.deploy.id.IdBinder; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Set; +import java.util.*; /** * In a collection of ID values. @@ -74,7 +66,6 @@ public final class IdInExpression extends NonPrepareExpression implements IdInCo return; } // Bind the ID values including EmbeddedId and multiple ID - DefaultExpressionRequest r = (DefaultExpressionRequest) request; BeanDescriptor descriptor = r.getBeanDescriptor(); IdBinder idBinder = descriptor.idBinder(); @@ -85,14 +76,13 @@ public final class IdInExpression extends NonPrepareExpression implements IdInCo * For use with deleting non-attached detail beans during stateless update. */ public void addSqlNoAlias(SpiExpressionRequest request) { - DefaultExpressionRequest r = (DefaultExpressionRequest) request; BeanDescriptor descriptor = r.getBeanDescriptor(); IdBinder idBinder = descriptor.idBinder(); if (idCollection.isEmpty()) { request.append(SQL_FALSE); // append false for this stage } else { - request.append(descriptor.idBinder().getBindIdInSql(null)); + request.parse(descriptor.idBinder().getBindIdInSql(null)); String inClause = idBinder.getIdInValueExpr(false, idCollection.size()); request.append(inClause); } @@ -106,10 +96,10 @@ public final class IdInExpression extends NonPrepareExpression implements IdInCo request.append(SQL_FALSE); // append false for this stage } else { if (idBinder.isComplexId()) { - request.append(descriptor.idBinderInLHSSql()); + request.parse(descriptor.idBinderInLHSSql()); request.append(idBinder.getIdInValueExpr(false, idCollection.size())); } else { - request.append(idBinder.getBeanProperty().name()); + request.parse(idBinder.getBeanProperty().name()); request.appendInExpression(false, idCollection); } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/InExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/InExpression.java index 127f849e9..02d301e6d 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/InExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/InExpression.java @@ -156,21 +156,20 @@ public final class InExpression extends AbstractExpression implements IdInCommon request.append(not ? SQL_TRUE : SQL_FALSE); return; } - ElPropertyValue prop = getElProp(request); if (prop != null) { if (prop.isAssocId()) { - request.append(prop.assocIdInExpr(propName)); + request.parse(prop.assocIdInExpr(propName)); request.append(prop.assocIdInValueExpr(not, bindValues.size())); return; } if (prop.isDbEncrypted()) { - request.append(prop.beanProperty().decryptProperty(propName)); + request.parse(prop.beanProperty().decryptProperty(propName)); request.appendInExpression(not, bindValues); return; } } - request.append(propName); + request.parse(propName); request.appendInExpression(not, bindValues); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/InPairsExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/InPairsExpression.java index 5066b4047..e654c7d92 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/InPairsExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/InPairsExpression.java @@ -85,14 +85,11 @@ final class InPairsExpression extends AbstractExpression { @Override public void addSql(SpiExpressionRequest request) { - if (entries.isEmpty()) { - String expr = not ? SQL_TRUE : SQL_FALSE; - request.append(expr); + request.append(not ? SQL_TRUE : SQL_FALSE); return; } - - request.append(request.getDbPlatformHandler().concat(property0, separator, property1, suffix)); + request.parse(request.getDbPlatformHandler().concat(property0, separator, property1, suffix)); request.appendInExpression(not, concatBindValues); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/InRangeExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/InRangeExpression.java index b0d2522c4..be455e71e 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/InRangeExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/InRangeExpression.java @@ -55,7 +55,7 @@ final class InRangeExpression extends AbstractExpression { if (prop != null && prop.isDbEncrypted()) { pname = prop.beanProperty().decryptProperty(propName); } - request.append("(").append(pname).append(" >= ? and ").append(pname).append(" < ?)"); + request.append("(").parse(pname).append(" >= ? and ").parse(pname).append(" < ?)"); } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/IsEmptyExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/IsEmptyExpression.java index e635d4ea0..de426f425 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/IsEmptyExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/IsEmptyExpression.java @@ -1,12 +1,12 @@ package io.ebeaninternal.server.expression; +import io.ebean.util.SplitName; import io.ebeaninternal.api.BindValuesKey; import io.ebeaninternal.api.ManyWhereJoins; import io.ebeaninternal.api.SpiExpression; import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.el.ElPropertyValue; -import io.ebean.util.SplitName; import java.io.IOException; @@ -78,13 +78,12 @@ final class IsEmptyExpression extends AbstractExpression { * Append an exists subQuery for the property. */ static void isEmptySql(SpiExpressionRequest request, ElPropertyValue prop, boolean empty, String propertyPath) { - if (empty) { request.append("not "); } request - .append("exists (select 1 from ") - .append(prop.assocIsEmpty(request, propertyPath)) + .append("exists (select 1 ") + .parse(prop.assocIsEmpty(request, propertyPath)) .append(")"); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/LikeExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/LikeExpression.java index e0b137154..e85d984d3 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/LikeExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/LikeExpression.java @@ -44,9 +44,9 @@ final class LikeExpression extends AbstractValueExpression { pname = prop.beanProperty().decryptProperty(propName); } if (caseInsensitive) { - request.append("lower(").append(pname).append(")"); + request.append("lower(").parse(pname).append(")"); } else { - request.append(pname); + request.parse(pname); } if (type == LikeType.EQUAL_TO) { request.append(" = ?"); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/NativeILikeExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/NativeILikeExpression.java index 9977c92e2..9527e922d 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/NativeILikeExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/NativeILikeExpression.java @@ -36,14 +36,12 @@ final class NativeILikeExpression extends AbstractExpression { @Override public void addSql(SpiExpressionRequest request) { - String pname = propName; ElPropertyValue prop = getElProp(request); if (prop != null && prop.isDbEncrypted()) { pname = prop.beanProperty().decryptProperty(propName); } - - request.append(pname).append(" ilike ?"); + request.parse(pname).append(" ilike ?"); } /** diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/NullExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/NullExpression.java index 0c3eb00b5..ab1f1a7c3 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/NullExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/NullExpression.java @@ -57,18 +57,16 @@ final class NullExpression extends AbstractExpression { @Override public void addSql(SpiExpressionRequest request) { - if (assocMany) { - // translate to exists subquery + // translate to exists sub-query IsEmptyExpression.isEmptySql(request, elProperty, !notNull, propertyPath); return; } - String nullExpr = notNull ? " is not null" : " is null"; if (elProperty != null && elProperty.isAssocId()) { - request.append(elProperty.assocIdExpression(propName, nullExpr)); + request.parse(elProperty.assocIdExpression(propName, nullExpr)); } else { - request.append(propName).append(nullExpr); + request.parse(propName).append(nullExpr); } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/RawExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/RawExpression.java index 53571cad7..72c968e28 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/RawExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/RawExpression.java @@ -1,10 +1,6 @@ package io.ebeaninternal.server.expression; -import io.ebeaninternal.api.BindValuesKey; -import io.ebeaninternal.api.ManyWhereJoins; -import io.ebeaninternal.api.SpiExpression; -import io.ebeaninternal.api.SpiExpressionRequest; -import io.ebeaninternal.api.SpiExpressionValidation; +import io.ebeaninternal.api.*; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.persist.MultiValueWrapper; @@ -57,7 +53,7 @@ final class RawExpression extends NonPrepareExpression { @Override public void addSql(SpiExpressionRequest request) { - request.append(sql); + request.parse(sql); } /** diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/SimpleExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/SimpleExpression.java index 5c3efb5e0..21b4a452c 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/SimpleExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/SimpleExpression.java @@ -2,11 +2,11 @@ package io.ebeaninternal.server.expression; import io.ebean.bean.EntityBean; import io.ebean.plugin.ExpressionPath; +import io.ebeaninternal.api.BindValuesKey; +import io.ebeaninternal.api.NaturalKeyQueryData; import io.ebeaninternal.api.SpiExpression; import io.ebeaninternal.api.SpiExpressionRequest; import io.ebeaninternal.server.el.ElPropertyValue; -import io.ebeaninternal.api.BindValuesKey; -import io.ebeaninternal.api.NaturalKeyQueryData; import java.io.IOException; import java.util.Arrays; @@ -97,20 +97,19 @@ public final class SimpleExpression extends AbstractValueExpression { @Override public void addSql(SpiExpressionRequest request) { - ElPropertyValue prop = getElProp(request); if (prop != null) { if (prop.isAssocId()) { - request.append(prop.assocIdExpression(propName, type.bind())); + request.parse(prop.assocIdExpression(propName, type.bind())); return; } if (prop.isDbEncrypted()) { String dsql = prop.beanProperty().decryptProperty(propName); - request.append(dsql).append(type.bind()); + request.parse(dsql).append(type.bind()); return; } } - request.append(propName).append(type.bind()); + request.parse(propName).append(type.bind()); } /** diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/SubQueryExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/SubQueryExpression.java index 8a2ae7c80..aaa5a0eb6 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/SubQueryExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/SubQueryExpression.java @@ -90,7 +90,7 @@ final class SubQueryExpression extends AbstractExpression implements Unsupported @Override public void addSql(SpiExpressionRequest request) { - request.append(propName).append(op.expression).append("(").append(sql).append(")"); + request.parse(propName).append(op.expression).append("(").parse(sql).append(")"); } @Override 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 a8d4d6adc..420e91451 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 @@ -11,7 +11,7 @@ abstract class BaseDbExpression implements DbExpressionHandler { @Override public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { String bitOp = bitOp(operator); - request.append("(").append(propName).append(" ").append(bitOp).append(" ? ").append(compare).append(" ?)"); + request.append("(").parse(propName).append(" ").append(bitOp).append(" ? ").append(compare).append(" ?)"); } private String bitOp(BitwiseOp operator) { @@ -30,7 +30,7 @@ abstract class BaseDbExpression implements DbExpressionHandler { */ protected void bitwiseFunction(SpiExpressionRequest request, String propName, BitwiseOp operator, String compare) { String funcName = functionName(operator); - request.append(funcName).append("(").append(propName).append(", ?) ").append(compare).append(" ?"); + request.append(funcName).append("(").parse(propName).append(", ?) ").append(compare).append(" ?"); } protected String functionName(BitwiseOp operator) { 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 60cb180d3..b3fcd3d37 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 @@ -11,6 +11,6 @@ final class H2DbExpression extends BasicDbExpression { @Override public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) { String funcName = functionName(operator); - request.append(funcName).append("(").append(propName).append(", cast(? as long)) ").append(compare).append(" cast(? as long)"); + request.append(funcName).append("(").parse(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 43919c1a0..1abd754f6 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 @@ -16,13 +16,12 @@ final class HanaDbExpression extends BaseDbExpression { @Override public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { - request.append("json_value(").append(propName).append(", '$.").append(path).append("')"); - request.append(operator.bind()); + request.append("json_value(").parse(propName).append(", '$.").append(path).append("')").append(operator.bind()); } @Override public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) { - request.append("cardinality(").append(propName).append(")"); + request.append("cardinality(").parse(propName).append(")"); if (empty) { request.append(" = 0"); } else { @@ -51,8 +50,7 @@ final class HanaDbExpression extends BaseDbExpression { if (!contains) { request.append(" not "); } - request.append(" member of ").append(propName).append(")"); - + request.append(" member of ").parse(propName).append(")"); } } 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 8116b2c4e..d525ca152 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 @@ -10,7 +10,6 @@ final class MariaDbExpression extends BasicDbExpression { @Override public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { - request.append("(").append(propName).append(" ->> '$.").append(path).append("')"); - request.append(operator.bind()); + request.append("(").parse(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 b0721a44e..f4d9ba7ff 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 @@ -10,8 +10,7 @@ final class MySqlDbExpression extends BasicDbExpression { @Override public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { - request.append("(").append(propName).append(" ->> '$.").append(path).append("')"); - request.append(operator.bind()); + request.append("(").parse(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 f1fbaef7a..51412d05b 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 @@ -17,12 +17,11 @@ final class OracleDbExpression extends BaseDbExpression { @Override public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { if (operator == Op.EXISTS) { - request.append("json_exists(").append(propName).append(", '$.").append(path).append("')"); + request.append("json_exists(").parse(propName).append(", '$.").append(path).append("')"); } else if (operator == Op.NOT_EXISTS) { - request.append("not json_exists(").append(propName).append(", '$.").append(path).append("')"); + request.append("not json_exists(").parse(propName).append(", '$.").append(path).append("')"); } else { - request.append("json_value(").append(propName).append(", '$.").append(path).append("')"); - request.append(operator.bind()); + request.append("json_value(").parse(propName).append(", '$.").append(path).append("')").append(operator.bind()); } } 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 a3f044072..541228e1a 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 @@ -15,27 +15,22 @@ final class PostgresDbExpression extends BaseDbExpression { @Override public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) { - StringBuilder sb = new StringBuilder(50); String[] paths = path.split("\\."); if (paths.length == 1) { // (t0.content ->> 'title') = 'Some value' - sb.append("(").append(propName).append(" ->> '").append(path).append("')"); - + request.append("(").parse(propName).append(" ->> '").append(path).append("')"); } else { // (t0.content #>> '{path,inner}') = 'Some value' - sb.append("(").append(propName).append(" #>> '{"); + request.append("(").parse(propName).append(" #>> '{"); for (int i = 0; i < paths.length; i++) { if (i > 0) { - sb.append(","); + request.append(","); } - sb.append(paths[i]); + request.append(paths[i]); } - sb.append("}')"); + request.append("}')"); } - - request.append(sb.toString()); - request.append(PostgresCast.cast(value)); - request.append(operator.bind()); + request.append(PostgresCast.cast(value)).append(operator.bind()); } @Override @@ -43,12 +38,11 @@ final class PostgresDbExpression extends BaseDbExpression { if (!contains) { request.append("not ("); } - request.append(propName).append(" @> array[?"); + request.parse(propName).append(" @> array[?"); for (int i = 1; i < values.length; i++) { request.append(",?"); } - request.append("]"); - request.append(PostgresCast.cast(values[0], true)); + request.append("]").append(PostgresCast.cast(values[0], true)); if (!contains) { request.append(")"); } @@ -56,7 +50,7 @@ final class PostgresDbExpression extends BaseDbExpression { @Override public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) { - request.append("coalesce(cardinality(").append(propName).append("),0)"); + request.append("coalesce(cardinality(").parse(propName).append("),0)"); if (empty) { request.append(" = 0"); } else { 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 78838a81e..afeae8be8 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 @@ -11,8 +11,7 @@ final class SqlServerDbExpression extends BaseDbExpression { @Override public void json(final SpiExpressionRequest request, final String propName, final String path, final Op operator, final Object value) { - request.append("json_value(").append(propName).append(", '$.").append(path).append("')"); - request.append(operator.bind()); + request.append("json_value(").parse(propName).append(", '$.").append(path).append("')").append(operator.bind()); } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPredicates.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPredicates.java index 1577768c1..f40b6dffb 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPredicates.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPredicates.java @@ -5,6 +5,7 @@ import io.ebeaninternal.api.BindParams; import io.ebeaninternal.api.CoreLog; import io.ebeaninternal.api.SpiExpressionList; import io.ebeaninternal.api.SpiQuery; +import io.ebeaninternal.server.bind.DataBind; import io.ebeaninternal.server.core.OrmQueryRequest; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.deploy.BeanPropertyAssocMany; @@ -14,7 +15,6 @@ import io.ebeaninternal.server.persist.Binder; import io.ebeaninternal.server.querydefn.OrmQueryProperties; import io.ebeaninternal.server.querydefn.OrmUpdateProperties; import io.ebeaninternal.server.rawsql.SpiRawSql; -import io.ebeaninternal.server.bind.DataBind; import io.ebeaninternal.server.util.BindParamsParser; import java.sql.Connection; @@ -47,26 +47,14 @@ public final class CQueryPredicates { private final Object idValue; private final BindParams bindParams; private DefaultExpressionRequest filterMany; - /** - * SQL generated from the where expressions. - */ - private String filterManyExprSql; /** * Bind values from the where expressions. */ private DefaultExpressionRequest where; - /** - * SQL generated from the where expressions. - */ - private String whereExprSql; /** * Bind values for having expression. */ private DefaultExpressionRequest having; - /** - * SQL generated from the having expression. - */ - private String havingExprSql; private String dbHaving; /** * logicalWhere with property names converted to db columns. @@ -190,70 +178,46 @@ public final class CQueryPredicates { buildUpdateClause(buildSql, deployParser); buildBindWhereRawSql(buildSql); + BeanPropertyAssocMany manyProperty = request.determineMany(); + if (buildSql) { + String logicalOrderBy = deriveOrderByWithMany(request.manyPropertyForOrderBy()); + if (logicalOrderBy != null) { + dbOrderBy = deployParser.parse(logicalOrderBy); + } + // create a copy of the includes required to support the orderBy + orderByIncludes = new HashSet<>(deployParser.getIncludes()); + } SpiExpressionList whereExp = query.getWhereExpressions(); if (whereExp != null) { this.where = new DefaultExpressionRequest(request, deployParser, binder, whereExp); if (buildSql) { - whereExprSql = where.buildSql(); + dbWhere = where.buildSql(); } } - BeanPropertyAssocMany manyProperty = request.determineMany(); if (manyProperty != null) { OrmQueryProperties chunk = query.getDetail().getChunk(manyProperty.name(), false); SpiExpressionList filterManyExpr = chunk.getFilterMany(); if (filterManyExpr != null) { this.filterMany = new DefaultExpressionRequest(request, deployParser, binder, filterManyExpr); if (buildSql) { - filterManyExprSql = filterMany.buildSql(); + dbFilterMany = filterMany.buildSql(); } } } - // having expression SpiExpressionList havingExpr = query.getHavingExpressions(); if (havingExpr != null) { this.having = new DefaultExpressionRequest(request, deployParser, binder, havingExpr); if (buildSql) { - havingExprSql = having.buildSql(); + dbHaving = having.buildSql(); } } if (buildSql) { - parsePropertiesToDbColumns(deployParser); + predicateIncludes = deployParser.getIncludes(); } } /** - * Parse/Convert property names to database columns in the where and order by - * clauses etc. - */ - private void parsePropertiesToDbColumns(DeployParser deployParser) { - // order by is dependent on the manyProperty (if there is one) - String logicalOrderBy = deriveOrderByWithMany(request.manyPropertyForOrderBy()); - if (logicalOrderBy != null) { - dbOrderBy = deployParser.parse(logicalOrderBy); - } - // create a copy of the includes required to support the orderBy - orderByIncludes = new HashSet<>(deployParser.getIncludes()); - dbWhere = deriveWhere(deployParser); - dbFilterMany = deriveFilterMany(deployParser); - dbHaving = deriveHaving(deployParser); - // all includes, including ones for manyWhere clause - predicateIncludes = deployParser.getIncludes(); - } - - private String deriveFilterMany(DeployParser deployParser) { - if (isEmpty(filterManyExprSql)) { - return null; - } else { - return deployParser.parse(filterManyExprSql); - } - } - - private String deriveWhere(DeployParser deployParser) { - return parse(whereExprSql, deployParser); - } - - /** - * Replace the table alias place holders. + * Replace the table alias place-holders. */ void parseTableAlias(SqlTreeAlias alias) { if (dbWhere != null) { @@ -272,20 +236,6 @@ public final class CQueryPredicates { } } - private boolean isEmpty(String s) { - return s == null || s.isEmpty(); - } - - private String parse(String expr, DeployParser deployParser) { - if (expr == null) return ""; - if (expr.isEmpty()) return expr; - return deployParser.parse(expr); - } - - private String deriveHaving(DeployParser deployParser) { - return parse(havingExprSql, deployParser); - } - private String parseOrderBy() { OrderBy orderBy = query.getOrderBy(); if (orderBy == null) { diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java b/ebean-core/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java index 5bd44e3de..a84d3b046 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java @@ -49,6 +49,12 @@ public class TDSpiExpressionRequest implements SpiExpressionRequest { return this; } + @Override + public SpiExpressionRequest parse(String expression) { + sql.append(expression); + return this; + } + @Override public void addBindEncryptKey(Object encryptKey) {