Polishing.
Align HQL parsing with Hibernate to accept generic function names. Also, align literals, add missing expression grammar for ID, NATURALID, VERSION, TYPE, FK and remove parser rules interfering with undesired parsing results. Add missing literals. See #3711
This commit is contained in:
@@ -25,7 +25,9 @@ grammar Hql;
|
||||
* management of complex rules in the generated Visitor. Finally, there are labels applied to rule elements (op=('+'|'-')
|
||||
* to simplify the processing.
|
||||
*
|
||||
* @author Greg Turnquist, Yannick Brandt
|
||||
* @author Greg Turnquist
|
||||
* @author Mark Paluch
|
||||
* @author Yannick Brandt
|
||||
* @since 3.1
|
||||
*/
|
||||
}
|
||||
@@ -307,9 +309,10 @@ setOperator
|
||||
// Literals
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-literals
|
||||
literal
|
||||
: NULL
|
||||
: STRING_LITERAL
|
||||
| JAVA_STRING_LITERAL
|
||||
| NULL
|
||||
| booleanLiteral
|
||||
| stringLiteral
|
||||
| numericLiteral
|
||||
| dateTimeLiteral
|
||||
| binaryLiteral
|
||||
@@ -321,19 +324,16 @@ booleanLiteral
|
||||
| FALSE
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-string-literals
|
||||
stringLiteral
|
||||
: STRINGLITERAL
|
||||
| JAVASTRINGLITERAL
|
||||
| CHARACTER
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-numeric-literals
|
||||
numericLiteral
|
||||
: INTEGER_LITERAL
|
||||
| FLOAT_LITERAL
|
||||
| HEXLITERAL
|
||||
;
|
||||
: INTEGER_LITERAL
|
||||
| LONG_LITERAL
|
||||
| BIG_INTEGER_LITERAL
|
||||
| FLOAT_LITERAL
|
||||
| DOUBLE_LITERAL
|
||||
| BIG_DECIMAL_LITERAL
|
||||
| HEX_LITERAL
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-datetime-literals
|
||||
dateTimeLiteral
|
||||
@@ -399,7 +399,7 @@ dateOrTimeField
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-binary-literals
|
||||
binaryLiteral
|
||||
: BINARY_LITERAL
|
||||
| '{' HEXLITERAL (',' HEXLITERAL)* '}'
|
||||
| '{' HEX_LITERAL (',' HEX_LITERAL)* '}'
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-enum-literals
|
||||
@@ -433,19 +433,29 @@ expression
|
||||
;
|
||||
|
||||
primaryExpression
|
||||
: caseList # CaseExpression
|
||||
| literal # LiteralExpression
|
||||
| parameter # ParameterExpression
|
||||
| function # FunctionExpression
|
||||
| generalPathFragment # GeneralPathExpression
|
||||
: caseList # CaseExpression
|
||||
| literal # LiteralExpression
|
||||
| parameter # ParameterExpression
|
||||
| entityTypeReference # EntityTypeExpression
|
||||
| entityIdReference # EntityIdExpression
|
||||
| entityVersionReference # EntityVersionExpression
|
||||
| entityNaturalIdReference # EntityNaturalIdExpression
|
||||
| syntacticDomainPath pathContinuation? # SyntacticPathExpression
|
||||
| function # FunctionExpression
|
||||
| generalPathFragment # GeneralPathExpression
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-Datetime-arithmetic
|
||||
// TBD
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-path-expressions
|
||||
/**
|
||||
* A much more complicated path expression involving operators and functions
|
||||
*
|
||||
* A path which needs to be resolved semantically. This recognizes
|
||||
* any path-like structure. Generally, the path is semantically
|
||||
* interpreted by the consumer of the parse-tree. However, there
|
||||
* are certain cases where we can syntactically recognize a navigable
|
||||
* path; see 'syntacticNavigablePath' rule
|
||||
*/
|
||||
path
|
||||
: treatedPath pathContinutation?
|
||||
: syntacticDomainPath pathContinuation?
|
||||
| generalPathFragment
|
||||
;
|
||||
|
||||
@@ -457,14 +467,120 @@ indexedPathAccessFragment
|
||||
: '[' expression ']' ('.' generalPathFragment)?
|
||||
;
|
||||
|
||||
/**
|
||||
* A simple path expression
|
||||
*
|
||||
* - a reference to an identification variable (not case-sensitive),
|
||||
* - followed by a list of period-separated identifiers (case-sensitive)
|
||||
*/
|
||||
simplePath
|
||||
: identifier simplePathElement*
|
||||
;
|
||||
|
||||
/**
|
||||
* An element of a simple path expression: a period, and an identifier (case-sensitive)
|
||||
*/
|
||||
simplePathElement
|
||||
: '.' identifier
|
||||
;
|
||||
|
||||
/**
|
||||
* A continuation of a path expression "broken" by an operator or function
|
||||
*/
|
||||
pathContinuation
|
||||
: '.' simplePath
|
||||
;
|
||||
|
||||
/**
|
||||
* The special function 'type()'
|
||||
*/
|
||||
entityTypeReference
|
||||
: TYPE '(' (path | parameter) ')'
|
||||
;
|
||||
|
||||
/**
|
||||
* The special function 'id()'
|
||||
*/
|
||||
entityIdReference
|
||||
: ID '(' path ')' pathContinuation?
|
||||
;
|
||||
|
||||
/**
|
||||
* The special function 'version()'
|
||||
*/
|
||||
entityVersionReference
|
||||
: VERSION '(' path ')'
|
||||
;
|
||||
|
||||
/**
|
||||
* The special function 'naturalid()'
|
||||
*/
|
||||
entityNaturalIdReference
|
||||
: NATURALID '(' path ')' pathContinuation?
|
||||
;
|
||||
|
||||
/**
|
||||
* An operator or function that may occur within a path expression
|
||||
*
|
||||
* Rule for cases where we syntactically know that the path is a
|
||||
* "domain path" because it is one of these special cases:
|
||||
*
|
||||
* * TREAT( path )
|
||||
* * ELEMENTS( path )
|
||||
* * INDICES( path )
|
||||
* * VALUE( path )
|
||||
* * KEY( path )
|
||||
* * path[ selector ]
|
||||
* * ARRAY_GET( embeddableArrayPath, index ).path
|
||||
* * COALESCE( array1, array2 )[ selector ].path
|
||||
*/
|
||||
syntacticDomainPath
|
||||
: treatedNavigablePath
|
||||
| collectionValueNavigablePath
|
||||
| mapKeyNavigablePath
|
||||
| simplePath indexedPathAccessFragment
|
||||
| simplePath slicedPathAccessFragment
|
||||
| toOneFkReference
|
||||
| function pathContinuation
|
||||
| function indexedPathAccessFragment pathContinuation?
|
||||
| function slicedPathAccessFragment
|
||||
;
|
||||
|
||||
/**
|
||||
* The slice operator to obtain elements between the lower and upper bound.
|
||||
*/
|
||||
slicedPathAccessFragment
|
||||
: '[' expression ':' expression ']'
|
||||
;
|
||||
|
||||
/**
|
||||
* A 'treat()' function that "breaks" a path expression
|
||||
*/
|
||||
treatedNavigablePath
|
||||
: TREAT '(' path AS simplePath ')' pathContinuation?
|
||||
;
|
||||
|
||||
/**
|
||||
* A 'value()' function that "breaks" a path expression
|
||||
*/
|
||||
collectionValueNavigablePath
|
||||
: elementValueQuantifier '(' path ')' pathContinuation?
|
||||
;
|
||||
|
||||
/**
|
||||
* A 'key()' or 'index()' function that "breaks" a path expression
|
||||
*/
|
||||
mapKeyNavigablePath
|
||||
: indexKeyQuantifier '(' path ')' pathContinuation?
|
||||
;
|
||||
|
||||
/**
|
||||
* The special function 'fk()'
|
||||
*/
|
||||
toOneFkReference
|
||||
: FK '(' path ')'
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-case-expressions
|
||||
caseList
|
||||
: simpleCaseExpression
|
||||
@@ -511,7 +627,7 @@ function
|
||||
*/
|
||||
standardFunction
|
||||
: castFunction
|
||||
| treatedPath
|
||||
| treatedNavigablePath
|
||||
| extractFunction
|
||||
| truncFunction
|
||||
| formatFunction
|
||||
@@ -587,7 +703,7 @@ trimSpecification
|
||||
;
|
||||
|
||||
trimCharacter
|
||||
: stringLiteral
|
||||
: STRING_LITERAL
|
||||
| parameter
|
||||
;
|
||||
|
||||
@@ -604,7 +720,7 @@ padSpecification
|
||||
;
|
||||
|
||||
padCharacter
|
||||
: stringLiteral
|
||||
: STRING_LITERAL
|
||||
;
|
||||
|
||||
padLength
|
||||
@@ -756,7 +872,7 @@ rollup
|
||||
* see 'Dialect.appendDatetimeFormat()'
|
||||
*/
|
||||
format
|
||||
: stringLiteral
|
||||
: STRING_LITERAL
|
||||
;
|
||||
|
||||
/**
|
||||
@@ -785,7 +901,7 @@ jpaNonstandardFunction
|
||||
* The name of a user-defined or native database function, given as a quoted string
|
||||
*/
|
||||
jpaNonstandardFunctionName
|
||||
: stringLiteral
|
||||
: STRING_LITERAL
|
||||
| identifier
|
||||
;
|
||||
|
||||
@@ -799,7 +915,7 @@ columnFunction
|
||||
* The function name, followed by a parenthesized list of ','-separated expressions
|
||||
*/
|
||||
genericFunction
|
||||
: genericFunctionName '(' (genericFunctionArguments | ASTERISK)? ')' pathContinutation?
|
||||
: genericFunctionName '(' (genericFunctionArguments | ASTERISK)? ')' pathContinuation?
|
||||
nthSideClause? nullsClause? withinGroupClause? filterClause? overClause?
|
||||
;
|
||||
|
||||
@@ -984,15 +1100,6 @@ frameExclusion
|
||||
| EXCLUDE NO OTHERS
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-treat-type
|
||||
treatedPath
|
||||
: TREAT '(' path AS simplePath')' pathContinutation?
|
||||
;
|
||||
|
||||
pathContinutation
|
||||
: '.' simplePath
|
||||
;
|
||||
|
||||
// Predicates
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-conditional-expressions
|
||||
predicate
|
||||
@@ -1027,6 +1134,16 @@ elementsValuesQuantifier
|
||||
| VALUES
|
||||
;
|
||||
|
||||
elementValueQuantifier
|
||||
: ELEMENT
|
||||
| VALUE
|
||||
;
|
||||
|
||||
indexKeyQuantifier
|
||||
: INDEX
|
||||
| KEY
|
||||
;
|
||||
|
||||
indicesKeysQuantifier
|
||||
: INDICES
|
||||
| KEYS
|
||||
@@ -1045,7 +1162,7 @@ betweenExpression
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-like-predicate
|
||||
stringPatternMatching
|
||||
: expression NOT? (LIKE | ILIKE) expression (ESCAPE (stringLiteral|parameter))?
|
||||
: expression NOT? (LIKE | ILIKE) expression (ESCAPE (STRING_LITERAL | JAVA_STRING_LITERAL |parameter))?
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-elements-indices
|
||||
@@ -1097,9 +1214,12 @@ parameterOrNumberLiteral
|
||||
| numericLiteral
|
||||
;
|
||||
|
||||
/**
|
||||
* An identification variable (an entity alias)
|
||||
*/
|
||||
variable
|
||||
: AS identifier
|
||||
| reservedWord
|
||||
| nakedIdentifier
|
||||
;
|
||||
|
||||
parameter
|
||||
@@ -1111,16 +1231,9 @@ entityName
|
||||
: identifier ('.' identifier)*
|
||||
;
|
||||
|
||||
identifier
|
||||
: reservedWord
|
||||
;
|
||||
|
||||
functionName
|
||||
: reservedWord ('.' reservedWord)*
|
||||
;
|
||||
|
||||
reservedWord
|
||||
: IDENTIFICATION_VARIABLE
|
||||
nakedIdentifier
|
||||
: IDENTIFIER
|
||||
| QUOTED_IDENTIFIER
|
||||
| f=(ALL
|
||||
| AND
|
||||
| ANY
|
||||
@@ -1133,8 +1246,10 @@ reservedWord
|
||||
| BY
|
||||
| CASE
|
||||
| CAST
|
||||
| CEILING
|
||||
| COLLATE
|
||||
| COLUMN
|
||||
| CONFLICT
|
||||
| CONSTRAINT
|
||||
| CONTAINS
|
||||
| COUNT
|
||||
| CROSS
|
||||
@@ -1153,6 +1268,7 @@ reservedWord
|
||||
| DEPTH
|
||||
| DESC
|
||||
| DISTINCT
|
||||
| DO
|
||||
| ELEMENT
|
||||
| ELEMENTS
|
||||
| ELSE
|
||||
@@ -1166,18 +1282,15 @@ reservedWord
|
||||
| EXCEPT
|
||||
| EXCLUDE
|
||||
| EXISTS
|
||||
| EXP
|
||||
| EXTRACT
|
||||
| FALSE
|
||||
| FETCH
|
||||
| FILTER
|
||||
| FIRST
|
||||
| FLOOR
|
||||
| FK
|
||||
| FOLLOWING
|
||||
| FOR
|
||||
| FORMAT
|
||||
| FROM
|
||||
| FULL
|
||||
| FUNCTION
|
||||
| GROUP
|
||||
| GROUPS
|
||||
@@ -1187,10 +1300,9 @@ reservedWord
|
||||
| IGNORE
|
||||
| ILIKE
|
||||
| IN
|
||||
| INCLUDES
|
||||
| INDEX
|
||||
| INCLUDES
|
||||
| INDICES
|
||||
| INNER
|
||||
| INSERT
|
||||
| INSTANT
|
||||
| INTERSECT
|
||||
@@ -1199,15 +1311,14 @@ reservedWord
|
||||
| IS
|
||||
| JOIN
|
||||
| KEY
|
||||
| KEYS
|
||||
| LAST
|
||||
| LATERAL
|
||||
| LEADING
|
||||
| LEFT
|
||||
| LIKE
|
||||
| LIMIT
|
||||
| LIST
|
||||
| LISTAGG
|
||||
| LN
|
||||
| LOCAL
|
||||
| LOCAL_DATE
|
||||
| LOCAL_DATETIME
|
||||
@@ -1231,6 +1342,7 @@ reservedWord
|
||||
| NEXT
|
||||
| NO
|
||||
| NOT
|
||||
| NOTHING
|
||||
| NULLS
|
||||
| OBJECT
|
||||
| OF
|
||||
@@ -1241,7 +1353,6 @@ reservedWord
|
||||
| OR
|
||||
| ORDER
|
||||
| OTHERS
|
||||
| OUTER
|
||||
| OVER
|
||||
| OVERFLOW
|
||||
| OVERLAY
|
||||
@@ -1250,7 +1361,6 @@ reservedWord
|
||||
| PERCENT
|
||||
| PLACING
|
||||
| POSITION
|
||||
| POWER
|
||||
| PRECEDING
|
||||
| QUARTER
|
||||
| RANGE
|
||||
@@ -1267,7 +1377,6 @@ reservedWord
|
||||
| SOME
|
||||
| SUBSTRING
|
||||
| SUM
|
||||
| TRUE
|
||||
| THEN
|
||||
| TIES
|
||||
| TIME
|
||||
@@ -1295,7 +1404,17 @@ reservedWord
|
||||
| WITH
|
||||
| WITHIN
|
||||
| WITHOUT
|
||||
| YEAR)
|
||||
| YEAR
|
||||
| ZONED)
|
||||
;
|
||||
|
||||
identifier
|
||||
: nakedIdentifier
|
||||
| FULL
|
||||
| INNER
|
||||
| LEFT
|
||||
| OUTER
|
||||
| RIGHT
|
||||
;
|
||||
|
||||
/*
|
||||
@@ -1334,14 +1453,20 @@ fragment X: 'x' | 'X';
|
||||
fragment Y: 'y' | 'Y';
|
||||
fragment Z: 'z' | 'Z';
|
||||
|
||||
ASTERISK : '*';
|
||||
|
||||
// The following are reserved identifiers:
|
||||
|
||||
ID : I D;
|
||||
VERSION : V E R S I O N;
|
||||
VERSIONED : V E R S I O N E D;
|
||||
NATURALID : N A T U R A L I D;
|
||||
FK : F K;
|
||||
ALL : A L L;
|
||||
AND : A N D;
|
||||
ANY : A N Y;
|
||||
AS : A S;
|
||||
ASC : A S C;
|
||||
ASTERISK : '*';
|
||||
AVG : A V G;
|
||||
BETWEEN : B E T W E E N;
|
||||
BOTH : B O T H;
|
||||
@@ -1349,7 +1474,6 @@ BREADTH : B R E A D T H;
|
||||
BY : B Y;
|
||||
CASE : C A S E;
|
||||
CAST : C A S T;
|
||||
CEILING : C E I L I N G;
|
||||
COLLATE : C O L L A T E;
|
||||
COLUMN : C O L U M N;
|
||||
CONFLICT : C O N F L I C T;
|
||||
@@ -1386,14 +1510,10 @@ EVERY : E V E R Y;
|
||||
EXCEPT : E X C E P T;
|
||||
EXCLUDE : E X C L U D E;
|
||||
EXISTS : E X I S T S;
|
||||
EXP : E X P;
|
||||
EXTRACT : E X T R A C T;
|
||||
FALSE : F A L S E;
|
||||
FETCH : F E T C H;
|
||||
FILTER : F I L T E R;
|
||||
FIRST : F I R S T;
|
||||
FK : F K;
|
||||
FLOOR : F L O O R;
|
||||
FOLLOWING : F O L L O W I N G;
|
||||
FOR : F O R;
|
||||
FORMAT : F O R M A T;
|
||||
@@ -1404,7 +1524,6 @@ GROUP : G R O U P;
|
||||
GROUPS : G R O U P S;
|
||||
HAVING : H A V I N G;
|
||||
HOUR : H O U R;
|
||||
ID : I D;
|
||||
IGNORE : I G N O R E;
|
||||
ILIKE : I L I K E;
|
||||
IN : I N;
|
||||
@@ -1429,7 +1548,6 @@ LIKE : L I K E;
|
||||
LIMIT : L I M I T;
|
||||
LIST : L I S T;
|
||||
LISTAGG : L I S T A G G;
|
||||
LN : L N;
|
||||
LOCAL : L O C A L;
|
||||
LOCAL_DATE : L O C A L '_' D A T E ;
|
||||
LOCAL_DATETIME : L O C A L '_' D A T E T I M E;
|
||||
@@ -1448,13 +1566,11 @@ MININDEX : M I N I N D E X;
|
||||
MINUTE : M I N U T E;
|
||||
MONTH : M O N T H;
|
||||
NANOSECOND : N A N O S E C O N D;
|
||||
NATURALID : N A T U R A L I D;
|
||||
NEW : N E W;
|
||||
NEXT : N E X T;
|
||||
NO : N O;
|
||||
NOT : N O T;
|
||||
NOTHING : N O T H I N G;
|
||||
NULL : N U L L;
|
||||
NULLS : N U L L S;
|
||||
OBJECT : O B J E C T;
|
||||
OF : O F;
|
||||
@@ -1474,7 +1590,6 @@ PARTITION : P A R T I T I O N;
|
||||
PERCENT : P E R C E N T;
|
||||
PLACING : P L A C I N G;
|
||||
POSITION : P O S I T I O N;
|
||||
POWER : P O W E R;
|
||||
PRECEDING : P R E C E D I N G;
|
||||
QUARTER : Q U A R T E R;
|
||||
RANGE : R A N G E;
|
||||
@@ -1501,7 +1616,6 @@ TO : T O;
|
||||
TRAILING : T R A I L I N G;
|
||||
TREAT : T R E A T;
|
||||
TRIM : T R I M;
|
||||
TRUE : T R U E;
|
||||
TRUNC : T R U N C;
|
||||
TRUNCATE : T R U N C A T E;
|
||||
TYPE : T Y P E;
|
||||
@@ -1511,8 +1625,6 @@ UPDATE : U P D A T E;
|
||||
USING : U S I N G;
|
||||
VALUE : V A L U E;
|
||||
VALUES : V A L U E S;
|
||||
VERSION : V E R S I O N;
|
||||
VERSIONED : V E R S I O N E D;
|
||||
WEEK : W E E K;
|
||||
WHEN : W H E N;
|
||||
WHERE : W H E R E;
|
||||
@@ -1520,20 +1632,102 @@ WITH : W I T H;
|
||||
WITHIN : W I T H I N;
|
||||
WITHOUT : W I T H O U T;
|
||||
YEAR : Y E A R;
|
||||
ZONED : Z O N E D;
|
||||
|
||||
NULL : N U L L;
|
||||
TRUE : T R U E;
|
||||
FALSE : F A L S E;
|
||||
|
||||
fragment
|
||||
INTEGER_NUMBER
|
||||
: DIGIT+
|
||||
;
|
||||
|
||||
fragment
|
||||
FLOATING_POINT_NUMBER
|
||||
: DIGIT+ '.' DIGIT* EXPONENT?
|
||||
| '.' DIGIT+ EXPONENT?
|
||||
| DIGIT+ EXPONENT
|
||||
| DIGIT+
|
||||
;
|
||||
|
||||
fragment
|
||||
EXPONENT : [eE] [+-]? DIGIT+;
|
||||
|
||||
fragment INTEGER_NUMBER : ('0' .. '9')+ ;
|
||||
fragment FLOAT_NUMBER : INTEGER_NUMBER+ '.'? INTEGER_NUMBER* (E [+-]? INTEGER_NUMBER)? ;
|
||||
fragment HEX_DIGIT : [0-9a-fA-F];
|
||||
|
||||
fragment SINGLE_QUOTE : '\'';
|
||||
fragment DOUBLE_QUOTE : '"';
|
||||
|
||||
STRING_LITERAL : SINGLE_QUOTE ( SINGLE_QUOTE SINGLE_QUOTE | ~('\'') )* SINGLE_QUOTE;
|
||||
|
||||
JAVA_STRING_LITERAL
|
||||
: DOUBLE_QUOTE ( ESCAPE_SEQUENCE | ~('"') )* DOUBLE_QUOTE
|
||||
| [jJ] SINGLE_QUOTE ( ESCAPE_SEQUENCE | ~('\'') )* SINGLE_QUOTE
|
||||
| [jJ] DOUBLE_QUOTE ( ESCAPE_SEQUENCE | ~('\'') )* DOUBLE_QUOTE
|
||||
;
|
||||
|
||||
INTEGER_LITERAL : INTEGER_NUMBER ('_' INTEGER_NUMBER)*;
|
||||
|
||||
LONG_LITERAL : INTEGER_NUMBER ('_' INTEGER_NUMBER)* LONG_SUFFIX;
|
||||
|
||||
FLOAT_LITERAL : FLOATING_POINT_NUMBER FLOAT_SUFFIX;
|
||||
|
||||
DOUBLE_LITERAL : FLOATING_POINT_NUMBER DOUBLE_SUFFIX?;
|
||||
|
||||
BIG_INTEGER_LITERAL : INTEGER_NUMBER BIG_INTEGER_SUFFIX;
|
||||
|
||||
BIG_DECIMAL_LITERAL : FLOATING_POINT_NUMBER BIG_DECIMAL_SUFFIX;
|
||||
|
||||
HEX_LITERAL : '0' [xX] HEX_DIGIT+ LONG_SUFFIX?;
|
||||
|
||||
CHARACTER : '\'' (~ ('\'' | '\\' )) '\'' ;
|
||||
STRINGLITERAL : '\'' ('\'' '\'' | ~('\''))* '\'' ;
|
||||
JAVASTRINGLITERAL : '"' ( ('\\' [btnfr"']) | ~('"'))* '"';
|
||||
INTEGER_LITERAL : INTEGER_NUMBER (L | B I)? ;
|
||||
FLOAT_LITERAL : FLOAT_NUMBER (D | F | B D)?;
|
||||
HEXLITERAL : '0' X HEX_DIGIT+ ;
|
||||
BINARY_LITERAL : [xX] '\'' HEX_DIGIT+ '\''
|
||||
| [xX] '"' HEX_DIGIT+ '"'
|
||||
;
|
||||
|
||||
IDENTIFICATION_VARIABLE : ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '$' | '_') ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '0' .. '9' | '$' | '_')* ;
|
||||
fragment
|
||||
LETTER : [a-zA-Z\u0080-\ufffe_$];
|
||||
|
||||
fragment
|
||||
DIGIT : [0-9];
|
||||
|
||||
fragment
|
||||
LONG_SUFFIX : [lL];
|
||||
|
||||
fragment
|
||||
FLOAT_SUFFIX : [fF];
|
||||
|
||||
fragment
|
||||
DOUBLE_SUFFIX : [dD];
|
||||
|
||||
fragment
|
||||
BIG_DECIMAL_SUFFIX : [bB] [dD];
|
||||
|
||||
fragment
|
||||
BIG_INTEGER_SUFFIX : [bB] [iI];
|
||||
|
||||
// Identifiers
|
||||
IDENTIFIER
|
||||
: LETTER (LETTER | DIGIT)*
|
||||
;
|
||||
|
||||
fragment
|
||||
BACKTICK : '`';
|
||||
|
||||
fragment BACKSLASH : '\\';
|
||||
|
||||
fragment
|
||||
UNICODE_ESCAPE
|
||||
: 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
|
||||
;
|
||||
|
||||
fragment
|
||||
ESCAPE_SEQUENCE
|
||||
: BACKSLASH [btnfr"']
|
||||
| BACKSLASH UNICODE_ESCAPE
|
||||
| BACKSLASH BACKSLASH
|
||||
;
|
||||
|
||||
QUOTED_IDENTIFIER
|
||||
: BACKTICK ( ESCAPE_SEQUENCE | '\\' BACKTICK | ~([`]) )* BACKTICK
|
||||
;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.springframework.data.jpa.repository.query.QueryTokens.TOKEN_COMMA;
|
||||
import static org.springframework.data.jpa.repository.query.QueryTokens.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -84,7 +84,7 @@ class HqlQueryIntrospector extends HqlBaseVisitor<Void> implements ParsedQueryIn
|
||||
}
|
||||
|
||||
private static String capturePrimaryAlias(VariableContext ctx) {
|
||||
return ((ctx).reservedWord() != null ? ctx.reservedWord() : ctx.identifier().reservedWord()).getText();
|
||||
return ((ctx).nakedIdentifier() != null ? ctx.nakedIdentifier() : ctx.identifier()).getText();
|
||||
}
|
||||
|
||||
private static List<QueryToken> captureSelectItems(List<HqlParser.SelectionContext> selections,
|
||||
|
||||
@@ -1032,8 +1032,10 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
return QueryRendererBuilder.from(QueryTokens.expression(ctx.NULL()));
|
||||
} else if (ctx.booleanLiteral() != null) {
|
||||
return visit(ctx.booleanLiteral());
|
||||
} else if (ctx.stringLiteral() != null) {
|
||||
return visit(ctx.stringLiteral());
|
||||
} else if (ctx.JAVA_STRING_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.expression(ctx.JAVA_STRING_LITERAL()));
|
||||
} else if (ctx.STRING_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.expression(ctx.STRING_LITERAL()));
|
||||
} else if (ctx.numericLiteral() != null) {
|
||||
return visit(ctx.numericLiteral());
|
||||
} else if (ctx.dateTimeLiteral() != null) {
|
||||
@@ -1057,27 +1059,23 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitStringLiteral(HqlParser.StringLiteralContext ctx) {
|
||||
|
||||
if (ctx.STRINGLITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.expression(ctx.STRINGLITERAL()));
|
||||
} else if (ctx.CHARACTER() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.expression(ctx.CHARACTER()));
|
||||
} else {
|
||||
return QueryTokenStream.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitNumericLiteral(HqlParser.NumericLiteralContext ctx) {
|
||||
|
||||
if (ctx.INTEGER_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.INTEGER_LITERAL()));
|
||||
} else if (ctx.LONG_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.LONG_LITERAL()));
|
||||
} else if (ctx.BIG_INTEGER_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.BIG_INTEGER_LITERAL()));
|
||||
} else if (ctx.FLOAT_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.FLOAT_LITERAL()));
|
||||
} else if (ctx.HEXLITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.HEXLITERAL()));
|
||||
} else if (ctx.DOUBLE_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.DOUBLE_LITERAL()));
|
||||
} else if (ctx.BIG_DECIMAL_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.BIG_DECIMAL_LITERAL()));
|
||||
} else if (ctx.HEX_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.HEX_LITERAL()));
|
||||
} else {
|
||||
return QueryTokenStream.empty();
|
||||
}
|
||||
@@ -1238,11 +1236,11 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
|
||||
if (ctx.BINARY_LITERAL() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.BINARY_LITERAL()));
|
||||
} else if (ctx.HEXLITERAL() != null) {
|
||||
} else if (ctx.HEX_LITERAL() != null) {
|
||||
|
||||
builder.append(TOKEN_OPEN_BRACE);
|
||||
|
||||
builder.append(QueryTokenStream.concat(ctx.HEXLITERAL(), it -> {
|
||||
builder.append(QueryTokenStream.concat(ctx.HEX_LITERAL(), it -> {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(it));
|
||||
}, TOKEN_COMMA));
|
||||
|
||||
@@ -1425,6 +1423,195 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
return visit(ctx.parameter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitEntityTypeExpression(HqlParser.EntityTypeExpressionContext ctx) {
|
||||
return visit(ctx.entityTypeReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitEntityIdExpression(HqlParser.EntityIdExpressionContext ctx) {
|
||||
return visit(ctx.entityIdReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitEntityVersionExpression(HqlParser.EntityVersionExpressionContext ctx) {
|
||||
return visit(ctx.entityVersionReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitEntityNaturalIdExpression(HqlParser.EntityNaturalIdExpressionContext ctx) {
|
||||
return visit(ctx.entityNaturalIdReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitSyntacticPathExpression(HqlParser.SyntacticPathExpressionContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.appendInline(visit(ctx.syntacticDomainPath()));
|
||||
|
||||
if (ctx.pathContinuation() != null) {
|
||||
builder.appendInline(visit(ctx.pathContinuation()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitPathContinuation(HqlParser.PathContinuationContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(TOKEN_DOT);
|
||||
builder.append(visit(ctx.simplePath()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitEntityTypeReference(HqlParser.EntityTypeReferenceContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(QueryTokens.token(ctx.TYPE()));
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
|
||||
if (ctx.path() != null) {
|
||||
builder.appendInline(visit(ctx.path()));
|
||||
}
|
||||
|
||||
if (ctx.parameter() != null) {
|
||||
builder.appendInline(visit(ctx.parameter()));
|
||||
}
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitEntityIdReference(HqlParser.EntityIdReferenceContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(QueryTokens.token(ctx.ID()));
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.appendInline(visit(ctx.path()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
|
||||
if (ctx.pathContinuation() != null) {
|
||||
builder.appendInline(visit(ctx.pathContinuation()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(QueryTokens.token(ctx.VERSION()));
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.appendInline(visit(ctx.path()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitEntityNaturalIdReference(HqlParser.EntityNaturalIdReferenceContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(QueryTokens.token(ctx.NATURALID()));
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.appendInline(visit(ctx.path()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
|
||||
if (ctx.pathContinuation() != null) {
|
||||
builder.appendInline(visit(ctx.pathContinuation()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitSyntacticDomainPath(HqlParser.SyntacticDomainPathContext ctx) {
|
||||
|
||||
if (ctx.treatedNavigablePath() != null) {
|
||||
return visit(ctx.treatedNavigablePath());
|
||||
}
|
||||
|
||||
if (ctx.collectionValueNavigablePath() != null) {
|
||||
return visit(ctx.collectionValueNavigablePath());
|
||||
}
|
||||
|
||||
if (ctx.mapKeyNavigablePath() != null) {
|
||||
return visit(ctx.mapKeyNavigablePath());
|
||||
}
|
||||
|
||||
if (ctx.toOneFkReference() != null) {
|
||||
return visit(ctx.toOneFkReference());
|
||||
}
|
||||
|
||||
if (ctx.function() != null) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(visit(ctx.function()));
|
||||
|
||||
if (ctx.indexedPathAccessFragment() != null) {
|
||||
builder.append(visit(ctx.indexedPathAccessFragment()));
|
||||
}
|
||||
|
||||
if (ctx.slicedPathAccessFragment() != null) {
|
||||
builder.append(visit(ctx.slicedPathAccessFragment()));
|
||||
}
|
||||
|
||||
if (ctx.pathContinuation() != null) {
|
||||
builder.append(visit(ctx.pathContinuation()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
if (ctx.indexedPathAccessFragment() != null) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(visit(ctx.simplePath()));
|
||||
builder.append(visit(ctx.indexedPathAccessFragment()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
if (ctx.slicedPathAccessFragment() != null) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(visit(ctx.simplePath()));
|
||||
builder.append(visit(ctx.slicedPathAccessFragment()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
return QueryRenderer.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitSlicedPathAccessFragment(HqlParser.SlicedPathAccessFragmentContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(TOKEN_OPEN_SQUARE_BRACKET);
|
||||
builder.appendInline(visit(ctx.expression(0)));
|
||||
builder.append(TOKEN_COLON);
|
||||
builder.appendInline(visit(ctx.expression(1)));
|
||||
builder.append(TOKEN_CLOSE_SQUARE_BRACKET);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitFunctionExpression(HqlParser.FunctionExpressionContext ctx) {
|
||||
return visit(ctx.function());
|
||||
@@ -1479,10 +1666,6 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
return visit(ctx.castFunction());
|
||||
}
|
||||
|
||||
if (ctx.treatedPath() != null) {
|
||||
return visit(ctx.treatedPath());
|
||||
}
|
||||
|
||||
if (ctx.extractFunction() != null) {
|
||||
return visit(ctx.extractFunction());
|
||||
}
|
||||
@@ -1634,7 +1817,7 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitPadCharacter(HqlParser.PadCharacterContext ctx) {
|
||||
return visit(ctx.stringLiteral());
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.STRING_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1908,7 +2091,7 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitFormat(HqlParser.FormatContext ctx) {
|
||||
return visit(ctx.stringLiteral());
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.STRING_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1970,7 +2153,7 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
return visit(ctx.identifier());
|
||||
}
|
||||
|
||||
return visit(ctx.stringLiteral());
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.STRING_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2378,12 +2561,12 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
if (ctx.treatedPath() != null) {
|
||||
if (ctx.syntacticDomainPath() != null) {
|
||||
|
||||
builder.append(visit(ctx.treatedPath()));
|
||||
builder.append(visit(ctx.syntacticDomainPath()));
|
||||
|
||||
if (ctx.pathContinutation() != null) {
|
||||
builder.append(visit(ctx.pathContinutation()));
|
||||
if (ctx.pathContinuation() != null) {
|
||||
builder.append(visit(ctx.pathContinuation()));
|
||||
}
|
||||
} else if (ctx.generalPathFragment() != null) {
|
||||
builder.append(visit(ctx.generalPathFragment()));
|
||||
@@ -2549,8 +2732,8 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
nested.append(TOKEN_CLOSE_PAREN);
|
||||
builder.append(nested);
|
||||
|
||||
if (ctx.pathContinutation() != null) {
|
||||
builder.append(visit(ctx.pathContinutation()));
|
||||
if (ctx.pathContinuation() != null) {
|
||||
builder.append(visit(ctx.pathContinuation()));
|
||||
}
|
||||
|
||||
if (ctx.nthSideClause() != null) {
|
||||
@@ -2821,8 +3004,8 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
@Override
|
||||
public QueryTokenStream visitTrimCharacter(HqlParser.TrimCharacterContext ctx) {
|
||||
|
||||
if (ctx.stringLiteral() != null) {
|
||||
return visit(ctx.stringLiteral());
|
||||
if (ctx.STRING_LITERAL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.STRING_LITERAL()));
|
||||
}
|
||||
|
||||
return visit(ctx.parameter());
|
||||
@@ -2899,7 +3082,7 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitTreatedPath(HqlParser.TreatedPathContext ctx) {
|
||||
public QueryTokenStream visitTreatedNavigablePath(HqlParser.TreatedNavigablePathContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
@@ -2914,24 +3097,88 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
builder.appendInline(nested);
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
|
||||
if (ctx.pathContinutation() != null) {
|
||||
builder.append(visit(ctx.pathContinutation()));
|
||||
if (ctx.pathContinuation() != null) {
|
||||
builder.append(visit(ctx.pathContinuation()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitPathContinutation(HqlParser.PathContinutationContext ctx) {
|
||||
public QueryTokenStream visitCollectionValueNavigablePath(HqlParser.CollectionValueNavigablePathContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(TOKEN_DOT);
|
||||
builder.append(visit(ctx.simplePath()));
|
||||
builder.append(visit(ctx.elementValueQuantifier()));
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.append(visit(ctx.path()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
|
||||
if (ctx.pathContinuation() != null) {
|
||||
builder.append(visit(ctx.pathContinuation()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitMapKeyNavigablePath(HqlParser.MapKeyNavigablePathContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(visit(ctx.indexKeyQuantifier()));
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.append(visit(ctx.path()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
|
||||
if (ctx.pathContinuation() != null) {
|
||||
builder.append(visit(ctx.pathContinuation()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitToOneFkReference(HqlParser.ToOneFkReferenceContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(QueryTokens.token(ctx.FK()));
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.append(visit(ctx.path()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitElementValueQuantifier(HqlParser.ElementValueQuantifierContext ctx) {
|
||||
|
||||
if (ctx.ELEMENT() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.ELEMENT()));
|
||||
}
|
||||
|
||||
if (ctx.VALUE() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.VALUE()));
|
||||
}
|
||||
|
||||
return QueryTokenStream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitIndexKeyQuantifier(HqlParser.IndexKeyQuantifierContext ctx) {
|
||||
|
||||
if (ctx.INDEX() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.INDEX()));
|
||||
}
|
||||
|
||||
if (ctx.KEY() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.KEY()));
|
||||
}
|
||||
|
||||
return QueryTokenStream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitIsBooleanPredicate(HqlParser.IsBooleanPredicateContext ctx) {
|
||||
|
||||
@@ -3176,8 +3423,10 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
|
||||
builder.append(QueryTokens.expression(ctx.ESCAPE()));
|
||||
|
||||
if (ctx.stringLiteral() != null) {
|
||||
builder.appendExpression(visit(ctx.stringLiteral()));
|
||||
if (ctx.STRING_LITERAL() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.STRING_LITERAL()));
|
||||
} else if (ctx.JAVA_STRING_LITERAL() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.JAVA_STRING_LITERAL()));
|
||||
} else if (ctx.parameter() != null) {
|
||||
builder.appendExpression(visit(ctx.parameter()));
|
||||
}
|
||||
@@ -3335,8 +3584,8 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
|
||||
builder.append(QueryTokens.expression(ctx.AS()));
|
||||
builder.append(visit(ctx.identifier()));
|
||||
} else if (ctx.reservedWord() != null) {
|
||||
builder.append(visit(ctx.reservedWord()));
|
||||
} else if (ctx.nakedIdentifier() != null) {
|
||||
builder.append(visit(ctx.nakedIdentifier()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
@@ -3371,20 +3620,33 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
@Override
|
||||
public QueryTokenStream visitIdentifier(HqlParser.IdentifierContext ctx) {
|
||||
|
||||
if (ctx.reservedWord() != null) {
|
||||
return visit(ctx.reservedWord());
|
||||
} else {
|
||||
return QueryTokenStream.empty();
|
||||
if (ctx.nakedIdentifier() != null) {
|
||||
return visit(ctx.nakedIdentifier());
|
||||
} else if (ctx.FULL() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.FULL()));
|
||||
} else if (ctx.LEFT() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.LEFT()));
|
||||
} else if (ctx.INNER() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.INNER()));
|
||||
} else if (ctx.OUTER() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.OUTER()));
|
||||
} else if (ctx.RIGHT() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.RIGHT()));
|
||||
}
|
||||
|
||||
return QueryTokenStream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitReservedWord(HqlParser.ReservedWordContext ctx) {
|
||||
public QueryTokenStream visitNakedIdentifier(HqlParser.NakedIdentifierContext ctx) {
|
||||
|
||||
if (ctx.IDENTIFICATION_VARIABLE() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.IDENTIFICATION_VARIABLE()));
|
||||
if (ctx.IDENTIFIER() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.IDENTIFIER()));
|
||||
} else if (ctx.QUOTED_IDENTIFIER() != null) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.QUOTED_IDENTIFIER()));
|
||||
} else {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.f));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@ import org.junit.jupiter.params.provider.ValueSource;
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch, Yannick Brandt
|
||||
* @author Mark Paluch
|
||||
* @author Yannick Brandt
|
||||
* @since 3.1
|
||||
*/
|
||||
class HqlQueryRendererTests {
|
||||
@@ -179,6 +180,180 @@ class HqlQueryRendererTests {
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void entityTypeReference() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT TYPE(e)
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT TYPE(?0)
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void entityIdReference() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT ID(e)
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT ID(e).foo
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void entityNaturalIdReference() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT NATURALID(e)
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT NATURALID(e).foo
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void entityVersionReference() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT VERSION(e)
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void treatedNavigablePath() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT TREAT(e as Integer).foo
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void collectionValueNavigablePath() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT ELEMENT(e)
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT ELEMENT(e).foo
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT VALUE(e)
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT VALUE(e).foo
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void mapKeyNavigablePath() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT KEY(e)
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT KEY(e).foo
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT INDEX(e)
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void toOneFkReference() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT FK(e)
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT FK(e.foo)
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void indexedPathAccessFragment() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT e.names[0]
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT e.payments[1].id
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT some_function()[0]
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT some_function()[1].id
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void slicedPathAccessFragment() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT e.names[0:1]
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT e.payments[1:2].id
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT some_function()[0:1]
|
||||
FROM Employee e
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
SELECT some_function()[1:2].id
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3711
|
||||
void functionPathContinuation() {
|
||||
|
||||
assertQuery("""
|
||||
SELECT some_function().foo
|
||||
FROM Employee e
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
void joinsExample1() {
|
||||
|
||||
@@ -299,7 +474,7 @@ class HqlQueryRendererTests {
|
||||
assertQuery("""
|
||||
SELECT b.name, b.ISBN
|
||||
FROM Order o JOIN TREAT(o.product AS Book) b
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -308,7 +483,7 @@ class HqlQueryRendererTests {
|
||||
assertQuery("""
|
||||
SELECT e FROM Employee e JOIN TREAT(e.projects AS LargeProject) lp
|
||||
WHERE lp.budget > 1000
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,7 +498,7 @@ class HqlQueryRendererTests {
|
||||
WHERE TREAT(p AS LargeProject).budget > 1000
|
||||
OR TREAT(p AS SmallProject).name LIKE 'Persist%'
|
||||
OR p.description LIKE "cost overrun"
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -334,7 +509,7 @@ class HqlQueryRendererTests {
|
||||
WHERE TREAT(p AS LargeProject).budget > 1000
|
||||
OR TREAT(p AS SmallProject).name LIKE 'Persist%'
|
||||
OR p.description LIKE 'cost overrun'
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -344,7 +519,7 @@ class HqlQueryRendererTests {
|
||||
SELECT e FROM Employee e
|
||||
WHERE TREAT(e AS Exempt).vacationDays > 10
|
||||
OR TREAT(e AS Contractor).hours > 100
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -408,7 +583,7 @@ class HqlQueryRendererTests {
|
||||
WHERE emp.salary > ALL (SELECT m.salary
|
||||
FROM Manager m
|
||||
WHERE m.department = emp.department)
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -420,7 +595,7 @@ class HqlQueryRendererTests {
|
||||
WHERE EXISTS (SELECT spouseEmp
|
||||
FROM Employee spouseEmp
|
||||
WHERE spouseEmp = emp.spouse)
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -488,7 +663,7 @@ class HqlQueryRendererTests {
|
||||
WHEN e.rating = 2 THEN e.salary * 1.05
|
||||
ELSE e.salary * 1.01
|
||||
END
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -501,7 +676,7 @@ class HqlQueryRendererTests {
|
||||
WHEN 2 THEN e.salary * 1.05
|
||||
ELSE e.salary * 1.01
|
||||
END
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -541,7 +716,7 @@ class HqlQueryRendererTests {
|
||||
SELECT e
|
||||
FROM Employee e
|
||||
WHERE TYPE(e) IN (Exempt, Contractor)
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1509,13 +1684,13 @@ class HqlQueryRendererTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test // GH-3711
|
||||
void ceilingFunctionShouldWork() {
|
||||
assertQuery("select ceiling(1.5) from Element a");
|
||||
}
|
||||
|
||||
@Test
|
||||
void lnFunctionSouldWork() {
|
||||
@Test // GH-3711
|
||||
void lnFunctionShouldWork() {
|
||||
assertQuery("select ln(7.5) from Element a");
|
||||
}
|
||||
|
||||
@@ -1568,10 +1743,18 @@ class HqlQueryRendererTests {
|
||||
void durationLiteralsShouldWork(String dtField) {
|
||||
|
||||
assertQuery("SELECT ce.id FROM CalendarEvent ce WHERE (ce.endDate - ce.startDate) > 5 %s".formatted(dtField));
|
||||
assertQuery("SELECT ce.id FROM CalendarEvent ce WHERE ce.text LIKE :text GROUP BY year(cd.date) HAVING (ce.endDate - ce.startDate) > 5 %s".formatted(dtField));
|
||||
assertQuery(
|
||||
"SELECT ce.id FROM CalendarEvent ce WHERE ce.text LIKE :text GROUP BY year(cd.date) HAVING (ce.endDate - ce.startDate) > 5 %s"
|
||||
.formatted(dtField));
|
||||
assertQuery("SELECT ce.id as id, cd.startDate + 5 %s AS summedDate FROM CalendarEvent ce".formatted(dtField));
|
||||
}
|
||||
|
||||
@ParameterizedTest // GH-3711
|
||||
@ValueSource(strings = { "1", "1_000", "1L", "1_000L", "1bi", "1.1f", "2.2d", "2.2bd" })
|
||||
void numberLiteralsShouldWork(String literal) {
|
||||
assertQuery(String.format("SELECT %s FROM User u where u.id = %s", literal, literal));
|
||||
}
|
||||
|
||||
@Test // GH-3025
|
||||
void binaryLiteralsShouldWork() {
|
||||
|
||||
|
||||
@@ -924,7 +924,7 @@ class HqlQueryTransformerTests {
|
||||
and iu = u
|
||||
)
|
||||
and ct.id = :teamId
|
||||
""", relationshipName, joinAlias, joinAlias));
|
||||
""", relationshipName, joinAlias, joinAlias));
|
||||
}
|
||||
|
||||
static Stream<Arguments> queriesWithReservedWordsAsIdentifiers() {
|
||||
@@ -933,7 +933,6 @@ class HqlQueryTransformerTests {
|
||||
Arguments.of("right", "rt"), //
|
||||
Arguments.of("left", "lt"), //
|
||||
Arguments.of("outer", "ou"), //
|
||||
Arguments.of("full", "full"), //
|
||||
Arguments.of("inner", "inr"));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user