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 2007/06/11 11:54:51 UTC

svn commit: r546067 - in /cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src: main/java/org/apache/cayenne/access/jdbc/ test/java/org/apache/cayenne/access/jdbc/

Author: aadamchik
Date: Mon Jun 11 02:54:50 2007
New Revision: 546067

URL: http://svn.apache.org/viewvc?view=rev&rev=546067
Log:
refactoring of EJBQL translator 

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslationContext.java
      - copied, changed from r544060, cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslator.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslatorTest.java
Removed:
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslator.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/jdbc/EJBQLTranslatorTest.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslator.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java?view=diff&rev=546067&r1=546066&r2=546067
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java Mon Jun 11 02:54:50 2007
@@ -23,7 +23,9 @@
 
 import org.apache.cayenne.access.OperationObserver;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
 import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
+import org.apache.cayenne.ejbql.EJBQLExpression;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.query.EJBQLQuery;
 import org.apache.cayenne.query.SQLActionVisitor;
@@ -50,8 +52,27 @@
 
     public void performAction(Connection connection, OperationObserver observer)
             throws SQLException, Exception {
-        EJBQLCompiledExpression expression = query.getExpression(getEntityResolver());
-        SQLTemplate sql = new EJBQLTranslator(expression).translate();
-        actionFactory.sqlAction(sql).performAction(connection, observer);
+        EJBQLCompiledExpression compiledExpression = query.getExpression(getEntityResolver());
+        final EJBQLTranslationContext context = new EJBQLTranslationContext(compiledExpression);
+        
+        compiledExpression.getExpression().visit(new EJBQLBaseVisitor(false) {
+
+            public boolean visitSelect(EJBQLExpression expression, int finishedChildIndex) {
+                EJBQLSelectTranslator visitor = new EJBQLSelectTranslator(context);
+                expression.visit(visitor);
+                return false;
+            }
+
+            public boolean visitDelete(EJBQLExpression expression, int finishedChildIndex) {
+                throw new UnsupportedOperationException("Not yet implemented");
+            }
+
+            public boolean visitUpdate(EJBQLExpression expression, int finishedChildIndex) {
+                throw new UnsupportedOperationException("Not yet implemented");
+            }
+        });
+
+        SQLTemplate sqlQuery = context.getQuery();
+        actionFactory.sqlAction(sqlQuery).performAction(connection, observer);
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslator.java?view=diff&rev=546067&r1=546066&r2=546067
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslator.java Mon Jun 11 02:54:50 2007
@@ -35,10 +35,10 @@
  */
 class EJBQLSelectTranslator extends EJBQLDelegatingVisitor {
 
-    private EJBQLTranslator parent;
+    private EJBQLTranslationContext parent;
     private Set columns;
 
-    EJBQLSelectTranslator(EJBQLTranslator parent) {
+    EJBQLSelectTranslator(EJBQLTranslationContext parent) {
         this.parent = parent;
     }
 
@@ -74,7 +74,7 @@
         }
     }
 
-    EJBQLTranslator getParent() {
+    EJBQLTranslationContext getParent() {
         return parent;
     }
 

Copied: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslationContext.java (from r544060, cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslator.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslationContext.java?view=diff&rev=546067&p1=cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslator.java&r1=544060&p2=cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslationContext.java&r2=546067
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslationContext.java Mon Jun 11 02:54:50 2007
@@ -21,52 +21,34 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
 import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
-import org.apache.cayenne.ejbql.EJBQLExpression;
 import org.apache.cayenne.query.SQLTemplate;
 
 /**
- * A translator of {@link EJBQLExpression} statements into the database SQL.
+ * A context used for translating of EJBQL to SQL.
  * 
  * @since 3.0
  * @author Andrus Adamchik
  */
-class EJBQLTranslator extends EJBQLBaseVisitor {
+class EJBQLTranslationContext {
 
     private Map aliases;
     private Map bindingVariables;
     private StringBuffer buffer;
     private EJBQLCompiledExpression compiledExpression;
 
-    EJBQLTranslator(EJBQLCompiledExpression compiledExpression) {
-        super(false);
+    EJBQLTranslationContext(EJBQLCompiledExpression compiledExpression) {
         this.compiledExpression = compiledExpression;
+        this.buffer = new StringBuffer();
     }
 
-    SQLTemplate translate() {
-        this.buffer = new StringBuffer();
-        compiledExpression.getExpression().visit(this);
+    SQLTemplate getQuery() {
         String sql = buffer.length() > 0 ? buffer.toString() : null;
         SQLTemplate query = new SQLTemplate(compiledExpression
                 .getRootDescriptor()
                 .getObjectClass(), sql);
         query.setParameters(bindingVariables);
         return query;
-    }
-
-    public boolean visitSelect(EJBQLExpression expression, int finishedChildIndex) {
-        EJBQLSelectTranslator visitor = new EJBQLSelectTranslator(this);
-        expression.visit(visitor);
-        return false;
-    }
-
-    public boolean visitDelete(EJBQLExpression expression, int finishedChildIndex) {
-        throw new UnsupportedOperationException("Not yet implemented");
-    }
-
-    public boolean visitUpdate(EJBQLExpression expression, int finishedChildIndex) {
-        throw new UnsupportedOperationException("Not yet implemented");
     }
 
     StringBuffer getBuffer() {

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslatorTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslatorTest.java?view=auto&rev=546067
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslatorTest.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/jdbc/EJBQLSelectTranslatorTest.java Mon Jun 11 02:54:50 2007
@@ -0,0 +1,217 @@
+/*****************************************************************
+ *   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.jdbc;
+
+import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
+import org.apache.cayenne.ejbql.EJBQLParser;
+import org.apache.cayenne.ejbql.EJBQLParserFactory;
+import org.apache.cayenne.query.SQLTemplate;
+import org.apache.cayenne.unit.CayenneCase;
+
+public class EJBQLSelectTranslatorTest extends CayenneCase {
+
+    private SQLTemplate translateSelect(String ejbql) {
+        EJBQLParser parser = EJBQLParserFactory.getParser();
+        EJBQLCompiledExpression select = parser.compile(ejbql, getDomain()
+                .getEntityResolver());
+
+        EJBQLTranslationContext tr = new EJBQLTranslationContext(select);
+        select.getExpression().visit(new EJBQLSelectTranslator(tr));
+        return tr.getQuery();
+    }
+
+    public void testSelectFrom() {
+        SQLTemplate query = translateSelect("select a from Artist a");
+        String sql = query.getDefaultTemplate();
+
+        // column order is unpredictable, just need to ensure that they are all there
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.indexOf("t0.ARTIST_ID") > 0);
+        assertTrue(sql, sql.indexOf("t0.ARTIST_NAME") > 0);
+        assertTrue(sql, sql.indexOf("t0.DATE_OF_BIRTH") > 0);
+        assertTrue(sql, sql.endsWith(" FROM ARTIST AS t0"));
+    }
+
+    public void testSelectDistinct() {
+        SQLTemplate query = translateSelect("select distinct a from Artist a");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT DISTINCT "));
+        assertTrue(sql, sql.endsWith(" FROM ARTIST AS t0"));
+    }
+
+    public void testSelectFromWhereEqual() {
+        SQLTemplate query = translateSelect("select a from Artist a where a.artistName = 'Dali'");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.endsWith(" FROM ARTIST AS t0 WHERE t0.ARTIST_NAME "
+                + "#bindEqual('Dali' 'VARCHAR')"));
+    }
+
+    public void testSelectFromWhereOrEqual() {
+        SQLTemplate query = translateSelect("select a from Artist a where a.artistName = 'Dali' "
+                + "or a.artistName = 'Malevich'");
+        String sql = query.getDefaultTemplate();
+
+        SQLTemplate query1 = translateSelect("select a from Artist a where a.artistName = 'Picasso' "
+                + "or a.artistName = 'Malevich' "
+                + "or a.artistName = 'Dali'");
+        String sql1 = query1.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.indexOf(" FROM ARTIST AS t0 WHERE ") > 0);
+        assertEquals(1, countDelimiters(sql, " OR ", sql.indexOf("WHERE ")));
+
+        assertTrue(sql1, sql1.startsWith("SELECT "));
+        assertTrue(sql1, sql.indexOf(" FROM ARTIST AS t0 WHERE ") > 0);
+        assertEquals(2, countDelimiters(sql1, " OR ", sql.indexOf("WHERE ")));
+    }
+
+    public void testSelectFromWhereAndEqual() {
+
+        SQLTemplate query = translateSelect("select a from Artist a where a.artistName = 'Dali' "
+                + "and a.artistName = 'Malevich'");
+        String sql = query.getDefaultTemplate();
+
+        SQLTemplate query1 = translateSelect("select a from Artist a where a.artistName = 'Picasso' "
+                + "and a.artistName = 'Malevich' "
+                + "and a.artistName = 'Dali'");
+        String sql1 = query1.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.indexOf(" WHERE ") > 0);
+        assertEquals(1, countDelimiters(sql, " AND ", sql.indexOf("WHERE ")));
+
+        assertTrue(sql1, sql1.startsWith("SELECT "));
+        assertTrue(sql1, sql1.indexOf(" WHERE ") > 0);
+        assertEquals(2, countDelimiters(sql1, " AND ", sql1.indexOf("WHERE ")));
+    }
+
+    public void testSelectFromWhereNot() {
+        SQLTemplate query = translateSelect("select a from Artist a where not (a.artistName = 'Dali')");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.endsWith(" WHERE NOT "
+                + "t0.ARTIST_NAME #bindEqual('Dali' 'VARCHAR')"));
+    }
+
+    public void testSelectFromWhereGreater() {
+        SQLTemplate query = translateSelect("select p from Painting p where p.estimatedPrice > 1.0");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.endsWith(" WHERE t0.ESTIMATED_PRICE > #bind($id0 'DECIMAL')"));
+    }
+
+    public void testSelectFromWhereGreaterOrEqual() {
+        SQLTemplate query = translateSelect("select p from Painting p where p.estimatedPrice >= 2");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql
+                .endsWith(" WHERE t0.ESTIMATED_PRICE >= #bind($id0 'INTEGER')"));
+    }
+
+    public void testSelectFromWhereLess() {
+        SQLTemplate query = translateSelect("select p from Painting p where p.estimatedPrice < 1.0");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.endsWith(" WHERE t0.ESTIMATED_PRICE < #bind($id0 'DECIMAL')"));
+    }
+
+    public void testSelectFromWhereLessOrEqual() {
+        SQLTemplate query = translateSelect("select p from Painting p where p.estimatedPrice <= 1.0");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql
+                .endsWith(" WHERE t0.ESTIMATED_PRICE <= #bind($id0 'DECIMAL')"));
+    }
+
+    public void testSelectFromWhereNotEqual() {
+        SQLTemplate query = translateSelect("select a from Artist a where a.artistName <> 'Dali'");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql
+                .endsWith(" WHERE t0.ARTIST_NAME #bindNotEqual('Dali' 'VARCHAR')"));
+    }
+
+    public void testSelectFromWhereBetween() {
+        SQLTemplate query = translateSelect("select p from Painting p where p.estimatedPrice between 3 and 5");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.endsWith(" WHERE t0.ESTIMATED_PRICE "
+                + "BETWEEN #bind($id0 'INTEGER') AND #bind($id1 'INTEGER')"));
+    }
+
+    public void testSelectFromWhereNotBetween() {
+        SQLTemplate query = translateSelect("select p from Painting p where p.estimatedPrice not between 3 and 5");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.endsWith(" WHERE t0.ESTIMATED_PRICE "
+                + "NOT BETWEEN #bind($id0 'INTEGER') AND #bind($id1 'INTEGER')"));
+    }
+
+    public void testSelectFromWhereLike() {
+        SQLTemplate query = translateSelect("select p from Painting p where p.paintingTitle like 'Stuff'");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.endsWith(" WHERE t0.PAINTING_TITLE "
+                + "LIKE #bind('Stuff' 'VARCHAR')"));
+    }
+
+    public void testSelectFromWhereNotLike() {
+        SQLTemplate query = translateSelect("select p from Painting p where p.paintingTitle NOT like 'Stuff'");
+        String sql = query.getDefaultTemplate();
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.endsWith(" WHERE t0.PAINTING_TITLE "
+                + "NOT LIKE #bind('Stuff' 'VARCHAR')"));
+    }
+
+    public void testSelectFromWhereRelationshipPropertyPath() {
+        SQLTemplate query = translateSelect("select p from Painting p where p.toArtist.artistName = 'AA2'");
+        String sql = query.getDefaultTemplate();
+
+        System.out.println("SQL: " + sql);
+
+        assertTrue(sql, sql.startsWith("SELECT "));
+        assertTrue(sql, sql.endsWith(" WHERE t1.ARTIST_NAME #bindEqual('AA2' 'VARCHAR')"));
+        // TODO: andrus, 3/25/2007 - implement joins support
+        // assertEquals(" FROM PAINTING t0 JOIN ARTIST t1 ON (t0.ARTIST_ID =
+        // t1.ARTIST_ID)", query.getParameters().get("from0"));
+    }
+
+    private int countDelimiters(String string, String delim, int fromIndex) {
+        int i = 0;
+        while ((fromIndex = string.indexOf(delim, fromIndex)) >= 0) {
+            fromIndex += delim.length();
+            i++;
+        }
+
+        return i;
+    }
+}