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 da793eb CAY-2522 Make ObjectSelect a direct query
da793eb is described below
commit da793eb55b8278764f4e8fe6d9e8f84d3a8ed9f8
Author: Nikita Timofeev <[email protected]>
AuthorDate: Wed Feb 20 11:42:40 2019 +0300
CAY-2522 Make ObjectSelect a direct query
---
RELEASE-NOTES.txt | 1 +
.../java/org/apache/cayenne/access/DataNode.java | 4 +-
.../apache/cayenne/access/jdbc/SelectAction.java | 12 +-
.../translator/select/ColumnSelectWrapper.java | 84 --------
.../translator/select/DefaultSelectTranslator.java | 13 +-
.../select/DefaultSelectTranslatorFactory.java | 12 +-
...SelectWrapper.java => FluentSelectWrapper.java} | 33 ++--
.../translator/select/PrefetchNodeStage.java | 6 +-
.../translator/select/SelectQueryWrapper.java | 9 +-
.../translator/select/SelectTranslatorFactory.java | 4 +-
.../select/TranslatableQueryWrapper.java | 2 -
.../java/org/apache/cayenne/dba/AutoAdapter.java | 9 +
.../java/org/apache/cayenne/dba/DbAdapter.java | 6 +
.../org/apache/cayenne/dba/JdbcActionBuilder.java | 9 +
.../java/org/apache/cayenne/dba/JdbcAdapter.java | 6 +
.../apache/cayenne/dba/db2/DB2ActionBuilder.java | 9 +
.../apache/cayenne/dba/db2/DB2SelectAction.java | 4 +-
.../cayenne/dba/derby/DerbyActionBuilder.java | 9 +
.../cayenne/dba/derby/DerbySelectAction.java | 4 +-
.../dba/firebird/FirebirdActionBuilder.java | 9 +
.../cayenne/dba/firebird/FirebirdSelectAction.java | 5 +-
.../org/apache/cayenne/dba/h2/H2ActionBuilder.java | 9 +
.../org/apache/cayenne/dba/h2/H2SelectAction.java | 4 +-
.../cayenne/dba/hsqldb/HSQLActionBuilder.java | 9 +
.../cayenne/dba/hsqldb/HSQLSelectAction.java | 4 +-
.../cayenne/dba/ingres/IngresActionBuilder.java | 9 +
.../cayenne/dba/ingres/IngresSelectAction.java | 4 +-
.../cayenne/dba/mysql/MySQLActionBuilder.java | 9 +
.../cayenne/dba/mysql/MySQLSelectAction.java | 4 +-
.../cayenne/dba/oracle/OracleActionBuilder.java | 9 +
.../cayenne/dba/oracle/OracleSelectAction.java | 4 +-
.../dba/postgres/PostgresActionBuilder.java | 9 +
.../cayenne/dba/postgres/PostgresSelectAction.java | 4 +-
.../cayenne/dba/sqlite/SQLiteActionBuilder.java | 9 +
.../cayenne/dba/sqlite/SQLiteSelectAction.java | 9 +-
.../org/apache/cayenne/exp/ExpressionFactory.java | 11 +-
.../org/apache/cayenne/exp/parser/ASTSubquery.java | 18 +-
.../org/apache/cayenne/query/ColumnSelect.java | 114 +++--------
...ueryMetadata.java => ColumnSelectMetadata.java} | 219 +++------------------
.../org/apache/cayenne/query/FluentSelect.java | 104 +++++-----
.../query/FluentSelectPrefetchRouterAction.java | 141 +++++++++++++
.../org/apache/cayenne/query/ObjectSelect.java | 96 +++------
.../apache/cayenne/query/ObjectSelectMetadata.java | 171 ++++++++++++++++
.../org/apache/cayenne/query/SQLActionVisitor.java | 6 +
.../apache/cayenne/query/SelectQueryMetadata.java | 121 ------------
.../cayenne/query/ToCacheKeyPrefetchProcessor.java | 66 +++++++
.../cayenne/query/ToCacheKeyTraversalHandler.java | 103 ++++++++++
.../translator/select/MockQueryWrapperBuilder.java | 5 -
.../org/apache/cayenne/query/ColumnSelectTest.java | 6 +-
.../org/apache/cayenne/query/ObjectSelectTest.java | 10 +-
.../cayenne/query/ObjectSelect_CompileIT.java | 188 ------------------
.../query/SelectQueryMetadataCacheKeyTest.java | 4 +-
52 files changed, 827 insertions(+), 902 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 4e52647..8d553b1 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -21,6 +21,7 @@ CAY-2511 Contribute custom properties for attributes
CAY-2517 EventManager: optimization of adding listeners
CAY-2518 Add method to append having qualifier expression to ObjectSelect
CAY-2520 Split ObjectId into several specialized variants
+CAY-2522 Make ObjectSelect a direct query
CAY-2540 Modeler: redesign dbRelationship editor dialog
Bug Fixes:
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java
index 1211bdc..7609c95 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java
@@ -40,7 +40,7 @@ import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.QueryMetadata;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
import org.apache.cayenne.tx.BaseTransaction;
import org.apache.cayenne.tx.Transaction;
import org.apache.cayenne.util.ToStringBuilder;
@@ -348,7 +348,7 @@ public class DataNode implements QueryEngine {
/**
* @since 4.0
*/
- public SelectTranslator selectTranslator(SelectQuery<?> query) {
+ public SelectTranslator selectTranslator(Select<?> query) {
return selectTranslatorFactory.translator(query, getAdapter(),
getEntityResolver());
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index ea632e6..691dbed 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -30,7 +30,7 @@ import org.apache.cayenne.log.JdbcEventLogger;
import org.apache.cayenne.query.PrefetchProcessor;
import org.apache.cayenne.query.PrefetchTreeNode;
import org.apache.cayenne.query.QueryMetadata;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -65,13 +65,13 @@ public class SelectAction extends BaseSQLAction {
}
- protected SelectQuery<?> query;
+ protected Select<?> query;
protected QueryMetadata queryMetadata;
/**
* @since 4.0
*/
- public SelectAction(SelectQuery<?> query, DataNode dataNode) {
+ public SelectAction(Select<?> query, DataNode dataNode) {
super(dataNode);
this.query = query;
this.queryMetadata =
query.getMetaData(dataNode.getEntityResolver());
@@ -163,10 +163,10 @@ public class SelectAction extends BaseSQLAction {
// needed, as the SQL result count does not directly correspond
to the
// number of objects returned from Cayenne.
- int fetchLimit = query.getFetchLimit();
+ int fetchLimit = queryMetadata.getFetchLimit();
int offset = translator.isSuppressingDistinct()
- ? query.getFetchOffset()
- : getInMemoryOffset(query.getFetchOffset());
+ ? queryMetadata.getFetchOffset()
+ :
getInMemoryOffset(queryMetadata.getFetchOffset());
if (fetchLimit > 0 || offset > 0) {
return new LimitResultIterator<>(iterator, offset,
fetchLimit);
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/ColumnSelectWrapper.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/ColumnSelectWrapper.java
deleted file mode 100644
index 21a0069..0000000
---
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/ColumnSelectWrapper.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-
-package org.apache.cayenne.access.translator.select;
-
-import java.util.Collection;
-import java.util.Objects;
-
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.property.BaseProperty;
-import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.query.ColumnSelect;
-import org.apache.cayenne.query.Ordering;
-import org.apache.cayenne.query.PrefetchTreeNode;
-import org.apache.cayenne.query.QueryMetadata;
-import org.apache.cayenne.query.Select;
-
-/**
- * @since 4.2
- */
-public class ColumnSelectWrapper implements TranslatableQueryWrapper {
-
- private final ColumnSelect<?> columnSelect;
-
- public ColumnSelectWrapper(ColumnSelect<?> columnSelect) {
- this.columnSelect = Objects.requireNonNull(columnSelect);
- }
-
- @Override
- public boolean isDistinct() {
- return columnSelect.isDistinct();
- }
-
- @Override
- public QueryMetadata getMetaData(EntityResolver resolver) {
- return columnSelect.getMetaData(resolver);
- }
-
- @Override
- public PrefetchTreeNode getPrefetchTree() {
- return columnSelect.getPrefetches();
- }
-
- @Override
- public Expression getQualifier() {
- return columnSelect.getWhere();
- }
-
- @Override
- public Collection<Ordering> getOrderings() {
- return columnSelect.getOrderings();
- }
-
- @Override
- public Collection<BaseProperty<?>> getColumns() {
- return columnSelect.getColumns();
- }
-
- @Override
- public Expression getHavingQualifier() {
- return columnSelect.getHaving();
- }
-
- @Override
- public Select<?> unwrap() {
- return columnSelect;
- }
-}
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 4107dbe..7cc62bc 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
@@ -28,12 +28,11 @@ import
org.apache.cayenne.access.translator.DbAttributeBinding;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.query.ColumnSelect;
-import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.SelectQuery;
/**
- * Default translator of select queries ({@link SelectQuery}, {@link
ObjectSelect} and {@link ColumnSelect}).
+ * Default translator of select queries ({@link SelectQuery} or {@link
FluentSelect}).
*
* @since 4.2
*/
@@ -80,12 +79,8 @@ public class DefaultSelectTranslator implements
SelectTranslator {
this(new SelectQueryWrapper(query), adapter, entityResolver);
}
- public DefaultSelectTranslator(ObjectSelect<?> query, DbAdapter adapter,
EntityResolver entityResolver) {
- this(new ObjectSelectWrapper(query), adapter, entityResolver);
- }
-
- public DefaultSelectTranslator(ColumnSelect<?> query, DbAdapter adapter,
EntityResolver entityResolver) {
- this(new ColumnSelectWrapper(query), adapter, entityResolver);
+ public DefaultSelectTranslator(FluentSelect<?> query, DbAdapter adapter,
EntityResolver entityResolver) {
+ this(new FluentSelectWrapper(query), adapter, entityResolver);
}
TranslatorContext getContext() {
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 eec4e1c..9fc437a 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
@@ -18,8 +18,11 @@
****************************************************************/
package org.apache.cayenne.access.translator.select;
+import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.query.FluentSelect;
+import org.apache.cayenne.query.Select;
import org.apache.cayenne.query.SelectQuery;
/**
@@ -31,7 +34,12 @@ import org.apache.cayenne.query.SelectQuery;
public class DefaultSelectTranslatorFactory implements SelectTranslatorFactory
{
@Override
- public SelectTranslator translator(SelectQuery<?> query, DbAdapter
adapter, EntityResolver entityResolver) {
- return adapter.getSelectTranslator(query, entityResolver);
+ public SelectTranslator translator(Select<?> query, DbAdapter adapter,
EntityResolver entityResolver) {
+ if(query instanceof SelectQuery) {
+ return
adapter.getSelectTranslator((SelectQuery<?>)query, entityResolver);
+ } else if(query instanceof FluentSelect) {
+ 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/ObjectSelectWrapper.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/FluentSelectWrapper.java
similarity index 69%
rename from
cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/ObjectSelectWrapper.java
rename to
cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/FluentSelectWrapper.java
index 684245e..dc59c2b 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/ObjectSelectWrapper.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/FluentSelectWrapper.java
@@ -25,60 +25,53 @@ import java.util.Objects;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.property.BaseProperty;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.Ordering;
-import org.apache.cayenne.query.PrefetchTreeNode;
import org.apache.cayenne.query.QueryMetadata;
-import org.apache.cayenne.query.Select;
/**
* @since 4.2
*/
-public class ObjectSelectWrapper implements TranslatableQueryWrapper {
+public class FluentSelectWrapper implements TranslatableQueryWrapper {
- private final ObjectSelect<?> selectQuery;
+ private final FluentSelect<?> select;
- public ObjectSelectWrapper(ObjectSelect<?> selectQuery) {
- this.selectQuery = Objects.requireNonNull(selectQuery);
+ public FluentSelectWrapper(FluentSelect<?> select) {
+ this.select = Objects.requireNonNull(select);
}
@Override
public boolean isDistinct() {
- return false;
+ return select.isDistinct();
}
@Override
public QueryMetadata getMetaData(EntityResolver resolver) {
- return selectQuery.getMetaData(resolver);
- }
-
- @Override
- public PrefetchTreeNode getPrefetchTree() {
- return selectQuery.getPrefetches();
+ return select.getMetaData(resolver);
}
@Override
public Expression getQualifier() {
- return selectQuery.getWhere();
+ return select.getWhere();
}
@Override
public Collection<Ordering> getOrderings() {
- return selectQuery.getOrderings();
+ return select.getOrderings();
}
@Override
public Collection<BaseProperty<?>> getColumns() {
- return null;
+ return select.getColumns();
}
@Override
public Expression getHavingQualifier() {
- return selectQuery.getHaving();
+ return select.getHaving();
}
@Override
- public Select<?> unwrap() {
- return selectQuery;
+ public FluentSelect<?> unwrap() {
+ return select;
}
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/PrefetchNodeStage.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/PrefetchNodeStage.java
index 90c0f3d..51006ac 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/PrefetchNodeStage.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/PrefetchNodeStage.java
@@ -50,19 +50,19 @@ class PrefetchNodeStage implements TranslationStage {
}
private void updatePrefetchNodes(TranslatorContext context) {
- if(context.getQuery().getPrefetchTree() == null) {
+ if(context.getMetadata().getPrefetchTree() == null) {
return;
}
// Set entity name, in case MixedConversionStrategy will be used to
select objects from this query
// Note: all prefetch nodes will point to query root, it is not a
problem until select query can't
// perform some sort of union or sub-queries.
- for(PrefetchTreeNode prefetch :
context.getQuery().getPrefetchTree().getChildren()) {
+ for(PrefetchTreeNode prefetch :
context.getMetadata().getPrefetchTree().getChildren()) {
prefetch.setEntityName(context.getMetadata().getObjEntity().getName());
}
}
private void processJoint(TranslatorContext context) {
- PrefetchTreeNode prefetch = context.getQuery().getPrefetchTree();
+ PrefetchTreeNode prefetch = context.getMetadata().getPrefetchTree();
if(prefetch == null) {
return;
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectQueryWrapper.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectQueryWrapper.java
index 576bb8d..c927107 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectQueryWrapper.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectQueryWrapper.java
@@ -26,9 +26,7 @@ import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.property.BaseProperty;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.query.Ordering;
-import org.apache.cayenne.query.PrefetchTreeNode;
import org.apache.cayenne.query.QueryMetadata;
-import org.apache.cayenne.query.Select;
import org.apache.cayenne.query.SelectQuery;
/**
@@ -53,11 +51,6 @@ public class SelectQueryWrapper implements
TranslatableQueryWrapper {
}
@Override
- public PrefetchTreeNode getPrefetchTree() {
- return selectQuery.getPrefetchTree();
- }
-
- @Override
public Expression getQualifier() {
return selectQuery.getQualifier();
}
@@ -78,7 +71,7 @@ public class SelectQueryWrapper implements
TranslatableQueryWrapper {
}
@Override
- public Select<?> unwrap() {
+ public SelectQuery<?> unwrap() {
return selectQuery;
}
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java
index 4c306b5..c71e5ea 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.access.translator.select;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
/**
* A factory for {@link SelectTranslator} objects.
@@ -32,6 +32,6 @@ public interface SelectTranslatorFactory {
/**
* Creates a proper translator for a BatchQuery
*/
- SelectTranslator translator(SelectQuery<?> query, DbAdapter adapter,
EntityResolver entityResolver);
+ SelectTranslator translator(Select<?> query, DbAdapter adapter,
EntityResolver entityResolver);
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TranslatableQueryWrapper.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TranslatableQueryWrapper.java
index 6bd2c41..5322847 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TranslatableQueryWrapper.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TranslatableQueryWrapper.java
@@ -42,8 +42,6 @@ public interface TranslatableQueryWrapper {
QueryMetadata getMetaData(EntityResolver resolver);
- PrefetchTreeNode getPrefetchTree();
-
Expression getQualifier();
Collection<Ordering> getOrderings();
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 fffd1c1..e8eac29 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
@@ -32,6 +32,7 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -105,6 +106,14 @@ public class AutoAdapter implements DbAdapter {
return getAdapter().getSelectTranslator(query, entityResolver);
}
+ /**
+ * @since 4.2
+ */
+ @Override
+ public SelectTranslator getSelectTranslator(FluentSelect<?> query,
EntityResolver entityResolver) {
+ return getAdapter().getSelectTranslator(query, entityResolver);
+ }
+
@Override
public String getBatchTerminator() {
return getAdapter().getBatchTerminator();
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 629ef13..7f97640 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
@@ -28,6 +28,7 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -62,6 +63,11 @@ public interface DbAdapter {
/**
* @since 4.2
+ */
+ SelectTranslator getSelectTranslator(FluentSelect<?> query,
EntityResolver entityResolver);
+
+ /**
+ * @since 4.2
* @return {@link Function} that can adjust SQL tree to specific
database flavour
*/
Function<Node, Node> getSqlTreeProcessor();
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 e255abf..63544cb 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
@@ -27,6 +27,7 @@ import org.apache.cayenne.access.jdbc.SQLTemplateAction;
import org.apache.cayenne.access.jdbc.SelectAction;
import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.EJBQLQuery;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SQLActionVisitor;
@@ -71,6 +72,14 @@ public class JdbcActionBuilder implements SQLActionVisitor {
return new SelectAction(query, dataNode);
}
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new SelectAction(query, dataNode);
+ }
+
@Override
public SQLAction sqlAction(SQLTemplate query) {
return new SQLTemplateAction(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 db3c5ad..8da76e0 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
@@ -42,6 +42,7 @@ import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbJoin;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -530,6 +531,11 @@ public class JdbcAdapter implements DbAdapter {
}
@Override
+ public SelectTranslator getSelectTranslator(FluentSelect<?> query,
EntityResolver entityResolver) {
+ return new DefaultSelectTranslator(query, this, entityResolver);
+ }
+
+ @Override
public Function<Node, Node> getSqlTreeProcessor() {
return Function.identity();
}
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 f22b8f2..f9a5392 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
@@ -20,6 +20,7 @@ package org.apache.cayenne.dba.db2;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -42,4 +43,12 @@ public class DB2ActionBuilder extends JdbcActionBuilder {
public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
return new DB2SelectAction(query, dataNode);
}
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new DB2SelectAction(query, dataNode);
+ }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2SelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2SelectAction.java
index d0f8fd1..64e1e6a 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2SelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2SelectAction.java
@@ -21,14 +21,14 @@ package org.apache.cayenne.dba.db2;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
/**
* @since 4.1
*/
public class DB2SelectAction extends SelectAction {
- public DB2SelectAction(SelectQuery<?> query, DataNode dataNode) {
+ public DB2SelectAction(Select<?> query, DataNode dataNode) {
super(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 b0b67ff..a95a9dc 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
@@ -21,6 +21,7 @@ package org.apache.cayenne.dba.derby;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -37,4 +38,12 @@ public class DerbyActionBuilder extends JdbcActionBuilder {
public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
return new DerbySelectAction(query, dataNode);
}
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new DerbySelectAction(query, dataNode);
+ }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySelectAction.java
index 6a1c921..2f2d2b1 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySelectAction.java
@@ -21,14 +21,14 @@ package org.apache.cayenne.dba.derby;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
/**
* @since 4.1
*/
public class DerbySelectAction extends SelectAction {
- public DerbySelectAction(SelectQuery<?> query, DataNode dataNode) {
+ public DerbySelectAction(Select<?> query, DataNode dataNode) {
super(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 92f606c..290a7b2 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
@@ -21,6 +21,7 @@ package org.apache.cayenne.dba.firebird;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -38,4 +39,12 @@ public class FirebirdActionBuilder extends JdbcActionBuilder
{
public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
return new FirebirdSelectAction(query, dataNode);
}
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new FirebirdSelectAction(query, dataNode);
+ }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSelectAction.java
index 184a909..d23372c 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSelectAction.java
@@ -21,15 +21,14 @@ package org.apache.cayenne.dba.firebird;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SQLAction;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
/**
* @since 4.1
*/
public class FirebirdSelectAction extends SelectAction {
- public FirebirdSelectAction(SelectQuery<?> query, DataNode dataNode) {
+ public FirebirdSelectAction(Select<?> query, DataNode dataNode) {
super(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 2cf2a10..81a9651 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
@@ -21,6 +21,7 @@ package org.apache.cayenne.dba.h2;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -36,4 +37,12 @@ public class H2ActionBuilder extends JdbcActionBuilder {
public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
return new H2SelectAction(query, dataNode);
}
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new H2SelectAction(query, dataNode);
+ }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SelectAction.java
index df7380d..f3a8b19 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SelectAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2SelectAction.java
@@ -21,14 +21,14 @@ package org.apache.cayenne.dba.h2;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
/**
* @since 4.1
*/
public class H2SelectAction extends SelectAction {
- public H2SelectAction(SelectQuery<?> query, DataNode dataNode) {
+ public H2SelectAction(Select<?> query, DataNode dataNode) {
super(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 010315a..9296862 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
@@ -25,6 +25,7 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.ProcedureAction;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.dba.JdbcActionBuilder;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -40,6 +41,14 @@ class HSQLActionBuilder extends JdbcActionBuilder {
return new HSQLSelectAction(query, dataNode);
}
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new HSQLSelectAction(query, dataNode);
+ }
+
@Override
public SQLAction procedureAction(ProcedureQuery query) {
return new ProcedureAction(query, dataNode) {
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLSelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLSelectAction.java
index 21f4e11..236823e 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLSelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLSelectAction.java
@@ -20,14 +20,14 @@ package org.apache.cayenne.dba.hsqldb;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
/**
* @since 3.0
*/
class HSQLSelectAction extends SelectAction {
- <T> HSQLSelectAction(SelectQuery<T> query, DataNode dataNode) {
+ <T> HSQLSelectAction(Select<T> query, DataNode dataNode) {
super(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 17f8283..45cd495 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
@@ -20,6 +20,7 @@ package org.apache.cayenne.dba.ingres;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -36,4 +37,12 @@ public class IngresActionBuilder extends JdbcActionBuilder {
public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
return new IngresSelectAction(query, dataNode);
}
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new IngresSelectAction(query, dataNode);
+ }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSelectAction.java
index 3c6e1cb..b723391 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSelectAction.java
@@ -20,11 +20,11 @@ package org.apache.cayenne.dba.ingres;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
public class IngresSelectAction extends SelectAction {
- public <T> IngresSelectAction(SelectQuery<T> query, DataNode dataNode) {
+ public <T> IngresSelectAction(Select<T> query, DataNode dataNode) {
super(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 de9cf7d..23b87cb 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
@@ -21,6 +21,7 @@ package org.apache.cayenne.dba.mysql;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -39,6 +40,14 @@ class MySQLActionBuilder extends JdbcActionBuilder {
return new MySQLSelectAction(query, dataNode);
}
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new MySQLSelectAction(query, dataNode);
+ }
+
@Override
public SQLAction procedureAction(ProcedureQuery query) {
return new MySQLProcedureAction(query, dataNode);
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSelectAction.java
index 0b522d3..82faa67 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSelectAction.java
@@ -20,14 +20,14 @@ package org.apache.cayenne.dba.mysql;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
/**
* @since 3.0
*/
class MySQLSelectAction extends SelectAction {
- <T> MySQLSelectAction(SelectQuery<T> query, DataNode dataNode) {
+ <T> MySQLSelectAction(Select<T> query, DataNode dataNode) {
super(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 1b2be24..bec3d40 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
@@ -22,6 +22,7 @@ package org.apache.cayenne.dba.oracle;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SQLTemplate;
@@ -62,4 +63,12 @@ class OracleActionBuilder extends JdbcActionBuilder {
public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
return new OracleSelectAction(query, dataNode);
}
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new OracleSelectAction(query, dataNode);
+ }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSelectAction.java
index 60e8e5a..03eba27 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSelectAction.java
@@ -21,14 +21,14 @@ package org.apache.cayenne.dba.oracle;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
/**
* @since 1.2
*/
class OracleSelectAction extends SelectAction {
- public <T> OracleSelectAction(SelectQuery<T> query, DataNode dataNode) {
+ public <T> OracleSelectAction(Select<T> query, DataNode dataNode) {
super(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 c583eca..d5f72e3 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
@@ -22,6 +22,7 @@ package org.apache.cayenne.dba.postgres;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -55,4 +56,12 @@ class PostgresActionBuilder extends JdbcActionBuilder {
public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
return new PostgresSelectAction(query, dataNode);
}
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new PostgresSelectAction(query, dataNode);
+ }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSelectAction.java
index c20e746..a4d5022 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSelectAction.java
@@ -20,14 +20,14 @@ package org.apache.cayenne.dba.postgres;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.Select;
/**
* @since 3.0
*/
class PostgresSelectAction extends SelectAction {
- <T> PostgresSelectAction(SelectQuery<T> query, DataNode dataNode) {
+ <T> PostgresSelectAction(Select<T> query, DataNode dataNode) {
super(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 c4cc53c..6d42536 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
@@ -20,6 +20,7 @@ package org.apache.cayenne.dba.sqlite;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.query.SelectQuery;
@@ -45,4 +46,12 @@ class SQLiteActionBuilder extends JdbcActionBuilder {
public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
return new SQLiteSelectAction(query, dataNode);
}
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
+ return new SQLiteSelectAction(query, dataNode);
+ }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSelectAction.java
index a578c23..2b9bdca 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSelectAction.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSelectAction.java
@@ -19,20 +19,15 @@
package org.apache.cayenne.dba.sqlite;
import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.query.SQLAction;
-import org.apache.cayenne.query.SelectQuery;
-
-import java.sql.Connection;
-import java.sql.SQLException;
+import org.apache.cayenne.query.Select;
/**
* @since 4.1
*/
public class SQLiteSelectAction extends SelectAction {
- public SQLiteSelectAction(SelectQuery<?> query, DataNode dataNode) {
+ public SQLiteSelectAction(Select<?> query, DataNode dataNode) {
super(query, dataNode);
}
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 ad9775e..2e10cb6 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
@@ -65,7 +65,7 @@ import org.apache.cayenne.exp.parser.JavaCharStream;
import org.apache.cayenne.exp.parser.SimpleNode;
import org.apache.cayenne.map.Entity;
import org.apache.cayenne.query.ColumnSelect;
-import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.SelectQuery;
import java.io.Reader;
@@ -1367,14 +1367,7 @@ public class ExpressionFactory {
/**
* @since 4.2
*/
- public static Expression exists(ObjectSelect<?> subQuery) {
- return new ASTExists(new ASTSubquery(subQuery));
- }
-
- /**
- * @since 4.2
- */
- public static Expression exists(ColumnSelect<?> subQuery) {
+ public static Expression exists(FluentSelect<?> subQuery) {
return new ASTExists(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 f157501..70cde59 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
@@ -23,14 +23,12 @@ import java.io.IOException;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.Persistent;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.query.ColumnSelect;
-import org.apache.cayenne.access.translator.select.ColumnSelectWrapper;
-import org.apache.cayenne.query.ObjectSelect;
-import org.apache.cayenne.access.translator.select.ObjectSelectWrapper;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.access.translator.select.FluentSelectWrapper;
import org.apache.cayenne.access.translator.select.SelectQueryWrapper;
import org.apache.cayenne.access.translator.select.TranslatableQueryWrapper;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.query.FluentSelect;
+import org.apache.cayenne.query.SelectQuery;
/**
* @since 4.2
@@ -43,12 +41,8 @@ public class ASTSubquery extends SimpleNode {
this(new SelectQueryWrapper(query));
}
- public ASTSubquery(ObjectSelect<?> query) {
- this(new ObjectSelectWrapper(query));
- }
-
- public ASTSubquery(ColumnSelect<?> query) {
- this(new ColumnSelectWrapper(query));
+ public ASTSubquery(FluentSelect<?> query) {
+ this(new FluentSelectWrapper(query));
}
public ASTSubquery(TranslatableQueryWrapper 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 b96b6bf..5e7333a 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
@@ -70,41 +70,23 @@ public class ColumnSelect<T> extends FluentSelect<T> {
// package private for tests
boolean singleColumn = true;
boolean distinct;
- boolean suppressDistinct;
+
+ ColumnSelectMetadata metaData = new ColumnSelectMetadata();
protected ColumnSelect() {
- super();
}
/**
* Copy constructor to convert ObjectSelect to ColumnSelect
*/
protected ColumnSelect(ObjectSelect<T> select) {
- super();
- this.name = select.name;
this.entityType = select.entityType;
this.entityName = select.entityName;
this.dbEntityName = select.dbEntityName;
this.where = select.where;
this.having = select.having;
this.orderings = select.orderings;
- this.prefetches = select.prefetches;
- this.limit = select.limit;
- this.offset = select.offset;
- this.pageSize = select.pageSize;
- this.statementFetchSize = select.statementFetchSize;
- this.cacheStrategy = select.cacheStrategy;
- this.cacheGroup = select.cacheGroup;
- }
-
- @Override
- protected Query createReplacementQuery(EntityResolver resolver) {
- SelectQuery<?> replacement =
(SelectQuery)super.createReplacementQuery(resolver);
- replacement.setColumns(columns);
- replacement.setCanReturnScalarValue(singleColumn);
- replacement.setDistinct(distinct);
- replacement.setSuppressDistinct(suppressDistinct);
- return replacement;
+ this.metaData.copyFromInfo(select.metaData);
}
/**
@@ -143,7 +125,6 @@ public class ColumnSelect<T> extends FluentSelect<T> {
this.entityType = entityType;
this.entityName = entityName;
this.dbEntityName = dbEntityName;
- this.replacementQuery = null;
return this;
}
@@ -233,7 +214,6 @@ public class ColumnSelect<T> extends FluentSelect<T> {
}
Collections.addAll(this.orderings, orderings);
- replacementQuery = null;
return this;
}
@@ -253,7 +233,6 @@ public class ColumnSelect<T> extends FluentSelect<T> {
}
this.orderings.addAll(orderings);
- replacementQuery = null;
return this;
}
@@ -263,17 +242,7 @@ public class ColumnSelect<T> extends FluentSelect<T> {
* @return this object
*/
public ColumnSelect<T> prefetch(PrefetchTreeNode prefetch) {
-
- if (prefetch == null) {
- return this;
- }
-
- if (prefetches == null) {
- prefetches = new PrefetchTreeNode();
- }
-
- prefetches.merge(prefetch);
- replacementQuery = null;
+ metaData.mergePrefetch(prefetch);
return this;
}
@@ -284,17 +253,10 @@ public class ColumnSelect<T> extends FluentSelect<T> {
* @return this object
*/
public ColumnSelect<T> prefetch(String path, int semantics) {
-
if (path == null) {
return this;
}
-
- if (prefetches == null) {
- prefetches = new PrefetchTreeNode();
- }
-
- prefetches.addPath(path).setSemantics(semantics);
- replacementQuery = null;
+ metaData.addPrefetch(path, semantics);
return this;
}
@@ -303,11 +265,7 @@ public class ColumnSelect<T> extends FluentSelect<T> {
* that should be ever be fetched from the database.
*/
public ColumnSelect<T> limit(int fetchLimit) {
- if (this.limit != fetchLimit) {
- this.limit = fetchLimit;
- this.replacementQuery = null;
- }
-
+ this.metaData.setFetchLimit(fetchLimit);
return this;
}
@@ -316,11 +274,7 @@ public class ColumnSelect<T> extends FluentSelect<T> {
* should be skipped when reading data from the database.
*/
public ColumnSelect<T> offset(int fetchOffset) {
- if (this.offset != fetchOffset) {
- this.offset = fetchOffset;
- this.replacementQuery = null;
- }
-
+ this.metaData.setFetchOffset(fetchOffset);
return this;
}
@@ -330,11 +284,7 @@ public class ColumnSelect<T> extends FluentSelect<T> {
* parts of the result are ever going to be accessed.
*/
public ColumnSelect<T> pageSize(int pageSize) {
- if (this.pageSize != pageSize) {
- this.pageSize = pageSize;
- this.replacementQuery = null;
- }
-
+ this.metaData.setPageSize(pageSize);
return this;
}
@@ -345,25 +295,13 @@ public class ColumnSelect<T> extends FluentSelect<T> {
* @see Statement#setFetchSize(int)
*/
public ColumnSelect<T> statementFetchSize(int size) {
- if (this.statementFetchSize != size) {
- this.statementFetchSize = size;
- this.replacementQuery = null;
- }
-
+ this.metaData.setStatementFetchSize(size);
return this;
}
public ColumnSelect<T> cacheStrategy(QueryCacheStrategy strategy) {
- if (this.cacheStrategy != strategy) {
- this.cacheStrategy = strategy;
- this.replacementQuery = null;
- }
-
- if(this.cacheGroup != null) {
- this.cacheGroup = null;
- this.replacementQuery = null;
- }
-
+ setCacheStrategy(strategy);
+ setCacheGroup(null);
return this;
}
@@ -372,8 +310,7 @@ public class ColumnSelect<T> extends FluentSelect<T> {
}
public ColumnSelect<T> cacheGroup(String cacheGroup) {
- this.cacheGroup = cacheGroup;
- this.replacementQuery = null;
+ setCacheGroup(cacheGroup);
return this;
}
@@ -451,7 +388,6 @@ public class ColumnSelect<T> extends FluentSelect<T> {
columns.add(firstProperty);
Collections.addAll(columns, otherProperties);
singleColumn = false;
- replacementQuery = null;
return (ColumnSelect<Object[]>)this;
}
@@ -478,7 +414,6 @@ public class ColumnSelect<T> extends FluentSelect<T> {
columns.addAll(properties);
singleColumn = false;
- replacementQuery = null;
return (ColumnSelect<Object[]>)this;
}
@@ -490,7 +425,6 @@ public class ColumnSelect<T> extends FluentSelect<T> {
this.columns.clear(); // if we don't clear then return type will
be incorrect
}
this.columns.add(property);
- this.replacementQuery = null;
return (ColumnSelect<E>) this;
}
@@ -640,9 +574,8 @@ public class ColumnSelect<T> extends FluentSelect<T> {
* Explicitly request distinct in query.
*/
public ColumnSelect<T> distinct() {
- this.suppressDistinct = false;
+ metaData.setSuppressingDistinct(false);
this.distinct = true;
- this.replacementQuery = null;
return this;
}
@@ -650,12 +583,12 @@ public class ColumnSelect<T> extends FluentSelect<T> {
* Explicitly suppress distinct in query.
*/
public ColumnSelect<T> suppressDistinct() {
- this.suppressDistinct = true;
+ metaData.setSuppressingDistinct(true);
this.distinct = false;
- this.replacementQuery = null;
return this;
}
+ @Override
public Collection<BaseProperty<?>> getColumns() {
return columns;
}
@@ -663,6 +596,7 @@ public class ColumnSelect<T> extends FluentSelect<T> {
/**
* @since 4.2
*/
+ @Override
public boolean isDistinct() {
return distinct;
}
@@ -671,4 +605,20 @@ public class ColumnSelect<T> extends FluentSelect<T> {
public T selectFirst(ObjectContext context) {
return context.selectFirst(limit(1));
}
+
+ boolean isSingleColumn() {
+ return singleColumn;
+ }
+
+ @Override
+ public QueryMetadata getMetaData(EntityResolver resolver) {
+ Object root = resolveRoot(resolver);
+ metaData.resolve(root, resolver, this);
+ return metaData;
+ }
+
+ @Override
+ protected BaseQueryMetadata getBaseMetaData() {
+ return metaData;
+ }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelectMetadata.java
similarity index 68%
copy from
cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
copy to
cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelectMetadata.java
index 9ee83bf..eb9a389 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelectMetadata.java
@@ -28,16 +28,10 @@ import java.util.Map;
import java.util.Set;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.ObjectId;
-import org.apache.cayenne.Persistent;
-import org.apache.cayenne.access.types.ValueObjectType;
-import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.exp.TraversalHandler;
import org.apache.cayenne.exp.parser.ASTDbPath;
-import org.apache.cayenne.exp.parser.ASTFunctionCall;
-import org.apache.cayenne.exp.parser.ASTScalar;
import org.apache.cayenne.exp.property.BaseProperty;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
@@ -58,12 +52,12 @@ import org.apache.cayenne.reflect.ToOneProperty;
import org.apache.cayenne.util.CayenneMapEntry;
/**
- * @since 3.0
+ * @since 4.2
*/
-class SelectQueryMetadata extends BaseQueryMetadata {
+class ColumnSelectMetadata extends BaseQueryMetadata {
+
+ private static final long serialVersionUID = -3622675304651257963L;
- private static final long serialVersionUID = 7465922769303943945L;
-
private Map<String, String> pathSplitAliases;
private boolean isSingleResultSetMapping;
private boolean suppressingDistinct;
@@ -74,7 +68,7 @@ class SelectQueryMetadata extends BaseQueryMetadata {
this.pathSplitAliases = new
HashMap<>(info.getPathSplitAliases());
}
- boolean resolve(Object root, EntityResolver resolver, SelectQuery<?>
query) {
+ boolean resolve(Object root, EntityResolver resolver, ColumnSelect<?>
query) {
if (super.resolve(root, resolver)) {
// generate unique cache key, but only if we are
caching..
@@ -84,7 +78,7 @@ class SelectQueryMetadata extends BaseQueryMetadata {
resolveAutoAliases(query);
buildResultSetMappingForColumns(query, resolver);
- isSingleResultSetMapping = query.canReturnScalarValue()
&& super.isSingleResultSetMapping();
+ isSingleResultSetMapping = query.isSingleColumn() &&
super.isSingleResultSetMapping();
return true;
}
@@ -92,7 +86,7 @@ class SelectQueryMetadata extends BaseQueryMetadata {
return false;
}
- private String makeCacheKey(SelectQuery<?> query, EntityResolver
resolver) {
+ private String makeCacheKey(ColumnSelect<?> query, EntityResolver
resolver) {
// create a unique key based on entity or columns, qualifier,
ordering, fetch offset and limit
@@ -115,15 +109,15 @@ class SelectQueryMetadata extends BaseQueryMetadata {
}
}
- if (query.getQualifier() != null) {
+ if (query.getWhere() != null) {
key.append('/');
if(traversalHandler == null) {
traversalHandler = new
ToCacheKeyTraversalHandler(resolver.getValueObjectTypeRegistry(), key);
}
- query.getQualifier().traverse(traversalHandler);
+ query.getWhere().traverse(traversalHandler);
}
- if (!query.getOrderings().isEmpty()) {
+ if (query.getOrderings() != null &&
!query.getOrderings().isEmpty()) {
for (Ordering o : query.getOrderings()) {
key.append('/').append(o.getSortSpecString());
if (!o.isAscending()) {
@@ -136,25 +130,25 @@ class SelectQueryMetadata extends BaseQueryMetadata {
}
}
- if (query.getFetchOffset() > 0 || query.getFetchLimit() > 0) {
+ if (fetchOffset > 0 || fetchLimit > 0) {
key.append('/');
- if (query.getFetchOffset() > 0) {
- key.append('o').append(query.getFetchOffset());
+ if (fetchOffset > 0) {
+ key.append('o').append(fetchOffset);
}
- if (query.getFetchLimit() > 0) {
- key.append('l').append(query.getFetchLimit());
+ if (fetchLimit > 0) {
+ key.append('l').append(fetchLimit);
}
}
// add prefetch to cache key per CAY-2349
- if(query.getPrefetchTree() != null) {
- query.getPrefetchTree().traverse(new
ToCacheKeyPrefetchProcessor(key));
+ if(prefetchTree != null) {
+ prefetchTree.traverse(new
ToCacheKeyPrefetchProcessor(key));
}
return key.toString();
}
- private void resolveAutoAliases(SelectQuery<?> query) {
+ private void resolveAutoAliases(ColumnSelect<?> query) {
resolveQualifierAliases(query);
resolveColumnsAliases(query);
resolveOrderingAliases(query);
@@ -162,14 +156,14 @@ class SelectQueryMetadata extends BaseQueryMetadata {
// TODO: include aliases in prefetches? flattened attributes?
}
- private void resolveQualifierAliases(SelectQuery<?> query) {
- Expression qualifier = query.getQualifier();
+ private void resolveQualifierAliases(ColumnSelect<?> query) {
+ Expression qualifier = query.getWhere();
if (qualifier != null) {
resolveAutoAliases(qualifier);
}
}
- private void resolveColumnsAliases(SelectQuery<?> query) {
+ private void resolveColumnsAliases(ColumnSelect<?> query) {
Collection<BaseProperty<?>> columns = query.getColumns();
if(columns != null) {
for(BaseProperty<?> property : columns) {
@@ -181,8 +175,8 @@ class SelectQueryMetadata extends BaseQueryMetadata {
}
}
- private void resolveOrderingAliases(SelectQuery<?> query) {
- List<Ordering> orderings = query.getOrderings();
+ private void resolveOrderingAliases(ColumnSelect<?> query) {
+ Collection<Ordering> orderings = query.getOrderings();
if(orderings != null) {
for(Ordering ordering : orderings) {
Expression sortSpec = ordering.getSortSpec();
@@ -193,8 +187,8 @@ class SelectQueryMetadata extends BaseQueryMetadata {
}
}
- private void resolveHavingQualifierAliases(SelectQuery<?> query) {
- Expression havingQualifier = query.getHavingQualifier();
+ private void resolveHavingQualifierAliases(ColumnSelect<?> query) {
+ Expression havingQualifier = query.getHaving();
if(havingQualifier != null) {
resolveAutoAliases(havingQualifier);
}
@@ -227,40 +221,15 @@ class SelectQueryMetadata extends BaseQueryMetadata {
}
}
- /**
- * @since 3.0
- */
@Override
public Map<String, String> getPathSplitAliases() {
return pathSplitAliases != null ? pathSplitAliases :
Collections.emptyMap();
}
/**
- * @since 3.0
- */
- public void addPathSplitAliases(String path, String... aliases) {
- if (aliases == null) {
- throw new NullPointerException("Null aliases");
- }
-
- if (aliases.length == 0) {
- throw new IllegalArgumentException("No aliases
specified");
- }
-
- if (pathSplitAliases == null) {
- pathSplitAliases = new HashMap<>();
- }
-
- for (String alias : aliases) {
- pathSplitAliases.put(alias, path);
- }
- }
-
- /**
* Build DB result descriptor, that will be used to read and convert
raw result of ColumnSelect
- * @since 4.0
*/
- private void buildResultSetMappingForColumns(SelectQuery<?> query,
EntityResolver resolver) {
+ private void buildResultSetMappingForColumns(ColumnSelect<?> query,
EntityResolver resolver) {
if(query.getColumns() == null || query.getColumns().isEmpty()) {
return;
}
@@ -333,7 +302,7 @@ class SelectQueryMetadata extends BaseQueryMetadata {
* @param resolver entity resolver to get ObjEntity and ClassDescriptor
* @return Entity result
*/
- private EntityResult buildEntityResultForColumn(SelectQuery<?> query,
BaseProperty<?> column, EntityResolver resolver) {
+ private EntityResult buildEntityResultForColumn(ColumnSelect<?> query,
BaseProperty<?> column, EntityResolver resolver) {
// This method is actually repeating logic of
DescriptorColumnExtractor.
// Here we don't care about intermediate joins and few other
things so it's shorter.
// Logic of these methods should be unified and simplified,
possibly to a single source of metadata,
@@ -383,8 +352,8 @@ class SelectQueryMetadata extends BaseQueryMetadata {
descriptor.visitAllProperties(visitor);
// Collection columns for joint prefetch
- if(query.getPrefetchTree() != null) {
- for (PrefetchTreeNode prefetch :
query.getPrefetchTree().adjacentJointNodes()) {
+ if(prefetchTree != null) {
+ for (PrefetchTreeNode prefetch :
prefetchTree.adjacentJointNodes()) {
// for each prefetch add columns from the
target entity
Expression prefetchExp =
ExpressionFactory.exp(prefetch.getPath());
ASTDbPath dbPrefetch = (ASTDbPath)
oe.translateToDbPath(prefetchExp);
@@ -427,147 +396,17 @@ class SelectQueryMetadata extends BaseQueryMetadata {
return result;
}
- /**
- * @since 4.0
- */
@Override
public boolean isSingleResultSetMapping() {
return isSingleResultSetMapping;
}
- /**
- * @since 4.0
- */
@Override
public boolean isSuppressingDistinct() {
return suppressingDistinct;
}
- /**
- * @since 4.0
- */
public void setSuppressingDistinct(boolean suppressingDistinct) {
this.suppressingDistinct = suppressingDistinct;
}
-
- /**
- * Expression traverse handler to create cache key string out of
Expression.
- * {@link Expression#appendAsString(Appendable)} where previously used
for that,
- * but it can't handle custom value objects properly (see CAY-2210).
- *
- * @see ValueObjectTypeRegistry
- *
- * @since 4.0
- */
- static class ToCacheKeyTraversalHandler implements TraversalHandler {
-
- private ValueObjectTypeRegistry registry;
- private StringBuilder out;
-
- ToCacheKeyTraversalHandler(ValueObjectTypeRegistry registry,
StringBuilder out) {
- this.registry = registry;
- this.out = out;
- }
-
- @Override
- public void finishedChild(Expression node, int childIndex,
boolean hasMoreChildren) {
- out.append(',');
- }
-
- @Override
- public void startNode(Expression node, Expression parentNode) {
- if(node.getType() == Expression.FUNCTION_CALL) {
-
out.append(((ASTFunctionCall)node).getFunctionName()).append('(');
- } else {
- out.append(node.getType()).append('(');
- }
- }
-
- @Override
- public void endNode(Expression node, Expression parentNode) {
- out.append(')');
- }
-
- @Override
- public void objectNode(Object leaf, Expression parentNode) {
- if(leaf == null) {
- out.append("null");
- return;
- }
-
- if(leaf instanceof ASTScalar) {
- leaf = ((ASTScalar) leaf).getValue();
- } else if(leaf instanceof Object[]) {
- for(Object value : (Object[])leaf) {
- objectNode(value, parentNode);
- out.append(',');
- }
- return;
- }
-
- if (leaf instanceof Persistent) {
- ObjectId id = ((Persistent) leaf).getObjectId();
- Object encode = (id != null) ? id : leaf;
- out.append(encode);
- } else if (leaf instanceof Enum<?>) {
- Enum<?> e = (Enum<?>) leaf;
-
out.append("e:").append(leaf.getClass().getName()).append(':').append(e.ordinal());
- } else {
- ValueObjectType<Object, ?> valueObjectType;
- if (registry == null || (valueObjectType =
registry.getValueType(leaf.getClass())) == null) {
- // Registry will be null in
cayenne-client context.
- // Maybe we shouldn't create cache key
at all in that case...
- out.append(leaf);
- } else {
-
out.append(valueObjectType.toCacheKey(leaf));
- }
- }
- }
- }
-
- /**
- * Prefetch processor that append prefetch tree into cache key.
- * @since 4.0
- */
- static class ToCacheKeyPrefetchProcessor implements PrefetchProcessor {
-
- StringBuilder out;
-
- ToCacheKeyPrefetchProcessor(StringBuilder out) {
- this.out = out;
- }
-
- @Override
- public boolean startPhantomPrefetch(PrefetchTreeNode node) {
- return true;
- }
-
- @Override
- public boolean startDisjointPrefetch(PrefetchTreeNode node) {
- out.append("/pd:").append(node.getPath());
- return true;
- }
-
- @Override
- public boolean startDisjointByIdPrefetch(PrefetchTreeNode node)
{
- out.append("/pi:").append(node.getPath());
- return true;
- }
-
- @Override
- public boolean startJointPrefetch(PrefetchTreeNode node) {
- out.append("/pj:").append(node.getPath());
- return true;
- }
-
- @Override
- public boolean startUnknownPrefetch(PrefetchTreeNode node) {
- out.append("/pu:").append(node.getPath());
- return true;
- }
-
- @Override
- public void finishPrefetch(PrefetchTreeNode node) {
- }
- }
}
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 2d9d1a3..a650e75 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
@@ -28,6 +28,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.property.BaseProperty;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.ObjEntity;
@@ -37,39 +38,26 @@ import org.apache.cayenne.map.ObjEntity;
*
* @since 4.0
*/
-public abstract class FluentSelect<T> extends IndirectQuery implements
Select<T> {
+public abstract class FluentSelect<T> extends AbstractQuery implements
Select<T> {
+ // root
protected Class<?> entityType;
protected String entityName;
protected String dbEntityName;
+
protected Expression where;
protected Expression having;
- protected Collection<Ordering> orderings;
- protected PrefetchTreeNode prefetches;
- protected int limit;
- protected int offset;
- protected int pageSize;
- protected int statementFetchSize;
- protected QueryCacheStrategy cacheStrategy;
- protected String cacheGroup;
-
boolean havingExpressionIsActive = false;
+ protected Collection<Ordering> orderings;
+
protected FluentSelect() {
}
- /**
- * Translates self to a SelectQuery.
- */
- @SuppressWarnings("unchecked")
- @Override
- protected Query createReplacementQuery(EntityResolver resolver) {
-
- @SuppressWarnings("rawtypes")
- SelectQuery replacement = new SelectQuery();
-
+ protected Object resolveRoot(EntityResolver resolver) {
+ Object root;
if (entityType != null) {
- replacement.setRoot(entityType);
+ root = entityType;
} else if (entityName != null) {
ObjEntity entity = resolver.getObjEntity(entityName);
@@ -77,7 +65,7 @@ public abstract class FluentSelect<T> extends IndirectQuery
implements Select<T>
throw new CayenneRuntimeException("Unrecognized ObjEntity
name: %s", entityName);
}
- replacement.setRoot(entity);
+ root = entity;
} else if (dbEntityName != null) {
DbEntity entity = resolver.getDbEntity(dbEntityName);
@@ -85,47 +73,27 @@ public abstract class FluentSelect<T> extends IndirectQuery
implements Select<T>
throw new CayenneRuntimeException("Unrecognized DbEntity name:
%s", dbEntityName);
}
- replacement.setRoot(entity);
+ root = entity;
} else {
throw new CayenneRuntimeException("Undefined root entity of the
query");
}
-
- replacement.setQualifier(where);
- replacement.setHavingQualifier(having);
- replacement.addOrderings(orderings);
- replacement.setPrefetchTree(prefetches);
- replacement.setCacheStrategy(cacheStrategy);
- replacement.setCacheGroup(cacheGroup);
- replacement.setFetchLimit(limit);
- replacement.setFetchOffset(offset);
- replacement.setPageSize(pageSize);
- replacement.setStatementFetchSize(statementFetchSize);
-
- return replacement;
- }
-
- public String getCacheGroup() {
- return cacheGroup;
- }
-
- public QueryCacheStrategy getCacheStrategy() {
- return cacheStrategy;
+ return root;
}
public int getStatementFetchSize() {
- return statementFetchSize;
+ return getBaseMetaData().getStatementFetchSize();
}
public int getPageSize() {
- return pageSize;
+ return getBaseMetaData().getPageSize();
}
public int getLimit() {
- return limit;
+ return getBaseMetaData().getFetchLimit();
}
public int getOffset() {
- return offset;
+ return getBaseMetaData().getFetchOffset();
}
public Class<?> getEntityType() {
@@ -159,7 +127,7 @@ public abstract class FluentSelect<T> extends IndirectQuery
implements Select<T>
}
public PrefetchTreeNode getPrefetches() {
- return prefetches;
+ return getBaseMetaData().getPrefetchTree();
}
void setActiveExpression(Expression exp) {
@@ -168,7 +136,6 @@ public abstract class FluentSelect<T> extends IndirectQuery
implements Select<T>
} else {
where = exp;
}
- replacementQuery = null;
}
Expression getActiveExpression() {
@@ -203,4 +170,41 @@ public abstract class FluentSelect<T> extends
IndirectQuery implements Select<T>
public ResultBatchIterator<T> batchIterator(ObjectContext context, int
size) {
return context.batchIterator(this, size);
}
+
+ @Override
+ public SQLAction createSQLAction(SQLActionVisitor visitor) {
+ return visitor.objectSelectAction(this);
+ }
+
+ @Override
+ public void route(QueryRouter router, EntityResolver resolver, Query
substitutedQuery) {
+ super.route(router, resolver, substitutedQuery);
+
+ // suppress prefetches for paginated queries.. instead prefetches will
be resolved per row...
+ if (getPageSize() <= 0) {
+ routePrefetches(router, resolver);
+ }
+ }
+
+ public boolean isFetchingDataRows() {
+ return false;
+ }
+
+ private void routePrefetches(QueryRouter router, EntityResolver resolver) {
+ new FluentSelectPrefetchRouterAction().route(this, router, resolver);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public Collection<BaseProperty<?>> getColumns() {
+ return null;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public boolean isDistinct() {
+ return false;
+ }
}
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
new file mode 100644
index 0000000..a67bf66
--- /dev/null
+++
b/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelectPrefetchRouterAction.java
@@ -0,0 +1,141 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.query;
+
+import java.util.Iterator;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.reflect.ClassDescriptor;
+import org.apache.cayenne.util.CayenneMapEntry;
+
+/**
+ * Preprocessor and router of SelectQuery prefetches.
+ * Copy of {@link SelectQueryPrefetchRouterAction}.
+ *
+ * @since 4.2
+ */
+class FluentSelectPrefetchRouterAction implements PrefetchProcessor {
+
+ FluentSelect<?> query;
+ QueryRouter router;
+ EntityResolver resolver;
+ ClassDescriptor classDescriptor;
+
+ /**
+ * Routes query prefetches, but not the query itself.
+ */
+ void route(FluentSelect<?> query, QueryRouter router, EntityResolver
resolver) {
+ if (!query.isFetchingDataRows() && query.getPrefetches() != null) {
+
+ this.query = query;
+ this.router = router;
+ this.resolver = resolver;
+ this.classDescriptor =
query.getMetaData(resolver).getClassDescriptor();
+
+ query.getPrefetches().traverse(this);
+ }
+ }
+
+ public boolean startPhantomPrefetch(PrefetchTreeNode node) {
+ return true;
+ }
+
+ public boolean startDisjointPrefetch(PrefetchTreeNode node) {
+ // don't do anything to root
+ if (node == query.getPrefetches()) {
+ return true;
+ }
+
+ String prefetchPath = node.getPath();
+
+ // find last relationship
+ Iterator<CayenneMapEntry> it =
classDescriptor.getEntity().resolvePathComponents(
+ prefetchPath);
+
+ ObjRelationship relationship = null;
+ while (it.hasNext()) {
+ relationship = (ObjRelationship) it.next();
+ }
+
+ if (relationship == null) {
+ throw new CayenneRuntimeException("Invalid prefetch '%s' for
entity '%s'"
+ , prefetchPath, classDescriptor.getEntity().getName());
+ }
+
+ // chain query and entity qualifiers
+ Expression queryQualifier = query.getWhere();
+
+ Expression entityQualifier = classDescriptor
+ .getEntityInheritanceTree()
+ .qualifierForEntityAndSubclasses();
+
+ if (entityQualifier != null) {
+ queryQualifier = (queryQualifier != null)
+ ? queryQualifier.andExp(entityQualifier)
+ : entityQualifier;
+ }
+
+ // create and configure PrefetchSelectQuery
+ PrefetchSelectQuery<?> prefetchQuery = new
PrefetchSelectQuery<>(prefetchPath, relationship);
+ prefetchQuery.setStatementFetchSize(query.getStatementFetchSize());
+
+ prefetchQuery.setQualifier(classDescriptor.getEntity()
+ .translateToRelatedEntity(queryQualifier, prefetchPath));
+
+ if (relationship.isSourceIndependentFromTargetChange()) {
+ // setup extra result columns to be able to relate result rows to
the parent
+ // result objects.
+ prefetchQuery.addResultPath("db:" +
relationship.getReverseDbRelationshipPath());
+ }
+
+ // pass prefetch subtree to enable joint prefetches...
+ prefetchQuery.setPrefetchTree(node);
+
+ // route...
+ prefetchQuery.route(router, resolver, null);
+ return true;
+ }
+
+ public boolean startDisjointByIdPrefetch(PrefetchTreeNode
prefetchTreeNode) {
+ // simply pass through
+ return true;
+ }
+
+ public boolean startJointPrefetch(PrefetchTreeNode node) {
+ // simply pass through
+ return true;
+ }
+
+ public boolean startUnknownPrefetch(PrefetchTreeNode node) {
+ // don't do anything to root
+ if (node == query.getPrefetches()) {
+ return true;
+ }
+
+ // route unknown as disjoint...
+ return startDisjointPrefetch(node);
+ }
+
+ public void finishPrefetch(PrefetchTreeNode node) {
+ }
+}
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 f633372..2ce2919 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
@@ -57,7 +57,7 @@ public class ObjectSelect<T> extends FluentSelect<T> {
private static final long serialVersionUID = -156124021150949227L;
- protected boolean fetchingDataRows;
+ protected ObjectSelectMetadata metaData = new ObjectSelectMetadata();
/**
* Creates a ObjectSelect that selects objects of a given persistent class.
@@ -154,17 +154,6 @@ public class ObjectSelect<T> extends FluentSelect<T> {
}
/**
- * Translates self to a SelectQuery.
- */
- @SuppressWarnings({"deprecation", "unchecked"})
- @Override
- protected Query createReplacementQuery(EntityResolver resolver) {
- SelectQuery<?> replacement = (SelectQuery<?>)
super.createReplacementQuery(resolver);
- replacement.setFetchingDataRows(fetchingDataRows);
- return replacement;
- }
-
- /**
* Sets the type of the entity to fetch without changing the return type of
* the query.
*
@@ -365,7 +354,6 @@ public class ObjectSelect<T> extends FluentSelect<T> {
}
Collections.addAll(this.orderings, orderings);
- replacementQuery = null;
return this;
}
@@ -386,7 +374,6 @@ public class ObjectSelect<T> extends FluentSelect<T> {
}
this.orderings.addAll(orderings);
- replacementQuery = null;
return this;
}
@@ -397,17 +384,7 @@ public class ObjectSelect<T> extends FluentSelect<T> {
* @return this object
*/
public ObjectSelect<T> prefetch(PrefetchTreeNode prefetch) {
-
- if (prefetch == null) {
- return this;
- }
-
- if (prefetches == null) {
- prefetches = new PrefetchTreeNode();
- }
-
- prefetches.merge(prefetch);
- replacementQuery = null;
+ metaData.mergePrefetch(prefetch);
return this;
}
@@ -418,17 +395,10 @@ public class ObjectSelect<T> extends FluentSelect<T> {
* @return this object
*/
public ObjectSelect<T> prefetch(String path, int semantics) {
-
if (path == null) {
return this;
}
-
- if (prefetches == null) {
- prefetches = new PrefetchTreeNode();
- }
-
- prefetches.addPath(path).setSemantics(semantics);
- replacementQuery = null;
+ metaData.addPrefetch(path, semantics);
return this;
}
@@ -436,13 +406,8 @@ public class ObjectSelect<T> extends FluentSelect<T> {
* Resets query fetch limit - a parameter that defines max number of
objects
* that should be ever be fetched from the database.
*/
- @SuppressWarnings("unchecked")
public ObjectSelect<T> limit(int fetchLimit) {
- if (this.limit != fetchLimit) {
- this.limit = fetchLimit;
- this.replacementQuery = null;
- }
-
+ this.metaData.setFetchLimit(fetchLimit);
return this;
}
@@ -451,11 +416,7 @@ public class ObjectSelect<T> extends FluentSelect<T> {
* should be skipped when reading data from the database.
*/
public ObjectSelect<T> offset(int fetchOffset) {
- if (this.offset != fetchOffset) {
- this.offset = fetchOffset;
- this.replacementQuery = null;
- }
-
+ this.metaData.setFetchOffset(fetchOffset);
return this;
}
@@ -465,11 +426,7 @@ public class ObjectSelect<T> extends FluentSelect<T> {
* parts of the result are ever going to be accessed.
*/
public ObjectSelect<T> pageSize(int pageSize) {
- if (this.pageSize != pageSize) {
- this.pageSize = pageSize;
- this.replacementQuery = null;
- }
-
+ this.metaData.setPageSize(pageSize);
return this;
}
@@ -480,25 +437,13 @@ public class ObjectSelect<T> extends FluentSelect<T> {
* @see Statement#setFetchSize(int)
*/
public ObjectSelect<T> statementFetchSize(int size) {
- if (this.statementFetchSize != size) {
- this.statementFetchSize = size;
- this.replacementQuery = null;
- }
-
+ this.metaData.setStatementFetchSize(size);
return this;
}
public ObjectSelect<T> cacheStrategy(QueryCacheStrategy strategy) {
- if (this.cacheStrategy != strategy) {
- this.cacheStrategy = strategy;
- this.replacementQuery = null;
- }
-
- if(this.cacheGroup != null) {
- this.cacheGroup = null;
- this.replacementQuery = null;
- }
-
+ setCacheStrategy(strategy);
+ setCacheGroup(null);
return this;
}
@@ -507,8 +452,7 @@ public class ObjectSelect<T> extends FluentSelect<T> {
}
public ObjectSelect<T> cacheGroup(String cacheGroup) {
- this.cacheGroup = cacheGroup;
- this.replacementQuery = null;
+ setCacheGroup(cacheGroup);
return this;
}
@@ -568,10 +512,7 @@ public class ObjectSelect<T> extends FluentSelect<T> {
*/
@SuppressWarnings("unchecked")
public ObjectSelect<DataRow> fetchDataRows() {
- if(!fetchingDataRows) {
- fetchingDataRows = true;
- replacementQuery = null;
- }
+ metaData.setFetchingDataRows(true);
return (ObjectSelect<DataRow>) this;
}
@@ -725,7 +666,20 @@ public class ObjectSelect<T> extends FluentSelect<T> {
return context.selectFirst(limit(1));
}
+ @Override
public boolean isFetchingDataRows() {
- return fetchingDataRows;
+ return metaData.isFetchingDataRows();
+ }
+
+ @Override
+ public QueryMetadata getMetaData(EntityResolver resolver) {
+ Object root = resolveRoot(resolver);
+ metaData.resolve(root, resolver, this);
+ return metaData;
+ }
+
+ @Override
+ protected BaseQueryMetadata 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
new file mode 100644
index 0000000..b23a4af
--- /dev/null
+++
b/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelectMetadata.java
@@ -0,0 +1,171 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.query;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.TraversalHandler;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * @since 4.2
+ */
+class ObjectSelectMetadata extends BaseQueryMetadata {
+
+ private static final long serialVersionUID = -4936484509363047672L;
+
+ private Map<String, String> pathSplitAliases;
+
+ @Override
+ void copyFromInfo(QueryMetadata info) {
+ super.copyFromInfo(info);
+ this.pathSplitAliases = new
HashMap<>(info.getPathSplitAliases());
+ }
+
+ boolean resolve(Object root, EntityResolver resolver, ObjectSelect<?>
query) {
+
+ if (super.resolve(root, resolver)) {
+ // generate unique cache key, but only if we are
caching..
+ if (cacheStrategy != null && cacheStrategy !=
QueryCacheStrategy.NO_CACHE) {
+ this.cacheKey = makeCacheKey(query, resolver);
+ }
+
+ resolveAutoAliases(query);
+ return true;
+ }
+
+ return false;
+ }
+
+ private String makeCacheKey(FluentSelect<?> query, EntityResolver
resolver) {
+
+ // create a unique key based on entity or columns, qualifier,
ordering, fetch offset and limit
+
+ StringBuilder key = new StringBuilder();
+ // handler to create string out of expressions, created lazily
+ TraversalHandler traversalHandler = null;
+
+ ObjEntity entity = getObjEntity();
+ if (entity != null) {
+ key.append(entity.getName());
+ } else if (dbEntity != null) {
+ key.append("db:").append(dbEntity.getName());
+ }
+
+ if (query.getWhere() != null) {
+ key.append('/');
+ traversalHandler = new
ToCacheKeyTraversalHandler(resolver.getValueObjectTypeRegistry(), key);
+ query.getWhere().traverse(traversalHandler);
+ }
+
+ if (query.getOrderings() != null &&
!query.getOrderings().isEmpty()) {
+ for (Ordering o : query.getOrderings()) {
+ key.append('/').append(o.getSortSpecString());
+ if (!o.isAscending()) {
+ key.append(":d");
+ }
+
+ if (o.isCaseInsensitive()) {
+ key.append(":i");
+ }
+ }
+ }
+
+ if (fetchLimit > 0 || fetchOffset > 0) {
+ key.append('/');
+ if (fetchOffset > 0) {
+ key.append('o').append(fetchOffset);
+ }
+ if (fetchLimit > 0) {
+ key.append('l').append(fetchLimit);
+ }
+ }
+
+ // add prefetch to cache key per CAY-2349
+ if(prefetchTree != null) {
+ prefetchTree.traverse(new
ToCacheKeyPrefetchProcessor(key));
+ }
+
+ return key.toString();
+ }
+
+ private void resolveAutoAliases(ObjectSelect<?> query) {
+ resolveQualifierAliases(query);
+ resolveOrderingAliases(query);
+ }
+
+ private void resolveQualifierAliases(ObjectSelect<?> query) {
+ Expression qualifier = query.getWhere();
+ if (qualifier != null) {
+ resolveAutoAliases(qualifier);
+ }
+ }
+
+
+ private void resolveOrderingAliases(ObjectSelect<?> query) {
+ Collection<Ordering> orderings = query.getOrderings();
+ if(orderings != null) {
+ for(Ordering ordering : orderings) {
+ Expression sortSpec = ordering.getSortSpec();
+ if(sortSpec != null) {
+ resolveAutoAliases(sortSpec);
+ }
+ }
+ }
+ }
+
+ private void resolveAutoAliases(Expression expression) {
+ Map<String, String> aliases = expression.getPathAliases();
+ if (!aliases.isEmpty()) {
+ if (pathSplitAliases == null) {
+ pathSplitAliases = new HashMap<>();
+ }
+
+ for(Map.Entry<String, String> entry :
aliases.entrySet()) {
+ pathSplitAliases.compute(entry.getKey(), (key,
value) -> {
+ if(value != null &&
!value.equals(entry.getValue())){
+ throw new
CayenneRuntimeException("Can't add the same alias to different path segments.");
+ } else {
+ return entry.getValue();
+ }
+ });
+ }
+ }
+
+ int len = expression.getOperandCount();
+ for (int i = 0; i < len; i++) {
+ Object operand = expression.getOperand(i);
+ if (operand instanceof Expression) {
+ resolveAutoAliases((Expression) operand);
+ }
+ }
+ }
+
+ @Override
+ public Map<String, String> getPathSplitAliases() {
+ return pathSplitAliases != null ? pathSplitAliases :
Collections.emptyMap();
+ }
+
+}
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 fd968e3..baf682f 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
@@ -43,6 +43,12 @@ public interface SQLActionVisitor {
<T> SQLAction objectSelectAction(SelectQuery<T> query);
/**
+ * Creates an action to execute a FluentSelect.
+ * @since 4.2
+ */
+ <T> SQLAction objectSelectAction(FluentSelect<T> query);
+
+ /**
* Creates an action to execute a SQLTemplate.
*/
SQLAction sqlAction(SQLTemplate query);
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
index 9ee83bf..2dc74a9 100644
---
a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
+++
b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
@@ -449,125 +449,4 @@ class SelectQueryMetadata extends BaseQueryMetadata {
public void setSuppressingDistinct(boolean suppressingDistinct) {
this.suppressingDistinct = suppressingDistinct;
}
-
- /**
- * Expression traverse handler to create cache key string out of
Expression.
- * {@link Expression#appendAsString(Appendable)} where previously used
for that,
- * but it can't handle custom value objects properly (see CAY-2210).
- *
- * @see ValueObjectTypeRegistry
- *
- * @since 4.0
- */
- static class ToCacheKeyTraversalHandler implements TraversalHandler {
-
- private ValueObjectTypeRegistry registry;
- private StringBuilder out;
-
- ToCacheKeyTraversalHandler(ValueObjectTypeRegistry registry,
StringBuilder out) {
- this.registry = registry;
- this.out = out;
- }
-
- @Override
- public void finishedChild(Expression node, int childIndex,
boolean hasMoreChildren) {
- out.append(',');
- }
-
- @Override
- public void startNode(Expression node, Expression parentNode) {
- if(node.getType() == Expression.FUNCTION_CALL) {
-
out.append(((ASTFunctionCall)node).getFunctionName()).append('(');
- } else {
- out.append(node.getType()).append('(');
- }
- }
-
- @Override
- public void endNode(Expression node, Expression parentNode) {
- out.append(')');
- }
-
- @Override
- public void objectNode(Object leaf, Expression parentNode) {
- if(leaf == null) {
- out.append("null");
- return;
- }
-
- if(leaf instanceof ASTScalar) {
- leaf = ((ASTScalar) leaf).getValue();
- } else if(leaf instanceof Object[]) {
- for(Object value : (Object[])leaf) {
- objectNode(value, parentNode);
- out.append(',');
- }
- return;
- }
-
- if (leaf instanceof Persistent) {
- ObjectId id = ((Persistent) leaf).getObjectId();
- Object encode = (id != null) ? id : leaf;
- out.append(encode);
- } else if (leaf instanceof Enum<?>) {
- Enum<?> e = (Enum<?>) leaf;
-
out.append("e:").append(leaf.getClass().getName()).append(':').append(e.ordinal());
- } else {
- ValueObjectType<Object, ?> valueObjectType;
- if (registry == null || (valueObjectType =
registry.getValueType(leaf.getClass())) == null) {
- // Registry will be null in
cayenne-client context.
- // Maybe we shouldn't create cache key
at all in that case...
- out.append(leaf);
- } else {
-
out.append(valueObjectType.toCacheKey(leaf));
- }
- }
- }
- }
-
- /**
- * Prefetch processor that append prefetch tree into cache key.
- * @since 4.0
- */
- static class ToCacheKeyPrefetchProcessor implements PrefetchProcessor {
-
- StringBuilder out;
-
- ToCacheKeyPrefetchProcessor(StringBuilder out) {
- this.out = out;
- }
-
- @Override
- public boolean startPhantomPrefetch(PrefetchTreeNode node) {
- return true;
- }
-
- @Override
- public boolean startDisjointPrefetch(PrefetchTreeNode node) {
- out.append("/pd:").append(node.getPath());
- return true;
- }
-
- @Override
- public boolean startDisjointByIdPrefetch(PrefetchTreeNode node)
{
- out.append("/pi:").append(node.getPath());
- return true;
- }
-
- @Override
- public boolean startJointPrefetch(PrefetchTreeNode node) {
- out.append("/pj:").append(node.getPath());
- return true;
- }
-
- @Override
- public boolean startUnknownPrefetch(PrefetchTreeNode node) {
- out.append("/pu:").append(node.getPath());
- return true;
- }
-
- @Override
- public void finishPrefetch(PrefetchTreeNode node) {
- }
- }
}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/query/ToCacheKeyPrefetchProcessor.java
b/cayenne-server/src/main/java/org/apache/cayenne/query/ToCacheKeyPrefetchProcessor.java
new file mode 100644
index 0000000..9363985
--- /dev/null
+++
b/cayenne-server/src/main/java/org/apache/cayenne/query/ToCacheKeyPrefetchProcessor.java
@@ -0,0 +1,66 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.query;
+
+/**
+ * Prefetch processor that append prefetch tree into cache key.
+ * @since 4.2
+ */
+class ToCacheKeyPrefetchProcessor implements PrefetchProcessor {
+
+ private final StringBuilder out;
+
+ ToCacheKeyPrefetchProcessor(StringBuilder out) {
+ this.out = out;
+ }
+
+ @Override
+ public boolean startPhantomPrefetch(PrefetchTreeNode node) {
+ return true;
+ }
+
+ @Override
+ public boolean startDisjointPrefetch(PrefetchTreeNode node) {
+ out.append("/pd:").append(node.getPath());
+ return true;
+ }
+
+ @Override
+ public boolean startDisjointByIdPrefetch(PrefetchTreeNode node) {
+ out.append("/pi:").append(node.getPath());
+ return true;
+ }
+
+ @Override
+ public boolean startJointPrefetch(PrefetchTreeNode node) {
+ out.append("/pj:").append(node.getPath());
+ return true;
+ }
+
+ @Override
+ public boolean startUnknownPrefetch(PrefetchTreeNode node) {
+ out.append("/pu:").append(node.getPath());
+ return true;
+ }
+
+ @Override
+ public void finishPrefetch(PrefetchTreeNode node) {
+ }
+}
diff --git
a/cayenne-server/src/main/java/org/apache/cayenne/query/ToCacheKeyTraversalHandler.java
b/cayenne-server/src/main/java/org/apache/cayenne/query/ToCacheKeyTraversalHandler.java
new file mode 100644
index 0000000..a8fb613
--- /dev/null
+++
b/cayenne-server/src/main/java/org/apache/cayenne/query/ToCacheKeyTraversalHandler.java
@@ -0,0 +1,103 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.query;
+
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.Persistent;
+import org.apache.cayenne.access.types.ValueObjectType;
+import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.TraversalHandler;
+import org.apache.cayenne.exp.parser.ASTFunctionCall;
+import org.apache.cayenne.exp.parser.ASTScalar;
+
+/**
+ * Expression traverse handler to create cache key string out of Expression.
+ * {@link Expression#appendAsString(Appendable)} where previously used for
that,
+ * but it can't handle custom value objects properly (see CAY-2210).
+ *
+ * @see ValueObjectTypeRegistry
+ * @since 4.2
+ */
+class ToCacheKeyTraversalHandler implements TraversalHandler {
+
+ private ValueObjectTypeRegistry registry;
+ private StringBuilder out;
+
+ ToCacheKeyTraversalHandler(ValueObjectTypeRegistry registry, StringBuilder
out) {
+ this.registry = registry;
+ this.out = out;
+ }
+
+ @Override
+ public void finishedChild(Expression node, int childIndex, boolean
hasMoreChildren) {
+ out.append(',');
+ }
+
+ @Override
+ public void startNode(Expression node, Expression parentNode) {
+ if(node.getType() == Expression.FUNCTION_CALL) {
+ out.append(((ASTFunctionCall)node).getFunctionName()).append('(');
+ } else {
+ out.append(node.getType()).append('(');
+ }
+ }
+
+ @Override
+ public void endNode(Expression node, Expression parentNode) {
+ out.append(')');
+ }
+
+ @Override
+ public void objectNode(Object leaf, Expression parentNode) {
+ if(leaf == null) {
+ out.append("null");
+ return;
+ }
+
+ if(leaf instanceof ASTScalar) {
+ leaf = ((ASTScalar) leaf).getValue();
+ } else if(leaf instanceof Object[]) {
+ for(Object value : (Object[])leaf) {
+ objectNode(value, parentNode);
+ out.append(',');
+ }
+ return;
+ }
+
+ if (leaf instanceof Persistent) {
+ ObjectId id = ((Persistent) leaf).getObjectId();
+ Object encode = (id != null) ? id : leaf;
+ out.append(encode);
+ } else if (leaf instanceof Enum<?>) {
+ Enum<?> e = (Enum<?>) leaf;
+
out.append("e:").append(leaf.getClass().getName()).append(':').append(e.ordinal());
+ } else {
+ ValueObjectType<Object, ?> valueObjectType;
+ if (registry == null || (valueObjectType =
registry.getValueType(leaf.getClass())) == null) {
+ // Registry will be null in cayenne-client context.
+ // Maybe we shouldn't create cache key at all in that case...
+ out.append(leaf);
+ } else {
+ out.append(valueObjectType.toCacheKey(leaf));
+ }
+ }
+ }
+}
diff --git
a/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/MockQueryWrapperBuilder.java
b/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/MockQueryWrapperBuilder.java
index 3c43204..4361150 100644
---
a/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/MockQueryWrapperBuilder.java
+++
b/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/MockQueryWrapperBuilder.java
@@ -104,11 +104,6 @@ class MockQueryWrapperBuilder {
}
@Override
- public PrefetchTreeNode getPrefetchTree() {
- return prefetchTreeNode;
- }
-
- @Override
public Expression getQualifier() {
return qualifier;
}
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 96c4017..ef0a0c9 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
@@ -243,17 +243,17 @@ public class ColumnSelectTest {
ColumnSelect<Artist> q = new ColumnSelect<>();
assertFalse(q.distinct);
- assertFalse(q.suppressDistinct);
+ assertFalse(q.metaData.isSuppressingDistinct());
q.distinct();
assertTrue(q.distinct);
- assertFalse(q.suppressDistinct);
+ assertFalse(q.metaData.isSuppressingDistinct());
q.suppressDistinct();
assertFalse(q.distinct);
- assertTrue(q.suppressDistinct);
+ assertTrue(q.metaData.isSuppressingDistinct());
}
}
\ No newline at end of file
diff --git
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelectTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelectTest.java
index dd9e1f2..ee7681b 100644
---
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelectTest.java
+++
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelectTest.java
@@ -372,11 +372,11 @@ public class ObjectSelectTest {
public void testCacheGroups_Collection() {
ObjectSelect<DataRow> q =
ObjectSelect.dataRowQuery(Artist.class);
- assertNull(q.getCacheStrategy());
+ assertEquals(QueryCacheStrategy.NO_CACHE, q.getCacheStrategy());
assertNull(q.getCacheGroup());
q.cacheGroup("a");
- assertNull(q.getCacheStrategy());
+ assertEquals(QueryCacheStrategy.NO_CACHE, q.getCacheStrategy());
assertEquals("a", q.getCacheGroup());
}
@@ -384,7 +384,7 @@ public class ObjectSelectTest {
public void testCacheStrategy() {
ObjectSelect<DataRow> q =
ObjectSelect.dataRowQuery(Artist.class);
- assertNull(q.getCacheStrategy());
+ assertEquals(QueryCacheStrategy.NO_CACHE, q.getCacheStrategy());
assertNull(q.getCacheGroup());
q.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, "b");
@@ -400,7 +400,7 @@ public class ObjectSelectTest {
public void testLocalCache() {
ObjectSelect<DataRow> q =
ObjectSelect.dataRowQuery(Artist.class);
- assertNull(q.getCacheStrategy());
+ assertEquals(QueryCacheStrategy.NO_CACHE, q.getCacheStrategy());
assertNull(q.getCacheGroup());
q.localCache("a");
@@ -416,7 +416,7 @@ public class ObjectSelectTest {
public void testSharedCache() {
ObjectSelect<DataRow> q =
ObjectSelect.dataRowQuery(Artist.class);
- assertNull(q.getCacheStrategy());
+ assertEquals(QueryCacheStrategy.NO_CACHE, q.getCacheStrategy());
assertNull(q.getCacheGroup());
q.sharedCache("b");
diff --git
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_CompileIT.java
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_CompileIT.java
deleted file mode 100644
index caecb15..0000000
---
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_CompileIT.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-package org.apache.cayenne.query;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-import org.apache.cayenne.CayenneDataObject;
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.DataRow;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.property.BaseProperty;
-import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.testdo.testmap.Artist;
-import org.apache.cayenne.unit.di.server.CayenneProjects;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
-public class ObjectSelect_CompileIT extends ServerCase {
-
- @Inject
- private EntityResolver resolver;
-
- @Test
- public void testCreateReplacementQuery_Bare() {
-
- // use only a minimal number of attributes, with null/defaults
for
- // everything else
- ObjectSelect<Artist> q = ObjectSelect.query(Artist.class);
-
- Query replacement = q.createReplacementQuery(resolver);
- assertThat(replacement, instanceOf(SelectQuery.class));
-
- @SuppressWarnings("unchecked")
- SelectQuery<Artist> selectQuery = (SelectQuery<Artist>)
replacement;
- assertNull(selectQuery.getQualifier());
- assertEquals(Artist.class, selectQuery.getRoot());
- assertEquals(0, selectQuery.getOrderings().size());
- assertNull(selectQuery.getPrefetchTree());
-
- assertEquals(QueryCacheStrategy.NO_CACHE,
selectQuery.getCacheStrategy());
- assertNull(selectQuery.getCacheGroup());
- assertEquals(0, selectQuery.getFetchLimit());
- assertEquals(0, selectQuery.getFetchOffset());
- assertEquals(0, selectQuery.getPageSize());
- assertEquals(0, selectQuery.getStatementFetchSize());
- }
-
- @Test
- public void testCreateReplacementQuery_Full() {
-
- // add all possible attributes to the query and make sure they
got propagated
- ObjectSelect<Artist> q =
ObjectSelect.query(Artist.class).where(Artist.ARTIST_NAME.eq("me"))
- .orderBy(Artist.DATE_OF_BIRTH.asc(),
Artist.ARTIST_NAME.desc()).prefetch(Artist.PAINTING_ARRAY.joint())
-
.localCache("cg2").limit(46).offset(9).pageSize(6).statementFetchSize(789);
-
- Query replacement = q.createReplacementQuery(resolver);
- assertThat(replacement, instanceOf(SelectQuery.class));
-
- @SuppressWarnings("unchecked")
- SelectQuery<Artist> selectQuery = (SelectQuery<Artist>)
replacement;
- assertEquals("artistName = \"me\"",
selectQuery.getQualifier().toString());
-
- assertEquals(2, selectQuery.getOrderings().size());
- assertArrayEquals(new Object[] { Artist.DATE_OF_BIRTH.asc(),
Artist.ARTIST_NAME.desc() }, selectQuery
- .getOrderings().toArray());
-
- PrefetchTreeNode prefetch = selectQuery.getPrefetchTree();
- assertNotNull(prefetch);
- assertEquals(1, prefetch.getChildren().size());
-
- PrefetchTreeNode childPrefetch =
prefetch.getNode(Artist.PAINTING_ARRAY.getName());
- assertEquals(Artist.PAINTING_ARRAY.getName(),
childPrefetch.getName());
- assertEquals(PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS,
childPrefetch.getSemantics());
-
- assertEquals(QueryCacheStrategy.LOCAL_CACHE,
selectQuery.getCacheStrategy());
- assertEquals("cg2", selectQuery.getCacheGroup());
- assertEquals(46, selectQuery.getFetchLimit());
- assertEquals(9, selectQuery.getFetchOffset());
- assertEquals(6, selectQuery.getPageSize());
- assertEquals(789, selectQuery.getStatementFetchSize());
- }
-
- @Test
- public void testCreateReplacementQuery_RootClass() {
- ObjectSelect<Artist> q = ObjectSelect.query(Artist.class);
-
- @SuppressWarnings("rawtypes")
- SelectQuery qr = (SelectQuery)
q.createReplacementQuery(resolver);
- assertEquals(Artist.class, qr.getRoot());
- assertFalse(qr.isFetchingDataRows());
- }
-
- @Test
- public void testCreateReplacementQuery_RootDataRow() {
- ObjectSelect<DataRow> q =
ObjectSelect.dataRowQuery(Artist.class);
-
- @SuppressWarnings("rawtypes")
- SelectQuery qr = (SelectQuery)
q.createReplacementQuery(resolver);
- assertEquals(Artist.class, qr.getRoot());
- assertTrue(qr.isFetchingDataRows());
- }
-
- @Test
- public void testCreateReplacementQuery_RootDbEntity() {
- ObjectSelect<DataRow> q = ObjectSelect.dbQuery("ARTIST");
-
- @SuppressWarnings("rawtypes")
- SelectQuery qr = (SelectQuery)
q.createReplacementQuery(resolver);
- assertEquals(resolver.getDbEntity("ARTIST"), qr.getRoot());
- assertTrue(qr.isFetchingDataRows());
- }
-
- @Test
- public void testCreateReplacementQuery_RootObjEntity() {
- ObjectSelect<CayenneDataObject> q =
ObjectSelect.query(CayenneDataObject.class, "Artist");
-
- @SuppressWarnings("rawtypes")
- SelectQuery qr = (SelectQuery)
q.createReplacementQuery(resolver);
- assertEquals(resolver.getObjEntity(Artist.class), qr.getRoot());
- assertFalse(qr.isFetchingDataRows());
- }
-
- @Test(expected = CayenneRuntimeException.class)
- public void testCreateReplacementQuery_RootAbscent() {
- ObjectSelect<DataRow> q =
ObjectSelect.dataRowQuery(Artist.class).entityName(null);
- q.createReplacementQuery(resolver);
- }
-
- @Test
- public void testCreateReplacementQuery_DataRows() {
- ObjectSelect<Artist> q = ObjectSelect.query(Artist.class);
-
- @SuppressWarnings("rawtypes")
- SelectQuery selectQuery1 = (SelectQuery)
q.createReplacementQuery(resolver);
- assertFalse(selectQuery1.isFetchingDataRows());
-
- q.fetchDataRows();
-
- @SuppressWarnings("rawtypes")
- SelectQuery selectQuery2 = (SelectQuery)
q.createReplacementQuery(resolver);
- assertTrue(selectQuery2.isFetchingDataRows());
- }
-
- @Test
- public void testCreateReplacementQuery_Columns() {
- ObjectSelect<Artist> q = ObjectSelect.query(Artist.class);
-
- SelectQuery selectQuery1 = (SelectQuery)
q.createReplacementQuery(resolver);
- assertNull(selectQuery1.getColumns());
-
- ColumnSelect<Object[]> newQ = q.columns(Artist.ARTIST_NAME,
Artist.DATE_OF_BIRTH);
-
- SelectQuery selectQuery2 = (SelectQuery)
newQ.createReplacementQuery(resolver);
- assertNotNull(selectQuery2.getColumns());
-
- Collection<BaseProperty<?>> properties =
Arrays.asList(Artist.ARTIST_NAME, Artist.DATE_OF_BIRTH);
- assertEquals(properties, selectQuery2.getColumns());
- }
-
-}
diff --git
a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryMetadataCacheKeyTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryMetadataCacheKeyTest.java
index 03675d6..a3352ef 100644
---
a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryMetadataCacheKeyTest.java
+++
b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryMetadataCacheKeyTest.java
@@ -329,11 +329,11 @@ public class SelectQueryMetadataCacheKeyTest {
}
private TraversalHandler newHandler() {
- return new SelectQueryMetadata.ToCacheKeyTraversalHandler(registry,
cacheKey = new StringBuilder());
+ return new ToCacheKeyTraversalHandler(registry, cacheKey = new
StringBuilder());
}
private PrefetchProcessor newPrefetchProcessor() {
- return new SelectQueryMetadata.ToCacheKeyPrefetchProcessor(cacheKey =
new StringBuilder());
+ return new ToCacheKeyPrefetchProcessor(cacheKey = new StringBuilder());
}
/* ************* Test types *************** */