cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject cayenne git commit: CAY-2027 Support for Expression outer join syntax in EJBQL
Date Sun, 13 Sep 2015 18:59:56 GMT
Repository: cayenne
Updated Branches:
  refs/heads/master 1799395a9 -> de8a52b2e


CAY-2027 Support for Expression outer join syntax in EJBQL


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/de8a52b2
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/de8a52b2
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/de8a52b2

Branch: refs/heads/master
Commit: de8a52b2eb9b44656433d11991bbb7cc6c5c2d6c
Parents: 1799395
Author: aadamchik <aadamchik@apache.org>
Authored: Sun Sep 13 14:13:14 2015 -0400
Committer: aadamchik <aadamchik@apache.org>
Committed: Sun Sep 13 14:59:49 2015 -0400

----------------------------------------------------------------------
 .../ejbql/EJBQLAggregateColumnTranslator.java   |  2 +-
 .../ejbql/EJBQLGroupByTranslator.java           |  2 +-
 .../translator/ejbql/EJBQLPathTranslator.java   | 27 ++++++++++++---
 .../ejbql/EJBQLSelectColumnsTranslator.java     |  2 +-
 .../apache/cayenne/ejbql/parser/Compiler.java   |  5 +++
 .../org/apache/cayenne/ejbql/EJBQLParser.jjt    |  2 +-
 .../cayenne/access/DataContextEJBQLJoinsIT.java | 36 ++++++++++++++++++++
 .../cayenne/ejbql/EJBQLParser_ParseTest.java    |  8 ++++-
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |  1 +
 9 files changed, 75 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/de8a52b2/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLAggregateColumnTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLAggregateColumnTranslator.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLAggregateColumnTranslator.java
index 902b63e..d3bc0e3 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLAggregateColumnTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLAggregateColumnTranslator.java
@@ -127,7 +127,7 @@ class EJBQLAggregateColumnTranslator extends EJBQLBaseVisitor {
             Collection<DbAttribute> dbAttr = ((ObjEntity) relationship.getTargetEntity()).getDbEntity().getAttributes();
 
             if (dbAttr.size() > 0) {
-                this.resolveJoin(true);
+                resolveJoin();
             }
             context.append('*');
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/de8a52b2/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLGroupByTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLGroupByTranslator.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLGroupByTranslator.java
index ba32677..cf4b16f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLGroupByTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLGroupByTranslator.java
@@ -78,7 +78,7 @@ class EJBQLGroupByTranslator extends EJBQLBaseVisitor {
                             .quotedFullyQualifiedName(descriptor.getEntity().getDbEntity()));
                 }
 
-                this.lastPathComponent = expression.getText();
+                resolveLastPathComponent(expression.getText());
                 this.fullPath = fullPath + '.' + lastPathComponent;
 
                 return true;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/de8a52b2/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLPathTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLPathTranslator.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLPathTranslator.java
index c7342d9..75c0687 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLPathTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLPathTranslator.java
@@ -31,6 +31,7 @@ import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbJoin;
 import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
@@ -48,6 +49,7 @@ public abstract class EJBQLPathTranslator extends EJBQLBaseVisitor {
 	private EJBQLTranslationContext context;
 	protected ObjEntity currentEntity;
 	protected String lastPathComponent;
+	protected boolean innerJoin;
 	protected String lastAlias;
 	protected String idPath;
 	protected String joinMarker;
@@ -98,14 +100,28 @@ public abstract class EJBQLPathTranslator extends EJBQLBaseVisitor {
 		// join will
 		// get lost...
 		if (lastPathComponent != null) {
-			resolveJoin(true);
+			resolveJoin();
 		}
 
-		this.lastPathComponent = expression.getText();
+		resolveLastPathComponent(expression.getText());
 		return true;
 	}
+	
+	/**
+	 * @since 4.0
+	 */
+	protected void resolveLastPathComponent(String pathComponent) {
+		
+		if (pathComponent.endsWith(Entity.OUTER_JOIN_INDICATOR)) {
+			this.lastPathComponent = pathComponent.substring(0, pathComponent.length() - 1);
+			this.innerJoin = false;
+		} else {
+			this.lastPathComponent = pathComponent;
+			this.innerJoin = true;
+		}
+	}
 
-	protected void resolveJoin(boolean inner) {
+	protected void resolveJoin() {
 
 		EJBQLJoinAppender joinAppender = context.getTranslatorFactory().getJoinAppender(context);
 
@@ -137,7 +153,7 @@ public abstract class EJBQLPathTranslator extends EJBQLBaseVisitor {
 			}
 
 			// register join
-			if (inner) {
+			if (innerJoin) {
 				joinAppender.appendInnerJoin(joinMarker, new EJBQLTableId(idPath), new EJBQLTableId(fullPath));
 			} else {
 				joinAppender.appendOuterJoin(joinMarker, new EJBQLTableId(idPath), new EJBQLTableId(fullPath));
@@ -213,7 +229,8 @@ public abstract class EJBQLPathTranslator extends EJBQLBaseVisitor {
 			// MEMBER OF and IS EMPTY operators. Outer join is needed for IS
 			// EMPTY... I
 			// guess MEMBER OF could've been done with an inner join though..
-			resolveJoin(false);
+			this.innerJoin = false;
+			resolveJoin();
 
 			DbRelationship dbRelationship = chooseDbRelationship(relationship);
 			DbEntity table = (DbEntity) dbRelationship.getTargetEntity();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/de8a52b2/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 3266337..41a4017 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
@@ -91,7 +91,7 @@ public class EJBQLSelectColumnsTranslator extends EJBQLBaseVisitor {
 
                 Iterator<DbAttribute> it = dbAttr.iterator();
                 if (dbAttr.size() > 0) {
-                    this.resolveJoin(true);
+                    resolveJoin();
                 }
 
                 String alias = this.lastAlias != null ? lastAlias : context.getTableAlias(idPath,
context

http://git-wip-us.apache.org/repos/asf/cayenne/blob/de8a52b2/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 375547d..5955b3e 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
@@ -34,6 +34,7 @@ import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbJoin;
 import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.map.EntityResult;
 import org.apache.cayenne.map.ObjAttribute;
@@ -147,6 +148,10 @@ class Compiler {
                 for (int i = 1; i < path.getChildrenCount(); i++) {
 
                     String pathChunk = path.getChild(i).getText();
+                    if(pathChunk.endsWith(Entity.OUTER_JOIN_INDICATOR)) {
+                    	pathChunk = pathChunk.substring(0, pathChunk.length() - 1);
+                    }
+                    
                     buffer.append('.').append(pathChunk);
 
                     PropertyDescriptor property = descriptor.getProperty(pathChunk);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/de8a52b2/cayenne-server/src/main/jjtree/org/apache/cayenne/ejbql/EJBQLParser.jjt
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/jjtree/org/apache/cayenne/ejbql/EJBQLParser.jjt b/cayenne-server/src/main/jjtree/org/apache/cayenne/ejbql/EJBQLParser.jjt
index ed947fa..1a418bb 100644
--- a/cayenne-server/src/main/jjtree/org/apache/cayenne/ejbql/EJBQLParser.jjt
+++ b/cayenne-server/src/main/jjtree/org/apache/cayenne/ejbql/EJBQLParser.jjt
@@ -253,7 +253,7 @@ TOKEN : /* literals */
 /* From the Java 1.0.2 specification */
 TOKEN : /* IDENTIFIERS */
 {
-  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
+  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* (["+"])? >
 	|
   < #LETTER:
 	  [

http://git-wip-us.apache.org/repos/asf/cayenne/blob/de8a52b2/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLJoinsIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLJoinsIT.java
b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLJoinsIT.java
index f91c351..1a5bd31 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLJoinsIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLJoinsIT.java
@@ -179,6 +179,42 @@ public class DataContextEJBQLJoinsIT extends ServerCase {
 	}
 
 	@Test
+	public void testImplicitJoins_OUTER_LastComponent() throws Exception {
+
+		tArtist.insert(33001, "AA1");
+		tArtist.insert(33002, "AA2");
+		tPainting.insert(33005, 33001, null, "CC1", 5000);
+		tPainting.insert(33006, 33001, null, "CC2", 5000);
+
+		String ejbql = "SELECT a FROM Artist a WHERE a.paintingArray+ is null";
+
+		EJBQLQuery query = new EJBQLQuery(ejbql);
+
+		List<?> artists = context.performQuery(query);
+		assertEquals(1, artists.size());
+		assertEquals(33002, Cayenne.intPKForObject((Artist) artists.get(0)));
+	}
+
+	@Test
+	public void testImplicitJoins_OUTER_InTheMiddle() throws Exception {
+
+		tGallery.insert(33001, "gallery1");
+		tGallery.insert(33002, "gallery2");
+		tArtist.insert(33001, "AA1");
+		tArtist.insert(33002, "AA2");
+		tPainting.insert(33005, 33001, 33001, "CC1", 5000);
+		tPainting.insert(33006, 33001, 33002, "CC2", 5000);
+
+		String ejbql = "SELECT a FROM Artist a WHERE a.paintingArray+.toGallery is null";
+
+		EJBQLQuery query = new EJBQLQuery(ejbql);
+
+		List<?> artists = context.performQuery(query);
+		assertEquals(1, artists.size());
+		assertEquals(33002, Cayenne.intPKForObject((Artist) artists.get(0)));
+	}
+
+	@Test
 	public void testPartialImplicitJoins1() throws Exception {
 		createTwoArtistsTwoPaintingsTwoGalleries();
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/de8a52b2/cayenne-server/src/test/java/org/apache/cayenne/ejbql/EJBQLParser_ParseTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/ejbql/EJBQLParser_ParseTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/ejbql/EJBQLParser_ParseTest.java
index f63ce7e..3f70977 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/ejbql/EJBQLParser_ParseTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/ejbql/EJBQLParser_ParseTest.java
@@ -46,6 +46,13 @@ public class EJBQLParser_ParseTest {
 		assertNotNull(select);
 	}
 
+	@Test
+	public void testImplicitOuterJoin() {
+		EJBQLExpression select = parser
+				.parse("SELECT a FROM Artist a WHERE a.paintingArray+.toGallery.galleryName = 'gallery2'");
+		assertNotNull(select);
+	}
+
 	/**
 	 * This should not parse because there are multiple non-bracketed
 	 * parameters.
@@ -62,6 +69,5 @@ public class EJBQLParser_ParseTest {
 			fail("expected an instance of " + EJBQLException.class.getSimpleName() + " to be thrown,
but; "
 					+ th.getClass().getSimpleName() + " was thrown");
 		}
-
 	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/de8a52b2/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 655f412..74daf95 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -31,6 +31,7 @@ CAY-2013 In-memory evaluation of DB expressions - non-id attributes
 CAY-2023 Decouple the use of ResourceLocator
 CAY-2025 Support for DBCP2
 CAY-2026 Java 7
+CAY-2027 Support for Expression outer join syntax in EJBQL
 
 Bug Fixes:
 


Mime
View raw message