This is an automated email from the ASF dual-hosted git repository. ntimofeev pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
The following commit(s) were added to refs/heads/master by this push: new ab7fddb8a Add generics to FluentSelect to merge identical code in ObjectSelect and ColumnSelect ab7fddb8a is described below commit ab7fddb8a04eb06cbe79e50ca41a72a0159858de Author: Nikita Timofeev <stari...@gmail.com> AuthorDate: Fri Jul 15 18:46:37 2022 +0300 Add generics to FluentSelect to merge identical code in ObjectSelect and ColumnSelect --- .../translator/select/DefaultSelectTranslator.java | 2 +- .../select/DefaultSelectTranslatorFactory.java | 2 +- .../translator/select/FluentSelectWrapper.java | 6 +- .../java/org/apache/cayenne/dba/AutoAdapter.java | 2 +- .../java/org/apache/cayenne/dba/DbAdapter.java | 2 +- .../org/apache/cayenne/dba/JdbcActionBuilder.java | 2 +- .../java/org/apache/cayenne/dba/JdbcAdapter.java | 2 +- .../apache/cayenne/dba/db2/DB2ActionBuilder.java | 2 +- .../cayenne/dba/derby/DerbyActionBuilder.java | 2 +- .../dba/firebird/FirebirdActionBuilder.java | 2 +- .../org/apache/cayenne/dba/h2/H2ActionBuilder.java | 2 +- .../cayenne/dba/hsqldb/HSQLActionBuilder.java | 2 +- .../cayenne/dba/ingres/IngresActionBuilder.java | 2 +- .../cayenne/dba/mysql/MySQLActionBuilder.java | 2 +- .../cayenne/dba/oracle/OracleActionBuilder.java | 2 +- .../dba/postgres/PostgresActionBuilder.java | 2 +- .../cayenne/dba/sqlite/SQLiteActionBuilder.java | 2 +- .../dba/sqlserver/SQLServerActionBuilder.java | 4 +- .../org/apache/cayenne/exp/ExpressionFactory.java | 4 +- .../org/apache/cayenne/exp/parser/ASTSubquery.java | 2 +- .../org/apache/cayenne/query/ColumnSelect.java | 361 +-------------------- .../apache/cayenne/query/ColumnSelectMetadata.java | 4 +- .../org/apache/cayenne/query/FluentSelect.java | 357 +++++++++++++++++++- .../query/FluentSelectPrefetchRouterAction.java | 4 +- .../org/apache/cayenne/query/ObjectSelect.java | 354 +------------------- .../apache/cayenne/query/ObjectSelectMetadata.java | 10 +- .../org/apache/cayenne/query/SQLActionVisitor.java | 2 +- .../org/apache/cayenne/query/ColumnSelectTest.java | 11 +- 28 files changed, 408 insertions(+), 743 deletions(-) diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java index 203d1c1af..0aacf108f 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java @@ -76,7 +76,7 @@ public class DefaultSelectTranslator implements SelectTranslator { this.context = new TranslatorContext(query, adapter, entityResolver, null); } - public DefaultSelectTranslator(FluentSelect<?> query, DbAdapter adapter, EntityResolver entityResolver) { + public DefaultSelectTranslator(FluentSelect<?, ?> query, DbAdapter adapter, EntityResolver entityResolver) { this(new FluentSelectWrapper(query), adapter, entityResolver); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java index e429b27f0..0c38c9ab0 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java @@ -35,7 +35,7 @@ public class DefaultSelectTranslatorFactory implements SelectTranslatorFactory { @Override public SelectTranslator translator(Select<?> query, DbAdapter adapter, EntityResolver entityResolver) { if(query instanceof FluentSelect) { - return adapter.getSelectTranslator((FluentSelect<?>)query, entityResolver); + return adapter.getSelectTranslator((FluentSelect<?, ?>)query, entityResolver); } throw new CayenneRuntimeException("Unsupported type of Select query %s", query); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/FluentSelectWrapper.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/FluentSelectWrapper.java index 3c4bed7a3..8eb442d9b 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/FluentSelectWrapper.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/FluentSelectWrapper.java @@ -34,9 +34,9 @@ import org.apache.cayenne.query.QueryMetadata; */ public class FluentSelectWrapper implements TranslatableQueryWrapper { - private final FluentSelect<?> select; + private final FluentSelect<?, ?> select; - public FluentSelectWrapper(FluentSelect<?> select) { + public FluentSelectWrapper(FluentSelect<?, ?> select) { this.select = Objects.requireNonNull(select); } @@ -71,7 +71,7 @@ public class FluentSelectWrapper implements TranslatableQueryWrapper { } @Override - public FluentSelect<?> unwrap() { + public FluentSelect<?, ?> unwrap() { return select; } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java index 45a374ce4..845154bfa 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java @@ -101,7 +101,7 @@ public class AutoAdapter implements DbAdapter { * @since 4.2 */ @Override - public SelectTranslator getSelectTranslator(FluentSelect<?> query, EntityResolver entityResolver) { + public SelectTranslator getSelectTranslator(FluentSelect<?, ?> query, EntityResolver entityResolver) { return getAdapter().getSelectTranslator(query, entityResolver); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java index c6bc77394..aa4ba1c18 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java @@ -56,7 +56,7 @@ public interface DbAdapter { /** * @since 4.2 */ - SelectTranslator getSelectTranslator(FluentSelect<?> query, EntityResolver entityResolver); + SelectTranslator getSelectTranslator(FluentSelect<?, ?> query, EntityResolver entityResolver); /** * @since 4.2 diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcActionBuilder.java index 8433e6cd6..2542931d2 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcActionBuilder.java @@ -70,7 +70,7 @@ public class JdbcActionBuilder implements SQLActionVisitor { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new SelectAction(query, dataNode); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java index 479b9da6c..06451fd6f 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java @@ -508,7 +508,7 @@ public class JdbcAdapter implements DbAdapter { } @Override - public SelectTranslator getSelectTranslator(FluentSelect<?> query, EntityResolver entityResolver) { + public SelectTranslator getSelectTranslator(FluentSelect<?, ?> query, EntityResolver entityResolver) { return new DefaultSelectTranslator(query, this, entityResolver); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2ActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2ActionBuilder.java index 5ef0f5216..46f29ac07 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2ActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2ActionBuilder.java @@ -42,7 +42,7 @@ public class DB2ActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new DB2SelectAction(query, dataNode); } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyActionBuilder.java index 46ea873a5..15801be22 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyActionBuilder.java @@ -37,7 +37,7 @@ public class DerbyActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new DerbySelectAction(query, dataNode); } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdActionBuilder.java index eca046e53..fb5b306ab 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdActionBuilder.java @@ -37,7 +37,7 @@ public class FirebirdActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new FirebirdSelectAction(query, dataNode); } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2ActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2ActionBuilder.java index 37c0a2187..36be4d966 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2ActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2ActionBuilder.java @@ -36,7 +36,7 @@ public class H2ActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new H2SelectAction(query, dataNode); } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLActionBuilder.java index 75aea976f..6a83b0b30 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLActionBuilder.java @@ -39,7 +39,7 @@ class HSQLActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new HSQLSelectAction(query, dataNode); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresActionBuilder.java index 76b874121..7efae8dca 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresActionBuilder.java @@ -36,7 +36,7 @@ public class IngresActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new IngresSelectAction(query, dataNode); } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLActionBuilder.java index d446ce35b..b55f488fa 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLActionBuilder.java @@ -38,7 +38,7 @@ class MySQLActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new MySQLSelectAction(query, dataNode); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java index bb033f973..94fa21547 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java @@ -62,7 +62,7 @@ class OracleActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new OracleSelectAction(query, dataNode); } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresActionBuilder.java index 3051c0eb1..191be3e4b 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresActionBuilder.java @@ -55,7 +55,7 @@ class PostgresActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new PostgresSelectAction(query, dataNode); } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteActionBuilder.java index c2be85d8b..74e25fd97 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteActionBuilder.java @@ -42,7 +42,7 @@ class SQLiteActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new SQLiteSelectAction(query, dataNode); } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java index f7d78452a..ce806a5f6 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java @@ -75,11 +75,11 @@ public class SQLServerActionBuilder extends JdbcActionBuilder { * @since 4.2 */ @Override - public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + public <T> SQLAction objectSelectAction(FluentSelect<T, ?> query) { return new SQLServerSelectAction(query, dataNode, needInMemoryOffset(query)); } - private boolean needInMemoryOffset(FluentSelect<?> query) { + private boolean needInMemoryOffset(FluentSelect<?, ?> query) { return query.getOrderings() == null || query.getOrderings().size() == 0 || version == null || version < 12; } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java index 7d3b207ac..094e352e4 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java @@ -1437,7 +1437,7 @@ public class ExpressionFactory { * @param subQuery {@link org.apache.cayenne.query.ObjectSelect} or {@link ColumnSelect} * @since 4.2 */ - public static Expression exists(FluentSelect<?> subQuery) { + public static Expression exists(FluentSelect<?, ?> subQuery) { return new ASTExists(new ASTSubquery(subQuery)); } @@ -1445,7 +1445,7 @@ public class ExpressionFactory { * @param subQuery {@link org.apache.cayenne.query.ObjectSelect} or {@link ColumnSelect} * @since 4.2 */ - public static Expression notExists(FluentSelect<?> subQuery) { + public static Expression notExists(FluentSelect<?, ?> subQuery) { return new ASTNotExists(new ASTSubquery(subQuery)); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSubquery.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSubquery.java index 32b5d7582..c2aa5fc9d 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSubquery.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSubquery.java @@ -35,7 +35,7 @@ public class ASTSubquery extends SimpleNode { private final TranslatableQueryWrapper query; - public ASTSubquery(FluentSelect<?> query) { + public ASTSubquery(FluentSelect<?, ?> query) { this(new FluentSelectWrapper(query)); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java index dd74e6063..8af55e47d 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java @@ -19,9 +19,7 @@ package org.apache.cayenne.query; -import java.sql.Statement; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.function.Function; @@ -34,9 +32,7 @@ import org.apache.cayenne.exp.property.ComparableProperty; import org.apache.cayenne.exp.property.NumericProperty; import org.apache.cayenne.exp.property.Property; import org.apache.cayenne.exp.property.PropertyFactory; -import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.EntityResolver; -import org.apache.cayenne.map.ObjEntity; /** * <p>A helper builder for queries selecting individual properties based on the root object.</p> @@ -65,13 +61,10 @@ import org.apache.cayenne.map.ObjEntity; * * @since 4.0 */ -public class ColumnSelect<T> extends FluentSelect<T> { +public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> { - private Collection<Property<?>> columns; - // package private for tests - boolean singleColumn = true; - - ColumnSelectMetadata metaData = new ColumnSelectMetadata(); + protected Collection<Property<?>> columns; + protected boolean singleColumn = true; protected ColumnSelect() { } @@ -89,286 +82,9 @@ public class ColumnSelect<T> extends FluentSelect<T> { this.metaData.copyFromInfo(select.metaData); } - /** - * Sets the type of the entity to fetch without changing the return type of - * the query. - * - * @return this object - */ - public ColumnSelect<T> entityType(Class<?> entityType) { - return resetEntity(entityType, null, null); - } - - /** - * Sets the {@link ObjEntity} name to fetch without changing the return type - * of the query. This form is most often used for generic entities that - * don't map to a distinct class. - * - * @return this object - */ - public ColumnSelect<T> entityName(String entityName) { - return resetEntity(null, entityName, null); - } - - /** - * Sets the {@link DbEntity} name to fetch without changing the return type - * of the query. This form is most often used for generic entities that - * don't map to a distinct class. - * - * @return this object - */ - public ColumnSelect<T> dbEntityName(String dbEntityName) { - return resetEntity(null, null, dbEntityName); - } - - private ColumnSelect<T> resetEntity(Class<?> entityType, String entityName, String dbEntityName) { - this.entityType = entityType; - this.entityName = entityName; - this.dbEntityName = dbEntityName; - return this; - } - - /** - * Appends a qualifier expression of this query. An equivalent to - * {@link #and(Expression...)} that can be used a syntactic sugar. - * - * @return this object - */ - public ColumnSelect<T> where(Expression expression) { - return and(expression); - } - - /** - * Appends a qualifier expression of this query, using provided expression - * String and an array of position parameters. This is an equivalent to - * calling "and". - * - * @return this object - */ - public ColumnSelect<T> where(String expressionString, Object... parameters) { - return and(ExpressionFactory.exp(expressionString, parameters)); - } - - /** - * AND's provided expressions to the existing WHERE clause expression. - * - * @return this object - */ - public ColumnSelect<T> and(Expression... expressions) { - if (expressions == null || expressions.length == 0) { - return this; - } - - return and(Arrays.asList(expressions)); - } - - /** - * OR's provided expressions to the existing WHERE clause expression. - * - * @return this object - */ - public ColumnSelect<T> or(Expression... expressions) { - if (expressions == null || expressions.length == 0) { - return this; - } - - return or(Arrays.asList(expressions)); - } - - /** - * Add an ascending ordering on the given property. If there is already an ordering - * on this query then add this ordering with a lower priority. - * - * @param property the property to sort on - * @return this object - */ - public ColumnSelect<T> orderBy(String property) { - return orderBy(new Ordering(property)); - } - - /** - * Add an ordering on the given property. If there is already an ordering - * on this query then add this ordering with a lower priority. - * - * @param property the property to sort on - * @param sortOrder the direction of the ordering - * @return this object - */ - public ColumnSelect<T> orderBy(String property, SortOrder sortOrder) { - return orderBy(new Ordering(property, sortOrder)); - } - - /** - * Add one or more orderings to this query. - * - * @return this object - */ - public ColumnSelect<T> orderBy(Ordering... orderings) { - - if (orderings == null) { - return this; - } - - if (this.orderings == null) { - this.orderings = new ArrayList<>(orderings.length); - } - - Collections.addAll(this.orderings, orderings); - return this; - } - - /** - * Adds a list of orderings to this query. - * - * @return this object - */ - public ColumnSelect<T> orderBy(Collection<Ordering> orderings) { - - if (orderings == null) { - return this; - } - - if (this.orderings == null) { - this.orderings = new ArrayList<>(orderings.size()); - } - - this.orderings.addAll(orderings); - return this; - } - - /** - * Merges prefetch into the query prefetch tree. - * - * @return this object - */ - public ColumnSelect<T> prefetch(PrefetchTreeNode prefetch) { - metaData.mergePrefetch(prefetch); - return this; - } - - /** - * Merges a prefetch path with specified semantics into the query prefetch - * tree. - * - * @return this object - */ - public ColumnSelect<T> prefetch(String path, int semantics) { - if (path == null) { - return this; - } - metaData.addPrefetch(path, semantics); - return this; - } - - /** - * Resets query fetch limit - a parameter that defines max number of objects - * that should be ever be fetched from the database. - */ - public ColumnSelect<T> limit(int fetchLimit) { - this.metaData.setFetchLimit(fetchLimit); - return this; - } - - /** - * Resets query fetch offset - a parameter that defines how many objects - * should be skipped when reading data from the database. - */ - public ColumnSelect<T> offset(int fetchOffset) { - this.metaData.setFetchOffset(fetchOffset); - return this; - } - - /** - * Resets query page size. A non-negative page size enables query result - * pagination that saves memory and processing time for large lists if only - * parts of the result are ever going to be accessed. - */ - public ColumnSelect<T> pageSize(int pageSize) { - this.metaData.setPageSize(pageSize); - return this; - } - - /** - * Sets fetch size of the PreparedStatement generated for this query. Only - * non-negative values would change the default size. - * - * @see Statement#setFetchSize(int) - */ - public ColumnSelect<T> statementFetchSize(int size) { - this.metaData.setStatementFetchSize(size); - return this; - } - - /** - * Sets query timeout of PreparedStatement generated for this query. - * @see Statement#setQueryTimeout(int) - */ - public ColumnSelect<T> queryTimeout(int timeout) { - this.metaData.setQueryTimeout(timeout); - return this; - } - - public ColumnSelect<T> cacheStrategy(QueryCacheStrategy strategy) { - setCacheStrategy(strategy); - setCacheGroup(null); - return this; - } - - public ColumnSelect<T> cacheStrategy(QueryCacheStrategy strategy, String cacheGroup) { - return cacheStrategy(strategy).cacheGroup(cacheGroup); - } - - public ColumnSelect<T> cacheGroup(String cacheGroup) { - setCacheGroup(cacheGroup); - return this; - } - - /** - * Instructs Cayenne to look for query results in the "local" cache when - * running the query. This is a short-hand notation for: - * <p> - * <pre> - * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup); - * </pre> - */ - public ColumnSelect<T> localCache(String cacheGroup) { - return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup); - } - - /** - * Instructs Cayenne to look for query results in the "local" cache when - * running the query. This is a short-hand notation for: - * <p> - * <pre> - * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE); - * </pre> - */ - public ColumnSelect<T> localCache() { - return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE); - } - - /** - * Instructs Cayenne to look for query results in the "shared" cache when - * running the query. This is a short-hand notation for: - * <p> - * <pre> - * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup); - * </pre> - */ - public ColumnSelect<T> sharedCache(String cacheGroup) { - return cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup); - } - - /** - * Instructs Cayenne to look for query results in the "shared" cache when - * running the query. This is a short-hand notation for: - * <p> - * <pre> - * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE); - * </pre> - */ - public ColumnSelect<T> sharedCache() { - return cacheStrategy(QueryCacheStrategy.SHARED_CACHE); + @Override + protected ColumnSelectMetadata createMetadata() { + return new ColumnSelectMetadata(); } /** @@ -428,7 +144,7 @@ public class ColumnSelect<T> extends FluentSelect<T> { } @SuppressWarnings("unchecked") - protected <E> ColumnSelect<E> column(Property<E> property) { + protected <E> ColumnSelect<E> column(Property<E> property) { if (this.columns == null) { this.columns = new ArrayList<>(1); } else { @@ -509,62 +225,11 @@ public class ColumnSelect<T> extends FluentSelect<T> { return and(ExpressionFactory.exp(expressionString, parameters)); } - /** - * AND's provided expressions to the existing WHERE or HAVING clause expression. - * - * @return this object - */ - public ColumnSelect<T> and(Collection<Expression> expressions) { - - if (expressions == null || expressions.isEmpty()) { - return this; - } - - Collection<Expression> all; - Expression activeExpression = getActiveExpression(); - - if (activeExpression != null) { - all = new ArrayList<>(expressions.size() + 1); - all.add(activeExpression); - all.addAll(expressions); - } else { - all = expressions; - } - - setActiveExpression(ExpressionFactory.and(all)); - return this; - } - - /** - * OR's provided expressions to the existing WHERE or HAVING clause expression. - * - * @return this object - */ - public ColumnSelect<T> or(Collection<Expression> expressions) { - if (expressions == null || expressions.isEmpty()) { - return this; - } - - Collection<Expression> all; - Expression activeExpression = getActiveExpression(); - - if (activeExpression != null) { - all = new ArrayList<>(expressions.size() + 1); - all.add(activeExpression); - all.addAll(expressions); - } else { - all = expressions; - } - - setActiveExpression(ExpressionFactory.or(all)); - return this; - } - /** * Explicitly request distinct in query. */ public ColumnSelect<T> distinct() { - metaData.setSuppressingDistinct(false); + getBaseMetaData().setSuppressingDistinct(false); this.distinct = true; return this; } @@ -573,7 +238,7 @@ public class ColumnSelect<T> extends FluentSelect<T> { * Explicitly suppress distinct in query. */ public ColumnSelect<T> suppressDistinct() { - metaData.setSuppressingDistinct(true); + getBaseMetaData().setSuppressingDistinct(true); this.distinct = false; return this; } @@ -595,13 +260,13 @@ public class ColumnSelect<T> extends FluentSelect<T> { @Override public QueryMetadata getMetaData(EntityResolver resolver) { Object root = resolveRoot(resolver); - metaData.resolve(root, resolver, this); + getBaseMetaData().resolve(root, resolver, this); return metaData; } @Override - protected BaseQueryMetadata getBaseMetaData() { - return metaData; + protected ColumnSelectMetadata getBaseMetaData() { + return (ColumnSelectMetadata) metaData; } /** @@ -618,7 +283,7 @@ public class ColumnSelect<T> extends FluentSelect<T> { */ @SuppressWarnings("unchecked") public <E> ColumnSelect<E> map(Function<T, E> mapper) { - this.metaData.setResultMapper(mapper); + getBaseMetaData().setResultMapper(mapper); return (ColumnSelect<E>)this; } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelectMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelectMetadata.java index 365853dce..76b780cdb 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelectMetadata.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelectMetadata.java @@ -65,12 +65,12 @@ class ColumnSelectMetadata extends ObjectSelectMetadata { } @Override - protected void resolveAutoAliases(FluentSelect<?> query) { + protected void resolveAutoAliases(FluentSelect<?, ?> query) { super.resolveAutoAliases(query); resolveColumnsAliases(query); } - protected void resolveColumnsAliases(FluentSelect<?> query) { + protected void resolveColumnsAliases(FluentSelect<?, ?> query) { Collection<Property<?>> columns = query.getColumns(); if(columns != null) { for(Property<?> property : columns) { diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java index 8dad2deb0..cf024f309 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java @@ -19,9 +19,14 @@ package org.apache.cayenne.query; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.Function; import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.ObjectContext; @@ -29,6 +34,7 @@ import org.apache.cayenne.ResultBatchIterator; import org.apache.cayenne.ResultIterator; import org.apache.cayenne.ResultIteratorCallback; import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.ExpressionFactory; import org.apache.cayenne.exp.property.Property; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.EntityResolver; @@ -39,7 +45,7 @@ import org.apache.cayenne.map.ObjEntity; * * @since 4.0 */ -public abstract class FluentSelect<T> extends AbstractQuery implements Select<T> { +public abstract class FluentSelect<T, S extends FluentSelect<T, S>> extends AbstractQuery implements Select<T> { // root protected Class<?> entityType; @@ -48,14 +54,19 @@ public abstract class FluentSelect<T> extends AbstractQuery implements Select<T> protected Expression where; protected Expression having; - boolean havingExpressionIsActive = false; + protected boolean havingExpressionIsActive = false; protected Collection<Ordering> orderings; - boolean distinct; + protected boolean distinct; + + protected ObjectSelectMetadata metaData; protected FluentSelect() { + metaData = createMetadata(); } + protected abstract ObjectSelectMetadata createMetadata(); + protected Object resolveRoot(EntityResolver resolver) { Object root; if (entityType != null) { @@ -82,6 +93,340 @@ public abstract class FluentSelect<T> extends AbstractQuery implements Select<T> return root; } + /** + * Sets the type of the entity to fetch without changing the return type of + * the query. + * + * @return this object + */ + public S entityType(Class<?> entityType) { + return resetEntity(entityType, null, null); + } + + /** + * Sets the {@link ObjEntity} name to fetch without changing the return type + * of the query. This form is most often used for generic entities that + * don't map to a distinct class. + * + * @return this object + */ + public S entityName(String entityName) { + return resetEntity(null, entityName, null); + } + + /** + * Sets the {@link DbEntity} name to fetch without changing the return type + * of the query. This form is most often used for generic entities that + * don't map to a distinct class. + * + * @return this object + */ + public S dbEntityName(String dbEntityName) { + return resetEntity(null, null, dbEntityName); + } + + @SuppressWarnings("unchecked") + private S resetEntity(Class<?> entityType, String entityName, String dbEntityName) { + this.entityType = entityType; + this.entityName = entityName; + this.dbEntityName = dbEntityName; + return (S)this; + } + + /** + * Appends a qualifier expression of this query. An equivalent to + * {@link #and(Expression...)} that can be used a syntactic sugar. + * + * @return this object + */ + public S where(Expression expression) { + return and(expression); + } + + /** + * Appends a qualifier expression of this query, using provided expression + * String and an array of position parameters. This is an equivalent to + * calling "and". + * + * @return this object + */ + public S where(String expressionString, Object... parameters) { + return and(ExpressionFactory.exp(expressionString, parameters)); + } + + /** + * AND's provided expressions to the existing WHERE clause expression. + * + * @return this object + */ + @SuppressWarnings("unchecked") + public S and(Expression... expressions) { + if (expressions == null || expressions.length == 0) { + return (S)this; + } + return and(Arrays.asList(expressions)); + } + + /** + * AND's provided expressions to the existing WHERE clause expression. + * + * @return this object + */ + + public S and(Collection<Expression> expressions) { + return joinExpression(expressions, ExpressionFactory::and); + } + + @SuppressWarnings("unchecked") + protected S joinExpression(Collection<Expression> expressions, Function<Collection<Expression>, Expression> joiner) { + if (expressions == null || expressions.isEmpty()) { + return (S)this; + } + + Collection<Expression> all; + Expression activeExpression = getActiveExpression(); + if (activeExpression != null) { + all = new ArrayList<>(expressions.size() + 1); + all.add(activeExpression); + all.addAll(expressions); + } else { + all = expressions; + } + + setActiveExpression(joiner.apply(all)); + return (S)this; + } + + /** + * OR's provided expressions to the existing WHERE clause expression. + * + * @return this object + */ + @SuppressWarnings("unchecked") + public S or(Expression... expressions) { + if (expressions == null || expressions.length == 0) { + return (S)this; + } + return or(Arrays.asList(expressions)); + } + + /** + * OR's provided expressions to the existing WHERE clause expression. + * + * @return this object + */ + public S or(Collection<Expression> expressions) { + return joinExpression(expressions, ExpressionFactory::or); + } + + /** + * Add an ascending ordering on the given property. If there is already an ordering + * on this query then add this ordering with a lower priority. + * + * @param property the property to sort on + * @return this object + */ + public S orderBy(String property) { + return orderBy(new Ordering(property)); + } + + /** + * Add an ordering on the given property. If there is already an ordering + * on this query then add this ordering with a lower priority. + * + * @param property the property to sort on + * @param sortOrder the direction of the ordering + * @return this object + */ + public S orderBy(String property, SortOrder sortOrder) { + return orderBy(new Ordering(property, sortOrder)); + } + + /** + * Add one or more orderings to this query. + * + * @return this object + */ + @SuppressWarnings("unchecked") + public S orderBy(Ordering... orderings) { + + if (orderings == null) { + return (S)this; + } + + if (this.orderings == null) { + this.orderings = new ArrayList<>(orderings.length); + } + + Collections.addAll(this.orderings, orderings); + + return (S)this; + } + + /** + * Adds a list of orderings to this query. + * + * @return this object + */ + @SuppressWarnings("unchecked") + public S orderBy(Collection<Ordering> orderings) { + + if (orderings == null) { + return (S)this; + } + + if (this.orderings == null) { + this.orderings = new ArrayList<>(orderings.size()); + } + + this.orderings.addAll(orderings); + + return (S)this; + } + + /** + * Merges prefetch into the query prefetch tree. + * + * @return this object + */ + @SuppressWarnings("unchecked") + public S prefetch(PrefetchTreeNode prefetch) { + getBaseMetaData().mergePrefetch(prefetch); + return (S)this; + } + + /** + * Merges a prefetch path with specified semantics into the query prefetch tree. + * + * @return this object + */ + @SuppressWarnings("unchecked") + public S prefetch(String path, int semantics) { + if (path == null) { + return (S)this; + } + getBaseMetaData().addPrefetch(path, semantics); + return (S)this; + } + + /** + * Resets query fetch limit - a parameter that defines max number of objects + * that should be ever be fetched from the database. + */ + @SuppressWarnings("unchecked") + public S limit(int fetchLimit) { + this.getBaseMetaData().setFetchLimit(fetchLimit); + return (S)this; + } + + /** + * Resets query fetch offset - a parameter that defines how many objects + * should be skipped when reading data from the database. + */ + @SuppressWarnings("unchecked") + public S offset(int fetchOffset) { + this.getBaseMetaData().setFetchOffset(fetchOffset); + return (S)this; + } + + /** + * Resets query page size. A non-negative page size enables query result + * pagination that saves memory and processing time for large lists if only + * parts of the result are ever going to be accessed. + */ + @SuppressWarnings("unchecked") + public S pageSize(int pageSize) { + this.getBaseMetaData().setPageSize(pageSize); + return (S)this; + } + + /** + * Sets fetch size of the PreparedStatement generated for this query. Only + * non-negative values would change the default size. + * + * @see Statement#setFetchSize(int) + */ + @SuppressWarnings("unchecked") + public S statementFetchSize(int size) { + this.getBaseMetaData().setStatementFetchSize(size); + return (S)this; + } + + /** + * Sets query timeout of PreparedStatement generated for this query. + * @see Statement#setQueryTimeout(int) + */ + @SuppressWarnings("unchecked") + public S queryTimeout(int timeout) { + this.getBaseMetaData().setQueryTimeout(timeout); + return (S)this; + } + + @SuppressWarnings("unchecked") + public S cacheStrategy(QueryCacheStrategy strategy) { + setCacheStrategy(strategy); + setCacheGroup(null); + return (S)this; + } + + public S cacheStrategy(QueryCacheStrategy strategy, String cacheGroup) { + return cacheStrategy(strategy).cacheGroup(cacheGroup); + } + + @SuppressWarnings("unchecked") + public S cacheGroup(String cacheGroup) { + setCacheGroup(cacheGroup); + return (S)this; + } + + /** + * Instructs Cayenne to look for query results in the "local" cache when + * running the query. This is a short-hand notation for: + * <p> + * <pre> + * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup); + * </pre> + */ + public S localCache(String cacheGroup) { + return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup); + } + + /** + * Instructs Cayenne to look for query results in the "local" cache when + * running the query. This is a short-hand notation for: + * <p> + * <pre> + * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE); + * </pre> + */ + public S localCache() { + return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE); + } + + /** + * Instructs Cayenne to look for query results in the "shared" cache when + * running the query. This is a short-hand notation for: + * <p> + * <pre> + * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup); + * </pre> + */ + public S sharedCache(String cacheGroup) { + return cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup); + } + + /** + * Instructs Cayenne to look for query results in the "shared" cache when + * running the query. This is a short-hand notation for: + * <p> + * <pre> + * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE); + * </pre> + */ + public S sharedCache() { + return cacheStrategy(QueryCacheStrategy.SHARED_CACHE); + } + public int getStatementFetchSize() { return getBaseMetaData().getStatementFetchSize(); } @@ -139,7 +484,7 @@ public abstract class FluentSelect<T> extends AbstractQuery implements Select<T> return getBaseMetaData().getPrefetchTree(); } - void setActiveExpression(Expression exp) { + protected void setActiveExpression(Expression exp) { if(havingExpressionIsActive) { having = exp; } else { @@ -147,7 +492,7 @@ public abstract class FluentSelect<T> extends AbstractQuery implements Select<T> } } - Expression getActiveExpression() { + protected Expression getActiveExpression() { if(havingExpressionIsActive) { return having; } else { @@ -196,7 +541,7 @@ public abstract class FluentSelect<T> extends AbstractQuery implements Select<T> } public boolean isFetchingDataRows() { - return false; + return getBaseMetaData().isFetchingDataRows(); } protected void routePrefetches(QueryRouter router, EntityResolver resolver) { diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelectPrefetchRouterAction.java b/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelectPrefetchRouterAction.java index f72895ac6..7da944e4c 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelectPrefetchRouterAction.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelectPrefetchRouterAction.java @@ -35,7 +35,7 @@ import org.apache.cayenne.util.CayenneMapEntry; */ class FluentSelectPrefetchRouterAction implements PrefetchProcessor { - FluentSelect<?> query; + FluentSelect<?, ?> query; QueryRouter router; EntityResolver resolver; ClassDescriptor classDescriptor; @@ -43,7 +43,7 @@ class FluentSelectPrefetchRouterAction implements PrefetchProcessor { /** * Routes query prefetches, but not the query itself. */ - void route(FluentSelect<?> query, QueryRouter router, EntityResolver resolver) { + void route(FluentSelect<?, ?> query, QueryRouter router, EntityResolver resolver) { if (!query.isFetchingDataRows() && query.getPrefetches() != null) { this.query = query; diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java index 58f65624c..bea18d1f3 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java @@ -18,11 +18,6 @@ ****************************************************************/ package org.apache.cayenne.query; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -54,12 +49,10 @@ import org.apache.cayenne.map.ObjEntity; * * @since 4.0 */ -public class ObjectSelect<T> extends FluentSelect<T> implements ParameterizedQuery { +public class ObjectSelect<T> extends FluentSelect<T, ObjectSelect<T>> implements ParameterizedQuery { private static final long serialVersionUID = -156124021150949227L; - protected ObjectSelectMetadata metaData = new ObjectSelectMetadata(); - /** * Creates a ObjectSelect that selects objects of a given persistent class. */ @@ -153,64 +146,9 @@ public class ObjectSelect<T> extends FluentSelect<T> implements ParameterizedQue protected ObjectSelect() { } - /** - * Sets the type of the entity to fetch without changing the return type of - * the query. - * - * @return this object - */ - public ObjectSelect<T> entityType(Class<?> entityType) { - return resetEntity(entityType, null, null); - } - - /** - * Sets the {@link ObjEntity} name to fetch without changing the return type - * of the query. This form is most often used for generic entities that - * don't map to a distinct class. - * - * @return this object - */ - public ObjectSelect<T> entityName(String entityName) { - return resetEntity(null, entityName, null); - } - - /** - * Sets the {@link DbEntity} name to fetch without changing the return type - * of the query. This form is most often used for generic entities that - * don't map to a distinct class. - * - * @return this object - */ - public ObjectSelect<T> dbEntityName(String dbEntityName) { - return resetEntity(null, null, dbEntityName); - } - - private ObjectSelect<T> resetEntity(Class<?> entityType, String entityName, String dbEntityName) { - this.entityType = entityType; - this.entityName = entityName; - this.dbEntityName = dbEntityName; - return this; - } - - /** - * Appends a qualifier expression of this query. An equivalent to - * {@link #and(Expression...)} that can be used a syntactic sugar. - * - * @return this object - */ - public ObjectSelect<T> where(Expression expression) { - return and(expression); - } - - /** - * Appends a qualifier expression of this query, using provided expression - * String and an array of position parameters. This is an equivalent to - * calling "and". - * - * @return this object - */ - public ObjectSelect<T> where(String expressionString, Object... parameters) { - return and(ExpressionFactory.exp(expressionString, parameters)); + @Override + protected ObjectSelectMetadata createMetadata() { + return new ObjectSelectMetadata(); } /** @@ -238,283 +176,6 @@ public class ObjectSelect<T> extends FluentSelect<T> implements ParameterizedQue return and(ExpressionFactory.exp(expressionString, parameters)); } - /** - * AND's provided expressions to the existing WHERE clause expression. - * - * @return this object - */ - public ObjectSelect<T> and(Expression... expressions) { - if (expressions == null || expressions.length == 0) { - return this; - } - - return and(Arrays.asList(expressions)); - } - - /** - * AND's provided expressions to the existing WHERE clause expression. - * - * @return this object - */ - public ObjectSelect<T> and(Collection<Expression> expressions) { - - if (expressions == null || expressions.isEmpty()) { - return this; - } - - Collection<Expression> all; - Expression activeExpression = getActiveExpression(); - - if(activeExpression != null) { - all = new ArrayList<>(expressions.size() + 1); - all.add(activeExpression); - all.addAll(expressions); - } else { - all = expressions; - } - - setActiveExpression(ExpressionFactory.and(all)); - return this; - } - - /** - * OR's provided expressions to the existing WHERE clause expression. - * - * @return this object - */ - public ObjectSelect<T> or(Expression... expressions) { - if (expressions == null || expressions.length == 0) { - return this; - } - - return or(Arrays.asList(expressions)); - } - - /** - * OR's provided expressions to the existing WHERE clause expression. - * - * @return this object - */ - public ObjectSelect<T> or(Collection<Expression> expressions) { - if (expressions == null || expressions.isEmpty()) { - return this; - } - - Collection<Expression> all; - Expression activeExpression = getActiveExpression(); - - if(activeExpression != null) { - all = new ArrayList<>(expressions.size() + 1); - all.add(activeExpression); - all.addAll(expressions); - } else { - all = expressions; - } - - setActiveExpression(ExpressionFactory.or(all)); - return this; - } - - /** - * Add an ascending ordering on the given property. If there is already an ordering - * on this query then add this ordering with a lower priority. - * - * @param property the property to sort on - * @return this object - */ - public ObjectSelect<T> orderBy(String property) { - return orderBy(new Ordering(property)); - } - - /** - * Add an ordering on the given property. If there is already an ordering - * on this query then add this ordering with a lower priority. - * - * @param property the property to sort on - * @param sortOrder the direction of the ordering - * @return this object - */ - public ObjectSelect<T> orderBy(String property, SortOrder sortOrder) { - return orderBy(new Ordering(property, sortOrder)); - } - - /** - * Add one or more orderings to this query. - * - * @return this object - */ - public ObjectSelect<T> orderBy(Ordering... orderings) { - - if (orderings == null) { - return this; - } - - if (this.orderings == null) { - this.orderings = new ArrayList<>(orderings.length); - } - - Collections.addAll(this.orderings, orderings); - - return this; - } - - /** - * Adds a list of orderings to this query. - * - * @return this object - */ - public ObjectSelect<T> orderBy(Collection<Ordering> orderings) { - - if (orderings == null) { - return this; - } - - if (this.orderings == null) { - this.orderings = new ArrayList<>(orderings.size()); - } - - this.orderings.addAll(orderings); - - return this; - } - - /** - * Merges prefetch into the query prefetch tree. - * - * @return this object - */ - public ObjectSelect<T> prefetch(PrefetchTreeNode prefetch) { - metaData.mergePrefetch(prefetch); - return this; - } - - /** - * Merges a prefetch path with specified semantics into the query prefetch - * tree. - * - * @return this object - */ - public ObjectSelect<T> prefetch(String path, int semantics) { - if (path == null) { - return this; - } - metaData.addPrefetch(path, semantics); - return this; - } - - /** - * Resets query fetch limit - a parameter that defines max number of objects - * that should be ever be fetched from the database. - */ - public ObjectSelect<T> limit(int fetchLimit) { - this.metaData.setFetchLimit(fetchLimit); - return this; - } - - /** - * Resets query fetch offset - a parameter that defines how many objects - * should be skipped when reading data from the database. - */ - public ObjectSelect<T> offset(int fetchOffset) { - this.metaData.setFetchOffset(fetchOffset); - return this; - } - - /** - * Resets query page size. A non-negative page size enables query result - * pagination that saves memory and processing time for large lists if only - * parts of the result are ever going to be accessed. - */ - public ObjectSelect<T> pageSize(int pageSize) { - this.metaData.setPageSize(pageSize); - return this; - } - - /** - * Sets fetch size of the PreparedStatement generated for this query. Only - * non-negative values would change the default size. - * - * @see Statement#setFetchSize(int) - */ - public ObjectSelect<T> statementFetchSize(int size) { - this.metaData.setStatementFetchSize(size); - return this; - } - - /** - * Sets query timeout for PreparedStatement generated for this query. - * - * @see Statement#setQueryTimeout(int) - * @since 4.2 - */ - public ObjectSelect<T> queryTimeout(int timeout) { - this.metaData.setQueryTimeout(timeout); - return this; - } - - public ObjectSelect<T> cacheStrategy(QueryCacheStrategy strategy) { - setCacheStrategy(strategy); - setCacheGroup(null); - return this; - } - - public ObjectSelect<T> cacheStrategy(QueryCacheStrategy strategy, String cacheGroup) { - return cacheStrategy(strategy).cacheGroup(cacheGroup); - } - - public ObjectSelect<T> cacheGroup(String cacheGroup) { - setCacheGroup(cacheGroup); - return this; - } - - /** - * Instructs Cayenne to look for query results in the "local" cache when - * running the query. This is a short-hand notation for: - * <p> - * <pre> - * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup); - * </pre> - */ - public ObjectSelect<T> localCache(String cacheGroup) { - return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup); - } - - /** - * Instructs Cayenne to look for query results in the "local" cache when - * running the query. This is a short-hand notation for: - * <p> - * <pre> - * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE); - * </pre> - */ - public ObjectSelect<T> localCache() { - return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE); - } - - /** - * Instructs Cayenne to look for query results in the "shared" cache when - * running the query. This is a short-hand notation for: - * <p> - * <pre> - * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup); - * </pre> - */ - public ObjectSelect<T> sharedCache(String cacheGroup) { - return cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup); - } - - /** - * Instructs Cayenne to look for query results in the "shared" cache when - * running the query. This is a short-hand notation for: - * <p> - * <pre> - * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE); - * </pre> - */ - public ObjectSelect<T> sharedCache() { - return cacheStrategy(QueryCacheStrategy.SHARED_CACHE); - } - /** * Forces query to fetch DataRows. This automatically changes whatever * result type was set previously to "DataRow". @@ -666,11 +327,6 @@ public class ObjectSelect<T> extends FluentSelect<T> implements ParameterizedQue return context.selectFirst(limit(1)); } - @Override - public boolean isFetchingDataRows() { - return metaData.isFetchingDataRows(); - } - @Override public QueryMetadata getMetaData(EntityResolver resolver) { Object root = resolveRoot(resolver); @@ -679,7 +335,7 @@ public class ObjectSelect<T> extends FluentSelect<T> implements ParameterizedQue } @Override - protected BaseQueryMetadata getBaseMetaData() { + protected ObjectSelectMetadata getBaseMetaData() { return metaData; } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelectMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelectMetadata.java index 164a7afb8..451480ea7 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelectMetadata.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelectMetadata.java @@ -60,7 +60,7 @@ class ObjectSelectMetadata extends BaseQueryMetadata { return false; } - protected String makeCacheKey(FluentSelect<?> query, EntityResolver resolver) { + protected String makeCacheKey(FluentSelect<?, ?> query, EntityResolver resolver) { // create a unique key based on entity or columns, qualifier, ordering, fetch offset and limit @@ -128,27 +128,27 @@ class ObjectSelectMetadata extends BaseQueryMetadata { return key.toString(); } - protected void resolveAutoAliases(FluentSelect<?> query) { + protected void resolveAutoAliases(FluentSelect<?, ?> query) { resolveQualifierAliases(query); resolveOrderingAliases(query); resolveHavingQualifierAliases(query); } - protected void resolveQualifierAliases(FluentSelect<?> query) { + protected void resolveQualifierAliases(FluentSelect<?, ?> query) { Expression qualifier = query.getWhere(); if (qualifier != null) { resolveAutoAliases(qualifier); } } - protected void resolveHavingQualifierAliases(FluentSelect<?> query) { + protected void resolveHavingQualifierAliases(FluentSelect<?, ?> query) { Expression havingQualifier = query.getHaving(); if(havingQualifier != null) { resolveAutoAliases(havingQualifier); } } - protected void resolveOrderingAliases(FluentSelect<?> query) { + protected void resolveOrderingAliases(FluentSelect<?, ?> query) { Collection<Ordering> orderings = query.getOrderings(); if(orderings != null) { for(Ordering ordering : orderings) { diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLActionVisitor.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLActionVisitor.java index 02c586b13..e2f423f98 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLActionVisitor.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLActionVisitor.java @@ -41,7 +41,7 @@ public interface SQLActionVisitor { * Creates an action to execute a FluentSelect. * @since 4.2 */ - <T> SQLAction objectSelectAction(FluentSelect<T> query); + <T> SQLAction objectSelectAction(FluentSelect<T,?> query); /** * Creates an action to execute a SQLTemplate. diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectTest.java b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectTest.java index ad336d041..2da4f1a11 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectTest.java @@ -107,10 +107,9 @@ public class ColumnSelectTest { assertNull(q.getWhere()); } - @SuppressWarnings("unchecked") @Test public void columns() { - ColumnSelect q = new ColumnSelect(); + ColumnSelect<?> q = new ColumnSelect<>(); assertNull(q.getColumns()); q.columns(Artist.ARTIST_NAME, Artist.PAINTING_ARRAY); assertEquals(Arrays.asList(Artist.ARTIST_NAME, Artist.PAINTING_ARRAY), q.getColumns()); @@ -124,7 +123,7 @@ public class ColumnSelectTest { @Test public void havingExpression() { - ColumnSelect q = new ColumnSelect(); + ColumnSelect<?> q = new ColumnSelect<>(); assertNull(q.getHaving()); assertNull(q.getWhere()); @@ -141,7 +140,7 @@ public class ColumnSelectTest { @Test public void havingString() { - ColumnSelect q = new ColumnSelect(); + ColumnSelect<?> q = new ColumnSelect<>(); assertNull(q.getHaving()); assertNull(q.getWhere()); @@ -158,7 +157,7 @@ public class ColumnSelectTest { @Test public void and() { - ColumnSelect q = new ColumnSelect(); + ColumnSelect<?> q = new ColumnSelect<>(); assertNull(q.getHaving()); assertNull(q.getWhere()); @@ -177,7 +176,7 @@ public class ColumnSelectTest { @Test public void or() { - ColumnSelect q = new ColumnSelect(); + ColumnSelect<?> q = new ColumnSelect<>(); assertNull(q.getHaving()); assertNull(q.getWhere());