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;
+ }
+}