Author: steve.ebersole(a)jboss.com
Date: 2009-05-01 16:26:15 -0400 (Fri, 01 May 2009)
New Revision: 16500
Added:
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByParser.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByRenderer.java
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java
Removed:
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java
Modified:
core/branches/antlr3/pom.xml
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/origin/ordering/OrderByParser.g
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/render/OrderByRenderer.g
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentTranslator.java
core/branches/antlr3/src/main/resources/org/hibernate/sql/ast/template/OrderBy.stg
core/branches/antlr3/src/test/java/org/hibernate/sql/TemplateTest.java
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/hql/resolve/TestHQLResolver.java
Log:
Initial working versions of order-by processing using antlr3+stringtemplate
Modified: core/branches/antlr3/pom.xml
===================================================================
--- core/branches/antlr3/pom.xml 2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/pom.xml 2009-05-01 20:26:15 UTC (rev 16500)
@@ -186,17 +186,18 @@
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr3-maven-plugin</artifactId>
- <version>3.1.3-steve</version>
+ <version>3.1.4-SNAPSHOT</version>
<configuration>
</configuration>
<executions>
<execution>
+ <!-- execution to generate "source grammars" -->
<goals>
<goal>antlr</goal>
- <goal>gunit</goal>
</goals>
</execution>
<execution>
+ <!-- execution to generate "test grammars" -->
<id>test-grammar-processing</id>
<phase>generate-test-sources</phase>
<goals>
@@ -211,6 +212,12 @@
</executions>
</plugin>
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>maven-gunit-plugin</artifactId>
+ <version>3.1.4-SNAPSHOT</version>
+ </plugin>
+
</plugins>
</build>
Modified:
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/origin/ordering/OrderByParser.g
===================================================================
---
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/origin/ordering/OrderByParser.g 2009-05-01
11:59:08 UTC (rev 16499)
+++
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/origin/ordering/OrderByParser.g 2009-05-01
20:26:15 UTC (rev 16500)
@@ -1,9 +1,10 @@
parser grammar OrderByParser;
options {
- tokenVocab=HQLLexer;
- output=AST;
- ASTLabelType=CommonTree;
+ tokenVocab = HQLLexer;
+ output = AST;
+ TokenLabelType = CommonToken;
+ ASTLabelType = CommonTree;
}
@parser::header {
@@ -82,7 +83,7 @@
throw new UnsupportedOperationException( "must be overridden!" );
}
- private boolean validateSoftKeyword(String text) {
+ private boolean validateSoftKeyword(String text) {
return validateLT(1, text);
}
@@ -107,37 +108,38 @@
/**
* Main recognition rule for this grammar
*/
-orderByFragment :
- sortSpecification ( COMMA sortSpecification )*
+orderByFragment
+ : sortSpecification ( COMMA sortSpecification )*
-> ^( ORDER_BY sortSpecification+ )
-;
+ ;
/**
* Reconition rule for what ANSI SQL terms the <tt>sort specification</tt>.
These are the atomic elements of the
* <tt>ORDER BY</tt> list pieces.
*/
-sortSpecification :
- sortKey collationSpecification? orderingSpecification?
+sortSpecification
+ : sortKey collationSpecification? orderingSpecification?
-> ^( SORT_SPEC sortKey collationSpecification? orderingSpecification? )
-;
+ ;
/**
* Reconition rule for what ANSI SQL terms the <tt>sort key</tt> which is the
expression (column, function, etc) upon
* which to base the sorting.
*/
-sortKey :
- expression
-;
+sortKey
+ : expression
+ ;
/**
* Reconition rule what this grammar recognizes as valid <tt>sort key</tt>.
*/
expression
- : QUOTED_IDENTIFIER -> ^( COLUMN[$QUOTED_IDENTIFIER] ALIAS_REF[Template.TEMPLATE]
QUOTED_IDENTIFIER[$QUOTED_IDENTIFIER] )
+ : QUOTED_IDENTIFIER -> ^( COLUMN ALIAS_REF[Template.TEMPLATE]
QUOTED_IDENTIFIER[$QUOTED_IDENTIFIER] )
// we treat the so-called standard functions differently because they are handled
differently by the HQL lexer which we also use here...
| standardFunction
+ | literal
// not identDotIdentStructure because we dont want QUOTED_IDENTIFIERs is here
| ( IDENTIFIER ( DOT IDENTIFIER )* LEFT_PAREN ) => generalFunction
// otherwise we fully expect a dot-identifier series, and then we just need to decode
the semantic of that structure
@@ -191,7 +193,7 @@
castFunction
: cast_keyword LEFT_PAREN expression as_keyword dataType RIGHT_PAREN
- -> ^( FUNCTION[$cast_keyword.start,$cast_keyword.text] expression as_keyword
dataType )
+ -> ^( cast_keyword expression dataType )
;
fragment
@@ -201,17 +203,18 @@
concatFunction
: concat_keyword LEFT_PAREN expression ( COMMA expression )+ RIGHT_PAREN
- -> ^( FUNCTION[$concat_keyword.start,$concat_keyword.text] expression+ )
+ -> ^( concat_keyword expression+ )
;
substringFunction
: substring_keyword LEFT_PAREN expression COMMA expression ( COMMA expression)?
RIGHT_PAREN
- -> ^( FUNCTION[$substring_keyword.start,$substring_keyword.text] expression+ )
+ -> ^( substring_keyword expression+ )
;
trimFunction
+ // todo : dont like the creation of subtree(s) for the operands in the trimOperands
rule
: trim_keyword LEFT_PAREN trimOperands RIGHT_PAREN
- -> ^( FUNCTION[$trim_keyword.start,$trim_keyword.text] trimOperands )
+ -> ^( trim_keyword trimOperands )
;
fragment
@@ -220,106 +223,117 @@
k=2;
}
@init {boolean hasSecondExpression = false;}
- : trimSpecification from_keyword expression -> ^(trimSpecification
STRING_LITERAL[" "] expression)
- | trimSpecification expression from_keyword expression -> ^(trimSpecification
expression+)
- | from_keyword expression -> ^(BOTH STRING_LITERAL[" "] expression)
- | cn=expression ( from_keyword expression {hasSecondExpression = true;} )?
- -> {hasSecondExpression}? ^(BOTH expression+)
- -> ^(BOTH STRING_LITERAL[" "] $cn)
+ : trimSpecification from_keyword expression
+ -> ^( trimSpecification STRING_LITERAL["' '"] expression)
+ | trimSpecification expression from_keyword expression
+ -> ^(trimSpecification expression+)
+ | from_keyword expression
+ -> ^(BOTH STRING_LITERAL["' '"] expression)
+ | cn=expression ( from_keyword expression {hasSecondExpression = true;} )?
+ -> {hasSecondExpression}? ^(BOTH expression+)
+ -> ^(BOTH STRING_LITERAL["' '"] $cn)
;
fragment
trimSpecification
- : leading_keyword
- | trailing_keyword
- | both_keyword
+ : leading_keyword
+ | trailing_keyword
+ | both_keyword
;
upperFunction
: upper_keyword LEFT_PAREN expression RIGHT_PAREN
- -> ^( FUNCTION[$upper_keyword.start,$upper_keyword.text] expression )
+ -> ^( upper_keyword expression )
;
lowerFunction
: lower_keyword LEFT_PAREN expression RIGHT_PAREN
- -> ^( FUNCTION[$lower_keyword.start,$lower_keyword.text] expression )
+ -> ^( lower_keyword expression )
;
lengthFunction
: length_keyword LEFT_PAREN expression RIGHT_PAREN
- -> ^( FUNCTION[$length_keyword.start,$length_keyword.text] expression )
+ -> ^( length_keyword expression )
;
locateFunction
: locate_keyword LEFT_PAREN expression COMMA expression ( COMMA expression )?
RIGHT_PAREN
- -> ^( FUNCTION[$locate_keyword.start,$locate_keyword.text] expression+ )
+ -> ^( locate_keyword expression+ )
;
absFunction
- : abs_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ : abs_keyword LEFT_PAREN expression RIGHT_PAREN
+ -> ^( abs_keyword expression )
;
sqrtFunction
- : sqrt_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ : sqrt_keyword LEFT_PAREN expression RIGHT_PAREN
+ -> ^( sqrt_keyword expression )
;
modFunction
- : mod_keyword^ LEFT_PAREN! expression COMMA! expression RIGHT_PAREN!
+ : mod_keyword LEFT_PAREN expression COMMA expression RIGHT_PAREN
+ -> ^( mod_keyword expression+ )
;
currentDateFunction
- : current_date_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
+ : current_date_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
;
currentTimeFunction
- : current_time_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
+ : current_time_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
;
currentTimestampFunction
- : current_timestamp_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
+ : current_timestamp_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
;
extractFunction
- : extract_keyword^ LEFT_PAREN! extractField from_keyword! expression RIGHT_PAREN!
+ : extract_keyword LEFT_PAREN extractField from_keyword expression RIGHT_PAREN
+ -> ^( extract_keyword extractField expression )
;
extractField
- : datetimeField
- | timeZoneField
+ : datetimeField
+ | timeZoneField
;
datetimeField
- : nonSecondDatetimeField
- | second_keyword
+ : nonSecondDatetimeField
+ | second_keyword
;
nonSecondDatetimeField
- : year_keyword
- | month_keyword
- | day_keyword
- | hour_keyword
- | minute_keyword
+ : year_keyword
+ | month_keyword
+ | day_keyword
+ | hour_keyword
+ | minute_keyword
;
timeZoneField
- : timezone_hour_keyword
- | timezone_minute_keyword
+ : timezone_hour_keyword
+ | timezone_minute_keyword
;
positionFunction
- : position_keyword^ LEFT_PAREN! expression in_keyword! expression RIGHT_PAREN!
+ : position_keyword LEFT_PAREN expression in_keyword expression RIGHT_PAREN
+ -> ^( position_keyword expression+ )
;
charLengthFunction
- : character_length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ : character_length_keyword LEFT_PAREN expression RIGHT_PAREN
+ -> ^( character_length_keyword expression )
;
octetLengthFunction
- : octet_length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ : octet_length_keyword LEFT_PAREN expression RIGHT_PAREN
+ -> ^( octet_length_keyword expression )
;
bitLengthFunction
- : bit_length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ : bit_length_keyword LEFT_PAREN expression RIGHT_PAREN
+ -> ^( bit_length_keyword expression )
;
@@ -335,10 +349,9 @@
/**
* Recognized function parameters.
*/
-functionArgument :
- expression
- | literal
-;
+functionArgument
+ : expression
+ ;
literal
: numeric_literal
@@ -361,30 +374,30 @@
collationSpecification!
: collateKeyword collationName
-> COLLATE[$collateKeyword.start,$collationName.text]
-;
+ ;
-collateKeyword :
- {(validateSoftKeyword("collate"))}?=> id=IDENTIFIER
- -> COLLATE[$id]
-;
+collateKeyword
+ : {(validateSoftKeyword("collate"))}?=> id=IDENTIFIER
+ -> COLLATE[$id]
+ ;
/**
* The collation name wrt {@link #collationSpecification}. Namely, the character-set.
*/
-collationName :
- IDENTIFIER
-;
+collationName
+ : IDENTIFIER
+ ;
/**
* Reconition rule for what ANSI SQL terms the <tt>ordering
specification</tt>; <tt>ASCENDING</tt> or
* <tt>DESCENDING</tt>.
*/
-orderingSpecification! :
- ascending_keyword
+orderingSpecification!
+ : ascending_keyword
-> ORDER_SPEC[$ascending_keyword.start,$ascending_keyword.text]
| descending_keyword
-> ORDER_SPEC[$descending_keyword.start,$descending_keyword.text]
-;
+ ;
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Modified:
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/render/OrderByRenderer.g
===================================================================
---
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/render/OrderByRenderer.g 2009-05-01
11:59:08 UTC (rev 16499)
+++
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/render/OrderByRenderer.g 2009-05-01
20:26:15 UTC (rev 16500)
@@ -38,143 +38,237 @@
* entirety.
*/
package org.hibernate.sql.ast.render;
+
+import org.antlr.stringtemplate.StringTemplate;
}
+@members {
+ protected StringTemplate quotedIdentifier(CommonToken recognizedIdentifierToken) {
+ return new StringTemplate( getTemplateLib(), recognizedIdentifierToken.getText()
);
+ }
+
+ protected StringTemplate basicFunctionTemplate(String functionName, List arguments)
{
+ return new StringTemplate(
+ getTemplateLib(),
+ "<name>(<arguments; separator=\", \">)",
+ new STAttrMap().put( "name", functionName ).put(
"arguments", arguments )
+ );
+ }
+
+ protected StringTemplate castFunctionTemplate(StringTemplate expression, String
datatype) {
+ return new StringTemplate(
+ getTemplateLib(),
+ "cast(<expression> as <datatype>)",
+ new STAttrMap().put( "expression", expression )
+ .put( "datatype", datatype )
+ );
+ }
+
+ protected StringTemplate trimFunctionTemplate(StringTemplate trimSpec, StringTemplate
trimCharacter, StringTemplate trimSource) {
+ return new StringTemplate(
+ getTemplateLib(),
+ "trim(<trimSpec> <trimCharacter> from
<trimSource>)",
+ new STAttrMap().put( "trimSpec", trimSpec )
+ .put( "trimCharacter", trimCharacter )
+ .put( "trimSource", trimSource )
+ );
+ }
+
+ protected StringTemplate extractFunctionTemplate(StringTemplate extractField,
StringTemplate expression) {
+ return new StringTemplate(
+ getTemplateLib(),
+ "extract(<extractField> from <expression>)",
+ new STAttrMap().put( "extractField", extractField )
+ .put( "expression", expression )
+ );
+ }
+
+ protected StringTemplate positionFunctionTemplate(StringTemplate searchString,
StringTemplate sourceString) {
+ return new StringTemplate(
+ getTemplateLib(),
+ "position(<searchString> in <sourceString>)",
+ new STAttrMap().put( "searchString", searchString )
+ .put( "sourceString", sourceString )
+ );
+ }
+}
+
// todo : merge with 'full sql rendering' grammar
// this is currently just a temporary subset grammar limited to the needs of
mapping-defined order-by fragments
-orderByClause
+orderByFragment
: ^( ORDER_BY sortSpecs+=sortSpecification+ )
- -> orderByClause( sortSpecifications={$sortSpecs} )
+ -> orderByFragment( sortSpecifications={$sortSpecs} )
;
sortSpecification
- : ^( SORT_SPEC sortKey COLLATE? ORDER_SPEC? )
+ : ^( SORT_SPEC sortKey collationSpecification? ORDER_SPEC? )
-> sortSpecification(
sortKey={$sortKey.st},
- collationSpecification={$COLLATE.text},
+ collationSpecification={$collationSpecification.st},
orderingSpecification={$ORDER_SPEC.text}
)
;
+collationSpecification
+ : COLLATE -> {%{"collate " + $COLLATE.text}}
+ ;
+
sortKey
- : expression
+ : expression -> {$expression.st}
;
expression
- : column
- | function
+ : valueExpression -> {$valueExpression.st}
;
+valueExpression
+ : column -> {$column.st}
+ | function -> {$function.st}
+ | literal -> {$literal.st}
+ | rowValueConstructor -> {$rowValueConstructor.st}
+ ;
+
+characterValueExpression
+ : valueExpression -> {$valueExpression.st}
+ ;
+
+numericValueExpression
+ : valueExpression -> {$valueExpression.st}
+ ;
+
column
: ^( COLUMN ALIAS_REF identifier )
- -> column( qualifier={$ALIAS_REF.text}, name={$identifier.text} )
+ -> column( qualifier={$ALIAS_REF.text}, name={$identifier.st} )
;
identifier
- : IDENTIFIER
- | QUOTED_IDENTIFIER
+ : IDENTIFIER -> {%{$IDENTIFIER.text}}
+ | QUOTED_IDENTIFIER -> { quotedIdentifier( (CommonToken)
$QUOTED_IDENTIFIER.getToken() ) }
;
+rowValueConstructor
+ : ^( VECTOR_EXPR expressions+=expression+ )
+ -> template( expressions={$expressions} ) "(<expressions;
separator=\", \">)"
+ ;
+
function
- : functionFunction
-// | castFunction
-// | concatFunction
-// | substringFunction
-// | trimFunction
-// | upperFunction
-// | lowerFunction
-// | lengthFunction
-// | locateFunction
- | absFunction
- | sqrtFunction
- | modFunction
- | currentDateFunction
- | currentTimeFunction
- | currentTimestampFunction
- | extractFunction
- | positionFunction
- | charLengthFunction
- | octetLengthFunction
- | bitLengthFunction
+ : functionFunction -> {$functionFunction.st}
+ | castFunction -> {$castFunction.st}
+ | concatFunction -> {$concatFunction.st}
+ | substringFunction -> {$substringFunction.st}
+ | trimFunction -> {$trimFunction.st}
+ | upperFunction -> {$upperFunction.st}
+ | lowerFunction -> {$lowerFunction.st}
+ | lengthFunction -> {$lengthFunction.st}
+ | locateFunction -> {$locateFunction.st}
+ | absFunction -> {$absFunction.st}
+ | sqrtFunction -> {$sqrtFunction.st}
+ | modFunction -> {$modFunction.st}
+ | currentDateFunction -> {$currentDateFunction.st}
+ | currentTimeFunction -> {$currentTimeFunction.st}
+ | currentTimestampFunction -> {$currentTimestampFunction.st}
+ | extractFunction -> {$extractFunction.st}
+ | positionFunction -> {$positionFunction.st}
+ | charLengthFunction -> {$charLengthFunction.st}
+ | octetLengthFunction -> {$octetLengthFunction.st}
+ | bitLengthFunction -> {$bitLengthFunction.st}
;
functionFunction
: ^( FUNCTION args+=functionArgument* )
- -> basicFunction( name={$FUNCTION.text}, args={$args} )
+ -> { basicFunctionTemplate( $FUNCTION.text, $args ) }
;
functionArgument
- : expression
- | literal
+ : expression -> {$expression.st}
;
-//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// rewritten in parser as ^( FUNCTION ... ) structures
-//castFunction
-// : ^( CAST valueExpression IDENTIFIER )
-// ;
-//
-//concatFunction
-// : ^( CONCAT valueExpression+ )
-// ;
-//
-//substringFunction
-// : ^(SUBSTRING characterValueExpression numericValueExpression
numericValueExpression?)
-// ;
-//
-//trimFunction
-// : ^(TRIM trimOperands)
-// ;
-//
-//trimOperands
-// : ^((LEADING|TRAILING|BOTH) characterValueExpression characterValueExpression)
-// ;
-//
-//upperFunction
-// : ^(UPPER characterValueExpression)
-// ;
-//
-//lowerFunction
-// : ^(LOWER characterValueExpression)
-// ;
-//
-//lengthFunction
-// : ^(LENGTH characterValueExpression)
-// ;
-//
-//locateFunction
-// : ^(LOCATE characterValueExpression characterValueExpression numericValueExpression?)
-// ;
-//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+castFunction
+ : ^( CAST valueExpression IDENTIFIER )
+ -> { castFunctionTemplate( $valueExpression.st, $IDENTIFIER.text ) }
+ ;
-absFunction
- : ^( ABS expression )
+concatFunction
+ : ^( CONCAT args+=valueExpression+ )
+ -> { basicFunctionTemplate( $CONCAT.text, $args ) }
;
+substringFunction
+ : ^( SUBSTRING args+=characterValueExpression args+=numericValueExpression
args+=numericValueExpression? )
+ -> { basicFunctionTemplate( $SUBSTRING.text, $args ) }
+ ;
+
+trimFunction
+ : ^( TRIM ^( trimSpec trimChar trimSource ) )
+ -> { trimFunctionTemplate( $trimSpec.st, $trimChar.st, $trimSource.st ) }
+ ;
+
+trimSpec
+ : LEADING -> {%{"leading"}}
+ | TRAILING -> {%{"trailing"}}
+ | BOTH -> {%{"both"}}
+ ;
+
+trimChar
+ : characterValueExpression -> { $characterValueExpression.st }
+ ;
+
+trimSource
+ : characterValueExpression -> { $characterValueExpression.st }
+ ;
+
+upperFunction
+ : ^( UPPER args+=characterValueExpression )
+ -> { basicFunctionTemplate( $UPPER.text, $args ) }
+ ;
+
+lowerFunction
+ : ^( LOWER args+=characterValueExpression )
+ -> { basicFunctionTemplate( $LOWER.text, $args ) }
+ ;
+
+lengthFunction
+ : ^( LENGTH args+=characterValueExpression )
+ -> { basicFunctionTemplate( $LENGTH.text, $args ) }
+ ;
+
+locateFunction
+ : ^( LOCATE args+=characterValueExpression args+=characterValueExpression
args+=numericValueExpression? )
+ -> { basicFunctionTemplate( $LOCATE.text, $args ) }
+ ;
+
+absFunction
+ : ^( ABS args+=expression )
+ -> { basicFunctionTemplate( $ABS.text, $args ) }
+ ;
+
sqrtFunction
- : ^(SQRT expression)
- ;
+ : ^( SQRT args+=expression )
+ -> { basicFunctionTemplate( $SQRT.text, $args ) }
+ ;
modFunction
- : ^(MOD expression expression)
- ;
+ : ^( MOD args+=expression args+=expression )
+ -> { basicFunctionTemplate( $MOD.text, $args ) }
+ ;
currentDateFunction
- : CURRENT_DATE
- ;
+ : CURRENT_DATE -> { basicFunctionTemplate( $CURRENT_DATE.text, null ) }
+ ;
currentTimeFunction
- : CURRENT_TIME
- ;
+ : CURRENT_TIME -> { basicFunctionTemplate( $CURRENT_TIME.text, null ) }
+ ;
currentTimestampFunction
- : CURRENT_TIMESTAMP
- ;
+ : CURRENT_TIMESTAMP -> { basicFunctionTemplate( $CURRENT_TIMESTAMP.text, null ) }
+ ;
extractFunction
- : ^(EXTRACT extractField expression)
- ;
+ : ^( EXTRACT extractField expression )
+ -> { extractFunctionTemplate( $extractField.st, $expression.st ) }
+ ;
extractField
: datetimeField
@@ -182,46 +276,50 @@
;
datetimeField
- : YEAR
- | MONTH
- | DAY
- | HOUR
- | MINUTE
- | SECOND
+ : YEAR -> {%{"year"}}
+ | MONTH -> {%{"month"}}
+ | DAY -> {%{"day"}}
+ | HOUR -> {%{"hour"}}
+ | MINUTE -> {%{"minute"}}
+ | SECOND -> {%{"second"}}
;
timeZoneField
- : TIMEZONE_HOUR
- | TIMEZONE_MINUTE
+ : TIMEZONE_HOUR -> {%{"timezone_hour"}}
+ | TIMEZONE_MINUTE -> {%{"timezone_minute"}}
;
positionFunction
- : ^(POSITION expression expression)
- ;
+ : ^( POSITION s1=expression s2=expression )
+ -> { positionFunctionTemplate( $s1.st, $s2.st ) }
+ ;
charLengthFunction
- : ^(CHARACTER_LENGTH expression)
- ;
+ : ^( CHARACTER_LENGTH args+=expression )
+ -> { basicFunctionTemplate( $CHARACTER_LENGTH.text, $args ) }
+ ;
octetLengthFunction
- : ^(OCTET_LENGTH expression)
- ;
+ : ^( OCTET_LENGTH args+=expression )
+ -> { basicFunctionTemplate( $OCTET_LENGTH.text, $args ) }
+ ;
bitLengthFunction
- : ^(BIT_LENGTH expression)
- ;
+ : ^( BIT_LENGTH args+=expression )
+ -> { basicFunctionTemplate( $BIT_LENGTH.text, $args ) }
+ ;
literal
- : numeric_literal
- | HEX_LITERAL
- | OCTAL_LITERAL
- | CHARACTER_LITERAL
- | STRING_LITERAL
+ : numeric_literal -> {$numeric_literal.st}
+ | HEX_LITERAL -> {%{$HEX_LITERAL.text}}
+ | OCTAL_LITERAL -> {%{$OCTAL_LITERAL.text}}
+ | CHARACTER_LITERAL -> {%{$CHARACTER_LITERAL.text}}
+ | STRING_LITERAL -> {%{$STRING_LITERAL.text}}
;
numeric_literal
- : INTEGER_LITERAL
- | DECIMAL_LITERAL
- | FLOATING_POINT_LITERAL
+ : INTEGER_LITERAL -> {%{$INTEGER_LITERAL.text}}
+ | DECIMAL_LITERAL -> {%{$DECIMAL_LITERAL.text}}
+ | FLOATING_POINT_LITERAL -> {%{$FLOATING_POINT_LITERAL.text}}
;
Modified:
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java
===================================================================
---
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java 2009-05-01
11:59:08 UTC (rev 16499)
+++
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java 2009-05-01
20:26:15 UTC (rev 16500)
@@ -58,12 +58,23 @@
*/
public HibernateToken(Token oldToken) {
super( oldToken );
- if ( null != oldToken
- && ( oldToken.getClass().equals( CommonToken.class ) || oldToken
- .getClass().equals( HibernateToken.class ) ) ) {
- start = ( ( CommonToken ) oldToken ).getStartIndex();
- stop = ( ( CommonToken ) oldToken ).getStopIndex();
+ if ( null != oldToken && CommonToken.class.isInstance( oldToken ) ) {
+ setStartIndex( ( ( CommonToken ) oldToken ).getStartIndex() );
+ setStopIndex( ( ( CommonToken ) oldToken ).getStopIndex() );
}
}
+ /**
+ * Constructor form used to track origination position information via the passed
+ * 'oldToken' param, but to utilize a new token type and text.
+ *
+ * @param oldToken The original token type (used for position tracking info).
+ * @param type The type of the new (this) token
+ * @param text The test of the new (this) token.
+ */
+ public HibernateToken(Token oldToken, int type, String text) {
+ this( oldToken );
+ setType( type );
+ setText( text );
+ }
}
Copied:
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByParser.java
(from rev 16468,
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java)
===================================================================
---
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByParser.java
(rev 0)
+++
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByParser.java 2009-05-01
20:26:15 UTC (rev 16500)
@@ -0,0 +1,117 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.sql.ast.origin.ordering;
+
+import org.antlr.runtime.TokenStream;
+import org.antlr.runtime.tree.CommonTree;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.sql.ast.common.HibernateTree;
+import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
+import org.hibernate.sql.Template;
+
+/**
+ * Extension of the Antlr-generated parser for the purpose of adding our custom parsing
behavior.
+ *
+ * @author Steve Ebersole
+ */
+public class ContextualOrderByParser extends OrderByParser {
+ private static final Logger log = LoggerFactory.getLogger( ContextualOrderByParser.class
);
+ private final TranslationContext context;
+
+ private final String openQuoteChar;
+ private final String closeQuoteChar;
+
+ public ContextualOrderByParser(TokenStream lexer, TranslationContext context) {
+ super( lexer );
+ this.context = context;
+
+ this.openQuoteChar = Character.toString( context.getDialect().openQuote() );
+ this.closeQuoteChar = Character.toString( context.getDialect().closeQuote() );
+ }
+
+ @Override
+ protected boolean isFunctionName(String text) {
+ log.trace( "Checking function name [" + text + "]" );
+ return context.getSqlFunctionRegistry().hasFunction( text );
+ }
+
+ @Override
+ protected boolean isPropertyName(String text) {
+ log.trace( "Checking property name [" + text + "]" );
+ try {
+ return context.getColumnMapper().map( text ) != null;
+ }
+ catch ( Throwable t ) {
+ return false;
+ }
+ }
+
+ @Override
+ protected CommonTree buildPropertyColumns(CommonTree propertyTree) {
+ final String text = extractPropertyName( propertyTree );
+ String[] columns = context.getColumnMapper().map( text );
+ if ( columns.length == 1 ) {
+ return buildColumn( columns[0] );
+ }
+ else {
+ HibernateTree vector = new HibernateTree( VECTOR_EXPR );
+ for ( String column : columns ) {
+ vector.addChild( buildColumn( column ) );
+ }
+ return vector;
+ }
+ }
+
+ private CommonTree buildColumn(String columnName) {
+ // ugh
+ HibernateTree columnNameNode;
+ if ( columnName.startsWith( openQuoteChar ) && columnName.endsWith(
closeQuoteChar ) ) {
+ columnName = columnName.substring( 1, columnName.length() - 1 );
+ columnNameNode = new HibernateTree( QUOTED_IDENTIFIER, columnName );
+ }
+ else {
+ columnNameNode = new HibernateTree( IDENTIFIER, columnName );
+ }
+
+ HibernateTree tree = new HibernateTree( COLUMN );
+ tree.addChild( new HibernateTree( ALIAS_REF, Template.TEMPLATE ) );
+ tree.addChild( columnNameNode );
+
+ return tree;
+ }
+
+ private String extractPropertyName(CommonTree propertyTree) {
+ if ( HQLLexer.DOT == propertyTree.getType() ) {
+ return extractPropertyName( ( CommonTree ) propertyTree.getChild( 0 ) ) +
"." +
+ extractPropertyName( ( CommonTree ) propertyTree.getChild( 1 ) );
+ }
+ else {
+ // assume IDENTIFIER... assertion?
+ return propertyTree.getText();
+ }
+ }
+}
Added:
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByRenderer.java
===================================================================
---
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByRenderer.java
(rev 0)
+++
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByRenderer.java 2009-05-01
20:26:15 UTC (rev 16500)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.sql.ast.origin.ordering;
+
+import java.util.List;
+
+import org.antlr.runtime.CommonToken;
+import org.antlr.runtime.tree.TreeNodeStream;
+import org.antlr.stringtemplate.StringTemplate;
+import org.antlr.stringtemplate.StringTemplateGroup;
+
+import org.hibernate.dialect.function.SQLFunction;
+import org.hibernate.sql.ast.render.OrderByRenderer;
+
+/**
+ * Subclassing of the Antlr-generated renderer to apply contextual semantics.
+ *
+ * @author Steve Ebersole
+ */
+public class ContextualOrderByRenderer extends OrderByRenderer {
+ private final TranslationContext translationContext;
+
+ private final StringTemplate quotedIdentifierTemplate;
+
+ private final StringTemplate basicFunctionNoArgsWithoutParens;
+ private final StringTemplate basicFunctionNoArgsWithParens;
+ private final StringTemplate basicFunctionWithArgs;
+
+ private final StringTemplate castFunction;
+ private final StringTemplate trimfunction;
+
+ public ContextualOrderByRenderer(
+ TreeNodeStream input,
+ TranslationContext translationContext,
+ StringTemplateGroup stringTemplateGroup) {
+ super( input );
+ setTemplateLib( stringTemplateGroup );
+ this.translationContext = translationContext;
+
+ //
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // todo : eventually get these directly from the Dialect
+ quotedIdentifierTemplate = buildQuotedIdentiferTemplate();
+
+ basicFunctionNoArgsWithoutParens = new StringTemplate( getTemplateLib(),
"<name>" );
+ basicFunctionNoArgsWithoutParens.defineFormalArgument( "name" );
+
+ basicFunctionNoArgsWithParens = new StringTemplate( getTemplateLib(),
"<name>()" );
+ basicFunctionNoArgsWithParens.defineFormalArgument( "name" );
+
+ basicFunctionWithArgs = new StringTemplate( getTemplateLib(),
"<name>(<arguments; separator=\", \">)" );
+ basicFunctionWithArgs.defineFormalArgument( "name" );
+ basicFunctionWithArgs.defineFormalArgument( "arguments" );
+
+ castFunction = new StringTemplate( getTemplateLib(), "cast(<expression> as
<datatype>)" );
+ castFunction.defineFormalArgument( "expression" );
+ castFunction.defineFormalArgument( "datatype" );
+
+ trimfunction = new StringTemplate( getTemplateLib(), "trim(<trimSpec>
<trimCharacter> from <trimSource >)" );
+ trimfunction.defineFormalArgument( "trimSpec" );
+ trimfunction.defineFormalArgument( "trimCharacter" );
+ trimfunction.defineFormalArgument( "trimSource" );
+ //
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ }
+
+ @Override
+ protected StringTemplate quotedIdentifier(CommonToken recognizedIdentifierToken) {
+ String identifierText = recognizedIdentifierToken.getText();
+ if ( identifierText.startsWith( "`" ) ) {
+ identifierText = identifierText.substring( 1, identifierText.length() - 1 );
+ StringTemplate template = quotedIdentifierTemplate.getInstanceOf();
+ template.setAttribute( "identifier", identifierText );
+ return template;
+ }
+ else {
+ return super.quotedIdentifier( recognizedIdentifierToken );
+ }
+ }
+
+ private StringTemplate buildQuotedIdentiferTemplate() {
+ String templateContent = translationContext.getDialect().openQuote() +
+ "<identifier>" +
+ translationContext.getDialect().closeQuote();
+ StringTemplate template = new StringTemplate( getTemplateLib(), templateContent
);
+ template.defineFormalArgument( "identifier" );
+ return template;
+ }
+
+ @Override
+ protected StringTemplate basicFunctionTemplate(String functionName, List arguments) {
+ if ( arguments == null || arguments.isEmpty() ) {
+ SQLFunction sqlFunction = translationContext.getSqlFunctionRegistry().findSQLFunction(
"functionName" );
+ StringTemplate template = sqlFunction.hasParenthesesIfNoArguments()
+ ? basicFunctionNoArgsWithParens
+ : basicFunctionNoArgsWithoutParens;
+ template.setAttribute( "name", functionName );
+ return template;
+ }
+ else {
+ StringTemplate template = basicFunctionWithArgs.getInstanceOf();
+ template.setAttribute( "name", functionName );
+ template.setAttribute( "arguments", arguments );
+ return template;
+ }
+ }
+
+ @Override
+ protected StringTemplate castFunctionTemplate(StringTemplate expression, String
datatype) {
+ StringTemplate template = castFunction.getInstanceOf();
+ template.setAttribute( "expression", expression );
+ template.setAttribute( "datatype", datatype );
+ return template;
+ }
+
+ @Override
+ protected StringTemplate trimFunctionTemplate(StringTemplate trimSpec, StringTemplate
trimCharacter, StringTemplate trimSource) {
+ StringTemplate template = trimfunction.getInstanceOf();
+ template.setAttribute( "trimSpec", trimSpec );
+ template.setAttribute( "trimCharacter", trimCharacter );
+ template.setAttribute( "trimSource", trimSource );
+ return template;
+ }
+}
Deleted:
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java
===================================================================
---
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java 2009-05-01
11:59:08 UTC (rev 16499)
+++
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java 2009-05-01
20:26:15 UTC (rev 16500)
@@ -1,109 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors. All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02110-1301 USA
- *
- */
-package org.hibernate.sql.ast.origin.ordering;
-
-import org.antlr.runtime.TokenStream;
-import org.antlr.runtime.tree.CommonTree;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.sql.ast.common.HibernateTree;
-import org.hibernate.sql.Template;
-
-/**
- * Extension of the Antlr-generated parser for the purpose of adding our custom parsing
behavior.
- *
- * @author Steve Ebersole
- */
-public class OrderByFragmentParser extends OrderByParser {
- private static final Logger log = LoggerFactory.getLogger( OrderByFragmentParser.class
);
- private final TranslationContext context;
-
- private final String openQuoteChar;
- private final String closeQuoteChar;
-
- public OrderByFragmentParser(TokenStream lexer, TranslationContext context) {
- super( lexer );
- this.context = context;
-
- this.openQuoteChar = Character.toString( context.getDialect().openQuote() );
- this.closeQuoteChar = Character.toString( context.getDialect().closeQuote() );
- }
-
- @Override
- protected boolean isFunctionName(String text) {
- log.trace( "Checking function name [" + text + "]" );
- return context.getSqlFunctionRegistry().hasFunction( text );
- }
-
- @Override
- protected boolean isPropertyName(String text) {
- log.trace( "Checking property name [" + text + "]" );
- try {
- return context.getColumnMapper().map( text ) != null;
- }
- catch ( Throwable t ) {
- return false;
- }
- }
-
- @Override
- protected CommonTree buildPropertyColumns(CommonTree propertyTree) {
- final String text = extractPropertyName( propertyTree );
- String[] columns = context.getColumnMapper().map( text );
- if ( columns.length == 1 ) {
- return buildColumn( columns[0] );
- }
- else {
- HibernateTree vector = new HibernateTree( VECTOR_EXPR );
- for ( String column : columns ) {
- vector.addChild( buildColumn( column ) );
- }
- return vector;
- }
- }
-
- private CommonTree buildColumn(String columnName) {
- // ugh
- HibernateTree columnNameNode;
- if ( columnName.startsWith( openQuoteChar ) && columnName.endsWith(
closeQuoteChar ) ) {
- columnName = columnName.substring( 1, columnName.length() - 1 );
- columnNameNode = new HibernateTree( QUOTED_IDENTIFIER, columnName );
- }
- else {
- columnNameNode = new HibernateTree( IDENTIFIER, columnName );
- }
-
- HibernateTree tree = new HibernateTree( COLUMN );
- tree.addChild( new HibernateTree( ALIAS_REF, Template.TEMPLATE ) );
- tree.addChild( columnNameNode );
-
- return tree;
- }
-
- private String extractPropertyName(CommonTree propertyTree) {
- return propertyTree.getText();
- }
-}
Modified:
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentTranslator.java
===================================================================
---
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentTranslator.java 2009-05-01
11:59:08 UTC (rev 16499)
+++
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentTranslator.java 2009-05-01
20:26:15 UTC (rev 16500)
@@ -33,7 +33,12 @@
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.Tree;
+import org.antlr.runtime.tree.CommonTreeNodeStream;
+import org.antlr.stringtemplate.StringTemplateGroup;
+import org.antlr.stringtemplate.CommonGroupLoader;
+import org.antlr.stringtemplate.StringTemplateErrorListener;
/**
* A translator which coordinates translation of an <tt>order-by</tt>
mapping.
@@ -58,13 +63,14 @@
*/
public String render(String fragment) {
HQLLexer lexer = new HQLLexer( new ANTLRStringStream( fragment ) );
- OrderByFragmentParser parser = new OrderByFragmentParser( new CommonTokenStream( lexer
), context );
+ ContextualOrderByParser parser = new ContextualOrderByParser( new CommonTokenStream(
lexer ), context );
+ Tree orderByTree;
try {
- Tree tree = ( Tree ) parser.orderByFragment().getTree();
+ orderByTree = ( Tree ) parser.orderByFragment().getTree();
if ( log.isTraceEnabled() ) {
TreePrinter printer = new TreePrinter( OrderByParser.class );
- log.trace( printer.renderAsString( tree, "--- {order-by fragment}
---" ) );
+ log.trace( printer.renderAsString( orderByTree, "--- {order-by
fragment} ---" ) );
}
}
catch ( HibernateException e ) {
@@ -74,18 +80,29 @@
throw new HibernateException( "Unable to parse order-by fragment", t );
}
-// OrderByFragmentRenderer renderer = new OrderByFragmentRenderer();
-// try {
-// renderer.orderByFragment( parser.getAST() );
-// }
-// catch ( HibernateException e ) {
-// throw e;
-// }
-// catch ( Throwable t ) {
-// throw new HibernateException( "Unable to render parsed order-by fragment",
t );
-// }
-//
-// return renderer.getRenderedFragment();
- return null;
+ // Load the string templates...
+ CommonGroupLoader groupLoader = new CommonGroupLoader(
+ "org/hibernate/sql/ast/template/",
+ new StringTemplateErrorListener() {
+ public void error(String s, Throwable throwable) {
+ throw new RuntimeException( s, throwable );
+ }
+
+ public void warning(String s) {
+ System.out.println( "GROUP-LOADER : " + s );
+ }
+ }
+ );
+ StringTemplateGroup.registerGroupLoader( groupLoader );
+ StringTemplateGroup stringTemplateGroup = groupLoader.loadGroup( "OrderBy"
);
+ ContextualOrderByRenderer renderer = new ContextualOrderByRenderer( new
CommonTreeNodeStream( orderByTree ), context, stringTemplateGroup );
+
+ try {
+ return renderer.orderByFragment().st.toString();
+ }
+ catch ( RecognitionException e ) {
+ throw new HibernateException( "Unable to render order-by fragment", e );
+ }
+
}
}
Modified:
core/branches/antlr3/src/main/resources/org/hibernate/sql/ast/template/OrderBy.stg
===================================================================
---
core/branches/antlr3/src/main/resources/org/hibernate/sql/ast/template/OrderBy.stg 2009-05-01
11:59:08 UTC (rev 16499)
+++
core/branches/antlr3/src/main/resources/org/hibernate/sql/ast/template/OrderBy.stg 2009-05-01
20:26:15 UTC (rev 16500)
@@ -1,26 +1,13 @@
group OrderBy;
-
-orderByClause(sortSpecifications) ::= <<
-order by <orderByFragment(sortSpecifications)>
->>
-
orderByFragment(sortSpecifications) ::= <<
<sortSpecifications; separator=", ">
>
sortSpecification(sortKey,collationSpecification,orderingSpecification) ::= <<
-<sortKey> <collationSpecification> <orderingSpecification>
+<[sortKey, collationSpecification, orderingSpecification]; separator="
">
>
column(qualifier,name) ::= <<
<qualifier>.<name>
>
-
-function(name,arguments) ::= <<
-<name>(<arguments; separator=", ">)
->>
-
-noArgumentFunction(name) ::= <<
-<name>
->>
\ No newline at end of file
Modified: core/branches/antlr3/src/test/java/org/hibernate/sql/TemplateTest.java
===================================================================
--- core/branches/antlr3/src/test/java/org/hibernate/sql/TemplateTest.java 2009-05-01
11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/test/java/org/hibernate/sql/TemplateTest.java 2009-05-01
20:26:15 UTC (rev 16500)
@@ -44,10 +44,7 @@
public class TemplateTest extends TestCase {
private static final PropertyMapping PROPERTY_MAPPING = new PropertyMapping() {
public String[] toColumns(String propertyName) throws QueryException,
UnsupportedOperationException {
- if ( "sql".equals( propertyName ) ) {
- return new String[] { "sql" };
- }
- else if ( "component".equals( propertyName ) ) {
+ if ( "component".equals( propertyName ) ) {
return new String[] { "comp_1", "comp_2" };
}
else if ( "component.prop1".equals( propertyName ) ) {
@@ -85,104 +82,152 @@
private static final SQLFunctionRegistry FUNCTION_REGISTRY = new SQLFunctionRegistry(
DIALECT, Collections.EMPTY_MAP );
- public void testParsing() {
+ public void testSQLReferences() {
String fragment = "sql asc, sql desc";
String template = doStandardRendering( fragment );
+
+ assertEquals( Template.TEMPLATE + ".sql asc, " + Template.TEMPLATE +
".sql desc", template );
}
-// public void testSQLReferences() {
-// String fragment = "sql asc, sql desc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( Template.TEMPLATE + ".sql asc, " + Template.TEMPLATE +
".sql desc", template );
-// }
-//
-// public void testQuotedSQLReferences() {
-// String fragment = "`sql` asc, `sql` desc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( Template.TEMPLATE + ".\"sql\" asc, " +
Template.TEMPLATE + ".\"sql\" desc", template );
-// }
-//
-// public void testPropertyReference() {
-// String fragment = "property asc, property desc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( Template.TEMPLATE + ".prop asc, " + Template.TEMPLATE +
".prop desc", template );
-// }
-//
-// public void testFunctionReference() {
-// String fragment = "upper(sql) asc, lower(sql) desc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( "upper(" + Template.TEMPLATE + ".sql) asc, lower("
+ Template.TEMPLATE + ".sql) desc", template );
-// }
-//
-// public void testQualifiedFunctionReference() {
-// String fragment = "qual.upper(property) asc, qual.lower(property) desc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( "qual.upper(" + Template.TEMPLATE + ".prop) asc,
qual.lower(" + Template.TEMPLATE + ".prop) desc", template );
-// }
-//
-// public void testDoubleQualifiedFunctionReference() {
-// String fragment = "qual1.qual2.upper(property) asc, qual1.qual2.lower(property)
desc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( "qual1.qual2.upper(" + Template.TEMPLATE + ".prop) asc,
qual1.qual2.lower(" + Template.TEMPLATE + ".prop) desc", template );
-// }
-//
-// public void testFunctionWithPropertyReferenceAsParam() {
-// String fragment = "upper(property) asc, lower(property) desc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( "upper(" + Template.TEMPLATE + ".prop) asc, lower("
+ Template.TEMPLATE + ".prop) desc", template );
-// }
-//
-// public void testNestedFunctionReferences() {
-// String fragment = "upper(lower(sql)) asc, lower(upper(sql)) desc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( "upper(lower(" + Template.TEMPLATE + ".sql)) asc,
lower(upper(" + Template.TEMPLATE + ".sql)) desc", template );
-// }
-//
-// public void testComplexNestedFunctionReferences() {
-// String fragment = "mod(mod(sql,2),3) asc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( "mod(mod(" + Template.TEMPLATE + ".sql, 2), 3)
asc", template );
-// }
-//
-// public void testCollation() {
-// String fragment = "`sql` COLLATE my_collation, `sql` COLLATE
your_collation";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( Template.TEMPLATE + ".\"sql\" collate my_collation,
" + Template.TEMPLATE + ".\"sql\" collate your_collation",
template );
-// }
-//
-// public void testCollationAndOrdering() {
-// String fragment = "sql COLLATE my_collation, upper(prop) COLLATE your_collation
asc, `sql` desc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( Template.TEMPLATE + ".sql collate my_collation, upper(" +
Template.TEMPLATE + ".prop) collate your_collation asc, " + Template.TEMPLATE +
".\"sql\" desc", template );
-//
-// }
-//
-// public void testComponentReferences() {
-// String fragment = "component asc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( Template.TEMPLATE + ".comp_1 asc, " + Template.TEMPLATE +
".comp_2 asc", template );
-//
-// }
-//
-// public void testComponentDerefReferences() {
-// String fragment = "component.prop1 asc";
-// String template = doStandardRendering( fragment );
-//
-// assertEquals( Template.TEMPLATE + ".comp_1 asc", template );
-// }
+ public void testQuotedSQLReferences() {
+ String fragment = "`sql` asc, `sql` desc";
+ String template = doStandardRendering( fragment );
+ assertEquals( Template.TEMPLATE + ".\"sql\" asc, " +
Template.TEMPLATE + ".\"sql\" desc", template );
+ }
+
+ public void testPropertyReference() {
+ String fragment = "property asc, property desc";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( Template.TEMPLATE + ".prop asc, " + Template.TEMPLATE +
".prop desc", template );
+ }
+
+ public void testFunctionReference() {
+ String fragment = "upper(sql) asc, lower(sql) desc";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( "upper(" + Template.TEMPLATE + ".sql) asc, lower(" +
Template.TEMPLATE + ".sql) desc", template );
+ }
+
+ public void testQualifiedFunctionReference() {
+ String fragment = "qual.upper(property) asc, qual.lower(property) desc";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( "qual.upper(" + Template.TEMPLATE + ".prop) asc,
qual.lower(" + Template.TEMPLATE + ".prop) desc", template );
+ }
+
+ public void testDoubleQualifiedFunctionReference() {
+ String fragment = "qual1.qual2.upper(property) asc, qual1.qual2.lower(property)
desc";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( "qual1.qual2.upper(" + Template.TEMPLATE + ".prop) asc,
qual1.qual2.lower(" + Template.TEMPLATE + ".prop) desc", template );
+ }
+
+ public void testFunctionWithPropertyReferenceAsParam() {
+ String fragment = "upper(property) asc, lower(property) desc";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( "upper(" + Template.TEMPLATE + ".prop) asc, lower(" +
Template.TEMPLATE + ".prop) desc", template );
+ }
+
+ public void testNestedFunctionReferences() {
+ String fragment = "upper(lower(sql)) asc, lower(upper(sql)) desc";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( "upper(lower(" + Template.TEMPLATE + ".sql)) asc,
lower(upper(" + Template.TEMPLATE + ".sql)) desc", template );
+ }
+
+ public void testComplexNestedFunctionReferences() {
+ String fragment = "mod(mod(sql,2),3) asc";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( "mod(mod(" + Template.TEMPLATE + ".sql, 2), 3) asc",
template );
+ }
+
+ public void testCollation() {
+ String fragment = "`sql` COLLATE my_collation, `sql` COLLATE
your_collation";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( Template.TEMPLATE + ".\"sql\" collate my_collation, "
+ Template.TEMPLATE + ".\"sql\" collate your_collation", template );
+ }
+
+ public void testCollationAndOrdering() {
+ String fragment = "sql COLLATE my_collation, upper(prop) COLLATE your_collation
asc, `sql` desc";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( Template.TEMPLATE + ".sql collate my_collation, upper(" +
Template.TEMPLATE + ".prop) collate your_collation asc, " + Template.TEMPLATE +
".\"sql\" desc", template );
+
+ }
+
+ public void testComponentReferences() {
+ // todo : inline the row value constructor expressions [(e1, e2) asc] -> [e1 asc, e2
asc]
+ String fragment = "component asc";
+ String template = doStandardRendering( fragment );
+ assertEquals( Template.TEMPLATE + ".comp_1 asc, " + Template.TEMPLATE +
".comp_2 asc", template );
+ }
+
+ public void testComponentDerefReferences() {
+ String fragment = "component.prop1 asc";
+ String template = doStandardRendering( fragment );
+
+ assertEquals( Template.TEMPLATE + ".comp_1 asc", template );
+ }
+
+
+ // test the various 'standard function' handlings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ public void testCastFunction() {
+ String template = doStandardRendering( "cast( sql as varchar )" );
+ assertEquals( "cast(" + Template.TEMPLATE + ".sql as varchar)",
template );
+ }
+
+ public void testConcatFunction() {
+ String template = doStandardRendering( "concat(sql, sql)" );
+ assertEquals( "concat(" + Template.TEMPLATE + ".sql, " +
Template.TEMPLATE + ".sql)", template );
+ }
+
+ public void testConcatExpression2Function() {
+ // todo : pull the concatenation-op rules over from the hql parser...
+ String template = doStandardRendering( "sql || sql" );
+ assertEquals( "concat(" + Template.TEMPLATE + ".sql, " +
Template.TEMPLATE + ".sql)", template );
+ }
+
+ public void testSubstringFunction() {
+ String template = doStandardRendering( "substring(sql,1)" );
+ assertEquals( "substring(" + Template.TEMPLATE + ".sql, 1)",
template );
+
+ template = doStandardRendering( "substring(sql,1,2)" );
+ assertEquals( "substring(" + Template.TEMPLATE + ".sql, 1, 2)",
template );
+ }
+
+ public void testTrimFunction() {
+ String template = doStandardRendering( "trim( both ' ' from sql )"
);
+ assertEquals( "trim(both ' ' from " + Template.TEMPLATE +
".sql)", template );
+
+ template = doStandardRendering( "trim( ' ' from sql )" );
+ assertEquals( "trim(both ' ' from " + Template.TEMPLATE +
".sql)", template );
+
+ template = doStandardRendering( "trim( sql )" );
+ assertEquals( "trim(both ' ' from " + Template.TEMPLATE +
".sql)", template );
+
+ template = doStandardRendering( "trim( leading from sql )" );
+ assertEquals( "trim(leading ' ' from " + Template.TEMPLATE +
".sql)", template );
+ }
+
+ public void testLengthFunction() {
+ String template = doStandardRendering( "length(sql)" );
+ assertEquals( "length(" + Template.TEMPLATE + ".sql)", template );
+ }
+
+ public void testLocateFunction() {
+ String template = doStandardRendering( "locate('abc', sql)" );
+ assertEquals( "locate('abc', " + Template.TEMPLATE +
".sql)", template );
+
+ template = doStandardRendering( "locate('abc', sql, 2)" );
+ assertEquals( "locate('abc', " + Template.TEMPLATE + ".sql,
2)", template );
+ }
+
public String doStandardRendering(String fragment) {
return Template.renderOrderByStringTemplate( fragment, MAPPER, null, DIALECT,
FUNCTION_REGISTRY );
}
Modified:
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/hql/resolve/TestHQLResolver.java
===================================================================
---
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/hql/resolve/TestHQLResolver.java 2009-05-01
11:59:08 UTC (rev 16499)
+++
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/hql/resolve/TestHQLResolver.java 2009-05-01
20:26:15 UTC (rev 16500)
@@ -1,20 +1,40 @@
+/*
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
package org.hibernate.sql.ast.origin.hql.resolve;
import junit.framework.TestCase;
-
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.runtime.tree.Tree;
+
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.hql.classic.ClassicQueryTranslatorFactory;
-import org.hibernate.sql.ast.origin.hql.resolve.HQLResolver;
+import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
import org.hibernate.sql.ast.origin.hql.parse.HQLParser;
-import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
public class TestHQLResolver extends TestCase {
@@ -41,11 +61,11 @@
}
public void testBasicStructure() throws RecognitionException {
- Tree queryTree = normalize( "from Animal" );
+ normalize( "from Animal" );
}
public void testBasicSelectStructure() throws Throwable {
- Tree queryTree = normalize( "from Zoo z where z.mammals['dog'].id =
?" );
+ normalize( "from Zoo z where z.mammals['dog'].id = ?" );
}
public Tree normalize( String hql ) throws RecognitionException {
@@ -84,7 +104,6 @@
ANTLRStringStream charStream = new ANTLRStringStream( input );
HQLLexer hqlLexer = new HQLLexer( charStream );
tokens = new CommonTokenStream( hqlLexer );
- HQLParser parser = new HQLParser( tokens );
- return parser;
+ return new HQLParser( tokens );
}
}
Deleted:
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java
===================================================================
---
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java 2009-05-01
11:59:08 UTC (rev 16499)
+++
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java 2009-05-01
20:26:15 UTC (rev 16500)
@@ -1,284 +0,0 @@
-/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors. All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02110-1301 USA
- */
-package org.hibernate.sql.ast.origin.ordering;
-
-import java.util.Collections;
-import java.util.Map;
-
-import junit.framework.TestCase;
-import junit.framework.AssertionFailedError;
-
-import org.hibernate.persister.entity.PropertyMapping;
-import org.hibernate.QueryException;
-import org.hibernate.Hibernate;
-import org.hibernate.HibernateException;
-import org.hibernate.dialect.Dialect;
-import org.hibernate.dialect.HSQLDialect;
-import org.hibernate.dialect.function.SQLFunctionRegistry;
-import org.hibernate.dialect.function.SQLFunction;
-import org.hibernate.dialect.function.SQLFunctionTemplate;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.sql.ast.util.ASTUtil;
-import org.hibernate.sql.ast.util.TreePrinter;
-import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
-import org.hibernate.sql.Template;
-import org.hibernate.type.Type;
-
-import org.antlr.runtime.ANTLRStringStream;
-import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.tree.Tree;
-import org.antlr.runtime.tree.CommonTree;
-
-/**
- * Assertions against the structures generated by various paths of the
"order-by" mapping fragment parser.
- *
- * @author Steve Ebersole
- */
-public class OrderByParserTest extends TestCase {
- public static final PropertyMapping STANDARD_PROPERTY_MAPPING = new PropertyMapping() {
- public String[] toColumns(String propertyName) throws QueryException,
UnsupportedOperationException {
- if ( "component".equals( propertyName ) ) {
- return new String[] { "comp_1", "comp_2" };
- }
- else if ( "component.prop1".equals( propertyName ) ) {
- return new String[] { "comp_1" };
- }
- else if ( "component.prop2".equals( propertyName ) ) {
- return new String[] { "comp_2" };
- }
- else if ( "property".equals( propertyName ) ) {
- return new String[] { "prop" };
- }
- throw new QueryException( "could not resolve property: " + propertyName );
- }
-
- public Type toType(String propertyName) throws QueryException {
- throw new UnsupportedOperationException( "toType(propertyName) not supported
here" );
- }
-
- public String[] toColumns(String alias, String propertyName) throws QueryException {
- throw new UnsupportedOperationException( "toColumns(alias,propertyName) not
supported here" );
- }
-
- public Type getType() {
- throw new UnsupportedOperationException( "getType() not supported here" );
- }
- };
-
- public static final ColumnMapper STANDARD_MAPPER = new ColumnMapper() {
- public String[] map(String reference) {
- return STANDARD_PROPERTY_MAPPING.toColumns( reference );
- }
- };
-
- public OrderByParserTest() {
- }
-
- public OrderByParserTest(String name) {
- super( name );
- }
-
- public void testSQLReferences() {
- String fragment = "sql asc, sql desc";
- CommonTree tree = parse( fragment );
-
- assertRootStructure( tree, 2 );
-
- Tree firstSortSpec = tree.getChild( 0 );
- assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec );
- assertEquals( 2, firstSortSpec.getChildCount() );
- assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
- assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
- assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
- assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
- assertEquals( "sql", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
- assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
- assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
-
- Tree secondSortSpec = tree.getChild( 1 );
- assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
- assertEquals( 2, secondSortSpec.getChildCount() );
- assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
- assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
- assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
- assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
- assertEquals( "sql", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
- assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
- assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
- }
-
- public void testQuotedSQLReferences() {
- String fragment = "`sql` asc, `sql` desc";
- CommonTree tree = parse( fragment );
-
- assertRootStructure( tree, 2 );
-
- Tree firstSortSpec = tree.getChild( 0 );
- assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
- assertEquals( 2, firstSortSpec.getChildCount() );
- assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
- assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
- assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
- assertTokenType( HQLLexer.QUOTED_IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 )
);
- assertEquals( "`sql`", firstSortSpec.getChild( 0 ).getChild( 1 ).getText()
);
- assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
- assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
-
- Tree secondSortSpec = tree.getChild( 1 );
- assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
- assertEquals( 2, secondSortSpec.getChildCount() );
- assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
- assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
- assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
- assertTokenType( HQLLexer.QUOTED_IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 )
);
- assertEquals( "`sql`", secondSortSpec.getChild( 0 ).getChild( 1 ).getText()
);
- assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
- assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
- }
-
- public void testPropertyReference() {
- String fragment = "property asc, property desc";
- CommonTree tree = parse( fragment );
-
- assertRootStructure( tree, 2 );
-
- Tree firstSortSpec = tree.getChild( 0 );
- assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
- assertEquals( 2, firstSortSpec.getChildCount() );
- assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
- assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
- assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
- assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
- assertEquals( "prop", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
- assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
- assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
-
- Tree secondSortSpec = tree.getChild( 1 );
- assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
- assertEquals( 2, secondSortSpec.getChildCount() );
- assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
- assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
- assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
- assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
- assertEquals( "prop", secondSortSpec.getChild( 0 ).getChild( 1 ).getText()
);
- assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
- assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
- }
-
- public void testFunctionReference() {
- String fragment = "upper(sql) asc, lower(sql) desc";
- CommonTree tree = parse( fragment );
-
- assertRootStructure( tree, 2 );
-
- Tree firstSortSpec = tree.getChild( 0 );
- assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
- assertEquals( 2, firstSortSpec.getChildCount() );
- assertTokenType( HQLLexer.UPPER, firstSortSpec.getChild( 0 ) );
- assertEquals( 1, firstSortSpec.getChild( 0 ).getChildCount() );
- assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ).getChild( 0 ) );
- assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 0
).getChild( 1 ) );
- assertEquals( "sql", firstSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1
).getText() );
- assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
-
- Tree secondSortSpec = tree.getChild( 1 );
- assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
- assertEquals( 2, secondSortSpec.getChildCount() );
- assertTokenType( HQLLexer.LOWER, secondSortSpec.getChild( 0 ) );
- assertEquals( 1, secondSortSpec.getChild( 0 ).getChildCount() );
- assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ).getChild( 0 ) );
- assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 0
).getChild( 1 ) );
- assertEquals( "sql", secondSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1
).getText() );
- assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
- }
-
- protected CommonTree parse(String orderByFragment) {
- final Dialect dialect = new HSQLDialect();
- final SQLFunction myFunction = new SQLFunctionTemplate( Hibernate.STRING,
"myFunction($1)" );
- final SQLFunctionRegistry functionRegistry = new SQLFunctionRegistry( dialect,
Collections.singletonMap( "myFunction", myFunction ) );
- return parse(
- orderByFragment,
- new TranslationContext() {
- public SessionFactoryImplementor getSessionFactory() {
- return null;
- }
-
- public Dialect getDialect() {
- return dialect;
- }
-
- public SQLFunctionRegistry getSqlFunctionRegistry() {
- return functionRegistry;
- }
-
- public ColumnMapper getColumnMapper() {
- return STANDARD_MAPPER;
- }
- }
- );
- }
-
- private static final TreePrinter TREE_PRINTER = new TreePrinter( HQLLexer.class );
-
- protected CommonTree parse(String orderByFragment, TranslationContext context) {
- try {
- HQLLexer lexer = new HQLLexer( new ANTLRStringStream( orderByFragment ) );
- OrderByFragmentParser parser = new OrderByFragmentParser( new CommonTokenStream( lexer
), context );
- CommonTree rtn = parser.orderByFragment().tree;
- // temp
- System.out.println(
- TREE_PRINTER.renderAsString( rtn, "fragment" )
- );
- return rtn;
- }
- catch ( HibernateException e ) {
- throw e;
- }
- catch ( Throwable t ) {
- throw new HibernateException( "Unable to parse order-by fragment", t );
- }
- }
-
- private static final Map<Integer,String> tokenNameMap = (
Map<Integer,String> ) ASTUtil.generateTokenNameCache( HQLLexer.class );
-
- public void assertTokenType(int expected, int actual) {
- if ( expected != actual ) {
- throw new AssertionFailedError(
- "expected:<"+ tokenNameMap.get( expected ) +"> but
was:<"+ tokenNameMap.get( actual ) +">"
- );
- }
- }
-
- public void assertTokenType(int expected, Tree tree) {
- if ( tree == null ) {
- throw new AssertionFailedError(
- "expected:<"+ tokenNameMap.get( expected ) +"> but
was:<null>"
- );
- }
- assertTokenType( expected, tree.getType() );
- }
-
- public void assertRootStructure(Tree tree, int expectedSortSpecCount) {
- assertTokenType( HQLLexer.ORDER_BY, tree.getType() );
- assertEquals( expectedSortSpecCount, tree.getChildCount() );
- }
-}
Added:
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java
===================================================================
---
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java
(rev 0)
+++
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java 2009-05-01
20:26:15 UTC (rev 16500)
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.sql.ast.origin.ordering;
+
+import java.util.Collections;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.persister.entity.PropertyMapping;
+import org.hibernate.QueryException;
+import org.hibernate.Hibernate;
+import org.hibernate.HibernateException;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.dialect.function.SQLFunctionRegistry;
+import org.hibernate.dialect.function.SQLFunction;
+import org.hibernate.dialect.function.SQLFunctionTemplate;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.sql.ast.util.ASTUtil;
+import org.hibernate.sql.ast.util.TreePrinter;
+import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
+import org.hibernate.sql.Template;
+import org.hibernate.type.Type;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.tree.Tree;
+import org.antlr.runtime.tree.CommonTree;
+
+/**
+ * Assertions against the structures generated by various paths of the
"order-by" mapping fragment parser.
+ *
+ * @author Steve Ebersole
+ */
+public class OrderByParserTest extends TestCase {
+ public static final PropertyMapping STANDARD_PROPERTY_MAPPING = new PropertyMapping() {
+ public String[] toColumns(String propertyName) throws QueryException,
UnsupportedOperationException {
+ if ( "component".equals( propertyName ) ) {
+ return new String[] { "comp_1", "comp_2" };
+ }
+ else if ( "component.prop1".equals( propertyName ) ) {
+ return new String[] { "comp_1" };
+ }
+ else if ( "component.prop2".equals( propertyName ) ) {
+ return new String[] { "comp_2" };
+ }
+ else if ( "property".equals( propertyName ) ) {
+ return new String[] { "prop" };
+ }
+ throw new QueryException( "could not resolve property: " + propertyName );
+ }
+
+ public Type toType(String propertyName) throws QueryException {
+ throw new UnsupportedOperationException( "toType(propertyName) not supported
here" );
+ }
+
+ public String[] toColumns(String alias, String propertyName) throws QueryException {
+ throw new UnsupportedOperationException( "toColumns(alias,propertyName) not
supported here" );
+ }
+
+ public Type getType() {
+ throw new UnsupportedOperationException( "getType() not supported here" );
+ }
+ };
+
+ public static final ColumnMapper STANDARD_MAPPER = new ColumnMapper() {
+ public String[] map(String reference) {
+ return STANDARD_PROPERTY_MAPPING.toColumns( reference );
+ }
+ };
+
+ public OrderByParserTest() {
+ }
+
+ public OrderByParserTest(String name) {
+ super( name );
+ }
+
+ public void testSQLReferences() {
+ String fragment = "sql asc, sql desc";
+ CommonTree tree = parse( fragment );
+
+ assertRootStructure( tree, 2 );
+
+ Tree firstSortSpec = tree.getChild( 0 );
+ assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec );
+ assertEquals( 2, firstSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
+ assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
+ assertEquals( "sql", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+ assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
+ assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+ Tree secondSortSpec = tree.getChild( 1 );
+ assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+ assertEquals( 2, secondSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
+ assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
+ assertEquals( "sql", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+ assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
+ assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+ }
+
+ public void testQuotedSQLReferences() {
+ String fragment = "`sql` asc, `sql` desc";
+ CommonTree tree = parse( fragment );
+
+ assertRootStructure( tree, 2 );
+
+ Tree firstSortSpec = tree.getChild( 0 );
+ assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
+ assertEquals( 2, firstSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
+ assertTokenType( HQLLexer.QUOTED_IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 )
);
+ assertEquals( "`sql`", firstSortSpec.getChild( 0 ).getChild( 1 ).getText()
);
+ assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
+ assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+ Tree secondSortSpec = tree.getChild( 1 );
+ assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+ assertEquals( 2, secondSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
+ assertTokenType( HQLLexer.QUOTED_IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 )
);
+ assertEquals( "`sql`", secondSortSpec.getChild( 0 ).getChild( 1 ).getText()
);
+ assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
+ assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+ }
+
+ public void testPropertyReference() {
+ String fragment = "property asc, property desc";
+ CommonTree tree = parse( fragment );
+
+ assertRootStructure( tree, 2 );
+
+ Tree firstSortSpec = tree.getChild( 0 );
+ assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
+ assertEquals( 2, firstSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
+ assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
+ assertEquals( "prop", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+ assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
+ assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+ Tree secondSortSpec = tree.getChild( 1 );
+ assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+ assertEquals( 2, secondSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText()
);
+ assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
+ assertEquals( "prop", secondSortSpec.getChild( 0 ).getChild( 1 ).getText()
);
+ assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
+ assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+ }
+
+ public void testFunctionReference() {
+ String fragment = "upper(sql) asc, lower(sql) desc";
+ CommonTree tree = parse( fragment );
+
+ assertRootStructure( tree, 2 );
+
+ Tree firstSortSpec = tree.getChild( 0 );
+ assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
+ assertEquals( 2, firstSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.UPPER, firstSortSpec.getChild( 0 ) );
+ assertEquals( 1, firstSortSpec.getChild( 0 ).getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 0
).getChild( 1 ) );
+ assertEquals( "sql", firstSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1
).getText() );
+ assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+ Tree secondSortSpec = tree.getChild( 1 );
+ assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+ assertEquals( 2, secondSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.LOWER, secondSortSpec.getChild( 0 ) );
+ assertEquals( 1, secondSortSpec.getChild( 0 ).getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 0
).getChild( 1 ) );
+ assertEquals( "sql", secondSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1
).getText() );
+ assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+ }
+
+ protected CommonTree parse(String orderByFragment) {
+ final Dialect dialect = new HSQLDialect();
+ final SQLFunction myFunction = new SQLFunctionTemplate( Hibernate.STRING,
"myFunction($1)" );
+ final SQLFunctionRegistry functionRegistry = new SQLFunctionRegistry( dialect,
Collections.singletonMap( "myFunction", myFunction ) );
+ return parse(
+ orderByFragment,
+ new TranslationContext() {
+ public SessionFactoryImplementor getSessionFactory() {
+ return null;
+ }
+
+ public Dialect getDialect() {
+ return dialect;
+ }
+
+ public SQLFunctionRegistry getSqlFunctionRegistry() {
+ return functionRegistry;
+ }
+
+ public ColumnMapper getColumnMapper() {
+ return STANDARD_MAPPER;
+ }
+ }
+ );
+ }
+
+ private static final TreePrinter TREE_PRINTER = new TreePrinter( HQLLexer.class );
+
+ protected CommonTree parse(String orderByFragment, TranslationContext context) {
+ try {
+ HQLLexer lexer = new HQLLexer( new ANTLRStringStream( orderByFragment ) );
+ ContextualOrderByParser parser = new ContextualOrderByParser( new CommonTokenStream(
lexer ), context );
+ CommonTree rtn = parser.orderByFragment().tree;
+ // temp
+ System.out.println(
+ TREE_PRINTER.renderAsString( rtn, "fragment" )
+ );
+ return rtn;
+ }
+ catch ( HibernateException e ) {
+ throw e;
+ }
+ catch ( Throwable t ) {
+ throw new HibernateException( "Unable to parse order-by fragment", t );
+ }
+ }
+
+ private static final Map<Integer,String> tokenNameMap = (
Map<Integer,String> ) ASTUtil.generateTokenNameCache( HQLLexer.class );
+
+ public void assertTokenType(int expected, int actual) {
+ if ( expected != actual ) {
+ throw new AssertionFailedError(
+ "expected:<"+ tokenNameMap.get( expected ) +"> but
was:<"+ tokenNameMap.get( actual ) +">"
+ );
+ }
+ }
+
+ public void assertTokenType(int expected, Tree tree) {
+ if ( tree == null ) {
+ throw new AssertionFailedError(
+ "expected:<"+ tokenNameMap.get( expected ) +"> but
was:<null>"
+ );
+ }
+ assertTokenType( expected, tree.getType() );
+ }
+
+ public void assertRootStructure(Tree tree, int expectedSortSpecCount) {
+ assertTokenType( HQLLexer.ORDER_BY, tree.getType() );
+ assertEquals( expectedSortSpecCount, tree.getChildCount() );
+ }
+}