|
From: <hib...@li...> - 2006-04-18 12:42:37
|
Author: pgmjsd
Date: 2006-04-18 08:42:33 -0400 (Tue, 18 Apr 2006)
New Revision: 9759
Modified:
branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g
branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java
Log:
Flattened property reference sub-trees.
Modified: branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g 2006-04-18 10:36:27 UTC (rev 9758)
+++ branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g 2006-04-18 12:42:33 UTC (rev 9759)
@@ -32,6 +32,7 @@
tokens
{
+ PROPERTY_REF;
BOGUS;
}
@@ -47,6 +48,7 @@
protected void popContext() { }
protected void defineRange(AST range,String path,AST alias, AST fetch) { }
+
}
// The main statement rule.
@@ -111,7 +113,7 @@
;
join
- : #(JOIN (joinType )? (FETCH)? propertyRef (ALIAS)? (FETCH)? (WITH)? )
+ : #(JOIN (joinType )? (FETCH)? propertyRef [true] (ALIAS)? (FETCH)? (WITH)? )
;
joinType
@@ -129,7 +131,7 @@
;
whereClause
- : #(WHERE (subtree)* )
+ : #(WHERE logicalExpr )
;
groupClause
@@ -144,12 +146,143 @@
: #(SET (subtree)* )
;
+logicalExpr
+ : #(AND logicalExpr logicalExpr)
+ | #(OR logicalExpr logicalExpr)
+ | #(NOT logicalExpr)
+ | comparisonExpr
+ ;
-propertyRef
- : #(DOT propertyRef propertyName )
- | identifier
+comparisonExpr
+ :
+ ( #(EQ exprOrSubquery exprOrSubquery)
+ | #(NE exprOrSubquery exprOrSubquery)
+ | #(LT exprOrSubquery exprOrSubquery)
+ | #(GT exprOrSubquery exprOrSubquery)
+ | #(LE exprOrSubquery exprOrSubquery)
+ | #(GE exprOrSubquery exprOrSubquery)
+ | #(LIKE exprOrSubquery expr ( #(ESCAPE expr) )? )
+ | #(NOT_LIKE exprOrSubquery expr ( #(ESCAPE expr) )? )
+ | #(BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery)
+ | #(NOT_BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery)
+ | #(IN exprOrSubquery inRhs )
+ | #(NOT_IN exprOrSubquery inRhs )
+ | #(IS_NULL exprOrSubquery)
+ | #(IS_NOT_NULL exprOrSubquery)
+ | #(EXISTS ( expr | collectionFunctionOrSubselect ) )
+ )
;
+inRhs
+ : #(IN_LIST ( collectionFunctionOrSubselect | ( (expr)* ) ) )
+ ;
+
+exprOrSubquery
+ : expr
+ | query
+ | #(ANY collectionFunctionOrSubselect)
+ | #(ALL collectionFunctionOrSubselect)
+ | #(SOME collectionFunctionOrSubselect)
+ ;
+
+collectionFunctionOrSubselect
+ : collectionFunction
+ | query
+ ;
+
+collectionFunction
+ : #(ELEMENTS propertyRef [true] )
+ | #(INDICES propertyRef [true] )
+ ;
+
+count
+ : #(COUNT ( DISTINCT | ALL )? ( aggregateExpr | ROW_STAR ) )
+ ;
+
+aggregateExpr
+ : expr
+ | collectionFunction
+ ;
+
+expr
+ : addrExpr
+ | #( VECTOR_EXPR (expr)* )
+ | constant
+ | arithmeticExpr
+ | functionCall // Function call, not in the SELECT clause.
+ | parameter
+ | count // Count, not in the SELECT clause.
+ ;
+
+arithmeticExpr
+ : #(PLUS expr expr)
+ | #(MINUS expr expr)
+ | #(DIV expr expr)
+ | #(STAR expr expr)
+ | #(UNARY_MINUS expr)
+ | caseExpr
+ ;
+
+caseExpr
+ : #(CASE (#(WHEN logicalExpr expr))+ (#(ELSE expr))?)
+ | #(CASE2 expr (#(WHEN expr expr))+ (#(ELSE expr))?)
+ ;
+
+addrExpr
+ : propertyRef [true]
+ | #(INDEX_OP addrExprLhs expr)
+ ;
+
+addrExprLhs
+ : addrExpr
+ ;
+
+constant
+ : literal
+ | NULL
+ | TRUE
+ | FALSE
+ ;
+
+literal
+ : NUM_INT
+ | NUM_LONG
+ | NUM_FLOAT
+ | NUM_DOUBLE
+ | QUOTED_STRING
+ ;
+
+parameter
+ : #(COLON identifier)
+ | #(PARAM (NUM_INT)?)
+ ;
+
+functionCall
+ : #(METHOD_CALL pathAsIdent ( #(EXPR_LIST (expr)* ) )? )
+ | #(AGGREGATE aggregateExpr )
+ ;
+
+propertyRef! [ boolean root ]
+ : i:identifier {
+ if (root) { // Make the tree very regular, property refs always have a child.
+ #propertyRef = #([PROPERTY_REF,#i.getText()],#i);
+ }
+ else { // Otherwise, just construct the tree.
+ #propertyRef = #i;
+ }
+ }
+ | #(d:DOT lhs:propertyRef [ false ] rhs:propertyName ) {
+ // Flatten nested DOTs...
+ AST first = (#lhs.getType() == DOT) ? #lhs.getFirstChild() : #lhs;
+ if (root) { // If this is the root of the path tree, then make a property ref node.
+ #propertyRef = #([PROPERTY_REF,#d.getText()],first,#rhs);
+ }
+ else { // If this is not the root of the path tree, then just flatten it.
+ #propertyRef = #(#d,first,#rhs);
+ }
+ }
+ ;
+
propertyName
: identifier
| CLASS
@@ -159,13 +292,6 @@
// Matches a path and returns the normalized string for the path (usually
// fully qualified a class name).
-path
- : identifier
- | #(DOT path identifier)
- ;
-
-// Matches a path and returns the normalized string for the path (usually
-// fully qualified a class name).
pathAsString returns [String p] {
p = "???";
String x = "?x?";
@@ -178,6 +304,15 @@
}
;
+// Returns a path as a single identifier node.
+pathAsIdent {
+ String text = "?text?";
+ }
+ : text=pathAsString {
+ #pathAsIdent = #([IDENT,text]);
+ }
+ ;
+
identifier
: (IDENT | WEIRD_IDENT)
;
Modified: branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java 2006-04-18 10:36:27 UTC (rev 9758)
+++ branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java 2006-04-18 12:42:33 UTC (rev 9759)
@@ -30,10 +30,20 @@
// First, get an AST by parsing some HQL text.
AST ast = resolve("from Animal");
// Assert:
- // * The root node should be a statement.
+ // The root node should be a statement.
assertTrue(ast instanceof StatementNode);
}
+ public void testSimpleImplicitJoin() throws Exception {
+ AST ast = resolve("from Animal a where a.mother.name like '%mary%'");
+ // The root node should be a statement.
+ assertTrue(ast instanceof StatementNode);
+
+ ast = resolve("from Animal a where a.mother.mother.name like '%weeble%'");
+ // The root node should be a statement.
+ assertTrue(ast instanceof StatementNode);
+ }
+
private AST resolve(String hql) throws RecognitionException, TokenStreamException {
AST hqlAst = HqlParserTest.doParse(hql,false);
// Now, pass it though the resolver phase, which yeilds
|