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 |