From b676476cd257b70f74f60419a093bf3d1972956b Mon Sep 17 00:00:00 2001 From: rbygrave Date: Wed, 11 Aug 2021 20:51:46 +1200 Subject: [PATCH] Add SpiQuery.Type.defaultSelect() for ATTRIBUTE and sub-query type queries --- .../java/io/ebeaninternal/api/SpiQuery.java | 21 +++++++++---- .../server/query/CQueryBuilder.java | 30 ------------------- .../server/querydefn/DefaultOrmQuery.java | 5 ++-- 3 files changed, 18 insertions(+), 38 deletions(-) diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java b/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java index 12a25fed8..5a6ae2217 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java @@ -84,7 +84,7 @@ public interface SpiQuery extends Query, SpiQueryFetch, TxnProfileEventCod /** * Find single attribute. */ - ATTRIBUTE(FIND_ATTRIBUTE, "findAttribute"), + ATTRIBUTE(FIND_ATTRIBUTE, "findAttribute", false, false), /** * Find rowCount. @@ -94,12 +94,12 @@ public interface SpiQuery extends Query, SpiQueryFetch, TxnProfileEventCod /** * A subquery used as part of an exists where clause. */ - SQ_EXISTS(FIND_SUBQUERY, "sqExists"), + SQ_EXISTS(FIND_SUBQUERY, "sqExists", false, false), /** * A subquery used as part of an in where clause. */ - SQ_IN(FIND_SUBQUERY, "sqIn"), + SQ_IN(FIND_SUBQUERY, "sqIn", false, false), /** * Delete query. @@ -112,17 +112,21 @@ public interface SpiQuery extends Query, SpiQueryFetch, TxnProfileEventCod UPDATE(FIND_UPDATE, "update", true); private final boolean update; + private final boolean defaultSelect; private final String profileEventId; private final String label; Type(String profileEventId, String label) { - this(profileEventId, label, false); + this(profileEventId, label, false, true); } - Type(String profileEventId, String label, boolean update) { + this(profileEventId, label, update, true); + } + Type(String profileEventId, String label, boolean update, boolean defaultSelect) { this.profileEventId = profileEventId; this.label = label; this.update = update; + this.defaultSelect = defaultSelect; } /** @@ -132,6 +136,13 @@ public interface SpiQuery extends Query, SpiQueryFetch, TxnProfileEventCod return update; } + /** + * Return true if this allows default select clause. + */ + public boolean defaultSelect() { + return defaultSelect; + } + public String profileEventId() { return profileEventId; } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilder.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilder.java index 41439e4b6..9a4b1d32e 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilder.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilder.java @@ -46,9 +46,7 @@ class CQueryBuilder { private final SqlLimiter sqlLimiter; private final CQueryBuilderRawSql rawSqlHandler; private final Binder binder; - private final boolean selectCountWithAlias; - private final CQueryHistorySupport historySupport; private final CQueryDraftSupport draftSupport; private final DatabasePlatform dbPlatform; @@ -79,7 +77,6 @@ class CQueryBuilder { if (sb.length() > 0) { sb.append(", "); } - sb.append(name); sb.append("."); sb.append(token.trim()); @@ -91,7 +88,6 @@ class CQueryBuilder { * Build the delete query. */ CQueryUpdate buildUpdateQuery(boolean deleteRequest, OrmQueryRequest request) { - SpiQuery query = request.getQuery(); String rootTableAlias = query.getAlias(); query.setupForDeleteOrUpdate(); @@ -105,7 +101,6 @@ class CQueryBuilder { } predicates.prepare(true); - SqlTree sqlTree = createSqlTree(request, predicates); String sql; @@ -114,7 +109,6 @@ class CQueryBuilder { } else { sql = buildUpdateSql(request, rootTableAlias, predicates, sqlTree); } - // cache the query plan queryPlan = new CQueryPlan(request, sql, sqlTree, predicates.getLogWhereSql()); request.putQueryPlan(queryPlan); @@ -122,7 +116,6 @@ class CQueryBuilder { } private String buildDeleteSql(OrmQueryRequest request, String rootTableAlias, CQueryPredicates predicates, SqlTree sqlTree) { - String alias = alias(rootTableAlias); if (sqlTree.noJoins() && !request.getQuery().hasMaxRowsOrFirstRow()) { if (dbPlatform.isSupportsDeleteTableAlias()) { @@ -151,7 +144,6 @@ class CQueryBuilder { } private String buildUpdateSql(OrmQueryRequest request, String rootTableAlias, CQueryPredicates predicates, SqlTree sqlTree) { - StringBuilder sb = new StringBuilder(200); sb.append("update ").append(request.getBeanDescriptor().getBaseTable()); if (rootTableAlias != null) { @@ -159,7 +151,6 @@ class CQueryBuilder { } sb.append(" set ").append(predicates.getDbUpdateClause()); String updateClause = sb.toString(); - if (sqlTree.noJoins() && request.isInlineSqlUpdateLimit()) { // simple - update table set ... where ... return aliasStrip(buildSqlUpdate(updateClause, request, predicates, sqlTree).getSql()); @@ -186,7 +177,6 @@ class CQueryBuilder { } CQueryFetchSingleAttribute buildFetchAttributeQuery(OrmQueryRequest request) { - SpiQuery query = request.getQuery(); query.setSingleAttribute(); if (!query.isIncludeSoftDeletes()) { @@ -218,7 +208,6 @@ class CQueryBuilder { * Build the find ids query. */ CQueryFetchSingleAttribute buildFetchIdsQuery(OrmQueryRequest request) { - SpiQuery query = request.getQuery(); query.setSelectId(); BeanDescriptor desc = request.getBeanDescriptor(); @@ -246,9 +235,7 @@ class CQueryBuilder { * Build the row count query. */ CQueryRowCount buildRowCountQuery(OrmQueryRequest request) { - SpiQuery query = request.getQuery(); - // always set the order by to null for row count query query.setOrder(null); query.setFirstRow(0); @@ -310,7 +297,6 @@ class CQueryBuilder { // cache the query plan queryPlan = new CQueryPlan(request, sql, sqlTree, predicates.getLogWhereSql()); request.putQueryPlan(queryPlan); - return new CQueryRowCount(queryPlan, request, predicates); } @@ -334,9 +320,7 @@ class CQueryBuilder { * names to physical deployment column names. */ CQuery buildQuery(OrmQueryRequest request) { - CQueryPredicates predicates = new CQueryPredicates(binder, request); - CQueryPlan queryPlan = request.getQueryPlan(); if (queryPlan != null) { // Reuse the query plan so skip generating SqlTree and SQL. @@ -370,7 +354,6 @@ class CQueryBuilder { boolean rawSql = request.isRawSql(); if (rawSql) { queryPlan = new CQueryPlanRawSql(request, res, sqlTree, predicates.getLogWhereSql()); - } else { queryPlan = new CQueryPlan(request, res, sqlTree, false, predicates.getLogWhereSql()); } @@ -380,11 +363,9 @@ class CQueryBuilder { // log the query plan based bean type (i.e. ignoring query disabling for logging the sql/plan) desc.getReadAuditLogger().queryPlan(new ReadAuditQueryPlan(desc.getFullName(), queryPlan.getAuditQueryKey(), queryPlan.getSql())); } - // cache the query plan because we can reuse it and also // gather query performance statistics based on it. request.putQueryPlan(queryPlan); - return new CQuery<>(request, predicates, queryPlan); } @@ -393,18 +374,15 @@ class CQueryBuilder { *

* The SqlTree is immutable after construction and so is safe to use by * concurrent threads. - *

*

* The predicates is used to add additional joins that come from the where or * order by clauses that are not already included for the select clause. - *

*/ private SqlTree createSqlTree(OrmQueryRequest request, CQueryPredicates predicates) { return createSqlTree(request, predicates, false); } private SqlTree createSqlTree(OrmQueryRequest request, CQueryPredicates predicates, boolean forceColumnAlias) { - if (request.isNativeSql()) { return createNativeSqlTree(request, predicates); } @@ -423,9 +401,7 @@ class CQueryBuilder { * Create the SqlTree by reading the ResultSetMetaData and mapping table/columns to bean property paths. */ private SqlTree createNativeSqlTree(OrmQueryRequest request, CQueryPredicates predicates) { - SpiQuery query = request.getQuery(); - // parse named parameters returning the final sql to execute String sql = predicates.parseBindParams(query.getNativeSql()); if (query.hasMaxRowsOrFirstRow()) { @@ -469,10 +445,8 @@ class CQueryBuilder { } private SqlTree createRawSqlSqlTree(OrmQueryRequest request, CQueryPredicates predicates) { - BeanDescriptor descriptor = request.getBeanDescriptor(); ColumnMapping columnMapping = request.getQuery().getRawSql().getColumnMapping(); - PathProperties pathProps = new PathProperties(); // convert list of columns into (tree like) PathProperties @@ -498,12 +472,10 @@ class CQueryBuilder { } OrmQueryDetail detail = new OrmQueryDetail(); - // transfer PathProperties into OrmQueryDetail for (PathProperties.Props props : pathProps.getPathProps()) { detail.fetch(props.getPath(), props.getProperties()); } - // check if @Id property included in RawSql boolean rawNoId = true; BeanProperty idProperty = descriptor.getIdProperty(); @@ -511,7 +483,6 @@ class CQueryBuilder { // contains the @Id property for the root level bean rawNoId = false; } - // build SqlTree based on OrmQueryDetail of the RawSql return new SqlTreeBuilder(request, predicates, detail, rawNoId).build(); } @@ -603,7 +574,6 @@ class CQueryBuilder { private void appendSelect() { if (selectClause != null) { sb.append(selectClause); - } else { useSqlLimiter = (query.hasMaxRowsOrFirstRow() && select.getManyProperty() == null); if (!useSqlLimiter) { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java index dea84fb80..b5aeec323 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -565,8 +565,7 @@ public class DefaultOrmQuery extends AbstractQuery implements SpiQuery { * Limit the number of fetch joins to Many properties, mark as query joins as needed. */ private void markQueryJoins() { - detail.markQueryJoins(beanDescriptor, lazyLoadManyPath, isAllowOneManyFetch(), - type != Type.ATTRIBUTE && type != Type.SQ_EXISTS && type != Type.SQ_IN); + detail.markQueryJoins(beanDescriptor, lazyLoadManyPath, isAllowOneManyFetch(), type.defaultSelect()); } private boolean isAllowOneManyFetch() { @@ -579,7 +578,7 @@ public class DefaultOrmQuery extends AbstractQuery implements SpiQuery { @Override public void setDefaultSelectClause() { - if (type != Type.ATTRIBUTE && type != Type.SQ_EXISTS && type != Type.SQ_IN) { + if (type.defaultSelect()) { detail.setDefaultSelectClause(beanDescriptor); } else if (!detail.hasSelectClause()) { // explicit empty select when single attribute query on non-root fetch path