You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/02/03 14:33:28 UTC
cayenne git commit: CAY-2032 SelectAction: DistinctResultIterator
ignores flattened relationships
Repository: cayenne
Updated Branches:
refs/heads/master 062e85259 -> e3704c287
CAY-2032 SelectAction: DistinctResultIterator ignores flattened relationships
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/e3704c28
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/e3704c28
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/e3704c28
Branch: refs/heads/master
Commit: e3704c2878273d339cb3b792d085a65e1a639ec8
Parents: 062e852
Author: Nikita Timofeev <st...@gmail.com>
Authored: Fri Feb 3 17:23:25 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Fri Feb 3 17:23:25 2017 +0300
----------------------------------------------------------------------
.../access/jdbc/DistinctResultIterator.java | 28 ++---
.../cayenne/access/jdbc/SelectAction.java | 8 +-
.../select/DefaultSelectTranslator.java | 10 +-
.../access/translator/select/JoinStack.java | 8 +-
.../translator/select/SelectTranslator.java | 6 +
.../cayenne/dba/openbase/OpenBaseJoinStack.java | 6 +-
.../dba/openbase/OpenBaseSelectTranslator.java | 2 +-
.../cayenne/dba/oracle/Oracle8JoinStack.java | 6 +-
.../dba/oracle/Oracle8SelectTranslator.java | 2 +-
.../cayenne/query/PrefetchSelectQuery.java | 6 +-
.../org/apache/cayenne/access/Cay2032IT.java | 115 +++++++++++++++++++
.../select/DefaultSelectTranslatorIT.java | 8 +-
.../apache/cayenne/testdo/cay_2032/Team.java | 9 ++
.../apache/cayenne/testdo/cay_2032/User.java | 9 ++
.../cayenne/testdo/cay_2032/auto/_Team.java | 35 ++++++
.../cayenne/testdo/cay_2032/auto/_User.java | 43 +++++++
.../cayenne/unit/di/server/CayenneProjects.java | 1 +
.../cayenne/unit/di/server/SchemaBuilder.java | 2 +-
.../src/test/resources/cay-2032.map.xml | 37 ++++++
.../src/test/resources/cayenne-cay-2032.xml | 4 +
docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 +
21 files changed, 306 insertions(+), 40 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/DistinctResultIterator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/DistinctResultIterator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/DistinctResultIterator.java
index 4cc0bb6..850b117 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/DistinctResultIterator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/DistinctResultIterator.java
@@ -45,7 +45,7 @@ public class DistinctResultIterator<T> implements ResultIterator<T> {
protected ResultIterator<T> delegate;
protected Set<Map<String, Object>> fetchedIds;
- protected DataRow nextDataRow;
+ protected T nextDataRow;
protected DbEntity defaultEntity;
protected boolean compareFullRows;
@@ -53,6 +53,7 @@ public class DistinctResultIterator<T> implements ResultIterator<T> {
* Creates new DistinctResultIterator wrapping another ResultIterator.
*
* @param delegate
+ * actual result iterator, that will be decorated by this DistinctResultIterator
* @param defaultEntity
* an entity needed to build ObjectIds for distinct comparison.
*/
@@ -67,7 +68,7 @@ public class DistinctResultIterator<T> implements ResultIterator<T> {
this.delegate = delegate;
this.defaultEntity = defaultEntity;
- this.fetchedIds = new HashSet<Map<String, Object>>();
+ this.fetchedIds = new HashSet<>();
this.compareFullRows = compareFullRows;
checkNextRow();
@@ -78,7 +79,7 @@ public class DistinctResultIterator<T> implements ResultIterator<T> {
*/
@Override
public Iterator<T> iterator() {
- return new ResultIteratorIterator<T>(this);
+ return new ResultIteratorIterator<>(this);
}
/**
@@ -113,9 +114,7 @@ public class DistinctResultIterator<T> implements ResultIterator<T> {
throw new NoSuchElementException("An attempt to read uninitialized row or past the end of the iterator.");
}
- // TODO:
- @SuppressWarnings("unchecked")
- T row = (T) nextDataRow;
+ T row = nextDataRow;
checkNextRow();
return row;
}
@@ -132,8 +131,7 @@ public class DistinctResultIterator<T> implements ResultIterator<T> {
checkNextRow();
}
- void checkNextRow() {
-
+ private void checkNextRow() {
if (this.compareFullRows) {
checkNextUniqueRow();
} else {
@@ -141,24 +139,22 @@ public class DistinctResultIterator<T> implements ResultIterator<T> {
}
}
- void checkNextUniqueRow() {
-
+ private void checkNextUniqueRow() {
nextDataRow = null;
while (delegate.hasNextRow()) {
- DataRow next = (DataRow) delegate.nextRow();
+ T next = delegate.nextRow();
- if (fetchedIds.add(next)) {
+ if (fetchedIds.add((DataRow)next)) {
this.nextDataRow = next;
break;
}
}
}
- void checkNextRowWithUniqueId() {
-
+ private void checkNextRowWithUniqueId() {
nextDataRow = null;
while (delegate.hasNextRow()) {
- DataRow next = (DataRow) delegate.nextRow();
+ T next = delegate.nextRow();
// create id map...
// TODO: this can be optimized by creating an array with id keys
@@ -166,7 +162,7 @@ public class DistinctResultIterator<T> implements ResultIterator<T> {
Map<String, Object> id = new HashMap<>();
for (final DbAttribute pk : defaultEntity.getPrimaryKeys()) {
- id.put(pk.getName(), next.get(pk.getName()));
+ id.put(pk.getName(), ((DataRow)next).get(pk.getName()));
}
if (fetchedIds.add(id)) {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
----------------------------------------------------------------------
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 fc84de6..ce2a22b 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
@@ -187,11 +187,11 @@ public class SelectAction extends BaseSQLAction {
// wrap result iterator if distinct has to be suppressed
// a joint prefetch warrants full row compare
-
final boolean[] compareFullRows = new boolean[1];
- final PrefetchTreeNode rootPrefetch = queryMetadata.getPrefetchTree();
+ compareFullRows[0] = translator.hasJoins();
- if (rootPrefetch != null) {
+ final PrefetchTreeNode rootPrefetch = queryMetadata.getPrefetchTree();
+ if (!compareFullRows[0] && rootPrefetch != null) {
rootPrefetch.traverse(new PrefetchProcessor() {
@Override
@@ -233,7 +233,7 @@ public class SelectAction extends BaseSQLAction {
});
}
- return new DistinctResultIterator<T>(iterator, queryMetadata.getDbEntity(), compareFullRows[0]);
+ return new DistinctResultIterator<>(iterator, queryMetadata.getDbEntity(), compareFullRows[0]);
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
----------------------------------------------------------------------
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 9adad76..affbe7a 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
@@ -117,7 +117,7 @@ public class DefaultSelectTranslator extends QueryAssembler implements SelectTra
}
protected JoinStack createJoinStack() {
- return new JoinStack(getAdapter(), queryMetadata.getDataMap(), this);
+ return new JoinStack(getAdapter(), this);
}
@Override
@@ -737,6 +737,14 @@ public class DefaultSelectTranslator extends QueryAssembler implements SelectTra
return null;
}
+ /**
+ * @since 4.0
+ */
+ @Override
+ public boolean hasJoins() {
+ return joinStack != null && joinStack.size() > 0;
+ }
+
static final class ColumnTracker {
private DbAttribute attribute;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/JoinStack.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/JoinStack.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/JoinStack.java
index 416f14c..5b11a3c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/JoinStack.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/JoinStack.java
@@ -55,7 +55,7 @@ public class JoinStack {
*/
private QualifierTranslator qualifierTranslator;
- protected JoinStack(DbAdapter dbAdapter, DataMap dataMap, QueryAssembler assembler) {
+ protected JoinStack(DbAdapter dbAdapter, QueryAssembler assembler) {
this.rootNode = new JoinTreeNode(this);
this.rootNode.setTargetTableAlias(newAlias());
@@ -99,7 +99,7 @@ public class JoinStack {
DbRelationship relationship = node.getRelationship();
- DbEntity targetEntity = (DbEntity) relationship.getTargetEntity();
+ DbEntity targetEntity = relationship.getTargetEntity();
String srcAlias = node.getSourceTableAlias();
String targetAlias = node.getTargetTableAlias();
@@ -134,7 +134,7 @@ public class JoinStack {
out.append(quotingStrategy.quotedIdentifier(targetEntity, targetAlias, join.getTargetName()));
}
- /**
+ /*
* Attaching root Db entity's qualifier
*/
Expression dbQualifier = targetEntity.getQualifier();
@@ -196,7 +196,7 @@ public class JoinStack {
while (node != null && node.getRelationship() != null) {
String relName = node.getRelationship().getName();
- /**
+ /*
* We must be in the same join as 'node', otherwise incorrect
* join statement like JOIN t1 ... ON (t0.id=t1.id AND
* t2.qualifier=0) could be generated
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
index 6554565..c987f57 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
@@ -42,4 +42,10 @@ public interface SelectTranslator {
ColumnDescriptor[] getResultColumns();
boolean isSuppressingDistinct();
+
+ /**
+ * @since 4.0
+ * @return do query has at least one join
+ */
+ boolean hasJoins();
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java
index a9c7579..9add9df 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java
@@ -39,8 +39,8 @@ import org.apache.cayenne.map.DbRelationship;
*/
class OpenBaseJoinStack extends JoinStack {
- protected OpenBaseJoinStack(DbAdapter dbAdapter, DataMap dataMap, QueryAssembler assembler) {
- super(dbAdapter, dataMap, assembler);
+ protected OpenBaseJoinStack(DbAdapter dbAdapter, QueryAssembler assembler) {
+ super(dbAdapter, assembler);
}
@Override
@@ -51,7 +51,7 @@ class OpenBaseJoinStack extends JoinStack {
return;
}
- DbEntity targetEntity = (DbEntity) relationship.getTargetEntity();
+ DbEntity targetEntity = relationship.getTargetEntity();
String targetAlias = node.getTargetTableAlias();
out.append(", ").append(targetEntity.getFullyQualifiedName()).append(' ').append(targetAlias);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java
index 342d0fd..e4ff7cc 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java
@@ -39,7 +39,7 @@ class OpenBaseSelectTranslator extends DefaultSelectTranslator {
@Override
protected JoinStack createJoinStack() {
- return new OpenBaseJoinStack(getAdapter(), queryMetadata.getDataMap(), this);
+ return new OpenBaseJoinStack(getAdapter(), this);
}
@Override
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java
index e27ee90..183775a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java
@@ -35,8 +35,8 @@ import org.apache.cayenne.map.DbRelationship;
// cloned from OpenBaseJoin stack... need better strategies of reuse...
class Oracle8JoinStack extends JoinStack {
- Oracle8JoinStack(DbAdapter dbAdapter, DataMap dataMap, QueryAssembler assembler) {
- super(dbAdapter, dataMap, assembler);
+ Oracle8JoinStack(DbAdapter dbAdapter, QueryAssembler assembler) {
+ super(dbAdapter, assembler);
}
@Override
@@ -47,7 +47,7 @@ class Oracle8JoinStack extends JoinStack {
return;
}
- DbEntity targetEntity = (DbEntity) relationship.getTargetEntity();
+ DbEntity targetEntity = relationship.getTargetEntity();
String targetAlias = node.getTargetTableAlias();
out.append(", ").append(targetEntity.getFullyQualifiedName()).append(' ').append(targetAlias);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java
index 6d1b16f..6df771c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java
@@ -41,7 +41,7 @@ class Oracle8SelectTranslator extends OracleSelectTranslator {
*/
@Override
protected JoinStack createJoinStack() {
- return new Oracle8JoinStack(getAdapter(), queryMetadata.getDataMap(), this);
+ return new Oracle8JoinStack(getAdapter(), this);
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchSelectQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchSelectQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchSelectQuery.java
index 33aa10e..9f181ad 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchSelectQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchSelectQuery.java
@@ -118,7 +118,7 @@ public class PrefetchSelectQuery extends SelectQuery<Object> {
/**
* Removes an extra result path. Note that this method doesn't check for expression
- * invariants, as it doesn't have a proper context to do so. E.g. for the purspose of
+ * invariants, as it doesn't have a proper context to do so. E.g. for the purpose of
* this method "db:ARTIST_NAME" and "obj:artistName" are not the same, though both
* will resolve to the same column name.
*/
@@ -136,7 +136,7 @@ public class PrefetchSelectQuery extends SelectQuery<Object> {
public Collection<String> getResultPaths() {
return resultPaths != null
? Collections.unmodifiableCollection(resultPaths)
- : Collections.EMPTY_SET;
+ : Collections.<String>emptySet();
}
/**
@@ -147,7 +147,7 @@ public class PrefetchSelectQuery extends SelectQuery<Object> {
*/
Collection<String> nonNullResultPaths() {
if (resultPaths == null) {
- resultPaths = new HashSet<String>();
+ resultPaths = new HashSet<>();
}
return resultPaths;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/java/org/apache/cayenne/access/Cay2032IT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/Cay2032IT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/Cay2032IT.java
new file mode 100644
index 0000000..7cfab34
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/Cay2032IT.java
@@ -0,0 +1,115 @@
+/*****************************************************************
+ * 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;
+
+import java.util.List;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.SortOrder;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.cay_2032.Team;
+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.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @since 4.0
+ */
+@UseServerRuntime(CayenneProjects.CAY_2032)
+public class Cay2032IT extends ServerCase {
+
+ @Inject
+ private DataContext context;
+
+ @Inject
+ private DBHelper dbHelper;
+
+ @Before
+ public void createTestData() throws Exception {
+ // USERS table has field `name` BLOB to trigger suppressDistinct in translator
+ TableHelper tUser = new TableHelper(dbHelper, "USERS");
+ tUser.setColumns("user_id");
+ tUser.insert(1);
+ tUser.insert(2);
+ tUser.insert(3);
+
+ TableHelper tTeam = new TableHelper(dbHelper, "TEAM");
+ tTeam.setColumns("team_id");
+ tTeam.insert(1);
+ tTeam.insert(2);
+ tTeam.insert(3);
+ tTeam.insert(4);
+
+ TableHelper tTeamHasUser = new TableHelper(dbHelper, "USER_HAS_TEAM");
+ tTeamHasUser.setColumns("team_id", "user_id");
+ tTeamHasUser.insert(1, 2);
+ tTeamHasUser.insert(2, 1);
+ tTeamHasUser.insert(2, 2);
+ tTeamHasUser.insert(2, 3);
+ tTeamHasUser.insert(3, 1);
+ tTeamHasUser.insert(3, 3);
+ }
+
+ private void checkResult(List<Team> result) throws Exception {
+ assertNotNull(result);
+ assertEquals(4, result.size());
+ assertEquals(1, result.get(0).getTeamUsers().size());
+ assertEquals(3, result.get(1).getTeamUsers().size());
+ assertEquals(2, result.get(2).getTeamUsers().size());
+ assertEquals(0, result.get(3).getTeamUsers().size());
+ }
+
+ @Test
+ public void testPrefetchDisjoint() throws Exception {
+ List<Team> result = ObjectSelect.query(Team.class)
+ .prefetch(Team.TEAM_USERS.disjoint())
+ .orderBy("db:team_id", SortOrder.ASCENDING)
+ .select(context);
+
+ checkResult(result);
+ }
+
+ @Test
+ public void testPrefetchDisjointById() throws Exception {
+ List<Team> result = ObjectSelect.query(Team.class)
+ .prefetch(Team.TEAM_USERS.disjointById())
+ .orderBy("db:team_id", SortOrder.ASCENDING)
+ .select(context);
+
+ checkResult(result);
+ }
+
+ @Test
+ public void testPrefetchJoint() throws Exception {
+ List<Team> result = ObjectSelect.query(Team.class)
+ .prefetch(Team.TEAM_USERS.joint())
+ .orderBy("db:team_id", SortOrder.ASCENDING)
+ .select(context);
+
+ checkResult(result);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorIT.java
index e090d0c..bb2248f 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorIT.java
@@ -74,11 +74,12 @@ public class DefaultSelectTranslatorIT extends ServerCase {
SelectQuery<Artist> q = new SelectQuery<Artist>(Artist.class, ExpressionFactory.likeExp("artistName", "a%"));
q.addOrdering("dateOfBirth", SortOrder.ASCENDING);
- String generatedSql = new DefaultSelectTranslator(q, dataNode.getAdapter(), dataNode.getEntityResolver())
- .getSql();
+ DefaultSelectTranslator defaultSelectTranslator = new DefaultSelectTranslator(q, dataNode.getAdapter(), dataNode.getEntityResolver());
+ String generatedSql = defaultSelectTranslator.getSql();
// do some simple assertions to make sure all parts are in
assertNotNull(generatedSql);
+ assertFalse(defaultSelectTranslator.hasJoins());
assertTrue(generatedSql.startsWith("SELECT "));
assertTrue(generatedSql.indexOf(" FROM ") > 0);
assertTrue(generatedSql.indexOf(" WHERE ") > generatedSql.indexOf(" FROM "));
@@ -226,7 +227,6 @@ public class DefaultSelectTranslatorIT extends ServerCase {
} else {
assertTrue(generatedSql.indexOf("ARTIST_NAME = ") > 0);
}
-
} finally {
entity.setQualifier(null);
middleEntity.setQualifier(null);
@@ -465,6 +465,7 @@ public class DefaultSelectTranslatorIT extends ServerCase {
// assert we only have one join
assertEquals(2, transl.joinStack.size());
+ assertTrue(transl.hasJoins());
}
@Test
@@ -490,6 +491,7 @@ public class DefaultSelectTranslatorIT extends ServerCase {
// assert we have one join
assertEquals(1, transl.joinStack.size());
+ assertTrue(transl.hasJoins());
}
@Test
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/Team.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/Team.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/Team.java
new file mode 100644
index 0000000..d6f3ac4
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/Team.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.testdo.cay_2032;
+
+import org.apache.cayenne.testdo.cay_2032.auto._Team;
+
+public class Team extends _Team {
+
+ private static final long serialVersionUID = 1L;
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/User.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/User.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/User.java
new file mode 100644
index 0000000..ab76f6a
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/User.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.testdo.cay_2032;
+
+import org.apache.cayenne.testdo.cay_2032.auto._User;
+
+public class User extends _User {
+
+ private static final long serialVersionUID = 1L;
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/auto/_Team.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/auto/_Team.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/auto/_Team.java
new file mode 100644
index 0000000..b5007ed
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/auto/_Team.java
@@ -0,0 +1,35 @@
+package org.apache.cayenne.testdo.cay_2032.auto;
+
+import java.util.List;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.exp.Property;
+import org.apache.cayenne.testdo.cay_2032.User;
+
+/**
+ * Class _Team was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _Team extends CayenneDataObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final String TEAM_ID_PK_COLUMN = "team_id";
+
+ public static final Property<List<User>> TEAM_USERS = Property.create("teamUsers", List.class);
+
+ public void addToTeamUsers(User obj) {
+ addToManyTarget("teamUsers", obj, true);
+ }
+ public void removeFromTeamUsers(User obj) {
+ removeToManyTarget("teamUsers", obj, true);
+ }
+ @SuppressWarnings("unchecked")
+ public List<User> getTeamUsers() {
+ return (List<User>)readProperty("teamUsers");
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/auto/_User.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/auto/_User.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/auto/_User.java
new file mode 100644
index 0000000..5f40fa9
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/cay_2032/auto/_User.java
@@ -0,0 +1,43 @@
+package org.apache.cayenne.testdo.cay_2032.auto;
+
+import java.util.List;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.exp.Property;
+import org.apache.cayenne.testdo.cay_2032.Team;
+
+/**
+ * Class _User was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _User extends CayenneDataObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final String USER_ID_PK_COLUMN = "user_id";
+
+ public static final Property<byte[]> NAME = Property.create("name", byte[].class);
+ public static final Property<List<Team>> USER_TEAMS = Property.create("userTeams", List.class);
+
+ public void setName(byte[] name) {
+ writeProperty("name", name);
+ }
+ public byte[] getName() {
+ return (byte[])readProperty("name");
+ }
+
+ public void addToUserTeams(Team obj) {
+ addToManyTarget("userTeams", obj, true);
+ }
+ public void removeFromUserTeams(Team obj) {
+ removeToManyTarget("userTeams", obj, true);
+ }
+ @SuppressWarnings("unchecked")
+ public List<Team> getUserTeams() {
+ return (List<Team>)readProperty("userTeams");
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
index ee51554..d7eb2f2 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
@@ -28,6 +28,7 @@ public class CayenneProjects {
// setup?)
public static final String ARRAY_TYPE_PROJECT = "cayenne-array-type.xml";
public static final String BINARY_PK_PROJECT = "cayenne-binary-pk.xml";
+ public static final String CAY_2032 = "cayenne-cay-2032.xml";
public static final String COMPOUND_PROJECT = "cayenne-compound.xml";
public static final String DATE_TIME_PROJECT = "cayenne-date-time.xml";
public static final String DELETE_RULES_PROJECT = "cayenne-delete-rules.xml";
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
index 05fc392..ec5d332 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
@@ -80,7 +80,7 @@ public class SchemaBuilder {
"table-primitives.map.xml", "generic.map.xml", "map-db1.map.xml", "map-db2.map.xml", "embeddable.map.xml",
"qualified.map.xml", "quoted-identifiers.map.xml", "inheritance-single-table1.map.xml",
"inheritance-vertical.map.xml", "oneway-rels.map.xml", "unsupported-distinct-types.map.xml",
- "array-type.map.xml" };
+ "array-type.map.xml", "cay-2032.map.xml" };
// hardcoded dependent entities that should be excluded
// if LOBs are not supported
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/resources/cay-2032.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cay-2032.map.xml b/cayenne-server/src/test/resources/cay-2032.map.xml
new file mode 100644
index 0000000..9a3b380
--- /dev/null
+++ b/cayenne-server/src/test/resources/cay-2032.map.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
+ project-version="9">
+ <property name="defaultPackage" value="org.apache.cayenne.testdo.cay_2032"/>
+ <db-entity name="TEAM">
+ <db-attribute name="team_id" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ </db-entity>
+ <db-entity name="USERS">
+ <db-attribute name="name" type="BLOB" length="255"/>
+ <db-attribute name="user_id" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ </db-entity>
+ <db-entity name="USER_HAS_TEAM">
+ <db-attribute name="team_id" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ <db-attribute name="user_id" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ </db-entity>
+ <obj-entity name="Team" className="org.apache.cayenne.testdo.cay_2032.Team" dbEntityName="TEAM">
+ </obj-entity>
+ <obj-entity name="User" className="org.apache.cayenne.testdo.cay_2032.User" dbEntityName="USERS">
+ <obj-attribute name="name" type="byte[]" db-attribute-path="name"/>
+ </obj-entity>
+ <db-relationship name="userHasTeam" source="TEAM" target="USER_HAS_TEAM" toMany="true">
+ <db-attribute-pair source="team_id" target="team_id"/>
+ </db-relationship>
+ <db-relationship name="userHasTeam" source="USERS" target="USER_HAS_TEAM" toMany="true">
+ <db-attribute-pair source="user_id" target="user_id"/>
+ </db-relationship>
+ <db-relationship name="team" source="USER_HAS_TEAM" target="TEAM" toMany="false">
+ <db-attribute-pair source="team_id" target="team_id"/>
+ </db-relationship>
+ <db-relationship name="user" source="USER_HAS_TEAM" target="USERS" toMany="false">
+ <db-attribute-pair source="user_id" target="user_id"/>
+ </db-relationship>
+ <obj-relationship name="teamUsers" source="Team" target="User" deleteRule="Deny" db-relationship-path="userHasTeam.user"/>
+ <obj-relationship name="userTeams" source="User" target="Team" deleteRule="Deny" db-relationship-path="userHasTeam.team"/>
+</data-map>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/cayenne-server/src/test/resources/cayenne-cay-2032.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-cay-2032.xml b/cayenne-server/src/test/resources/cayenne-cay-2032.xml
new file mode 100644
index 0000000..f9427a7
--- /dev/null
+++ b/cayenne-server/src/test/resources/cayenne-cay-2032.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="9">
+ <map name="cay-2032"/>
+</domain>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e3704c28/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index c165ab6..733956d 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -31,6 +31,7 @@ CAY-2212 cdbimport cleanup and configuration schema refactoring
Bug Fixes:
+CAY-2032 SelectAction: DistinctResultIterator ignores flattened relationships
CAY-2137 When generating SQL from EJBQL, use "AND" to separate multiple join conditions
CAY-2174 Change FK attribute name cause ObjAttribute appear after Reverse Engineering
CAY-2175 AliasName used in EJBQLQuery is not working if it contains mixed case