You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2016/08/16 07:25:02 UTC
cayenne git commit: CAY-2102 EJBQL: db: path not supported in select
columns
Repository: cayenne
Updated Branches:
refs/heads/master 21acbdec1 -> 5869e40f6
CAY-2102 EJBQL: db: path not supported in select columns
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/5869e40f
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/5869e40f
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/5869e40f
Branch: refs/heads/master
Commit: 5869e40f61e547cb33285803eede286a780cb0f3
Parents: 21acbde
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Tue Aug 16 09:37:22 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Tue Aug 16 10:24:52 2016 +0300
----------------------------------------------------------------------
.../translator/ejbql/EJBQLDbPathTranslator.java | 54 +++++++++++++++--
.../ejbql/EJBQLSelectColumnsTranslator.java | 64 ++++++++++++++++++--
.../apache/cayenne/ejbql/parser/Compiler.java | 23 ++++---
.../cayenne/ejbql/parser/EJBQLDbPath.java | 4 +-
.../apache/cayenne/ejbql/parser/EJBQLPath.java | 4 +-
.../cayenne/access/DataContextEJBQLQueryIT.java | 36 +++++++++++
docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 +
7 files changed, 164 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/5869e40f/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
index 8f1038c..7496255 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
@@ -18,11 +18,6 @@
****************************************************************/
package org.apache.cayenne.access.translator.ejbql;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
import org.apache.cayenne.ejbql.EJBQLException;
import org.apache.cayenne.ejbql.EJBQLExpression;
@@ -33,6 +28,11 @@ import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.Relationship;
import org.apache.cayenne.reflect.ClassDescriptor;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
private EJBQLTranslationContext context;
@@ -173,7 +173,7 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
}
}
- private void processTerminatingRelationship(DbRelationship relationship) {
+ protected void processTerminatingRelationship(DbRelationship relationship) {
if (relationship.isToMany()) {
@@ -235,4 +235,46 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
public void setUsingAliases(boolean usingAliases) {
this.usingAliases = usingAliases;
}
+
+ protected void resolveJoin() {
+
+ EJBQLJoinAppender joinAppender = context.getTranslatorFactory().getJoinAppender(context);
+
+ String newPath = idPath + '.' + lastPathComponent;
+ String oldPath = joinAppender.registerReusableJoin(idPath, lastPathComponent, newPath);
+
+ this.fullPath = fullPath + '.' + lastPathComponent;
+
+ if (oldPath != null) {
+ this.idPath = oldPath;
+ DbRelationship lastRelationship = currentEntity.getRelationship(lastPathComponent);
+ if (lastRelationship != null) {
+ DbEntity targetEntity = lastRelationship.getTargetEntity();
+
+ this.lastAlias = context.getTableAlias(fullPath,
+ context.getQuotingStrategy().quotedFullyQualifiedName(targetEntity));
+ } else {
+ String tableName = context.getQuotingStrategy().quotedFullyQualifiedName(currentEntity);
+ this.lastAlias = context.getTableAlias(oldPath, tableName);
+ }
+ } else {
+ DbRelationship lastRelationship = currentEntity.getRelationship(lastPathComponent);
+
+ DbEntity targetEntity = null;
+ if (lastRelationship != null) {
+ targetEntity = lastRelationship.getTargetEntity();
+ } else {
+ targetEntity = currentEntity;
+ }
+
+ // register join
+ joinAppender.appendInnerJoin(joinMarker, new EJBQLTableId(idPath), new EJBQLTableId(fullPath));
+ // TODO: outer joins handling
+
+ this.lastAlias = context.getTableAlias(fullPath,
+ context.getQuotingStrategy().quotedFullyQualifiedName(targetEntity));
+
+ this.idPath = newPath;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/5869e40f/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectColumnsTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectColumnsTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectColumnsTranslator.java
index 41a4017..c0f5eaf 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectColumnsTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectColumnsTranslator.java
@@ -18,10 +18,6 @@
****************************************************************/
package org.apache.cayenne.access.translator.ejbql;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
@@ -34,6 +30,10 @@ import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
/**
* Translator of the EJBQL select clause.
*
@@ -64,6 +64,62 @@ public class EJBQLSelectColumnsTranslator extends EJBQLBaseVisitor {
}
@Override
+ public boolean visitDbPath(EJBQLExpression expression, int finishedChildIndex) {
+
+ EJBQLDbPathTranslator pathTranslator = new EJBQLDbPathTranslator(context) {
+ @Override
+ protected void appendMultiColumnPath(EJBQLMultiColumnOperand operand) {
+ throw new EJBQLException("Can't use multi-column paths in column clause");
+ }
+
+ @Override
+ protected void processTerminatingRelationship(DbRelationship relationship) {
+ Map<String, String> xfields = null;
+ if (context.isAppendingResultColumns()) {
+ xfields = context.nextEntityResult().getFields();
+ }
+
+ final Map<String, String> fields = xfields;
+
+ DbEntity table = (DbEntity) relationship.getTargetEntity();
+ Collection<DbAttribute> dbAttr = table.getAttributes();
+
+ Iterator<DbAttribute> it = dbAttr.iterator();
+ if (dbAttr.size() > 0) {
+ resolveJoin();
+ }
+
+ String alias = this.lastAlias != null ? lastAlias : context.getTableAlias(idPath, context
+ .getQuotingStrategy().quotedFullyQualifiedName(table));
+
+ boolean first = true;
+ while (it.hasNext()) {
+
+ context.append(!first ? ", " : " ");
+
+ DbAttribute dbAttribute = it.next();
+ appendColumn(TypesMapping.getJavaBySqlType(dbAttribute.getType()), alias, dbAttribute,
+ fields != null ? fields.get(dbAttribute.getName()) : "");
+
+ first = false;
+ }
+ }
+
+ @Override
+ protected void processTerminatingAttribute(DbAttribute attribute) {
+ String alias = this.lastAlias != null ? lastAlias : context.getTableAlias(idPath, context
+ .getQuotingStrategy().quotedFullyQualifiedName(currentEntity));
+
+ appendColumn(TypesMapping.getJavaBySqlType(attribute.getType()), alias, attribute,
+ context.isAppendingResultColumns() ? context.nextColumnAlias() : "");
+ }
+ };
+
+ expression.visit(pathTranslator);
+ return false;
+ }
+
+ @Override
public boolean visitPath(EJBQLExpression expression, int finishedChildIndex) {
EJBQLPathTranslator pathTranslator = new EJBQLPathTranslator(context) {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/5869e40f/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/Compiler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/Compiler.java b/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/Compiler.java
index 5955b3e..aae5e17 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/Compiler.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/Compiler.java
@@ -18,14 +18,6 @@
****************************************************************/
package org.apache.cayenne.ejbql.parser;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
import org.apache.cayenne.ejbql.EJBQLException;
@@ -49,6 +41,14 @@ import org.apache.cayenne.reflect.PropertyVisitor;
import org.apache.cayenne.reflect.ToManyProperty;
import org.apache.cayenne.reflect.ToOneProperty;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* Produces an {@link EJBQLCompiledExpression} out of an EJBQL expression tree.
*
@@ -619,6 +619,13 @@ class Compiler {
}
@Override
+ public boolean visitDbPath(EJBQLExpression expression, int finishedChildIndex) {
+ addPath((EJBQLPath) expression);
+ addResultSetColumn();
+ return false;
+ }
+
+ @Override
public boolean visitPath(EJBQLExpression expression, int finishedChildIndex) {
addPath((EJBQLPath) expression);
addResultSetColumn();
http://git-wip-us.apache.org/repos/asf/cayenne/blob/5869e40f/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDbPath.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDbPath.java b/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDbPath.java
index 2f7444d..918b2e2 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDbPath.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDbPath.java
@@ -28,8 +28,8 @@ public class EJBQLDbPath extends EJBQLPath {
@Override
protected boolean visitChild(EJBQLExpressionVisitor visitor, int childIndex) {
- return super.visitChild(visitor, childIndex)
- && visitor.visitDbPath(this, childIndex);
+ children[childIndex].visit(visitor);
+ return visitor.visitDbPath(this, childIndex);
}
@Override
http://git-wip-us.apache.org/repos/asf/cayenne/blob/5869e40f/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java b/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java
index 41374e1..497edfe 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java
@@ -68,7 +68,7 @@ public class EJBQLPath extends SimpleNode {
@Override
protected boolean visitChild(EJBQLExpressionVisitor visitor, int childIndex) {
- return super.visitChild(visitor, childIndex)
- && visitor.visitPath(this, childIndex);
+ children[childIndex].visit(visitor);
+ return visitor.visitPath(this, childIndex);
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/5869e40f/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryIT.java
index e29e584..62c4cf3 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryIT.java
@@ -201,6 +201,42 @@ public class DataContextEJBQLQueryIT extends ServerCase {
}
@Test
+ public void testSelectDbPath() throws Exception {
+ createFourArtistsTwoPaintings();
+
+ String ejbql = "select db:p.ESTIMATED_PRICE "
+ + "from Painting p order by p.estimatedPrice";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List<?> data = context.performQuery(query);
+ assertEquals(2, data.size());
+
+ assertTrue(data.get(0) instanceof BigDecimal);
+ assertEquals(new BigDecimal(3000d), data.get(0));
+
+ assertTrue(data.get(1) instanceof BigDecimal);
+ assertEquals(new BigDecimal(5000d), data.get(1));
+ }
+
+ @Test
+ public void testSelectDbPath_Relationship() throws Exception {
+ createFourArtistsTwoPaintings();
+
+ String ejbql = "select db:p.toArtist "
+ + "from Painting p order by p.estimatedPrice";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List<?> data = context.performQuery(query);
+ assertEquals(2, data.size());
+
+ assertTrue(data.get(0) instanceof Artist);
+ assertEquals(33001, Cayenne.intPKForObject((Artist) data.get(0)));
+
+ assertTrue(data.get(1) instanceof Artist);
+ assertEquals(33002, Cayenne.intPKForObject((Artist) data.get(1)));
+ }
+
+ @Test
public void testSimpleSelect() throws Exception {
createFourArtistsTwoPaintings();
http://git-wip-us.apache.org/repos/asf/cayenne/blob/5869e40f/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 4a1f6d9..8889bbb 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -25,6 +25,7 @@ CAY-2076 Implement Jetty HTTP/1.1 and HTTP/2 Client support for ROP Client
CAY-2083 Implement Protostuff as serialization service for Cayenne ROP
CAY-2090 Untangle HttpRemoteService from ServiceContext thread local setup
CAY-2100 Add supporting generated keys for PostgreSQL
+CAY-2102 EJBQL: db: path not supported in select columns
Bug Fixes: