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/03/26 11:30:40 UTC
svn commit: r522464 - in
/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src:
main/java/org/apache/cayenne/access/jdbc/ main/java/org/apache/cayenne/ejbql/
main/java/org/apache/cayenne/ejbql/parser/
main/java/org/apache/cayenne/query/ test/jav...
Author: aadamchik
Date: Mon Mar 26 02:30:37 2007
New Revision: 522464
URL: http://svn.apache.org/viewvc?view=rev&rev=522464
Log:
CAY-452: EJB QL Cayenne Query
support for most conditions, paths; clearing space for joins support
Added:
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathTranslator.java
- copied, changed from r520869, cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathVisitor.java
Removed:
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathVisitor.java
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateProcessor.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLBaseVisitor.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLDelegatingVisitor.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpression.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpressionVisitor.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDelete.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLSelect.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLUpdate.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/SimpleNode.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLConditionTranslator.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLFromTranslator.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLSelectTranslator.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLTranslator.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryTest.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/query/EJBQLTranslatorTest.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLQueryTest.xml
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateProcessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateProcessor.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateProcessor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateProcessor.java Mon Mar 26 02:30:37 2007
@@ -26,15 +26,14 @@
import java.util.List;
import java.util.Map;
+import org.apache.cayenne.CayenneRuntimeException;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.InternalContextAdapterImpl;
-import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.RuntimeInstance;
import org.apache.velocity.runtime.log.NullLogSystem;
import org.apache.velocity.runtime.parser.ParseException;
import org.apache.velocity.runtime.parser.node.SimpleNode;
-import org.apache.cayenne.CayenneRuntimeException;
/**
* Processor for SQL velocity templates.
@@ -144,7 +143,10 @@
nodeTree = velocityRuntime.parse(new StringReader(template), template);
}
catch (ParseException pex) {
- throw new ParseErrorException(pex.getMessage());
+ throw new CayenneRuntimeException("Error parsing template '"
+ + template
+ + "' : "
+ + pex.getMessage());
}
if (nodeTree == null) {
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLBaseVisitor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLBaseVisitor.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLBaseVisitor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLBaseVisitor.java Mon Mar 26 02:30:37 2007
@@ -121,7 +121,7 @@
return continueFlag;
}
- public boolean visitDelete(EJBQLExpression expression) {
+ public boolean visitDelete(EJBQLExpression expression, int finishedChildIndex) {
return continueFlag;
}
@@ -289,7 +289,7 @@
return continueFlag;
}
- public boolean visitPath(EJBQLExpression expression) {
+ public boolean visitPath(EJBQLExpression expression, int finishedChildIndex) {
return continueFlag;
}
@@ -301,7 +301,7 @@
return continueFlag;
}
- public boolean visitSelect(EJBQLExpression expression) {
+ public boolean visitSelect(EJBQLExpression expression, int finishedChildIndex) {
return continueFlag;
}
@@ -361,7 +361,7 @@
return continueFlag;
}
- public boolean visitUpdate(EJBQLExpression expression) {
+ public boolean visitUpdate(EJBQLExpression expression, int finishedChildIndex) {
return continueFlag;
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLDelegatingVisitor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLDelegatingVisitor.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLDelegatingVisitor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLDelegatingVisitor.java Mon Mar 26 02:30:37 2007
@@ -128,8 +128,10 @@
return delegate != null ? delegate.visitDecimalLiteral(expression) : false;
}
- public boolean visitDelete(EJBQLExpression expression) {
- return delegate != null ? delegate.visitDelete(expression) : false;
+ public boolean visitDelete(EJBQLExpression expression, int finishedChildIndex) {
+ return delegate != null
+ ? delegate.visitDelete(expression, finishedChildIndex)
+ : false;
}
public boolean visitDescending(EJBQLExpression expression) {
@@ -318,8 +320,10 @@
return delegate != null ? delegate.visitOuterJoin(expression) : false;
}
- public boolean visitPath(EJBQLExpression expression) {
- return delegate != null ? delegate.visitPath(expression) : false;
+ public boolean visitPath(EJBQLExpression expression, int finishedChildIndex) {
+ return delegate != null
+ ? delegate.visitPath(expression, finishedChildIndex)
+ : false;
}
public boolean visitPatternValue(EJBQLExpression expression) {
@@ -332,8 +336,10 @@
: false;
}
- public boolean visitSelect(EJBQLExpression expression) {
- return delegate != null ? delegate.visitSelect(expression) : false;
+ public boolean visitSelect(EJBQLExpression expression, int finishedChildIndex) {
+ return delegate != null
+ ? delegate.visitSelect(expression, finishedChildIndex)
+ : false;
}
public boolean visitSelectExpression(EJBQLExpression expression) {
@@ -394,8 +400,10 @@
return delegate != null ? delegate.visitTrimTrailing(expression) : false;
}
- public boolean visitUpdate(EJBQLExpression expression) {
- return delegate != null ? delegate.visitUpdate(expression) : false;
+ public boolean visitUpdate(EJBQLExpression expression, int finishedChildIndex) {
+ return delegate != null
+ ? delegate.visitUpdate(expression, finishedChildIndex)
+ : false;
}
public boolean visitUpdateField(EJBQLExpression expression) {
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpression.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpression.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpression.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpression.java Mon Mar 26 02:30:37 2007
@@ -47,4 +47,9 @@
* Returns a text property of the node.
*/
String getText();
+
+ /**
+ * Returns an optional boolean flag that negates the value of the expression.
+ */
+ boolean isNegated();
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpressionVisitor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpressionVisitor.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpressionVisitor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/EJBQLExpressionVisitor.java Mon Mar 26 02:30:37 2007
@@ -93,7 +93,16 @@
boolean visitDecimalLiteral(EJBQLExpression expression);
- boolean visitDelete(EJBQLExpression expression);
+ /**
+ * Called on visiting "delete" expression and also after visiting every expression
+ * child.
+ *
+ * @param expression a "delete" node being visited.
+ * @param finishedChildIndex "-1" when the expression node is visited for the first
+ * time, before its children; otherwise this is an index of a child just
+ * visited.
+ */
+ boolean visitDelete(EJBQLExpression expression, int finishedChildIndex);
boolean visitDescending(EJBQLExpression expression);
@@ -260,13 +269,30 @@
boolean visitOuterJoin(EJBQLExpression expression);
- boolean visitPath(EJBQLExpression expression);
+ /**
+ * Called on visiting "path" expression and also after visiting every expression
+ * child.
+ *
+ * @param expression a "path" node being visited.
+ * @param finishedChildIndex "-1" when the expression node is visited for the first
+ * time, before its children; otherwise this is an index of a child just
+ * visited.
+ */
+ boolean visitPath(EJBQLExpression expression, int finishedChildIndex);
boolean visitPatternValue(EJBQLExpression expression);
boolean visitPositionalInputParameter(EJBQLExpression expression);
- boolean visitSelect(EJBQLExpression expression);
+ /**
+ * Called on visiting "select" and also after visiting every expression child.
+ *
+ * @param expression a "select" node being visited.
+ * @param finishedChildIndex "-1" when the expression node is visited for the first
+ * time, before its children; otherwise this is an index of a child just
+ * visited.
+ */
+ boolean visitSelect(EJBQLExpression expression, int finishedChildIndex);
boolean visitSelectExpression(EJBQLExpression expression);
@@ -305,14 +331,23 @@
boolean visitTrimTrailing(EJBQLExpression expression);
- boolean visitUpdate(EJBQLExpression expression);
-
+ /**
+ * Called on visiting "update" expression and also after visiting every expression
+ * child.
+ *
+ * @param expression a "update" node being visited.
+ * @param finishedChildIndex "-1" when the expression node is visited for the first
+ * time, before its children; otherwise this is an index of a child just
+ * visited.
+ */
+ boolean visitUpdate(EJBQLExpression expression, int finishedChildIndex);
+
boolean visitUpdateField(EJBQLExpression expression);
-
+
boolean visitUpdateItem(EJBQLExpression expression);
-
+
boolean visitUpdateValue(EJBQLExpression expression);
-
+
boolean visitUpper(EJBQLExpression expression);
boolean visitWhere(EJBQLExpression expression);
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDelete.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDelete.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDelete.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLDelete.java Mon Mar 26 02:30:37 2007
@@ -25,15 +25,21 @@
* @author Andrus Adamchik
*/
public class EJBQLDelete extends SimpleNode {
- public EJBQLDelete(int id) {
- super(id);
- }
+
+ public EJBQLDelete(int id) {
+ super(id);
+ }
EJBQLDelete(AbstractParser parser, int id) {
super(id);
}
-
+
protected boolean visitNode(EJBQLExpressionVisitor visitor) {
- return visitor.visitDelete(this);
+ return visitor.visitDelete(this, -1);
+ }
+
+ protected boolean visitChild(EJBQLExpressionVisitor visitor, int childIndex) {
+ return super.visitChild(visitor, childIndex)
+ && visitor.visitDelete(this, childIndex);
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLPath.java Mon Mar 26 02:30:37 2007
@@ -35,6 +35,11 @@
}
protected boolean visitNode(EJBQLExpressionVisitor visitor) {
- return visitor.visitPath(this);
+ return visitor.visitPath(this, -1);
+ }
+
+ protected boolean visitChild(EJBQLExpressionVisitor visitor, int childIndex) {
+ return super.visitChild(visitor, childIndex)
+ && visitor.visitPath(this, childIndex);
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLSelect.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLSelect.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLSelect.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLSelect.java Mon Mar 26 02:30:37 2007
@@ -29,12 +29,17 @@
public EJBQLSelect(int id) {
super(id);
}
-
+
EJBQLSelect(AbstractParser parser, int id) {
super(id);
}
protected boolean visitNode(EJBQLExpressionVisitor visitor) {
- return visitor.visitSelect(this);
+ return visitor.visitSelect(this, -1);
+ }
+
+ protected boolean visitChild(EJBQLExpressionVisitor visitor, int childIndex) {
+ return super.visitChild(visitor, childIndex)
+ && visitor.visitSelect(this, childIndex);
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLUpdate.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLUpdate.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLUpdate.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/EJBQLUpdate.java Mon Mar 26 02:30:37 2007
@@ -25,15 +25,21 @@
* @author Andrus Adamchik
*/
public class EJBQLUpdate extends SimpleNode {
- public EJBQLUpdate(int id) {
- super(id);
- }
-
+
+ public EJBQLUpdate(int id) {
+ super(id);
+ }
+
EJBQLUpdate(AbstractParser parser, int id) {
super(id);
}
-
+
protected boolean visitNode(EJBQLExpressionVisitor visitor) {
- return visitor.visitUpdate(this);
+ return visitor.visitUpdate(this, -1);
+ }
+
+ protected boolean visitChild(EJBQLExpressionVisitor visitor, int childIndex) {
+ return super.visitChild(visitor, childIndex)
+ && visitor.visitUpdate(this, childIndex);
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/SimpleNode.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/SimpleNode.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/SimpleNode.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/ejbql/parser/SimpleNode.java Mon Mar 26 02:30:37 2007
@@ -46,6 +46,10 @@
public String getText() {
return text;
}
+
+ public boolean isNegated() {
+ return not;
+ }
/**
* A recursive visit method that passes a visitor to this node and all its children,
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLConditionTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLConditionTranslator.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLConditionTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLConditionTranslator.java Mon Mar 26 02:30:37 2007
@@ -18,7 +18,10 @@
****************************************************************/
package org.apache.cayenne.query;
+import java.math.BigDecimal;
+
import org.apache.cayenne.ejbql.EJBQLDelegatingVisitor;
+import org.apache.cayenne.ejbql.EJBQLException;
import org.apache.cayenne.ejbql.EJBQLExpression;
/**
@@ -38,8 +41,23 @@
return true;
}
- public boolean visitEquals(EJBQLExpression expression, int finishedChildIndex) {
- afterChild(expression, " #", finishedChildIndex);
+ public boolean visitBetween(EJBQLExpression expression, int finishedChildIndex) {
+ setDelegate(null);
+ switch (finishedChildIndex) {
+ case 0:
+ if (expression.isNegated()) {
+ parent.getParent().getBuffer().append(" NOT");
+ }
+ parent.getParent().getBuffer().append(" BETWEEN #bind(");
+ break;
+ case 1:
+ parent.getParent().getBuffer().append(") AND #bind(");
+ break;
+ case 2:
+ parent.getParent().getBuffer().append(")");
+ break;
+ }
+
return true;
}
@@ -48,6 +66,112 @@
return true;
}
+ public boolean visitEquals(EJBQLExpression expression, int finishedChildIndex) {
+ setDelegate(null);
+ switch (finishedChildIndex) {
+ case 0:
+ parent.getParent().getBuffer().append(" #bindEqual(");
+ break;
+ case 1:
+ parent.getParent().getBuffer().append(")");
+ break;
+ }
+
+ return true;
+ }
+
+ public boolean visitNot(EJBQLExpression expression) {
+ parent.getParent().getBuffer().append(" NOT");
+ return true;
+ }
+
+ public boolean visitNotEquals(EJBQLExpression expression, int finishedChildIndex) {
+ setDelegate(null);
+ switch (finishedChildIndex) {
+ case 0:
+ parent.getParent().getBuffer().append(" #bindNotEqual(");
+ break;
+ case 1:
+ parent.getParent().getBuffer().append(")");
+ break;
+ }
+
+ return true;
+ }
+
+ public boolean visitGreaterThan(EJBQLExpression expression, int finishedChildIndex) {
+ setDelegate(null);
+ switch (finishedChildIndex) {
+ case 0:
+ parent.getParent().getBuffer().append(" > #bind(");
+ break;
+ case 1:
+ parent.getParent().getBuffer().append(")");
+ break;
+ }
+
+ return true;
+ }
+
+ public boolean visitGreaterOrEqual(EJBQLExpression expression, int finishedChildIndex) {
+ setDelegate(null);
+ switch (finishedChildIndex) {
+ case 0:
+ parent.getParent().getBuffer().append(" >= #bind(");
+ break;
+ case 1:
+ parent.getParent().getBuffer().append(")");
+ break;
+ }
+
+ return true;
+ }
+
+ public boolean visitLessOrEqual(EJBQLExpression expression, int finishedChildIndex) {
+ setDelegate(null);
+ switch (finishedChildIndex) {
+ case 0:
+ parent.getParent().getBuffer().append(" <= #bind(");
+ break;
+ case 1:
+ parent.getParent().getBuffer().append(")");
+ break;
+ }
+
+ return true;
+ }
+
+ public boolean visitLessThan(EJBQLExpression expression, int finishedChildIndex) {
+ setDelegate(null);
+ switch (finishedChildIndex) {
+ case 0:
+ parent.getParent().getBuffer().append(" < #bind(");
+ break;
+ case 1:
+ parent.getParent().getBuffer().append(")");
+ break;
+ }
+
+ return true;
+ }
+
+ public boolean visitLike(EJBQLExpression expression, int finishedChildIndex) {
+ setDelegate(null);
+ switch (finishedChildIndex) {
+ case 0:
+ if (expression.isNegated()) {
+ parent.getParent().getBuffer().append(" NOT");
+ }
+ parent.getParent().getBuffer().append(" LIKE #bind(");
+ break;
+ case 1:
+ parent.getParent().getBuffer().append(")");
+ break;
+ }
+
+ return true;
+ }
+
protected void afterChild(EJBQLExpression e, String text, int childIndex) {
if (childIndex >= 0) {
if (childIndex + 1 < e.getChildrenCount()) {
@@ -59,13 +183,71 @@
}
}
- public boolean visitPath(EJBQLExpression expression) {
- setDelegate(new EJBQLPathVisitor());
+ public boolean visitPath(EJBQLExpression expression, int finishedChildIndex) {
+ if (finishedChildIndex < 0) {
+ setDelegate(new EJBQLPathTranslator(parent));
+ return true;
+ }
+ else {
+ return super.visitPath(expression, finishedChildIndex);
+ }
+ }
+
+ public boolean visitStringLiteral(EJBQLExpression expression) {
+ if (expression.getText() == null) {
+ parent.getParent().getBuffer().append("null");
+ }
+ else {
+ // note that String Literal text is already wrapped in single quotes, with
+ // quotes that are part of the string escaped.
+ parent.getParent().getBuffer().append(expression.getText()).append(
+ " 'VARCHAR'");
+ }
+ return true;
+ }
+
+ public boolean visitIntegerLiteral(EJBQLExpression expression) {
+ if (expression.getText() == null) {
+ parent.getParent().getBuffer().append("null");
+ }
+ else {
+ Object value;
+
+ try {
+ value = new Integer(expression.getText());
+ }
+ catch (NumberFormatException nfex) {
+ throw new EJBQLException("Invalid integer: " + expression.getText());
+ }
+
+ String var = parent.getParent().bindParameter(value);
+ parent.getParent().getBuffer().append('$').append(var).append(" 'INTEGER'");
+ }
+ return true;
+ }
+
+ public boolean visitDecimalLiteral(EJBQLExpression expression) {
+ if (expression.getText() == null) {
+ parent.getParent().getBuffer().append("null");
+ }
+ else {
+ Object value;
+
+ try {
+ value = new BigDecimal(expression.getText());
+ }
+ catch (NumberFormatException nfex) {
+ throw new EJBQLException("Invalid decimal: " + expression.getText());
+ }
+
+ String var = parent.getParent().bindParameter(value);
+ parent.getParent().getBuffer().append('$').append(var).append(" 'DECIMAL'");
+ }
return true;
}
- public boolean visitStringLiteral(EJBQLExpression expression) {
-
+ public boolean visitPatternValue(EJBQLExpression expression) {
+ // TODO: andrus 3/25/2007 - implement me
return true;
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLFromTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLFromTranslator.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLFromTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLFromTranslator.java Mon Mar 26 02:30:37 2007
@@ -20,8 +20,6 @@
import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
import org.apache.cayenne.ejbql.EJBQLExpression;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.reflect.ClassDescriptor;
public class EJBQLFromTranslator extends EJBQLBaseVisitor {
@@ -40,19 +38,12 @@
return true;
}
- public boolean visitIdentificationVariable(EJBQLExpression expression) {
+ public boolean visitIdentifier(EJBQLExpression expression) {
+ parent.appendRootIdentifier(expression.getText());
return true;
}
- public boolean visitIdentifier(EJBQLExpression expression) {
- String identifier = expression.getText();
- ClassDescriptor descriptor = parent
- .getParent()
- .getCompiledExpression()
- .getEntityDescriptor(identifier);
-
- DbEntity table = descriptor.getEntity().getDbEntity();
- parent.appendTable(identifier, table);
+ public boolean visitIdentificationVariable(EJBQLExpression expression) {
return true;
}
}
Copied: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathTranslator.java (from r520869, cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathVisitor.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathTranslator.java?view=diff&rev=522464&p1=cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathVisitor.java&r1=520869&p2=cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathTranslator.java&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathVisitor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLPathTranslator.java Mon Mar 26 02:30:37 2007
@@ -19,12 +19,89 @@
package org.apache.cayenne.query;
import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
+import org.apache.cayenne.ejbql.EJBQLException;
+import org.apache.cayenne.ejbql.EJBQLExpression;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.reflect.ClassDescriptor;
-class EJBQLPathVisitor extends EJBQLBaseVisitor {
+class EJBQLPathTranslator extends EJBQLBaseVisitor {
- EJBQLPathVisitor() {
+ private EJBQLSelectTranslator parent;
+ private ObjEntity currentEntity;
+ private String lastPathComponent;
+ private String idPath;
+
+ EJBQLPathTranslator(EJBQLSelectTranslator parent) {
super(true);
+ this.parent = parent;
+ }
+
+ public boolean visitPath(EJBQLExpression expression, int finishedChildIndex) {
+
+ if (finishedChildIndex > 0) {
+
+ if (finishedChildIndex + 1 < expression.getChildrenCount()) {
+ processIntermediatePath();
+ }
+ else {
+ processLastPath();
+ }
+ }
+ return true;
+ }
+
+ public boolean visitIdentifier(EJBQLExpression expression) {
+ ClassDescriptor descriptor = parent
+ .getParent()
+ .getCompiledExpression()
+ .getEntityDescriptor(expression.getText());
+ if (descriptor == null) {
+ throw new EJBQLException("Invalid identification variable: "
+ + expression.getText());
+ }
+
+ this.currentEntity = descriptor.getEntity();
+ this.idPath = expression.getText();
+ return true;
}
-
+ public boolean visitIdentificationVariable(EJBQLExpression expression) {
+ if (this.lastPathComponent != null) {
+ this.idPath += '.' + lastPathComponent;
+ }
+
+ this.lastPathComponent = expression.getText();
+ return true;
+ }
+
+ private void processIntermediatePath() {
+ ObjRelationship relationship = (ObjRelationship) currentEntity
+ .getRelationship(lastPathComponent);
+ if (relationship == null) {
+ throw new EJBQLException("Unknown relationship '"
+ + lastPathComponent
+ + "' for entity '"
+ + currentEntity.getName()
+ + "'");
+ }
+
+ parent.appendInnerJoin(idPath + '.' + lastPathComponent);
+ this.currentEntity = (ObjEntity) relationship.getTargetEntity();
+ }
+
+ private void processLastPath() {
+ // TODO: andrus 3/25/2007 - process terminal relationships
+ ObjAttribute attribute = (ObjAttribute) currentEntity
+ .getAttribute(lastPathComponent);
+
+ DbEntity table = currentEntity.getDbEntity();
+ String alias = parent.getParent().createAlias(
+ idPath,
+ table.getFullyQualifiedName());
+ parent.getParent().getBuffer().append(' ').append(alias).append('.').append(
+ attribute.getDbAttributeName());
+ }
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLQuery.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLQuery.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLQuery.java Mon Mar 26 02:30:37 2007
@@ -44,11 +44,7 @@
*/
protected Query createReplacementQuery(EntityResolver resolver) {
EJBQLCompiledExpression expression = getExpression(resolver);
-
- EJBQLTranslator translator = new EJBQLTranslator(expression);
- String sql = translator.translate();
-
- return new SQLTemplate(expression.getRootDescriptor().getObjectClass(), sql);
+ return new EJBQLTranslator(expression).translate();
}
/**
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLSelectTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLSelectTranslator.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLSelectTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLSelectTranslator.java Mon Mar 26 02:30:37 2007
@@ -19,6 +19,7 @@
package org.apache.cayenne.query;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Set;
import org.apache.cayenne.dba.TypesMapping;
@@ -26,6 +27,7 @@
import org.apache.cayenne.ejbql.EJBQLExpression;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.reflect.ClassDescriptor;
/**
* A translator of EJBQL select statements into SQL.
@@ -37,15 +39,28 @@
private EJBQLTranslator parent;
private Set columns;
+ private StringBuffer fromClause;
+ private Set fromIds;
+ private Set innerJoins;
EJBQLSelectTranslator(EJBQLTranslator parent) {
this.parent = parent;
}
- void appendTable(String identifier, DbEntity table) {
- String fqn = table.getFullyQualifiedName();
- String alias = parent.createAlias(identifier, fqn);
- parent.getBuffer().append(' ').append(fqn).append(' ').append(alias);
+ void appendRootIdentifier(String identifier) {
+ if (fromIds == null) {
+ fromIds = new HashSet();
+ }
+
+ fromIds.add(identifier);
+ }
+
+ void appendInnerJoin(String path) {
+ if (innerJoins == null) {
+ innerJoins = new HashSet();
+ }
+
+ innerJoins.add(path);
}
void appendColumn(String identifier, DbAttribute column) {
@@ -80,6 +95,25 @@
}
}
+ private void postprocess() {
+
+ if (fromIds != null && fromClause != null) {
+ Iterator it = fromIds.iterator();
+ while (it.hasNext()) {
+ String id = (String) it.next();
+ ClassDescriptor descriptor = parent
+ .getCompiledExpression()
+ .getEntityDescriptor(id);
+ DbEntity table = descriptor.getEntity().getDbEntity();
+ String fqn = table.getFullyQualifiedName();
+ String alias = parent.createAlias(id, fqn);
+ fromClause.append(' ').append(fqn).append(' ').append(alias);
+ }
+ }
+
+ // TODO: andrus, 3/26/2007 - inner joins
+ }
+
EJBQLTranslator getParent() {
return parent;
}
@@ -90,7 +124,9 @@
}
public boolean visitFrom(EJBQLExpression expression) {
- parent.getBuffer().append(" FROM");
+ this.fromClause = new StringBuffer(" FROM");
+ String fromId = parent.bindParameter(fromClause, "from");
+ parent.getBuffer().append(" $").append(fromId);
setDelegate(new EJBQLFromTranslator(this));
return true;
}
@@ -101,9 +137,15 @@
return true;
}
- public boolean visitSelect(EJBQLExpression expression) {
- parent.getBuffer().append("SELECT");
- setDelegate(new EJBQLSelectColumnsTranslator(this));
+ public boolean visitSelect(EJBQLExpression expression, int finishedChildIndex) {
+ if (finishedChildIndex < 0) {
+ parent.getBuffer().append("SELECT");
+ setDelegate(new EJBQLSelectColumnsTranslator(this));
+ }
+ else if (finishedChildIndex + 1 == expression.getChildrenCount()) {
+ postprocess();
+ }
+
return true;
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLTranslator.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/EJBQLTranslator.java Mon Mar 26 02:30:37 2007
@@ -34,6 +34,7 @@
class EJBQLTranslator extends EJBQLBaseVisitor {
private Map aliases;
+ private Map bindingVariables;
private StringBuffer buffer;
private EJBQLCompiledExpression compiledExpression;
@@ -42,23 +43,28 @@
this.compiledExpression = compiledExpression;
}
- String translate() {
+ SQLTemplate translate() {
this.buffer = new StringBuffer();
compiledExpression.getExpression().visit(this);
- return buffer.length() > 0 ? buffer.toString() : null;
+ 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) {
+ public boolean visitSelect(EJBQLExpression expression, int finishedChildIndex) {
EJBQLSelectTranslator visitor = new EJBQLSelectTranslator(this);
expression.visit(visitor);
return false;
}
- public boolean visitDelete(EJBQLExpression expression) {
+ public boolean visitDelete(EJBQLExpression expression, int finishedChildIndex) {
throw new UnsupportedOperationException("Not yet implemented");
}
- public boolean visitUpdate(EJBQLExpression expression) {
+ public boolean visitUpdate(EJBQLExpression expression, int finishedChildIndex) {
throw new UnsupportedOperationException("Not yet implemented");
}
@@ -71,11 +77,47 @@
}
/**
+ * Creates a new parameter variable, binding provided value to it.
+ */
+ String bindParameter(Object value) {
+ return bindParameter(value, "id");
+ }
+
+ /**
+ * Creates a new parameter variable with the specified prefix, binding provided value
+ * to it.
+ */
+ String bindParameter(Object value, String prefix) {
+ if (bindingVariables == null) {
+ bindingVariables = new HashMap();
+ }
+
+ String var = prefix + bindingVariables.size();
+ bindingVariables.put(var, value);
+ return var;
+ }
+
+ /**
* Retrieves a SQL alias for the combination of EJBQL id variable and a table name. If
* such alias hasn't been used, it is created on the fly.
*/
- String createAlias(String idVariable, String tableName) {
- String key = idVariable + ":" + tableName;
+ String createAlias(String idPath, String tableName) {
+
+ StringBuffer keyBuffer = new StringBuffer();
+
+ // per JPA spec, 4.4.2, "Identification variables are case insensitive.", while
+ // relationship path is case-sensitive
+
+ int dot = idPath.indexOf('.');
+ if (dot > 0) {
+ keyBuffer.append(idPath.substring(0, dot).toLowerCase()).append(
+ idPath.substring(dot));
+ }
+ else {
+ keyBuffer.append(idPath.toLowerCase());
+ }
+
+ String key = keyBuffer.append(':').append(tableName).toString();
String alias;
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryTest.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLQueryTest.java Mon Mar 26 02:30:37 2007
@@ -18,9 +18,14 @@
****************************************************************/
package org.apache.cayenne.access;
+import java.math.BigDecimal;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import org.apache.art.Artist;
+import org.apache.art.Painting;
import org.apache.cayenne.PersistenceState;
import org.apache.cayenne.query.EJBQLQuery;
import org.apache.cayenne.unit.CayenneCase;
@@ -41,5 +46,138 @@
assertEquals(4, artists.size());
assertTrue(artists.get(0) instanceof Artist);
assertTrue(((Artist) artists.get(0)).getPersistenceState() == PersistenceState.COMMITTED);
+ }
+
+ public void testSelectFromWhereEqual() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select a from Artist a where a.artistName = 'AA2'";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List artists = createDataContext().performQuery(query);
+ assertEquals(1, artists.size());
+ assertEquals("AA2", ((Artist) artists.get(0)).getArtistName());
+ }
+
+ public void testSelectFromWhereNot() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select a from Artist a where not a.artistName = 'AA2'";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List artists = createDataContext().performQuery(query);
+ assertEquals(3, artists.size());
+ Iterator it = artists.iterator();
+ while (it.hasNext()) {
+ Artist a = (Artist) it.next();
+ assertFalse("AA2".equals(a.getArtistName()));
+ }
+ }
+
+ public void testSelectFromWhereNotEquals() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select a from Artist a where a.artistName <> 'AA2'";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List artists = createDataContext().performQuery(query);
+ assertEquals(3, artists.size());
+ Iterator it = artists.iterator();
+ while (it.hasNext()) {
+ Artist a = (Artist) it.next();
+ assertFalse("AA2".equals(a.getArtistName()));
+ }
+ }
+
+ public void testSelectFromWhereOrEqual() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select a from Artist a where a.artistName = 'AA2' or a.artistName = 'BB1'";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List artists = createDataContext().performQuery(query);
+ assertEquals(2, artists.size());
+
+ Set names = new HashSet();
+ Iterator it = artists.iterator();
+ while (it.hasNext()) {
+ names.add(((Artist) it.next()).getArtistName());
+ }
+
+ assertTrue(names.contains("AA2"));
+ assertTrue(names.contains("BB1"));
+ }
+
+ public void testSelectFromWhereAndEqual() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select P from Painting P where P.paintingTitle = 'P1' "
+ + "AND p.estimatedPrice = 3000";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List ps = createDataContext().performQuery(query);
+ assertEquals(1, ps.size());
+
+ Painting p = (Painting) ps.get(0);
+ assertEquals("P1", p.getPaintingTitle());
+ assertEquals(new BigDecimal(3000), p.getEstimatedPrice());
+ }
+
+ public void testSelectFromWhereGreater() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select P from Painting P WHERE p.estimatedPrice > 3000";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List ps = createDataContext().performQuery(query);
+ assertEquals(1, ps.size());
+
+ Painting p = (Painting) ps.get(0);
+ assertEquals("P2", p.getPaintingTitle());
+ assertEquals(new BigDecimal(5000), p.getEstimatedPrice());
+ }
+
+ public void testSelectFromWhereGreaterOrEqual() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select P from Painting P WHERE p.estimatedPrice >= 3000";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List ps = createDataContext().performQuery(query);
+ assertEquals(2, ps.size());
+ }
+
+ public void testSelectFromWhereLess() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select P from Painting P WHERE p.estimatedPrice < 5000";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List ps = createDataContext().performQuery(query);
+ assertEquals(1, ps.size());
+
+ Painting p = (Painting) ps.get(0);
+ assertEquals("P1", p.getPaintingTitle());
+ assertEquals(new BigDecimal(3000), p.getEstimatedPrice());
+ }
+
+ public void testSelectFromWhereLessOrEqual() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select P from Painting P WHERE p.estimatedPrice <= 5000";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List ps = createDataContext().performQuery(query);
+ assertEquals(2, ps.size());
+ }
+
+ public void testSelectFromWhereDecimalNumber() throws Exception {
+ createTestData("prepare");
+
+ String ejbql = "select P from Painting P WHERE p.estimatedPrice <= 5000.00";
+ EJBQLQuery query = new EJBQLQuery(ejbql);
+
+ List ps = createDataContext().performQuery(query);
+ assertEquals(2, ps.size());
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/query/EJBQLTranslatorTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/query/EJBQLTranslatorTest.java?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/query/EJBQLTranslatorTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/query/EJBQLTranslatorTest.java Mon Mar 26 02:30:37 2007
@@ -32,17 +32,16 @@
getDomain().getEntityResolver());
EJBQLTranslator tr = new EJBQLTranslator(select);
- String sql = tr.translate();
-
- // System.out.println("Expression: " + select.getExpression());
- // System.out.println("SQL: " + sql);
+ SQLTemplate query = tr.translate();
+ 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 t0"));
+ assertTrue(sql, sql.endsWith(" $from0"));
+ assertEquals(" FROM ARTIST t0", query.getParameters().get("from0").toString());
}
public void testSelectDistinct() {
@@ -52,13 +51,12 @@
getDomain().getEntityResolver());
EJBQLTranslator tr = new EJBQLTranslator(select);
- String sql = tr.translate();
-
- // System.out.println("Expression: " + select.getExpression());
- // System.out.println("SQL: " + sql);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
assertTrue(sql, sql.startsWith("SELECT DISTINCT "));
- assertTrue(sql, sql.endsWith(" FROM ARTIST t0"));
+ assertTrue(sql, sql.endsWith(" $from0"));
+ assertEquals(" FROM ARTIST t0", query.getParameters().get("from0").toString());
}
public void testSelectFromWhereEqual() {
@@ -68,44 +66,261 @@
getDomain().getEntityResolver());
EJBQLTranslator tr = new EJBQLTranslator(select);
- String sql = tr.translate();
-
- // System.out.println("Expression: " + select.getExpression());
- // System.out.println("SQL: " + sql);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
assertTrue(sql, sql.startsWith("SELECT "));
- // assertTrue(sql, sql.endsWith(" FROM ARTIST t0 WHERE t0.ARTIST_NAME = ?"));
+ assertTrue(sql, sql.endsWith(" $from0 WHERE t0.ARTIST_NAME "
+ + "#bindEqual('Dali' 'VARCHAR')"));
+ assertEquals(" FROM ARTIST t0", query.getParameters().get("from0").toString());
}
public void testSelectFromWhereOrEqual() {
EJBQLParser parser = EJBQLParserFactory.getParser();
- EJBQLCompiledExpression select = parser
- .compile(
- "select a from Artist a where a.artistName = 'Dali' or a.artistName = 'Malevich'",
- getDomain().getEntityResolver());
+ EJBQLCompiledExpression select = parser.compile(
+ "select a from Artist a where a.artistName = 'Dali' "
+ + "or a.artistName = 'Malevich'",
+ getDomain().getEntityResolver());
EJBQLTranslator tr = new EJBQLTranslator(select);
- String sql = tr.translate();
-
- // System.out.println("Expression: " + select.getExpression());
- // System.out.println("SQL: " + sql);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
EJBQLCompiledExpression select1 = parser.compile(
- "select a from Artist a where a.artistName = 'Dali' "
+ "select a from Artist a where a.artistName = 'Picasso' "
+ "or a.artistName = 'Malevich' "
- + "or a.artistName = 'Picasso'",
+ + "or a.artistName = 'Dali'",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr1 = new EJBQLTranslator(select1);
+ SQLTemplate query1 = tr1.translate();
+ String sql1 = query1.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.indexOf(" $from0 WHERE ") > 0);
+ assertEquals(" FROM ARTIST t0", query.getParameters().get("from0").toString());
+ assertEquals(1, countDelimiters(sql, " OR ", sql.indexOf("WHERE ")));
+
+ assertTrue(sql1, sql1.startsWith("SELECT "));
+ assertTrue(sql1, sql.indexOf(" $from0 WHERE ") > 0);
+ assertEquals(" FROM ARTIST t0", query1.getParameters().get("from0").toString());
+ assertEquals(2, countDelimiters(sql1, " OR ", sql.indexOf("WHERE ")));
+ }
+
+ public void testSelectFromWhereAndEqual() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select a from Artist a where a.artistName = 'Dali' "
+ + "and a.artistName = 'Malevich'",
getDomain().getEntityResolver());
- EJBQLTranslator tr1 = new EJBQLTranslator(select);
- String sql1 = tr1.translate();
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ EJBQLCompiledExpression select1 = parser.compile(
+ "select a from Artist a where a.artistName = 'Picasso' "
+ + "and a.artistName = 'Malevich' "
+ + "and a.artistName = 'Dali'",
+ getDomain().getEntityResolver());
- System.out.println("Expression: " + select1.getExpression());
- System.out.println("SQL: " + sql1);
+ EJBQLTranslator tr1 = new EJBQLTranslator(select1);
+ SQLTemplate query1 = tr1.translate();
+ String sql1 = query1.getDefaultTemplate();
assertTrue(sql, sql.startsWith("SELECT "));
- assertTrue(sql, sql.indexOf(" FROM ARTIST t0 WHERE ") > 0);
+ assertTrue(sql, sql.indexOf(" $from0 WHERE ") > 0);
+ assertEquals(1, countDelimiters(sql, " AND ", sql.indexOf("WHERE ")));
assertTrue(sql1, sql1.startsWith("SELECT "));
- assertTrue(sql1, sql1.indexOf(" FROM ARTIST t0 WHERE ") > 0);
+ assertTrue(sql1, sql1.indexOf(" $from0 WHERE ") > 0);
+ assertEquals(2, countDelimiters(sql1, " AND ", sql1.indexOf("WHERE ")));
+ }
+
+ public void testSelectFromWhereNot() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select a from Artist a where not (a.artistName = 'Dali')",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 WHERE NOT "
+ + "t0.ARTIST_NAME #bindEqual('Dali' 'VARCHAR')"));
+ }
+
+ public void testSelectFromWhereGreater() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select p from Painting p where p.estimatedPrice > 1.0",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "WHERE t0.ESTIMATED_PRICE > #bind($id1 'DECIMAL')"));
+ }
+
+ public void testSelectFromWhereGreaterOrEqual() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select p from Painting p where p.estimatedPrice >= 2",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "WHERE t0.ESTIMATED_PRICE >= #bind($id1 'INTEGER')"));
+ }
+
+ public void testSelectFromWhereLess() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select p from Painting p where p.estimatedPrice < 1.0",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "WHERE t0.ESTIMATED_PRICE < #bind($id1 'DECIMAL')"));
+ }
+
+ public void testSelectFromWhereLessOrEqual() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select p from Painting p where p.estimatedPrice <= 1.0",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "WHERE t0.ESTIMATED_PRICE <= #bind($id1 'DECIMAL')"));
+ }
+
+ public void testSelectFromWhereNotEqual() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select a from Artist a where a.artistName <> 'Dali'",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "WHERE t0.ARTIST_NAME #bindNotEqual('Dali' 'VARCHAR')"));
+ }
+
+ public void testSelectFromWhereBetween() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select p from Painting p where p.estimatedPrice between 3 and 5",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "WHERE t0.ESTIMATED_PRICE "
+ + "BETWEEN #bind($id1 'INTEGER') AND #bind($id2 'INTEGER')"));
+ }
+
+ public void testSelectFromWhereNotBetween() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select p from Painting p where p.estimatedPrice not between 3 and 5",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "WHERE t0.ESTIMATED_PRICE "
+ + "NOT BETWEEN #bind($id1 'INTEGER') AND #bind($id2 'INTEGER')"));
+ }
+
+ public void testSelectFromWhereLike() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select p from Painting p where p.paintingTitle like 'Stuff'",
+ getDomain().getEntityResolver());
+
+ System.out.println(select.getExpression().toString());
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "WHERE t0.PAINTING_TITLE "
+ + "LIKE #bind('Stuff' 'VARCHAR')"));
+ }
+
+ public void testSelectFromWhereNotLike() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select p from Painting p where p.paintingTitle NOT like 'Stuff'",
+ getDomain().getEntityResolver());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "WHERE t0.PAINTING_TITLE "
+ + "NOT LIKE #bind('Stuff' 'VARCHAR')"));
+ }
+
+ public void testSelectFromWhereRelationshipPropertyPath() {
+ EJBQLParser parser = EJBQLParserFactory.getParser();
+ EJBQLCompiledExpression select = parser.compile(
+ "select p from Painting p where p.toArtist.artistName = 'AA2'",
+ getDomain().getEntityResolver());
+
+ System.out.println("Expression: " + select.getExpression());
+
+ EJBQLTranslator tr = new EJBQLTranslator(select);
+ SQLTemplate query = tr.translate();
+ String sql = query.getDefaultTemplate();
+
+ System.out.println("SQL: " + sql);
+
+ assertTrue(sql, sql.startsWith("SELECT "));
+ assertTrue(sql, sql.endsWith(" $from0 "
+ + "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;
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLQueryTest.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLQueryTest.xml?view=diff&rev=522464&r1=522463&r2=522464
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLQueryTest.xml (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLQueryTest.xml Mon Mar 26 02:30:37 2007
@@ -35,6 +35,19 @@
</value></constructor-arg>
</bean>
+ <bean id="P11" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+ <constructor-arg type="java.lang.Class"><value>org.apache.art.Painting</value></constructor-arg>
+ <constructor-arg><value>
+ INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) VALUES (33001, 'P1', 33001, 3000)
+ </value></constructor-arg>
+ </bean>
+
+ <bean id="P12" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+ <constructor-arg type="java.lang.Class"><value>org.apache.art.Painting</value></constructor-arg>
+ <constructor-arg><value>
+ INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) VALUES (33002, 'P2', 33002, 5000)
+ </value></constructor-arg>
+ </bean>
<!-- ======================================= -->
@@ -48,6 +61,8 @@
<ref bean="A2"/>
<ref bean="A3"/>
<ref bean="A4"/>
+ <ref bean="P11"/>
+ <ref bean="P12"/>
</list>
</constructor-arg>
</bean>