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: