From a8338e23b282786cf798a45b140ee7dd9da10206 Mon Sep 17 00:00:00 2001 From: "Greg L. Turnquist" Date: Fri, 2 Jun 2023 13:09:01 -0500 Subject: [PATCH 1/2] New branch. --- pom.xml | 2 +- spring-data-envers/pom.xml | 4 ++-- spring-data-jpa-distribution/pom.xml | 2 +- spring-data-jpa/pom.xml | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 91916af9b9..e03ef258bb 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-jpa-parent - 3.2.0-SNAPSHOT + 3.2.0-official-hql-SNAPSHOT pom Spring Data JPA Parent diff --git a/spring-data-envers/pom.xml b/spring-data-envers/pom.xml index 0c3d16ef85..33afb1dd95 100755 --- a/spring-data-envers/pom.xml +++ b/spring-data-envers/pom.xml @@ -5,12 +5,12 @@ org.springframework.data spring-data-envers - 3.2.0-SNAPSHOT + 3.2.0-official-hql-SNAPSHOT org.springframework.data spring-data-jpa-parent - 3.2.0-SNAPSHOT + 3.2.0-official-hql-SNAPSHOT ../pom.xml diff --git a/spring-data-jpa-distribution/pom.xml b/spring-data-jpa-distribution/pom.xml index 991cd8cbf0..2e22138c8b 100644 --- a/spring-data-jpa-distribution/pom.xml +++ b/spring-data-jpa-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-jpa-parent - 3.2.0-SNAPSHOT + 3.2.0-official-hql-SNAPSHOT ../pom.xml diff --git a/spring-data-jpa/pom.xml b/spring-data-jpa/pom.xml index 7145881fb0..7df9600b1d 100644 --- a/spring-data-jpa/pom.xml +++ b/spring-data-jpa/pom.xml @@ -6,7 +6,7 @@ org.springframework.data spring-data-jpa - 3.2.0-SNAPSHOT + 3.2.0-official-hql-SNAPSHOT Spring Data JPA Spring Data module for JPA repositories. @@ -15,7 +15,7 @@ org.springframework.data spring-data-jpa-parent - 3.2.0-SNAPSHOT + 3.2.0-official-hql-SNAPSHOT ../pom.xml From 923d02897f92590992845af859fc48937115a1d8 Mon Sep 17 00:00:00 2001 From: "Greg L. Turnquist" Date: Fri, 2 Jun 2023 13:09:16 -0500 Subject: [PATCH 2/2] Switch to Hibernate's official parser for HQL. Rewrite our custom visitors to plug into Hibernate's official parser for HQL. See #3002 Original Pull Request: #3003 --- .../data/jpa/repository/query/Hql.g4 | 1061 ----- .../jpa/repository/query/HqlQueryParser.java | 8 +- .../repository/query/HqlQueryRenderer.java | 4074 ++++++++++++----- .../repository/query/HqlQueryTransformer.java | 180 +- .../query/JpaQueryParsingToken.java | 3 + .../query/HqlQueryRendererTests.java | 4 +- .../query/HqlQueryTransformerTests.java | 18 +- 7 files changed, 3076 insertions(+), 2272 deletions(-) delete mode 100644 spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 diff --git a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 deleted file mode 100644 index 1ca0c466b4..0000000000 --- a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * Copyright 2011-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -grammar Hql; - -@header { -/** - * HQL per https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#query-language - * - * This is a mixture of Hibernate's BNF and missing bits of grammar. There are gaps and inconsistencies in the - * BNF itself, explained by other fragments of their spec. Additionally, alternate labels are used to provide easier - * management of complex rules in the generated Visitor. Finally, there are labels applied to rule elements (op=('+'|'-') - * to simplify the processing. - * - * @author Greg Turnquist - * @since 3.1 - */ -} - -/* - Parser rules - */ - -start - : ql_statement EOF - ; - -ql_statement - : selectStatement - | updateStatement - | deleteStatement - | insertStatement - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-select -selectStatement - : queryExpression - ; - -queryExpression - : withClause? orderedQuery (setOperator orderedQuery)* - ; - -withClause - : WITH cte (',' cte)* - ; - -cte - : identifier AS (NOT? MATERIALIZED)? '(' queryExpression ')' searchClause? cycleClause? - ; - -searchClause - : SEARCH (BREADTH | DEPTH) FIRST BY searchSpecifications SET identifier - ; - -searchSpecifications - : searchSpecification (',' searchSpecification)* - ; - -searchSpecification - : identifier sortDirection? nullsPrecedence? - ; - -cycleClause - : CYCLE cteAttributes SET identifier (TO literal DEFAULT literal)? (USING identifier)? - ; - -cteAttributes - : identifier (',' identifier)* - ; - -orderedQuery - : (query | '(' queryExpression ')') queryOrder? - ; - -query - : selectClause fromClause? whereClause? (groupByClause havingClause?)? # SelectQuery - | fromClause whereClause? (groupByClause havingClause?)? selectClause? # FromQuery - ; - -queryOrder - : orderByClause limitClause? offsetClause? fetchClause? - ; - -fromClause - : FROM entityWithJoins (',' entityWithJoins)* - ; - -entityWithJoins - : fromRoot (joinSpecifier)* - ; - -joinSpecifier - : join - | crossJoin - | jpaCollectionJoin - ; - -fromRoot - : entityName variable? - | LATERAL? '(' subquery ')' variable? - ; - -join - : joinType JOIN FETCH? joinTarget joinRestriction? // Spec BNF says joinType isn't optional, but text says that it is. - ; - -joinTarget - : path variable? # JoinPath - | LATERAL? '(' subquery ')' variable? # JoinSubquery - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-update -updateStatement - : UPDATE VERSIONED? targetEntity setClause whereClause? - ; - -targetEntity - : entityName variable? - ; - -setClause - : SET assignment (',' assignment)* - ; - -assignment - : simplePath '=' expressionOrPredicate - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-delete -deleteStatement - : DELETE FROM? targetEntity whereClause? - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-insert -insertStatement - : INSERT INTO? targetEntity targetFields (queryExpression | valuesList) - ; - -// Already defined underneath updateStatement -//targetEntity -// : entityName variable? -// ; - -targetFields - : '(' simplePath (',' simplePath)* ')' - ; - -valuesList - : VALUES values (',' values)* - ; - -values - : '(' expression (',' expression)* ')' - ; - -instantiation - : NEW instantiationTarget '(' instantiationArguments ')' - ; - -alias - : AS? identifier // spec says IDENTIFIER but clearly does NOT mean a reserved word - ; - -groupedItem - : identifier - | INTEGER_LITERAL - | expression - ; - -sortedItem - : sortExpression sortDirection? nullsPrecedence? - ; - -sortExpression - : identifier - | INTEGER_LITERAL - | expression - ; - -sortDirection - : ASC - | DESC - ; - -nullsPrecedence - : NULLS (FIRST | LAST) - ; - -limitClause - : LIMIT parameterOrIntegerLiteral - ; - -offsetClause - : OFFSET parameterOrIntegerLiteral (ROW | ROWS)? - ; - -fetchClause - : FETCH (FIRST | NEXT) (parameterOrIntegerLiteral | parameterOrNumberLiteral '%') (ROW | ROWS) (ONLY | WITH TIES) - ; - -/******************* - Gaps in the spec. - *******************/ - -subquery - : queryExpression - ; - -selectClause - : SELECT DISTINCT? selectionList - ; - -selectionList - : selection (',' selection)* - ; - -selection - : selectExpression variable? - ; - -selectExpression - : instantiation - | mapEntrySelection - | jpaSelectObjectSyntax - | expressionOrPredicate - ; - -mapEntrySelection - : ENTRY '(' path ')' - ; - -/** - * Deprecated syntax dating back to EJB-QL prior to EJB 3, required by JPA, never documented in Hibernate - */ -jpaSelectObjectSyntax - : OBJECT '(' identifier ')' - ; - -whereClause - : WHERE predicate (',' predicate)* - ; - -joinType - : INNER? - | (LEFT | RIGHT | FULL)? OUTER? - | CROSS - ; - -crossJoin - : CROSS JOIN entityName variable? - ; - -joinRestriction - : (ON | WITH) predicate - ; - -// Deprecated syntax dating back to EJB-QL prior to EJB 3, required by JPA, never documented in Hibernate -jpaCollectionJoin - : ',' IN '(' path ')' variable? - ; - -groupByClause - : GROUP BY groupedItem (',' groupedItem)* - ; - -orderByClause - : ORDER BY sortedItem (',' sortedItem)* - ; - -havingClause - : HAVING predicate (',' predicate)* - ; - -setOperator - : UNION ALL? - | INTERSECT ALL? - | EXCEPT ALL? - ; - -// Literals -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-literals -literal - : NULL - | booleanLiteral - | stringLiteral - | numericLiteral - | dateTimeLiteral - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-boolean-literals -booleanLiteral - : TRUE - | 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 - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-datetime-literals -dateTimeLiteral - : LOCAL_DATE - | LOCAL_TIME - | LOCAL_DATETIME - | CURRENT_DATE - | CURRENT_TIME - | CURRENT_TIMESTAMP - | OFFSET_DATETIME - | (LOCAL | CURRENT) DATE - | (LOCAL | CURRENT) TIME - | (LOCAL | CURRENT | OFFSET) DATETIME - | INSTANT - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-duration-literals -// TBD - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-binary-literals -// TBD - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-enum-literals -// TBD - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-java-constants -// TBD - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-entity-name-literals -// TBD - -// Expressions -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-expressions -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-concatenation -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-numeric-arithmetic -expression - : '(' expression ')' # GroupedExpression - | '(' expressionOrPredicate (',' expressionOrPredicate)+ ')' # TupleExpression - | '(' subquery ')' # SubqueryExpression - | primaryExpression # PlainPrimaryExpression - | op=('+' | '-') numericLiteral # SignedNumericLiteral - | op=('+' | '-') expression # SignedExpression - | expression op=('*' | '/') expression # MultiplicationExpression - | expression op=('+' | '-') expression # AdditionExpression - | expression '||' expression # HqlConcatenationExpression - ; - -primaryExpression - : caseList # CaseExpression - | literal # LiteralExpression - | parameter # ParameterExpression - | 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 -identificationVariable - : identifier - | simplePath - ; - -path - : treatedPath pathContinutation? - | generalPathFragment - ; - -generalPathFragment - : simplePath indexedPathAccessFragment? - ; - -indexedPathAccessFragment - : '[' expression ']' ('.' generalPathFragment)? - ; - -simplePath - : identifier simplePathElement* - ; - -simplePathElement - : '.' identifier - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-case-expressions -caseList - : simpleCaseExpression - | searchedCaseExpression - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-simple-case-expressions -simpleCaseExpression - : CASE expressionOrPredicate caseWhenExpressionClause+ (ELSE expressionOrPredicate)? END - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-searched-case-expressions -searchedCaseExpression - : CASE caseWhenPredicateClause+ (ELSE expressionOrPredicate)? END - ; - -caseWhenExpressionClause - : WHEN expression THEN expressionOrPredicate - ; - -caseWhenPredicateClause - : WHEN predicate THEN expressionOrPredicate - ; - -// Functions -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-exp-functions -function - : functionName '(' (functionArguments | ASTERISK)? ')' pathContinutation? filterClause? withinGroup? overClause? # GenericFunction - | functionName '(' subquery ')' # FunctionWithSubquery - | castFunction # CastFunctionInvocation - | extractFunction # ExtractFunctionInvocation - | trimFunction # TrimFunctionInvocation - | everyFunction # EveryFunctionInvocation - | anyFunction # AnyFunctionInvocation - | treatedPath # TreatedPathInvocation - ; - -functionArguments - : DISTINCT? expressionOrPredicate (',' expressionOrPredicate)* - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-aggregate-functions-filter -filterClause - : FILTER '(' whereClause ')' - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-aggregate-functions-orderedset -withinGroup - : WITHIN GROUP '(' orderByClause ')' - ; - -overClause - : OVER '(' partitionClause? orderByClause? frameClause? ')' - ; - -partitionClause - : PARTITION BY expression (',' expression)* - ; - -frameClause - : (RANGE|ROWS|GROUPS) frameStart frameExclusion? - | (RANGE|ROWS|GROUPS) BETWEEN frameStart AND frameEnd frameExclusion? - ; - -frameStart - : UNBOUNDED PRECEDING # UnboundedPrecedingFrameStart - | expression PRECEDING # ExpressionPrecedingFrameStart - | CURRENT ROW # CurrentRowFrameStart - | expression FOLLOWING # ExpressionFollowingFrameStart - ; - -frameExclusion - : EXCLUDE CURRENT ROW # CurrentRowFrameExclusion - | EXCLUDE GROUP # GroupFrameExclusion - | EXCLUDE TIES # TiesFrameExclusion - | EXCLUDE NO OTHERS # NoOthersFrameExclusion - ; - -frameEnd - : expression PRECEDING # ExpressionPrecedingFrameEnd - | CURRENT ROW # CurrentRowFrameEnd - | expression FOLLOWING # ExpressionFollowingFrameEnd - | UNBOUNDED FOLLOWING # UnboundedFollowingFrameEnd - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-functions -castFunction - : CAST '(' expression AS identifier ')' - ; - -extractFunction - : EXTRACT '(' expression FROM expression ')' - | dateTimeFunction '(' expression ')' - ; - -trimFunction - : TRIM '(' (LEADING | TRAILING | BOTH)? stringLiteral? FROM? expression ')' - ; - -dateTimeFunction - : d=(YEAR - | MONTH - | DAY - | WEEK - | QUARTER - | HOUR - | MINUTE - | SECOND - | NANOSECOND - | EPOCH) - ; - -everyFunction - : every=(EVERY | ALL) '(' predicate ')' - | every=(EVERY | ALL) '(' subquery ')' - | every=(EVERY | ALL) (ELEMENTS | INDICES) '(' simplePath ')' - ; - -anyFunction - : any=(ANY | SOME) '(' predicate ')' - | any=(ANY | SOME) '(' subquery ')' - | any=(ANY | SOME) (ELEMENTS | INDICES) '(' simplePath ')' - ; - -// 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 - : '(' predicate ')' # GroupedPredicate - | dealingWithNullExpression # NullExpressionPredicate - | inExpression # InPredicate - | betweenExpression # BetweenPredicate - | relationalExpression # RelationalPredicate - | stringPatternMatching # LikePredicate - | existsExpression # ExistsPredicate - | collectionExpression # CollectionPredicate - | NOT predicate # NotPredicate - | predicate AND predicate # AndPredicate - | predicate OR predicate # OrPredicate - | expression # ExpressionPredicate - ; - -expressionOrPredicate - : expression - | predicate - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-relational-comparisons -// NOTE: The TIP shows that "!=" is also supported. Hibernate's source code shows that "^=" is another NOT_EQUALS option as well. -relationalExpression - : expression op=('=' | '>' | '>=' | '<' | '<=' | '<>' | '!=' | '^=' ) expression - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-between-predicate -betweenExpression - : expression NOT? BETWEEN expression AND expression - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-null-predicate -dealingWithNullExpression - : expression IS NOT? NULL - | expression IS NOT? DISTINCT FROM expression - ; - -// 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 (character|parameter))? - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-elements-indices -// TBD - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-in-predicate -inExpression - : expression NOT? IN inList - ; - -inList - : (ELEMENTS | INDICES) '(' simplePath ')' - | '(' subquery ')' - | parameter - | '(' (expressionOrPredicate (',' expressionOrPredicate)*)? ')' - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-exists-predicate -// TBD -existsExpression - : EXISTS (ELEMENTS | INDICES) '(' simplePath ')' - | EXISTS expression - ; - -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-collection-operators -collectionExpression - : expression IS NOT? EMPTY - | expression NOT? MEMBER OF path - ; - -// Projection -// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-select-new -instantiationTarget - : LIST - | MAP - | simplePath - ; - -instantiationArguments - : instantiationArgument (',' instantiationArgument)* - ; - -instantiationArgument - : (expressionOrPredicate | instantiation) variable? - ; - -// Low level parsing rules - -parameterOrIntegerLiteral - : parameter - | INTEGER_LITERAL - ; - -parameterOrNumberLiteral - : parameter - | numericLiteral - ; - -variable - : AS identifier - | reservedWord - ; - -parameter - : prefix=':' identifier - | prefix='?' INTEGER_LITERAL? - ; - -entityName - : identifier ('.' identifier)* - ; - -identifier - : reservedWord - ; - -character - : CHARACTER - ; - -functionName - : reservedWord - ; - -reservedWord - : IDENTIFICATION_VARIABLE - | f=(ALL - | AND - | ANY - | AS - | ASC - | AVG - | BETWEEN - | BOTH - | BREADTH - | BY - | CASE - | CAST - | COLLATE - | COUNT - | CROSS - | CUBE - | CURRENT - | CURRENT_DATE - | CURRENT_INSTANT - | CURRENT_TIME - | CURRENT_TIMESTAMP - | CYCLE - | DATE - | DATETIME - | DAY - | DEFAULT - | DELETE - | DEPTH - | DESC - | DISTINCT - | ELEMENT - | ELEMENTS - | ELSE - | EMPTY - | END - | ENTRY - | EPOCH - | ERROR - | ESCAPE - | EVERY - | EXCEPT - | EXCLUDE - | EXISTS - | EXTRACT - | FETCH - | FILTER - | FIRST - | FLOOR - | FOLLOWING - | FOR - | FORMAT - | FROM - | FULL - | FUNCTION - | GROUP - | GROUPS - | HAVING - | HOUR - | ID - | IGNORE - | ILIKE - | IN - | INDEX - | INDICES - | INNER - | INSERT - | INSTANT - | INTERSECT - | INTO - | IS - | JOIN - | KEY - | LAST - | LEADING - | LEFT - | LIKE - | LIMIT - | LIST - | LISTAGG - | LOCAL - | LOCAL_DATE - | LOCAL_DATETIME - | LOCAL_TIME - | MAP - | MATERIALIZED - | MAX - | MAXELEMENT - | MAXINDEX - | MEMBER - | MICROSECOND - | MILLISECOND - | MIN - | MINELEMENT - | MININDEX - | MINUTE - | MONTH - | NANOSECOND - | NATURALID - | NEW - | NEXT - | NO - | NOT - | NULLS - | OBJECT - | OF - | OFFSET - | OFFSET_DATETIME - | ON - | ONLY - | OR - | ORDER - | OTHERS - | OUTER - | OVER - | OVERFLOW - | OVERLAY - | PAD - | PARTITION - | PERCENT - | PLACING - | POSITION - | PRECEDING - | QUARTER - | RANGE - | RESPECT - | RIGHT - | ROLLUP - | ROW - | ROWS - | SEARCH - | SECOND - | SELECT - | SET - | SIZE - | SOME - | SUBSTRING - | SUM - | THEN - | TIES - | TIME - | TIMESTAMP - | TIMEZONE_HOUR - | TIMEZONE_MINUTE - | TO - | TRAILING - | TREAT - | TRIM - | TRUNC - | TRUNCATE - | TYPE - | UNBOUNDED - | UNION - | UPDATE - | USING - | VALUE - | VALUES - | VERSION - | VERSIONED - | WEEK - | WHEN - | WHERE - | WITH - | WITHIN - | WITHOUT - | YEAR) - ; - -/* - Lexer rules - */ - - -WS : [ \t\r\n] -> skip ; - -// Build up case-insentive tokens - -fragment A: 'a' | 'A'; -fragment B: 'b' | 'B'; -fragment C: 'c' | 'C'; -fragment D: 'd' | 'D'; -fragment E: 'e' | 'E'; -fragment F: 'f' | 'F'; -fragment G: 'g' | 'G'; -fragment H: 'h' | 'H'; -fragment I: 'i' | 'I'; -fragment J: 'j' | 'J'; -fragment K: 'k' | 'K'; -fragment L: 'l' | 'L'; -fragment M: 'm' | 'M'; -fragment N: 'n' | 'N'; -fragment O: 'o' | 'O'; -fragment P: 'p' | 'P'; -fragment Q: 'q' | 'Q'; -fragment R: 'r' | 'R'; -fragment S: 's' | 'S'; -fragment T: 't' | 'T'; -fragment U: 'u' | 'U'; -fragment V: 'v' | 'V'; -fragment W: 'w' | 'W'; -fragment X: 'x' | 'X'; -fragment Y: 'y' | 'Y'; -fragment Z: 'z' | 'Z'; - -// The following are reserved identifiers: - -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; -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; -COUNT : C O U N T; -CROSS : C R O S S; -CUBE : C U B E; -CURRENT : C U R R E N T; -CURRENT_DATE : C U R R E N T '_' D A T E; -CURRENT_INSTANT : C U R R E N T '_' I N S T A N T; -CURRENT_TIME : C U R R E N T '_' T I M E; -CURRENT_TIMESTAMP : C U R R E N T '_' T I M E S T A M P; -CYCLE : C Y C L E; -DATE : D A T E; -DATETIME : D A T E T I M E ; -DAY : D A Y; -DEFAULT : D E F A U L T; -DELETE : D E L E T E; -DEPTH : D E P T H; -DESC : D E S C; -DISTINCT : D I S T I N C T; -ELEMENT : E L E M E N T; -ELEMENTS : E L E M E N T S; -ELSE : E L S E; -EMPTY : E M P T Y; -END : E N D; -ENTRY : E N T R Y; -EPOCH : E P O C H; -ERROR : E R R O R; -ESCAPE : E S C A P E; -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; -FROM : F R O M; -FULL : F U L L; -FUNCTION : F U N C T I O N; -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; -INDEX : I N D E X; -INDICES : I N D I C E S; -INNER : I N N E R; -INSERT : I N S E R T; -INSTANT : I N S T A N T; -INTERSECT : I N T E R S E C T; -INTO : I N T O; -IS : I S; -JOIN : J O I N; -KEY : K E Y; -LAST : L A S T; -LATERAL : L A T E R A L; -LEADING : L E A D I N G; -LEFT : L E F T; -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; -LOCAL_TIME : L O C A L '_' T I M E; -MAP : M A P; -MATERIALIZED : M A T E R I A L I Z E D; -MAX : M A X; -MAXELEMENT : M A X E L E M E N T; -MAXINDEX : M A X I N D E X; -MEMBER : M E M B E R; -MICROSECOND : M I C R O S E C O N D; -MILLISECOND : M I L L I S E C O N D; -MIN : M I N; -MINELEMENT : M I N E L E M E N T; -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; -NULL : N U L L; -NULLS : N U L L S; -OBJECT : O B J E C T; -OF : O F; -OFFSET : O F F S E T; -OFFSET_DATETIME : O F F S E T '_' D A T E T I M E; -ON : O N; -ONLY : O N L Y; -OR : O R; -ORDER : O R D E R; -OTHERS : O T H E R S; -OUTER : O U T E R; -OVER : O V E R; -OVERFLOW : O V E R F L O W; -OVERLAY : O V E R L A Y; -PAD : P A D; -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; -RESPECT : R E S P E C T; -RIGHT : R I G H T; -ROLLUP : R O L L U P; -ROW : R O W; -ROWS : R O W S; -SEARCH : S E A R C H; -SECOND : S E C O N D; -SELECT : S E L E C T; -SET : S E T; -SIZE : S I Z E; -SOME : S O M E; -SUBSTRING : S U B S T R I N G; -SUM : S U M; -THEN : T H E N; -TIES : T I E S; -TIME : T I M E; -TIMESTAMP : T I M E S T A M P; -TIMEZONE_HOUR : T I M E Z O N E '_' H O U R; -TIMEZONE_MINUTE : T I M E Z O N E '_' M I N U T E; -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; -UNBOUNDED : U N B O U N D E D; -UNION : U N I O N; -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; -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; - -fragment INTEGER_NUMBER : ('0' .. '9')+ ; -fragment FLOAT_NUMBER : INTEGER_NUMBER+ '.'? INTEGER_NUMBER* (E [+-]? INTEGER_NUMBER)? ; - -CHARACTER : '\'' (~ ('\'' | '\\' )) '\'' ; -STRINGLITERAL : '\'' ('\'' '\'' | ~('\'' | '\\'))* '\'' ; -JAVASTRINGLITERAL : '"' ( ('\\' [btnfr"']) | ~('"'))* '"'; -INTEGER_LITERAL : INTEGER_NUMBER (L | B I)? ; -FLOAT_LITERAL : FLOAT_NUMBER (D | F | B D)?; -HEXLITERAL : '0' X ('0' .. '9' | A | B | C | D | E)+ ; - -IDENTIFICATION_VARIABLE : ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '$' | '_') ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '0' .. '9' | '$' | '_')* ; - diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryParser.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryParser.java index 8f9cdcaacf..eb567a13c9 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryParser.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryParser.java @@ -20,12 +20,14 @@ import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.ParserRuleContext; +import org.hibernate.grammars.hql.HqlLexer; +import org.hibernate.grammars.hql.HqlParser; import org.springframework.data.domain.Sort; import org.springframework.lang.Nullable; /** - * Implements the {@code HQL} parsing operations of a {@link JpaQueryParserSupport} using the ANTLR-generated - * {@link HqlParser} and {@link HqlQueryTransformer}. + * Implements the {@code HQL} parsing operations of a {@link JpaQueryParserSupport} using Hibernate's ANTLR-generated + * {@link HqlParser} and a custom {@link HqlQueryTransformer}. * * @author Greg Turnquist * @author Mark Paluch @@ -50,7 +52,7 @@ public static ParserRuleContext parseQuery(String query) { configureParser(query, lexer, parser); - return parser.start(); + return parser.statement(); } /** diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java index 17458b20e6..44f5bd80e9 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java @@ -20,21 +20,19 @@ import java.util.ArrayList; import java.util.List; +import org.hibernate.grammars.hql.HqlParser; +import org.hibernate.grammars.hql.HqlParserBaseVisitor; + /** * An ANTLR {@link org.antlr.v4.runtime.tree.ParseTreeVisitor} that renders an HQL query without making any changes. * * @author Greg Turnquist * @since 3.1 */ -class HqlQueryRenderer extends HqlBaseVisitor> { - - @Override - public List visitStart(HqlParser.StartContext ctx) { - return visit(ctx.ql_statement()); - } +class HqlQueryRenderer extends HqlParserBaseVisitor> { @Override - public List visitQl_statement(HqlParser.Ql_statementContext ctx) { + public List visitStatement(HqlParser.StatementContext ctx) { if (ctx.selectStatement() != null) { return visit(ctx.selectStatement()); @@ -55,25 +53,167 @@ public List visitSelectStatement(HqlParser.SelectStatement } @Override - public List visitQueryExpression(HqlParser.QueryExpressionContext ctx) { + public List visitSubquery(HqlParser.SubqueryContext ctx) { + return visit(ctx.queryExpression()); + } + + @Override + public List visitTargetEntity(HqlParser.TargetEntityContext ctx) { List tokens = new ArrayList<>(); - if (ctx.withClause() != null) { - tokens.addAll(visit(ctx.withClause())); + tokens.addAll(visit(ctx.entityName())); + if (ctx.variable() != null) { + tokens.addAll(visit(ctx.variable())); } - tokens.addAll(visit(ctx.orderedQuery(0))); + return tokens; + } + + @Override + public List visitDeleteStatement(HqlParser.DeleteStatementContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.DELETE())); + if (ctx.FROM() != null) { + tokens.add(new JpaQueryParsingToken(ctx.FROM())); + } + tokens.addAll(visit(ctx.targetEntity())); + if (ctx.whereClause() != null) { + tokens.addAll(visit(ctx.whereClause())); + } + + return tokens; + } + + @Override + public List visitUpdateStatement(HqlParser.UpdateStatementContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.UPDATE())); + if (ctx.VERSIONED() != null) { + tokens.add(new JpaQueryParsingToken(ctx.VERSIONED())); + } + tokens.addAll(visit(ctx.targetEntity())); + tokens.addAll(visit(ctx.setClause())); + if (ctx.whereClause() != null) { + tokens.addAll(visit(ctx.whereClause())); + } + + return tokens; + } + + @Override + public List visitSetClause(HqlParser.SetClauseContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.SET())); + + ctx.assignment().forEach(assignmentContext -> { + + tokens.addAll(visit(assignmentContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + SPACE(tokens); + + return tokens; + } + + @Override + public List visitAssignment(HqlParser.AssignmentContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.simplePath())); + tokens.add(TOKEN_EQUALS); + tokens.addAll(visit(ctx.expressionOrPredicate())); + + return tokens; + } - for (int i = 1; i < ctx.orderedQuery().size(); i++) { + @Override + public List visitInsertStatement(HqlParser.InsertStatementContext ctx) { + + List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.setOperator(i - 1))); - tokens.addAll(visit(ctx.orderedQuery(i))); + tokens.add(new JpaQueryParsingToken(ctx.INSERT())); + if (ctx.INTO() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INTO())); + } + tokens.addAll(visit(ctx.targetEntity())); + tokens.addAll(visit(ctx.targetFields())); + if (ctx.queryExpression() != null) { + tokens.addAll(visit(ctx.queryExpression())); + } else if (ctx.valuesList() != null) { + tokens.addAll(visit(ctx.valuesList())); } return tokens; } + @Override + public List visitTargetFields(HqlParser.TargetFieldsContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(TOKEN_OPEN_PAREN); + + ctx.simplePath().forEach(simplePathContext -> { + + tokens.addAll(visit(simplePathContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitValuesList(HqlParser.ValuesListContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.VALUES())); + + ctx.values().forEach(valuesContext -> { + + tokens.addAll(visit(valuesContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + + return tokens; + } + + @Override + public List visitValues(HqlParser.ValuesContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(TOKEN_OPEN_PAREN); + + ctx.expressionOrPredicate().forEach(expressionOrPredicateContext -> { + + tokens.addAll(visit(expressionOrPredicateContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + @Override public List visitWithClause(HqlParser.WithClauseContext ctx) { @@ -106,7 +246,7 @@ public List visitCte(HqlParser.CteContext ctx) { if (ctx.MATERIALIZED() != null) { tokens.add(TOKEN_MATERIALIZED); } - + tokens.add(TOKEN_OPEN_PAREN); tokens.addAll(visit(ctx.queryExpression())); tokens.add(TOKEN_CLOSE_PAREN); @@ -121,6 +261,21 @@ public List visitCte(HqlParser.CteContext ctx) { return tokens; } + @Override + public List visitCteAttributes(HqlParser.CteAttributesContext ctx) { + + List tokens = new ArrayList<>(); + + ctx.identifier().forEach(identifierContext -> { + + tokens.addAll(visit(identifierContext)); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + + return tokens; + } + @Override public List visitSearchClause(HqlParser.SearchClauseContext ctx) { @@ -204,90 +359,84 @@ public List visitCycleClause(HqlParser.CycleClauseContext } @Override - public List visitCteAttributes(HqlParser.CteAttributesContext ctx) { + public List visitSimpleQueryGroup(HqlParser.SimpleQueryGroupContext ctx) { List tokens = new ArrayList<>(); - ctx.identifier().forEach(identifierContext -> { + if (ctx.withClause() != null) { + tokens.addAll(visit(ctx.withClause())); + } - tokens.addAll(visit(identifierContext)); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + tokens.addAll(visit(ctx.orderedQuery())); return tokens; } @Override - public List visitOrderedQuery(HqlParser.OrderedQueryContext ctx) { + public List visitSetQueryGroup(HqlParser.SetQueryGroupContext ctx) { List tokens = new ArrayList<>(); - if (ctx.query() != null) { - tokens.addAll(visit(ctx.query())); - } else if (ctx.queryExpression() != null) { - - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.queryExpression())); - tokens.add(TOKEN_CLOSE_PAREN); + if (ctx.withClause() != null) { + tokens.addAll(visit(ctx.withClause())); } - if (ctx.queryOrder() != null) { - tokens.addAll(visit(ctx.queryOrder())); + tokens.addAll(visit(ctx.orderedQuery(0))); + + for (int i = 0; i < ctx.setOperator().size(); i++) { + + tokens.addAll(visit(ctx.setOperator(i))); + tokens.addAll(visit(ctx.orderedQuery(i + 1))); } return tokens; } @Override - public List visitSelectQuery(HqlParser.SelectQueryContext ctx) { + public List visitQuerySpecExpression(HqlParser.QuerySpecExpressionContext ctx) { List tokens = new ArrayList<>(); - if (ctx.selectClause() != null) { - tokens.addAll(visit(ctx.selectClause())); - } - - if (ctx.fromClause() != null) { - tokens.addAll(visit(ctx.fromClause())); - } - - if (ctx.whereClause() != null) { - tokens.addAll(visit(ctx.whereClause())); - } - - if (ctx.groupByClause() != null) { - tokens.addAll(visit(ctx.groupByClause())); - } + tokens.addAll(visit(ctx.query())); - if (ctx.havingClause() != null) { - tokens.addAll(visit(ctx.havingClause())); + if (ctx.queryOrder() != null) { + tokens.addAll(visit(ctx.queryOrder())); } return tokens; } @Override - public List visitFromQuery(HqlParser.FromQueryContext ctx) { + public List visitNestedQueryExpression(HqlParser.NestedQueryExpressionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.fromClause())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.queryExpression())); + tokens.add(TOKEN_CLOSE_PAREN); - if (ctx.whereClause() != null) { - tokens.addAll(visit(ctx.whereClause())); + if (ctx.queryOrder() != null) { + tokens.addAll(visit(ctx.queryOrder())); } - if (ctx.groupByClause() != null) { - tokens.addAll(visit(ctx.groupByClause())); - } + return tokens; + } - if (ctx.havingClause() != null) { - tokens.addAll(visit(ctx.havingClause())); + @Override + public List visitSetOperator(HqlParser.SetOperatorContext ctx) { + + List tokens = new ArrayList<>(); + + if (ctx.UNION() != null) { + tokens.add(new JpaQueryParsingToken(ctx.UNION())); + } else if (ctx.INTERSECT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INTERSECT())); + } else if (ctx.EXCEPT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.EXCEPT())); } - if (ctx.selectClause() != null) { - tokens.addAll(visit(ctx.selectClause())); + if (ctx.ALL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ALL())); } return tokens; @@ -315,127 +464,101 @@ public List visitQueryOrder(HqlParser.QueryOrderContext ct } @Override - public List visitFromClause(HqlParser.FromClauseContext ctx) { + public List visitQuery(HqlParser.QueryContext ctx) { List tokens = new ArrayList<>(); - // TODO: Read up on Framework's LeastRecentlyUsedCache - tokens.add(new JpaQueryParsingToken(ctx.FROM())); + if (ctx.getChild(0) instanceof HqlParser.SelectClauseContext) { - ctx.entityWithJoins().forEach(entityWithJoinsContext -> { - tokens.addAll(visit(entityWithJoinsContext)); - NOSPACE(tokens); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); - SPACE(tokens); + tokens.addAll(visit(ctx.selectClause())); - return tokens; - } + if (ctx.fromClause() != null) { + tokens.addAll(visit(ctx.fromClause())); + } + } else { + tokens.addAll(visit(ctx.fromClause())); + } - @Override - public List visitEntityWithJoins(HqlParser.EntityWithJoinsContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.addAll(visit(ctx.fromRoot())); - SPACE(tokens); + if (ctx.whereClause() != null) { + tokens.addAll(visit(ctx.whereClause())); + } - ctx.joinSpecifier().forEach(joinSpecifierContext -> { - tokens.addAll(visit(joinSpecifierContext)); - }); + if (ctx.groupByClause() != null) { + tokens.addAll(visit(ctx.groupByClause())); + } - return tokens; - } + if (ctx.havingClause() != null) { + tokens.addAll(visit(ctx.havingClause())); + } - @Override - public List visitJoinSpecifier(HqlParser.JoinSpecifierContext ctx) { + if (ctx.getChild(0) instanceof HqlParser.FromClauseContext) { - if (ctx.join() != null) { - return visit(ctx.join()); - } else if (ctx.crossJoin() != null) { - return visit(ctx.crossJoin()); - } else if (ctx.jpaCollectionJoin() != null) { - return visit(ctx.jpaCollectionJoin()); - } else { - return List.of(); + if (ctx.selectClause() != null) { + tokens.addAll(visit(ctx.selectClause())); + } } + + return tokens; } @Override - public List visitFromRoot(HqlParser.FromRootContext ctx) { + public List visitFromClause(HqlParser.FromClauseContext ctx) { List tokens = new ArrayList<>(); - if (ctx.entityName() != null) { - - tokens.addAll(visit(ctx.entityName())); + // TODO: Read up on Framework's LeastRecentlyUsedCache + tokens.add(new JpaQueryParsingToken(ctx.FROM())); - if (ctx.variable() != null) { - tokens.addAll(visit(ctx.variable())); - } + ctx.entityWithJoins().forEach(entityWithJoinsContext -> { + tokens.addAll(visit(entityWithJoinsContext)); NOSPACE(tokens); - } else if (ctx.subquery() != null) { - - if (ctx.LATERAL() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LATERAL())); - } - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.subquery())); - tokens.add(TOKEN_CLOSE_PAREN); - - if (ctx.variable() != null) { - tokens.addAll(visit(ctx.variable())); - } - } + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + SPACE(tokens); return tokens; } @Override - public List visitJoin(HqlParser.JoinContext ctx) { + public List visitEntityWithJoins(HqlParser.EntityWithJoinsContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.joinType())); - tokens.add(new JpaQueryParsingToken(ctx.JOIN())); - - if (ctx.FETCH() != null) { - tokens.add(new JpaQueryParsingToken(ctx.FETCH())); - } - - tokens.addAll(visit(ctx.joinTarget())); + tokens.addAll(visit(ctx.fromRoot())); + SPACE(tokens); - if (ctx.joinRestriction() != null) { - tokens.addAll(visit(ctx.joinRestriction())); - } + ctx.children.forEach(parseTree -> { + if (parseTree instanceof HqlParser.JoinContext // + || parseTree instanceof HqlParser.CrossJoinContext // + || parseTree instanceof HqlParser.JpaCollectionJoinContext) { + tokens.addAll(visit(parseTree)); + } + }); return tokens; } @Override - public List visitJoinPath(HqlParser.JoinPathContext ctx) { + public List visitRootEntity(HqlParser.RootEntityContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.path())); + tokens.addAll(visit(ctx.entityName())); if (ctx.variable() != null) { tokens.addAll(visit(ctx.variable())); } + NOSPACE(tokens); return tokens; } @Override - public List visitJoinSubquery(HqlParser.JoinSubqueryContext ctx) { + public List visitRootSubquery(HqlParser.RootSubqueryContext ctx) { List tokens = new ArrayList<>(); - if (ctx.LATERAL() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LATERAL())); - } - tokens.add(TOKEN_OPEN_PAREN); tokens.addAll(visit(ctx.subquery())); tokens.add(TOKEN_CLOSE_PAREN); @@ -443,36 +566,51 @@ public List visitJoinSubquery(HqlParser.JoinSubqueryContex if (ctx.variable() != null) { tokens.addAll(visit(ctx.variable())); } + NOSPACE(tokens); return tokens; } @Override - public List visitUpdateStatement(HqlParser.UpdateStatementContext ctx) { + public List visitEntityName(HqlParser.EntityNameContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.UPDATE())); + ctx.identifier().forEach(identifierContext -> { - if (ctx.VERSIONED() != null) { - tokens.add(new JpaQueryParsingToken(ctx.VERSIONED())); - } + tokens.addAll(visit(identifierContext)); + NOSPACE(tokens); + tokens.add(TOKEN_DOT); + }); + CLIP(tokens); + SPACE(tokens); - tokens.addAll(visit(ctx.targetEntity())); - tokens.addAll(visit(ctx.setClause())); + return tokens; + } - if (ctx.whereClause() != null) { - tokens.addAll(visit(ctx.whereClause())); + @Override + public List visitVariable(HqlParser.VariableContext ctx) { + + List tokens = new ArrayList<>(); + + if (ctx.identifier() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.AS())); + tokens.addAll(visit(ctx.identifier())); + } else if (ctx.nakedIdentifier() != null) { + tokens.addAll(visit(ctx.nakedIdentifier())); } return tokens; } @Override - public List visitTargetEntity(HqlParser.TargetEntityContext ctx) { + public List visitCrossJoin(HqlParser.CrossJoinContext ctx) { List tokens = new ArrayList<>(); + tokens.add(new JpaQueryParsingToken(ctx.CROSS())); + tokens.add(new JpaQueryParsingToken(ctx.JOIN())); tokens.addAll(visit(ctx.entityName())); if (ctx.variable() != null) { @@ -483,995 +621,2270 @@ public List visitTargetEntity(HqlParser.TargetEntityContex } @Override - public List visitSetClause(HqlParser.SetClauseContext ctx) { + public List visitJpaCollectionJoin(HqlParser.JpaCollectionJoinContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.SET())); + tokens.add(TOKEN_COMMA); + tokens.add(new JpaQueryParsingToken(ctx.IN(), false)); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + NOSPACE(tokens); + tokens.add(TOKEN_CLOSE_PAREN); - ctx.assignment().forEach(assignmentContext -> { - tokens.addAll(visit(assignmentContext)); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + if (ctx.variable() != null) { + tokens.addAll(visit(ctx.variable())); + } return tokens; } @Override - public List visitAssignment(HqlParser.AssignmentContext ctx) { + public List visitJoin(HqlParser.JoinContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.simplePath())); - tokens.add(TOKEN_EQUALS); - tokens.addAll(visit(ctx.expressionOrPredicate())); + tokens.addAll(visit(ctx.joinType())); + tokens.add(new JpaQueryParsingToken(ctx.JOIN())); + + if (ctx.FETCH() != null) { + tokens.add(new JpaQueryParsingToken(ctx.FETCH())); + } + + tokens.addAll(visit(ctx.joinTarget())); + + if (ctx.joinRestriction() != null) { + tokens.addAll(visit(ctx.joinRestriction())); + } return tokens; } @Override - public List visitDeleteStatement(HqlParser.DeleteStatementContext ctx) { + public List visitJoinType(HqlParser.JoinTypeContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.DELETE())); - - if (ctx.FROM() != null) { - tokens.add(new JpaQueryParsingToken(ctx.FROM())); + if (ctx.INNER() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INNER())); } - - tokens.addAll(visit(ctx.targetEntity())); - - if (ctx.whereClause() != null) { - tokens.addAll(visit(ctx.whereClause())); + if (ctx.LEFT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LEFT())); + } + if (ctx.RIGHT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.RIGHT())); + } + if (ctx.FULL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.FULL())); + } + if (ctx.OUTER() != null) { + tokens.add(new JpaQueryParsingToken(ctx.OUTER())); } return tokens; } @Override - public List visitInsertStatement(HqlParser.InsertStatementContext ctx) { + public List visitJoinPath(HqlParser.JoinPathContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.INSERT())); - - if (ctx.INTO() != null) { - tokens.add(new JpaQueryParsingToken(ctx.INTO())); - } - - tokens.addAll(visit(ctx.targetEntity())); - tokens.addAll(visit(ctx.targetFields())); + tokens.addAll(visit(ctx.path())); - if (ctx.queryExpression() != null) { - tokens.addAll(visit(ctx.queryExpression())); - } else if (ctx.valuesList() != null) { - tokens.addAll(visit(ctx.valuesList())); + if (ctx.variable() != null) { + tokens.addAll(visit(ctx.variable())); } return tokens; } @Override - public List visitTargetFields(HqlParser.TargetFieldsContext ctx) { + public List visitJoinSubquery(HqlParser.JoinSubqueryContext ctx) { List tokens = new ArrayList<>(); - tokens.add(TOKEN_OPEN_PAREN); - - ctx.simplePath().forEach(simplePathContext -> { - tokens.addAll(visit(simplePathContext)); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + if (ctx.LATERAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LATERAL())); + } + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.subquery())); tokens.add(TOKEN_CLOSE_PAREN); + if (ctx.variable() != null) { + tokens.addAll(visit(ctx.variable())); + } + return tokens; } @Override - public List visitValuesList(HqlParser.ValuesListContext ctx) { + public List visitJoinRestriction(HqlParser.JoinRestrictionContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.VALUES())); + if (ctx.ON() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ON())); + } else if (ctx.WITH() != null) { + tokens.add(new JpaQueryParsingToken(ctx.WITH())); + } - ctx.values().forEach(valuesContext -> { - tokens.addAll(visit(valuesContext)); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + tokens.addAll(visit(ctx.predicate())); return tokens; } @Override - public List visitValues(HqlParser.ValuesContext ctx) { + public List visitSelectClause(HqlParser.SelectClauseContext ctx) { List tokens = new ArrayList<>(); - tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.SELECT())); - ctx.expression().forEach(expressionContext -> { - tokens.addAll(visit(expressionContext)); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + if (ctx.DISTINCT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.DISTINCT())); + } - tokens.add(TOKEN_CLOSE_PAREN); + tokens.addAll(visit(ctx.selectionList())); return tokens; } @Override - public List visitInstantiation(HqlParser.InstantiationContext ctx) { + public List visitSelectionList(HqlParser.SelectionListContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.NEW())); - tokens.addAll(visit(ctx.instantiationTarget())); - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.instantiationArguments())); - tokens.add(TOKEN_CLOSE_PAREN); + ctx.selection().forEach(selectionContext -> { + tokens.addAll(visit(selectionContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + SPACE(tokens); return tokens; } @Override - public List visitAlias(HqlParser.AliasContext ctx) { + public List visitSelection(HqlParser.SelectionContext ctx) { List tokens = new ArrayList<>(); - if (ctx.AS() != null) { - tokens.add(new JpaQueryParsingToken(ctx.AS())); - } + tokens.addAll(visit(ctx.selectExpression())); - tokens.addAll(visit(ctx.identifier())); + if (ctx.variable() != null) { + tokens.addAll(visit(ctx.variable())); + } return tokens; } @Override - public List visitGroupedItem(HqlParser.GroupedItemContext ctx) { + public List visitSelectExpression(HqlParser.SelectExpressionContext ctx) { - if (ctx.identifier() != null) { - return visit(ctx.identifier()); - } else if (ctx.INTEGER_LITERAL() != null) { - return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); - } else if (ctx.expression() != null) { - return visit(ctx.expression()); - } else { - return List.of(); - } - } + if (ctx.instantiation() != null) { + return visit(ctx.instantiation()); + } else if (ctx.mapEntrySelection() != null) { + return visit(ctx.mapEntrySelection()); + } else if (ctx.jpaSelectObjectSyntax() != null) { + return visit(ctx.jpaSelectObjectSyntax()); + } else if (ctx.expressionOrPredicate() != null) { + return visit(ctx.expressionOrPredicate()); + } else { + return List.of(); + } + } @Override - public List visitSortedItem(HqlParser.SortedItemContext ctx) { + public List visitMapEntrySelection(HqlParser.MapEntrySelectionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.sortExpression())); + tokens.add(new JpaQueryParsingToken(ctx.ENTRY())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); - if (ctx.sortDirection() != null) { - tokens.addAll(visit(ctx.sortDirection())); - } + return tokens; + } - if (ctx.nullsPrecedence() != null) { - tokens.addAll(visit(ctx.nullsPrecedence())); - } + @Override + public List visitInstantiation(HqlParser.InstantiationContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.NEW())); + tokens.addAll(visit(ctx.instantiationTarget())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.instantiationArguments())); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitSortExpression(HqlParser.SortExpressionContext ctx) { + public List visitInstantiationTarget(HqlParser.InstantiationTargetContext ctx) { - if (ctx.identifier() != null) { - return visit(ctx.identifier()); - } else if (ctx.INTEGER_LITERAL() != null) { - return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); - } else if (ctx.expression() != null) { - return visit(ctx.expression()); + if (ctx.LIST() != null) { + return List.of(new JpaQueryParsingToken(ctx.LIST())); + } else if (ctx.MAP() != null) { + return List.of(new JpaQueryParsingToken(ctx.MAP())); + } else if (ctx.simplePath() != null) { + + List tokens = visit(ctx.simplePath()); + NOSPACE(tokens); + return tokens; } else { return List.of(); } } @Override - public List visitSortDirection(HqlParser.SortDirectionContext ctx) { + public List visitInstantiationArguments(HqlParser.InstantiationArgumentsContext ctx) { - if (ctx.ASC() != null) { - return List.of(new JpaQueryParsingToken(ctx.ASC())); - } else if (ctx.DESC() != null) { - return List.of(new JpaQueryParsingToken(ctx.DESC())); - } else { - return List.of(); - } + List tokens = new ArrayList<>(); + + ctx.instantiationArgument().forEach(instantiationArgumentContext -> { + tokens.addAll(visit(instantiationArgumentContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + + return tokens; } @Override - public List visitNullsPrecedence(HqlParser.NullsPrecedenceContext ctx) { + public List visitInstantiationArgument(HqlParser.InstantiationArgumentContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.NULLS())); + tokens.addAll(visit(ctx.instantiationArgumentExpression())); - if (ctx.FIRST() != null) { - tokens.add(new JpaQueryParsingToken(ctx.FIRST())); - } else if (ctx.LAST() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LAST())); + if (ctx.variable() != null) { + tokens.addAll(visit(ctx.variable())); } return tokens; } @Override - public List visitLimitClause(HqlParser.LimitClauseContext ctx) { + public List visitInstantiationArgumentExpression( + HqlParser.InstantiationArgumentExpressionContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.LIMIT())); - tokens.addAll(visit(ctx.parameterOrIntegerLiteral())); + if (ctx.expressionOrPredicate() != null) { + tokens.addAll(visit(ctx.expressionOrPredicate())); + } else if (ctx.instantiation() != null) { + tokens.addAll(visit(ctx.instantiation())); + } return tokens; } @Override - public List visitOffsetClause(HqlParser.OffsetClauseContext ctx) { + public List visitJpaSelectObjectSyntax(HqlParser.JpaSelectObjectSyntaxContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.OFFSET())); - tokens.addAll(visit(ctx.parameterOrIntegerLiteral())); + tokens.add(new JpaQueryParsingToken(ctx.OBJECT(), false)); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.identifier())); + NOSPACE(tokens); + tokens.add(TOKEN_CLOSE_PAREN); - if (ctx.ROW() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ROW())); - } else if (ctx.ROWS() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ROWS())); - } + return tokens; + } + + @Override + public List visitSimplePath(HqlParser.SimplePathContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.identifier())); + NOSPACE(tokens); + + ctx.simplePathElement().forEach(simplePathElementContext -> { + tokens.addAll(visit(simplePathElementContext)); + NOSPACE(tokens); + }); + SPACE(tokens); return tokens; } @Override - public List visitFetchClause(HqlParser.FetchClauseContext ctx) { + public List visitSimplePathElement(HqlParser.SimplePathElementContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.FETCH())); + tokens.add(TOKEN_DOT); + tokens.addAll(visit(ctx.identifier())); - if (ctx.FIRST() != null) { - tokens.add(new JpaQueryParsingToken(ctx.FIRST())); - } else if (ctx.NEXT() != null) { - tokens.add(new JpaQueryParsingToken(ctx.NEXT())); - } + return tokens; + } - if (ctx.parameterOrIntegerLiteral() != null) { - tokens.addAll(visit(ctx.parameterOrIntegerLiteral())); - } else if (ctx.parameterOrNumberLiteral() != null) { + @Override + public List visitPath(HqlParser.PathContext ctx) { - tokens.addAll(visit(ctx.parameterOrNumberLiteral())); - tokens.add(TOKEN_PERCENT); - } + List tokens = new ArrayList<>(); - if (ctx.ROW() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ROW())); - } else if (ctx.ROWS() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ROWS())); - } + if (ctx.syntacticDomainPath() != null) { - if (ctx.ONLY() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ONLY())); - } else if (ctx.WITH() != null) { + tokens.addAll(visit(ctx.syntacticDomainPath())); - tokens.add(new JpaQueryParsingToken(ctx.WITH())); - tokens.add(new JpaQueryParsingToken(ctx.TIES())); + if (ctx.pathContinuation() != null) { + NOSPACE(tokens); + tokens.addAll(visit(ctx.pathContinuation())); + } + } else if (ctx.generalPathFragment() != null) { + tokens.addAll(visit(ctx.generalPathFragment())); } return tokens; } @Override - public List visitSubquery(HqlParser.SubqueryContext ctx) { - return visit(ctx.queryExpression()); + public List visitPathContinuation(HqlParser.PathContinuationContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(TOKEN_DOT); + tokens.addAll(visit(ctx.simplePath())); + + return tokens; } @Override - public List visitSelectClause(HqlParser.SelectClauseContext ctx) { + public List visitSyntacticDomainPath(HqlParser.SyntacticDomainPathContext ctx) { - List tokens = new ArrayList<>(); - - tokens.add(new JpaQueryParsingToken(ctx.SELECT())); + if (ctx.treatedNavigablePath() != null) { + return visit(ctx.treatedNavigablePath()); + } else if (ctx.collectionValueNavigablePath() != null) { + return visit(ctx.collectionValueNavigablePath()); + } else if (ctx.mapKeyNavigablePath() != null) { + return visit(ctx.mapKeyNavigablePath()); + } else if (ctx.simplePath() != null) { - if (ctx.DISTINCT() != null) { - tokens.add(new JpaQueryParsingToken(ctx.DISTINCT())); - } + List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.selectionList())); + tokens.addAll(visit(ctx.simplePath())); + tokens.addAll(visit(ctx.indexedPathAccessFragment())); - return tokens; + return tokens; + } else { + return List.of(); + } } @Override - public List visitSelectionList(HqlParser.SelectionListContext ctx) { + public List visitGeneralPathFragment(HqlParser.GeneralPathFragmentContext ctx) { List tokens = new ArrayList<>(); - ctx.selection().forEach(selectionContext -> { - tokens.addAll(visit(selectionContext)); - NOSPACE(tokens); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); - SPACE(tokens); + tokens.addAll(visit(ctx.simplePath())); + + if (ctx.indexedPathAccessFragment() != null) { + tokens.addAll(visit(ctx.indexedPathAccessFragment())); + } return tokens; } @Override - public List visitSelection(HqlParser.SelectionContext ctx) { + public List visitIndexedPathAccessFragment(HqlParser.IndexedPathAccessFragmentContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.selectExpression())); + tokens.add(TOKEN_OPEN_SQUARE_BRACKET); + tokens.addAll(visit(ctx.expression())); + tokens.add(TOKEN_CLOSE_SQUARE_BRACKET); - if (ctx.variable() != null) { - tokens.addAll(visit(ctx.variable())); + if (ctx.generalPathFragment() != null) { + + tokens.add(TOKEN_DOT); + tokens.addAll(visit(ctx.generalPathFragment())); } return tokens; } @Override - public List visitSelectExpression(HqlParser.SelectExpressionContext ctx) { + public List visitTreatedNavigablePath(HqlParser.TreatedNavigablePathContext ctx) { - if (ctx.instantiation() != null) { - return visit(ctx.instantiation()); - } else if (ctx.mapEntrySelection() != null) { - return visit(ctx.mapEntrySelection()); - } else if (ctx.jpaSelectObjectSyntax() != null) { - return visit(ctx.jpaSelectObjectSyntax()); - } else if (ctx.expressionOrPredicate() != null) { - return visit(ctx.expressionOrPredicate()); - } else { - return List.of(); + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.TREAT(), false)); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_AS); + tokens.addAll(visit(ctx.simplePath())); + NOSPACE(tokens); + tokens.add(TOKEN_CLOSE_PAREN); + + if (ctx.pathContinuation() != null) { + + NOSPACE(tokens); + tokens.addAll(visit(ctx.pathContinuation())); } + + return tokens; } @Override - public List visitMapEntrySelection(HqlParser.MapEntrySelectionContext ctx) { + public List visitCollectionValueNavigablePath( + HqlParser.CollectionValueNavigablePathContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.ENTRY())); + if (ctx.VALUE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.VALUE())); + } else if (ctx.ELEMENT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ELEMENT())); + } + + NOSPACE(tokens); tokens.add(TOKEN_OPEN_PAREN); tokens.addAll(visit(ctx.path())); + NOSPACE(tokens); tokens.add(TOKEN_CLOSE_PAREN); + if (ctx.pathContinuation() != null) { + tokens.addAll(visit(ctx.pathContinuation())); + } + return tokens; } @Override - public List visitJpaSelectObjectSyntax(HqlParser.JpaSelectObjectSyntaxContext ctx) { + public List visitMapKeyNavigablePath(HqlParser.MapKeyNavigablePathContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.OBJECT(), false)); + if (ctx.KEY() != null) { + tokens.add(new JpaQueryParsingToken(ctx.KEY(), false)); + } else if (ctx.INDEX() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INDEX(), false)); + } + tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.identifier())); + tokens.addAll(visit(ctx.path())); NOSPACE(tokens); tokens.add(TOKEN_CLOSE_PAREN); + if (ctx.pathContinuation() != null) { + + NOSPACE(tokens); + tokens.addAll(visit(ctx.pathContinuation())); + } + return tokens; } @Override - public List visitWhereClause(HqlParser.WhereClauseContext ctx) { + public List visitGroupByClause(HqlParser.GroupByClauseContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.WHERE())); + tokens.add(new JpaQueryParsingToken(ctx.GROUP())); + tokens.add(new JpaQueryParsingToken(ctx.BY())); - ctx.predicate().forEach(predicateContext -> { - tokens.addAll(visit(predicateContext)); + ctx.groupByExpression().forEach(groupByExpressionContext -> { + tokens.addAll(visit(groupByExpressionContext)); + NOSPACE(tokens); tokens.add(TOKEN_COMMA); }); CLIP(tokens); + SPACE(tokens); return tokens; } @Override - public List visitJoinType(HqlParser.JoinTypeContext ctx) { + public List visitGroupByExpression(HqlParser.GroupByExpressionContext ctx) { List tokens = new ArrayList<>(); - if (ctx.INNER() != null) { - tokens.add(new JpaQueryParsingToken(ctx.INNER())); + if (ctx.identifier() != null) { + tokens.addAll(visit(ctx.identifier())); + } else if (ctx.INTEGER_LITERAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); + } else if (ctx.expression() != null) { + tokens.addAll(visit(ctx.expression())); + } + + return tokens; + } + + @Override + public List visitHavingClause(HqlParser.HavingClauseContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.HAVING())); + tokens.addAll(visit(ctx.predicate())); + + return tokens; + } + + @Override + public List visitOrderByClause(HqlParser.OrderByClauseContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.ORDER())); + tokens.add(new JpaQueryParsingToken(ctx.BY())); + + ctx.sortSpecification().forEach(sortedItemContext -> { + tokens.addAll(visit(sortedItemContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + + return tokens; + } + + @Override + public List visitOrderByFragment(HqlParser.OrderByFragmentContext ctx) { + + List tokens = new ArrayList<>(); + + ctx.sortSpecification().forEach(sortedItemContext -> { + tokens.addAll(visit(sortedItemContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + + return tokens; + } + + @Override + public List visitSortSpecification(HqlParser.SortSpecificationContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.sortExpression())); + + if (ctx.sortDirection() != null) { + tokens.addAll(visit(ctx.sortDirection())); + } + + if (ctx.nullsPrecedence() != null) { + tokens.addAll(visit(ctx.nullsPrecedence())); + } + + return tokens; + } + + @Override + public List visitNullsPrecedence(HqlParser.NullsPrecedenceContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.NULLS())); + + if (ctx.FIRST() != null) { + tokens.add(new JpaQueryParsingToken(ctx.FIRST())); + } else if (ctx.LAST() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LAST())); + } + + return tokens; + } + + @Override + public List visitSortExpression(HqlParser.SortExpressionContext ctx) { + + if (ctx.identifier() != null) { + return visit(ctx.identifier()); + } else if (ctx.INTEGER_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); + } else if (ctx.expression() != null) { + return visit(ctx.expression()); + } else { + return List.of(); + } + } + + @Override + public List visitSortDirection(HqlParser.SortDirectionContext ctx) { + + if (ctx.ASC() != null) { + return List.of(new JpaQueryParsingToken(ctx.ASC())); + } else if (ctx.DESC() != null) { + return List.of(new JpaQueryParsingToken(ctx.DESC())); + } else { + return List.of(); + } + } + + @Override + public List visitCollateFunction(HqlParser.CollateFunctionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.COLLATE())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.expression())); + tokens.add(TOKEN_AS); + tokens.addAll(visit(ctx.collation())); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitCollation(HqlParser.CollationContext ctx) { + return visit(ctx.simplePath()); + } + + @Override + public List visitLimitClause(HqlParser.LimitClauseContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.LIMIT())); + tokens.addAll(visit(ctx.parameterOrIntegerLiteral())); + + return tokens; + } + + @Override + public List visitOffsetClause(HqlParser.OffsetClauseContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.OFFSET())); + tokens.addAll(visit(ctx.parameterOrIntegerLiteral())); + + if (ctx.ROW() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ROW())); + } else if (ctx.ROWS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ROWS())); + } + + return tokens; + } + + @Override + public List visitFetchClause(HqlParser.FetchClauseContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.FETCH())); + + if (ctx.FIRST() != null) { + tokens.add(new JpaQueryParsingToken(ctx.FIRST())); + } else if (ctx.NEXT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.NEXT())); + } + + if (ctx.parameterOrIntegerLiteral() != null) { + tokens.addAll(visit(ctx.parameterOrIntegerLiteral())); + } else if (ctx.parameterOrNumberLiteral() != null) { + + tokens.addAll(visit(ctx.parameterOrNumberLiteral())); + tokens.add(TOKEN_PERCENT); + } + + if (ctx.ROW() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ROW())); + } else if (ctx.ROWS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ROWS())); + } + + if (ctx.ONLY() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ONLY())); + } else if (ctx.WITH() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.WITH())); + tokens.add(new JpaQueryParsingToken(ctx.TIES())); + } + + return tokens; + } + + @Override + public List visitParameterOrIntegerLiteral(HqlParser.ParameterOrIntegerLiteralContext ctx) { + + if (ctx.parameter() != null) { + return visit(ctx.parameter()); + } else if (ctx.INTEGER_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); + } else { + return List.of(); + } + } + + @Override + public List visitParameterOrNumberLiteral(HqlParser.ParameterOrNumberLiteralContext ctx) { + + if (ctx.parameter() != null) { + return visit(ctx.parameter()); + } else if (ctx.INTEGER_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); + } else if (ctx.FLOAT_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.FLOAT_LITERAL())); + } else if (ctx.DOUBLE_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.DOUBLE_LITERAL())); + } else { + return List.of(); + } + } + + @Override + public List visitWhereClause(HqlParser.WhereClauseContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.WHERE())); + tokens.addAll(visit(ctx.predicate())); + + return tokens; + } + + @Override + public List visitBetweenPredicate(HqlParser.BetweenPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression(0))); + + if (ctx.NOT() != null) { + tokens.add(TOKEN_NOT); + } + tokens.add(new JpaQueryParsingToken(ctx.BETWEEN())); + tokens.addAll(visit(ctx.expression(1))); + tokens.add(new JpaQueryParsingToken(ctx.AND())); + tokens.addAll(visit(ctx.expression(2))); + + return tokens; + } + + @Override + public List visitExistsPredicate(HqlParser.ExistsPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.EXISTS())); + tokens.addAll(visit(ctx.expression())); + + return tokens; + } + + @Override + public List visitAndPredicate(HqlParser.AndPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.predicate(0))); + tokens.add(new JpaQueryParsingToken(ctx.AND())); + tokens.addAll(visit(ctx.predicate(1))); + + return tokens; + } + + @Override + public List visitGroupedPredicate(HqlParser.GroupedPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.predicate())); + NOSPACE(tokens); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitLikePredicate(HqlParser.LikePredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression(0))); + + if (ctx.NOT() != null) { + tokens.add(TOKEN_NOT); + } + if (ctx.LIKE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LIKE())); + } else if (ctx.ILIKE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ILIKE())); + } + tokens.addAll(visit(ctx.expression(1))); + + if (ctx.likeEscape() != null) { + tokens.addAll(visit(ctx.likeEscape())); + } + + return tokens; + } + + @Override + public List visitInPredicate(HqlParser.InPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression())); + + if (ctx.NOT() != null) { + tokens.add(TOKEN_NOT); + } + tokens.add(new JpaQueryParsingToken(ctx.IN())); + tokens.addAll(visit(ctx.inList())); + + return tokens; + } + + @Override + public List visitComparisonPredicate(HqlParser.ComparisonPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression(0))); + tokens.addAll(visit(ctx.comparisonOperator())); + tokens.addAll(visit(ctx.expression(1))); + + return tokens; + } + + @Override + public List visitExistsCollectionPartPredicate( + HqlParser.ExistsCollectionPartPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.EXISTS())); + if (ctx.ELEMENTS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); + } else if (ctx.INDICES() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + } + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.simplePath())); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitNegatedPredicate(HqlParser.NegatedPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.NOT())); + tokens.addAll(visit(ctx.predicate())); + + return tokens; + } + + @Override + public List visitBooleanExpressionPredicate(HqlParser.BooleanExpressionPredicateContext ctx) { + return visit(ctx.expression()); + } + + @Override + public List visitOrPredicate(HqlParser.OrPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.predicate(0))); + tokens.add(new JpaQueryParsingToken(ctx.OR())); + tokens.addAll(visit(ctx.predicate(1))); + + return tokens; + } + + @Override + public List visitMemberOfPredicate(HqlParser.MemberOfPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression())); + if (ctx.NOT() != null) { + tokens.add(TOKEN_NOT); + } + tokens.add(new JpaQueryParsingToken(ctx.MEMBER())); + if (ctx.OF() != null) { + tokens.add(new JpaQueryParsingToken(ctx.OF())); + } + tokens.addAll(visit(ctx.path())); + + return tokens; + } + + @Override + public List visitIsEmptyPredicate(HqlParser.IsEmptyPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression())); + tokens.add(new JpaQueryParsingToken(ctx.IS())); + if (ctx.NOT() != null) { + tokens.add(TOKEN_NOT); + } + tokens.add(new JpaQueryParsingToken(ctx.EMPTY())); + + return tokens; + } + + @Override + public List visitIsNullPredicate(HqlParser.IsNullPredicateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression())); + tokens.add(new JpaQueryParsingToken(ctx.IS())); + if (ctx.NOT() != null) { + tokens.add(TOKEN_NOT); + } + tokens.add(new JpaQueryParsingToken(ctx.NULL())); + + return tokens; + } + + @Override + public List visitComparisonOperator(HqlParser.ComparisonOperatorContext ctx) { + + if (ctx.EQUAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.EQUAL())); + } else if (ctx.NOT_EQUAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.NOT_EQUAL())); + } else if (ctx.GREATER() != null) { + return List.of(new JpaQueryParsingToken(ctx.GREATER())); + } else if (ctx.GREATER_EQUAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.GREATER_EQUAL())); + } else if (ctx.LESS() != null) { + return List.of(new JpaQueryParsingToken(ctx.LESS())); + } else if (ctx.LESS_EQUAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.LESS_EQUAL())); + } else if (ctx.IS() != null) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.IS())); + if (ctx.NOT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.NOT())); + } + tokens.add(new JpaQueryParsingToken(ctx.DISTINCT())); + tokens.add(new JpaQueryParsingToken(ctx.FROM())); + + return tokens; + } else { + return List.of(); + } + } + + @Override + public List visitPersistentCollectionReferenceInList( + HqlParser.PersistentCollectionReferenceInListContext ctx) { + + List tokens = new ArrayList<>(); + + if (ctx.ELEMENTS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); + } else if (ctx.INDICES() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + } + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.simplePath())); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitExplicitTupleInList(HqlParser.ExplicitTupleInListContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(TOKEN_OPEN_PAREN); + + ctx.expressionOrPredicate().forEach(expressionOrPredicateContext -> { + tokens.addAll(visit(expressionOrPredicateContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitSubqueryInList(HqlParser.SubqueryInListContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.subquery())); + NOSPACE(tokens); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitParamInList(HqlParser.ParamInListContext ctx) { + return visit(ctx.parameter()); + } + + @Override + public List visitLikeEscape(HqlParser.LikeEscapeContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.ESCAPE())); + if (ctx.STRING_LITERAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.STRING_LITERAL())); + } else if (ctx.JAVA_STRING_LITERAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.JAVA_STRING_LITERAL())); + } else if (ctx.parameter() != null) { + tokens.addAll(visit(ctx.parameter())); + } + + return tokens; + } + + @Override + public List visitAdditionExpression(HqlParser.AdditionExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression(0))); + tokens.addAll(visit(ctx.additiveOperator())); + tokens.addAll(visit(ctx.expression(1))); + + return tokens; + } + + @Override + public List visitFromDurationExpression(HqlParser.FromDurationExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression())); + tokens.add(new JpaQueryParsingToken(ctx.BY())); + tokens.addAll(visit(ctx.datetimeField())); + + return tokens; + } + + @Override + public List visitBarePrimaryExpression(HqlParser.BarePrimaryExpressionContext ctx) { + return visit(ctx.primaryExpression()); + } + + @Override + public List visitTupleExpression(HqlParser.TupleExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(TOKEN_OPEN_PAREN); + + ctx.expressionOrPredicate().forEach(expressionOrPredicateContext -> { + + tokens.addAll(visit(expressionOrPredicateContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitUnaryExpression(HqlParser.UnaryExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.signOperator())); + tokens.addAll(visit(ctx.expression())); + + return tokens; + } + + @Override + public List visitGroupedExpression(HqlParser.GroupedExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.expression())); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitConcatenationExpression(HqlParser.ConcatenationExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression(0))); + tokens.add(TOKEN_DOUBLE_PIPE); + tokens.addAll(visit(ctx.expression(1))); + + return tokens; + } + + @Override + public List visitMultiplicationExpression(HqlParser.MultiplicationExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression(0))); + NOSPACE(tokens); + tokens.addAll(visit(ctx.multiplicativeOperator())); + NOSPACE(tokens); + tokens.addAll(visit(ctx.expression(1))); + + return tokens; + } + + @Override + public List visitToDurationExpression(HqlParser.ToDurationExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.expression())); + tokens.addAll(visit(ctx.datetimeField())); + + return tokens; + } + + @Override + public List visitSubqueryExpression(HqlParser.SubqueryExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.subquery())); + NOSPACE(tokens); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitUnaryNumericLiteralExpression( + HqlParser.UnaryNumericLiteralExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.signOperator())); + tokens.addAll(visit(ctx.numericLiteral())); + + return tokens; + } + + @Override + public List visitCaseExpression(HqlParser.CaseExpressionContext ctx) { + return visit(ctx.caseList()); + } + + @Override + public List visitLiteralExpression(HqlParser.LiteralExpressionContext ctx) { + return visit(ctx.literal()); + } + + @Override + public List visitParameterExpression(HqlParser.ParameterExpressionContext ctx) { + return visit(ctx.parameter()); + } + + @Override + public List visitEntityTypeExpression(HqlParser.EntityTypeExpressionContext ctx) { + return visit(ctx.entityTypeReference()); + } + + @Override + public List visitEntityIdExpression(HqlParser.EntityIdExpressionContext ctx) { + return visit(ctx.entityIdReference()); + } + + @Override + public List visitEntityVersionExpression(HqlParser.EntityVersionExpressionContext ctx) { + return visit(ctx.entityVersionReference()); + } + + @Override + public List visitEntityNaturalIdExpression(HqlParser.EntityNaturalIdExpressionContext ctx) { + return visit(ctx.entityNaturalIdReference()); + } + + @Override + public List visitToOneFkExpression(HqlParser.ToOneFkExpressionContext ctx) { + return visit(ctx.toOneFkReference()); + } + + @Override + public List visitSyntacticPathExpression(HqlParser.SyntacticPathExpressionContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.syntacticDomainPath())); + if (ctx.pathContinuation() != null) { + tokens.addAll(visit(ctx.pathContinuation())); + } + + return tokens; + } + + @Override + public List visitFunctionExpression(HqlParser.FunctionExpressionContext ctx) { + return visit(ctx.function()); + } + + @Override + public List visitGeneralPathExpression(HqlParser.GeneralPathExpressionContext ctx) { + return visit(ctx.generalPathFragment()); + } + + @Override + public List visitExpressionOrPredicate(HqlParser.ExpressionOrPredicateContext ctx) { + + if (ctx.expression() != null) { + return visit(ctx.expression()); + } else if (ctx.predicate() != null) { + return visit(ctx.predicate()); + } else { + return List.of(); + } + } + + @Override + public List visitMultiplicativeOperator(HqlParser.MultiplicativeOperatorContext ctx) { + + if (ctx.SLASH() != null) { + return List.of(new JpaQueryParsingToken(ctx.SLASH())); + } else if (ctx.PERCENT_OP() != null) { + return List.of(new JpaQueryParsingToken(ctx.PERCENT_OP())); + } else if (ctx.ASTERISK() != null) { + return List.of(new JpaQueryParsingToken(ctx.ASTERISK())); + } else { + return List.of(); } - if (ctx.LEFT() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LEFT())); + } + + @Override + public List visitAdditiveOperator(HqlParser.AdditiveOperatorContext ctx) { + + if (ctx.PLUS() != null) { + return List.of(new JpaQueryParsingToken(ctx.PLUS())); + } else if (ctx.MINUS() != null) { + return List.of(new JpaQueryParsingToken(ctx.MINUS())); + } else { + return List.of(); } - if (ctx.RIGHT() != null) { - tokens.add(new JpaQueryParsingToken(ctx.RIGHT())); + } + + @Override + public List visitSignOperator(HqlParser.SignOperatorContext ctx) { + + if (ctx.PLUS() != null) { + return List.of(new JpaQueryParsingToken(ctx.PLUS())); + } else if (ctx.MINUS() != null) { + return List.of(new JpaQueryParsingToken(ctx.MINUS())); + } else { + return List.of(); } - if (ctx.FULL() != null) { - tokens.add(new JpaQueryParsingToken(ctx.FULL())); + } + + @Override + public List visitEntityTypeReference(HqlParser.EntityTypeReferenceContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.TYPE(), false)); + tokens.add(TOKEN_OPEN_PAREN); + if (ctx.path() != null) { + tokens.addAll(visit(ctx.path())); + } else if (ctx.parameter() != null) { + tokens.addAll(visit(ctx.parameter())); } - if (ctx.OUTER() != null) { - tokens.add(new JpaQueryParsingToken(ctx.OUTER())); + NOSPACE(tokens); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitEntityIdReference(HqlParser.EntityIdReferenceContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.ID())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + + if (ctx.pathContinuation() != null) { + tokens.addAll(visit(ctx.pathContinuation())); + } + + return tokens; + } + + @Override + public List visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.VERSION())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitEntityNaturalIdReference(HqlParser.EntityNaturalIdReferenceContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.NATURALID())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + + if (ctx.pathContinuation() != null) { + tokens.addAll(visit(ctx.pathContinuation())); + } + + return tokens; + } + + @Override + public List visitToOneFkReference(HqlParser.ToOneFkReferenceContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.FK())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + + return tokens; + } + + @Override + public List visitCaseList(HqlParser.CaseListContext ctx) { + + if (ctx.simpleCaseList() != null) { + return visit(ctx.simpleCaseList()); + } else if (ctx.searchedCaseList() != null) { + return visit(ctx.searchedCaseList()); + } else { + return List.of(); + } + } + + @Override + public List visitSimpleCaseList(HqlParser.SimpleCaseListContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.CASE())); + tokens.addAll(visit(ctx.expressionOrPredicate())); + ctx.simpleCaseWhen().forEach(simpleCaseWhenContext -> { + tokens.addAll(visit(simpleCaseWhenContext)); + }); + if (ctx.caseOtherwise() != null) { + tokens.addAll(visit(ctx.caseOtherwise())); + } + tokens.add(new JpaQueryParsingToken(ctx.END())); + + return tokens; + } + + @Override + public List visitSimpleCaseWhen(HqlParser.SimpleCaseWhenContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.WHEN())); + tokens.addAll(visit(ctx.expression())); + tokens.add(new JpaQueryParsingToken(ctx.THEN())); + tokens.addAll(visit(ctx.expressionOrPredicate())); + + return tokens; + } + + @Override + public List visitCaseOtherwise(HqlParser.CaseOtherwiseContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.ELSE())); + tokens.addAll(visit(ctx.expressionOrPredicate())); + + return tokens; + } + + @Override + public List visitSearchedCaseList(HqlParser.SearchedCaseListContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.CASE())); + ctx.searchedCaseWhen().forEach(searchedCaseWhenContext -> { + tokens.addAll(visit(searchedCaseWhenContext)); + }); + if (ctx.caseOtherwise() != null) { + tokens.addAll(visit(ctx.caseOtherwise())); + } + tokens.add(new JpaQueryParsingToken(ctx.END())); + + return tokens; + } + + @Override + public List visitSearchedCaseWhen(HqlParser.SearchedCaseWhenContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.WHEN())); + tokens.addAll(visit(ctx.predicate())); + tokens.add(new JpaQueryParsingToken(ctx.THEN())); + tokens.addAll(visit(ctx.expressionOrPredicate())); + + return tokens; + } + + @Override + public List visitLiteral(HqlParser.LiteralContext ctx) { + + if (ctx.STRING_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.STRING_LITERAL())); + } else if (ctx.JAVA_STRING_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.JAVA_STRING_LITERAL())); + } else if (ctx.NULL() != null) { + return List.of(new JpaQueryParsingToken(ctx.NULL())); + } else if (ctx.booleanLiteral() != null) { + return visit(ctx.booleanLiteral()); + } else if (ctx.numericLiteral() != null) { + return visit(ctx.numericLiteral()); + } else if (ctx.binaryLiteral() != null) { + return visit(ctx.binaryLiteral()); + } else if (ctx.temporalLiteral() != null) { + return visit(ctx.temporalLiteral()); + } else if (ctx.generalizedLiteral() != null) { + return visit(ctx.generalizedLiteral()); + } else { + return List.of(); + } + } + + @Override + public List visitBooleanLiteral(HqlParser.BooleanLiteralContext ctx) { + + if (ctx.TRUE() != null) { + return List.of(new JpaQueryParsingToken(ctx.TRUE())); + } else if (ctx.FALSE() != null) { + return List.of(new JpaQueryParsingToken(ctx.FALSE())); + } else { + return List.of(); + } + } + + @Override + public List visitNumericLiteral(HqlParser.NumericLiteralContext ctx) { + + if (ctx.INTEGER_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); + } else if (ctx.LONG_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.LONG_LITERAL())); + } else if (ctx.BIG_INTEGER_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.BIG_INTEGER_LITERAL())); + } else if (ctx.FLOAT_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.FLOAT_LITERAL())); + } else if (ctx.DOUBLE_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.DOUBLE_LITERAL())); + } else if (ctx.BIG_DECIMAL_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.BIG_DECIMAL_LITERAL())); + } else if (ctx.HEX_LITERAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.HEX_LITERAL())); + } else { + return List.of(); + } + } + + @Override + public List visitBinaryLiteral(HqlParser.BinaryLiteralContext ctx) { + + List tokens = new ArrayList<>(); + + if (ctx.BINARY_LITERAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.BINARY_LITERAL())); + } else if (ctx.LEFT_BRACE() != null) { + + tokens.add(TOKEN_OPEN_BRACE); + ctx.HEX_LITERAL().forEach(terminalNode -> { + tokens.add(new JpaQueryParsingToken(terminalNode)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + tokens.add(TOKEN_CLOSE_BRACE); + + } + + return tokens; + } + + @Override + public List visitTemporalLiteral(HqlParser.TemporalLiteralContext ctx) { + + if (ctx.dateTimeLiteral() != null) { + return visit(ctx.dateTimeLiteral()); + } else if (ctx.dateLiteral() != null) { + return visit(ctx.dateLiteral()); + } else if (ctx.timeLiteral() != null) { + return visit(ctx.timeLiteral()); + } else if (ctx.jdbcTimestampLiteral() != null) { + return visit(ctx.jdbcTimestampLiteral()); + } else if (ctx.jdbcDateLiteral() != null) { + return visit(ctx.jdbcDateLiteral()); + } else if (ctx.jdbcTimeLiteral() != null) { + return visit(ctx.jdbcTimeLiteral()); + } else { + return List.of(); + } + } + + @Override + public List visitDateTimeLiteral(HqlParser.DateTimeLiteralContext ctx) { + + if (ctx.localDateTimeLiteral() != null) { + return visit(ctx.localDateTimeLiteral()); + } else if (ctx.zonedDateTimeLiteral() != null) { + return visit(ctx.zonedDateTimeLiteral()); + } else if (ctx.offsetDateTimeLiteral() != null) { + return visit(ctx.offsetDateTimeLiteral()); + } else { + return List.of(); + } + } + + @Override + public List visitLocalDateTimeLiteral(HqlParser.LocalDateTimeLiteralContext ctx) { + + List tokens = new ArrayList<>(); + + if (ctx.LEFT_BRACE() != null) { + + tokens.add(TOKEN_OPEN_BRACE); + tokens.addAll(visit(ctx.localDateTime())); + tokens.add(TOKEN_CLOSE_BRACE); + } else if (ctx.DATETIME() != null) { + + if (ctx.LOCAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LOCAL())); + } + tokens.add(new JpaQueryParsingToken(ctx.DATETIME())); + tokens.addAll(visit(ctx.localDateTime())); + } + + return tokens; + } + + @Override + public List visitZonedDateTimeLiteral(HqlParser.ZonedDateTimeLiteralContext ctx) { + + List tokens = new ArrayList<>(); + + if (ctx.LEFT_BRACE() != null) { + + tokens.add(TOKEN_OPEN_BRACE); + tokens.addAll(visit(ctx.zonedDateTime())); + tokens.add(TOKEN_CLOSE_BRACE); + } else if (ctx.DATETIME() != null) { + + if (ctx.ZONED() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ZONED())); + } + tokens.add(new JpaQueryParsingToken(ctx.DATETIME())); + tokens.addAll(visit(ctx.zonedDateTime())); + } + + return tokens; + } + + @Override + public List visitOffsetDateTimeLiteral(HqlParser.OffsetDateTimeLiteralContext ctx) { + + List tokens = new ArrayList<>(); + + if (ctx.LEFT_BRACE() != null) { + + tokens.add(TOKEN_OPEN_BRACE); + tokens.addAll(visit(ctx.offsetDateTime())); + tokens.add(TOKEN_CLOSE_BRACE); + } else if (ctx.DATETIME() != null) { + + if (ctx.OFFSET() != null) { + tokens.add(new JpaQueryParsingToken(ctx.OFFSET())); + } + tokens.add(new JpaQueryParsingToken(ctx.DATETIME())); + tokens.addAll(visit(ctx.offsetDateTimeWithMinutes())); } - if (ctx.CROSS() != null) { - tokens.add(new JpaQueryParsingToken(ctx.CROSS())); + + return tokens; + } + + @Override + public List visitDateLiteral(HqlParser.DateLiteralContext ctx) { + + List tokens = new ArrayList<>(); + + if (ctx.LEFT_BRACE() != null) { + + tokens.add(TOKEN_OPEN_BRACE); + tokens.addAll(visit(ctx.date())); + tokens.add(TOKEN_CLOSE_BRACE); + } else if (ctx.DATE() != null) { + + if (ctx.LOCAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LOCAL())); + } + tokens.add(new JpaQueryParsingToken(ctx.DATE())); + tokens.addAll(visit(ctx.date())); } return tokens; } @Override - public List visitCrossJoin(HqlParser.CrossJoinContext ctx) { + public List visitTimeLiteral(HqlParser.TimeLiteralContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.CROSS())); - tokens.add(new JpaQueryParsingToken(ctx.JOIN())); - tokens.addAll(visit(ctx.entityName())); + if (ctx.LEFT_BRACE() != null) { - if (ctx.variable() != null) { - tokens.addAll(visit(ctx.variable())); + tokens.add(TOKEN_OPEN_BRACE); + tokens.addAll(visit(ctx.time())); + tokens.add(TOKEN_CLOSE_BRACE); + } else if (ctx.TIME() != null) { + + if (ctx.LOCAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LOCAL())); + } + tokens.add(new JpaQueryParsingToken(ctx.TIME())); + tokens.addAll(visit(ctx.time())); } return tokens; } @Override - public List visitJoinRestriction(HqlParser.JoinRestrictionContext ctx) { + public List visitDateTime(HqlParser.DateTimeContext ctx) { - List tokens = new ArrayList<>(); - - if (ctx.ON() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ON())); - } else if (ctx.WITH() != null) { - tokens.add(new JpaQueryParsingToken(ctx.WITH())); + if (ctx.localDateTime() != null) { + return visit(ctx.localDateTime()); + } else if (ctx.zonedDateTime() != null) { + return visit(ctx.zonedDateTime()); + } else if (ctx.offsetDateTime() != null) { + return visit(ctx.offsetDateTime()); + } else { + return List.of(); } + } - tokens.addAll(visit(ctx.predicate())); + @Override + public List visitLocalDateTime(HqlParser.LocalDateTimeContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.date())); + tokens.addAll(visit(ctx.time())); return tokens; } @Override - public List visitJpaCollectionJoin(HqlParser.JpaCollectionJoinContext ctx) { + public List visitZonedDateTime(HqlParser.ZonedDateTimeContext ctx) { List tokens = new ArrayList<>(); - tokens.add(TOKEN_COMMA); - tokens.add(new JpaQueryParsingToken(ctx.IN(), false)); - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.path())); - NOSPACE(tokens); - tokens.add(TOKEN_CLOSE_PAREN); - - if (ctx.variable() != null) { - tokens.addAll(visit(ctx.variable())); - } + tokens.addAll(visit(ctx.date())); + tokens.addAll(visit(ctx.time())); + tokens.addAll(visit(ctx.zoneId())); return tokens; } @Override - public List visitGroupByClause(HqlParser.GroupByClauseContext ctx) { + public List visitOffsetDateTime(HqlParser.OffsetDateTimeContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.GROUP())); - tokens.add(new JpaQueryParsingToken(ctx.BY())); - - ctx.groupedItem().forEach(groupedItemContext -> { - tokens.addAll(visit(groupedItemContext)); - NOSPACE(tokens); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); - SPACE(tokens); + tokens.addAll(visit(ctx.date())); + tokens.addAll(visit(ctx.time())); + tokens.addAll(visit(ctx.offset())); return tokens; } @Override - public List visitOrderByClause(HqlParser.OrderByClauseContext ctx) { + public List visitOffsetDateTimeWithMinutes(HqlParser.OffsetDateTimeWithMinutesContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.ORDER())); - tokens.add(new JpaQueryParsingToken(ctx.BY())); + tokens.addAll(visit(ctx.date())); + tokens.addAll(visit(ctx.time())); + tokens.addAll(visit(ctx.offsetWithMinutes())); - ctx.sortedItem().forEach(sortedItemContext -> { - tokens.addAll(visit(sortedItemContext)); - NOSPACE(tokens); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + return tokens; + } + + @Override + public List visitDate(HqlParser.DateContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.addAll(visit(ctx.year())); + tokens.add(new JpaQueryParsingToken(ctx.MINUS(0))); + tokens.addAll(visit(ctx.month())); + tokens.add(new JpaQueryParsingToken(ctx.MINUS(1))); + tokens.addAll(visit(ctx.day())); return tokens; } @Override - public List visitHavingClause(HqlParser.HavingClauseContext ctx) { + public List visitTime(HqlParser.TimeContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.HAVING())); + tokens.addAll(visit(ctx.hour())); + tokens.add(new JpaQueryParsingToken(ctx.COLON(0))); + tokens.addAll(visit(ctx.minute())); - ctx.predicate().forEach(predicateContext -> { - tokens.addAll(visit(predicateContext)); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + if (ctx.second() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.COLON(1))); + tokens.addAll(visit(ctx.second())); + } return tokens; } @Override - public List visitSetOperator(HqlParser.SetOperatorContext ctx) { + public List visitOffset(HqlParser.OffsetContext ctx) { List tokens = new ArrayList<>(); - if (ctx.UNION() != null) { - tokens.add(new JpaQueryParsingToken(ctx.UNION())); - } else if (ctx.INTERSECT() != null) { - tokens.add(new JpaQueryParsingToken(ctx.INTERSECT())); - } else if (ctx.EXCEPT() != null) { - tokens.add(new JpaQueryParsingToken(ctx.EXCEPT())); + if (ctx.PLUS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.PLUS())); + } else if (ctx.MINUS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.MINUS())); } + tokens.addAll(visit(ctx.hour())); - if (ctx.ALL() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ALL())); + if (ctx.COLON() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.COLON())); + tokens.addAll(visit(ctx.minute())); } return tokens; } @Override - public List visitLiteral(HqlParser.LiteralContext ctx) { + public List visitOffsetWithMinutes(HqlParser.OffsetWithMinutesContext ctx) { - if (ctx.NULL() != null) { - return List.of(new JpaQueryParsingToken(ctx.NULL())); - } else if (ctx.booleanLiteral() != null) { - return visit(ctx.booleanLiteral()); - } else if (ctx.stringLiteral() != null) { - return visit(ctx.stringLiteral()); - } else if (ctx.numericLiteral() != null) { - return visit(ctx.numericLiteral()); - } else if (ctx.dateTimeLiteral() != null) { - return visit(ctx.dateTimeLiteral()); - } else { - return List.of(); + List tokens = new ArrayList<>(); + + if (ctx.PLUS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.PLUS())); + } else if (ctx.MINUS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.MINUS())); } + tokens.addAll(visit(ctx.hour())); + tokens.add(new JpaQueryParsingToken(ctx.COLON())); + tokens.addAll(visit(ctx.minute())); + + return tokens; } @Override - public List visitBooleanLiteral(HqlParser.BooleanLiteralContext ctx) { + public List visitYear(HqlParser.YearContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); + } - if (ctx.TRUE() != null) { - return List.of(new JpaQueryParsingToken(ctx.TRUE())); - } else if (ctx.FALSE() != null) { - return List.of(new JpaQueryParsingToken(ctx.FALSE())); - } else { - return List.of(); - } + @Override + public List visitMonth(HqlParser.MonthContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); } @Override - public List visitStringLiteral(HqlParser.StringLiteralContext ctx) { + public List visitDay(HqlParser.DayContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); + } - if (ctx.STRINGLITERAL() != null) { - return List.of(new JpaQueryParsingToken(ctx.STRINGLITERAL())); - } else if (ctx.CHARACTER() != null) { - return List.of(new JpaQueryParsingToken(ctx.CHARACTER())); - } else { - return List.of(); - } + @Override + public List visitHour(HqlParser.HourContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); } @Override - public List visitNumericLiteral(HqlParser.NumericLiteralContext ctx) { + public List visitMinute(HqlParser.MinuteContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); + } + + @Override + public List visitSecond(HqlParser.SecondContext ctx) { if (ctx.INTEGER_LITERAL() != null) { return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); } else if (ctx.FLOAT_LITERAL() != null) { return List.of(new JpaQueryParsingToken(ctx.FLOAT_LITERAL())); - } else if (ctx.HEXLITERAL() != null) { - return List.of(new JpaQueryParsingToken(ctx.HEXLITERAL())); } else { return List.of(); } } @Override - public List visitDateTimeLiteral(HqlParser.DateTimeLiteralContext ctx) { + public List visitZoneId(HqlParser.ZoneIdContext ctx) { List tokens = new ArrayList<>(); - if (ctx.LOCAL_DATE() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LOCAL_DATE())); - } else if (ctx.LOCAL_TIME() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LOCAL_TIME())); - } else if (ctx.LOCAL_DATETIME() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LOCAL_DATETIME())); - } else if (ctx.CURRENT_DATE() != null) { - tokens.add(new JpaQueryParsingToken(ctx.CURRENT_DATE())); - } else if (ctx.CURRENT_TIME() != null) { - tokens.add(new JpaQueryParsingToken(ctx.CURRENT_TIME())); - } else if (ctx.CURRENT_TIMESTAMP() != null) { - tokens.add(new JpaQueryParsingToken(ctx.CURRENT_TIMESTAMP())); - } else if (ctx.OFFSET_DATETIME() != null) { - tokens.add(new JpaQueryParsingToken(ctx.OFFSET_DATETIME())); - } else { - - if (ctx.LOCAL() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LOCAL())); - } else if (ctx.CURRENT() != null) { - tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); - } else if (ctx.OFFSET() != null) { - tokens.add(new JpaQueryParsingToken(ctx.OFFSET())); - } - - if (ctx.DATE() != null) { - tokens.add(new JpaQueryParsingToken(ctx.DATE())); - } else if (ctx.TIME() != null) { - tokens.add(new JpaQueryParsingToken(ctx.TIME())); - } else if (ctx.DATETIME() != null) { - tokens.add(new JpaQueryParsingToken(ctx.DATETIME())); - } + if (ctx.IDENTIFIER() != null) { - if (ctx.INSTANT() != null) { - tokens.add(new JpaQueryParsingToken(ctx.INSTANT())); - } + ctx.IDENTIFIER().forEach(terminalNode -> { + tokens.add(new JpaQueryParsingToken(terminalNode)); + NOSPACE(tokens); + tokens.add(TOKEN_SLASH); + }); + CLIP(tokens); + } else if (ctx.STRING_LITERAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.STRING_LITERAL())); } return tokens; } @Override - public List visitPlainPrimaryExpression(HqlParser.PlainPrimaryExpressionContext ctx) { - return visit(ctx.primaryExpression()); - } - - @Override - public List visitTupleExpression(HqlParser.TupleExpressionContext ctx) { + public List visitJdbcTimestampLiteral(HqlParser.JdbcTimestampLiteralContext ctx) { List tokens = new ArrayList<>(); - tokens.add(TOKEN_OPEN_PAREN); - - ctx.expressionOrPredicate().forEach(expressionOrPredicateContext -> { - tokens.addAll(visit(expressionOrPredicateContext)); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + tokens.add(new JpaQueryParsingToken(ctx.TIMESTAMP_ESCAPE_START())); - tokens.add(TOKEN_CLOSE_PAREN); + if (ctx.dateTime() != null) { + tokens.addAll(visit(ctx.dateTime())); + } else if (ctx.genericTemporalLiteralText() != null) { + tokens.addAll(visit(ctx.genericTemporalLiteralText())); + } + tokens.add(TOKEN_CLOSE_BRACE); return tokens; } @Override - public List visitHqlConcatenationExpression(HqlParser.HqlConcatenationExpressionContext ctx) { + public List visitJdbcDateLiteral(HqlParser.JdbcDateLiteralContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.expression(0))); - tokens.add(TOKEN_DOUBLE_PIPE); - tokens.addAll(visit(ctx.expression(1))); + tokens.add(new JpaQueryParsingToken(ctx.DATE_ESCAPE_START())); + if (ctx.date() != null) { + tokens.addAll(visit(ctx.date())); + } else if (ctx.genericTemporalLiteralText() != null) { + tokens.addAll(visit(ctx.genericTemporalLiteralText())); + } + tokens.add(TOKEN_CLOSE_BRACE); return tokens; } @Override - public List visitGroupedExpression(HqlParser.GroupedExpressionContext ctx) { + + public List visitJdbcTimeLiteral(HqlParser.JdbcTimeLiteralContext ctx) { List tokens = new ArrayList<>(); - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.expression())); - tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.TIME_ESCAPE_START())); + + if (ctx.time() != null) { + tokens.addAll(visit(ctx.time())); + } else if (ctx.genericTemporalLiteralText() != null) { + tokens.addAll(visit(ctx.genericTemporalLiteralText())); + } + tokens.add(TOKEN_CLOSE_BRACE); return tokens; } @Override - public List visitAdditionExpression(HqlParser.AdditionExpressionContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.addAll(visit(ctx.expression(0))); - tokens.add(new JpaQueryParsingToken(ctx.op)); - tokens.addAll(visit(ctx.expression(1))); - - return tokens; + public List visitGenericTemporalLiteralText(HqlParser.GenericTemporalLiteralTextContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.STRING_LITERAL())); } @Override - public List visitSignedNumericLiteral(HqlParser.SignedNumericLiteralContext ctx) { + public List visitGeneralizedLiteral(HqlParser.GeneralizedLiteralContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.op)); - tokens.addAll(visit(ctx.numericLiteral())); + tokens.add(TOKEN_OPEN_BRACE); + tokens.addAll(visit(ctx.generalizedLiteralType())); + tokens.add(TOKEN_COLON); + tokens.addAll(visit(ctx.generalizedLiteralType())); + tokens.add(TOKEN_CLOSE_BRACE); return tokens; } @Override - public List visitMultiplicationExpression(HqlParser.MultiplicationExpressionContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.addAll(visit(ctx.expression(0))); - NOSPACE(tokens); - tokens.add(new JpaQueryParsingToken(ctx.op, false)); - tokens.addAll(visit(ctx.expression(1))); - - return tokens; + public List visitGeneralizedLiteralType(HqlParser.GeneralizedLiteralTypeContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.STRING_LITERAL())); } @Override - public List visitSubqueryExpression(HqlParser.SubqueryExpressionContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.subquery())); - NOSPACE(tokens); - tokens.add(TOKEN_CLOSE_PAREN); - - return tokens; + public List visitGeneralizedLiteralText(HqlParser.GeneralizedLiteralTextContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.STRING_LITERAL())); } @Override - public List visitSignedExpression(HqlParser.SignedExpressionContext ctx) { + public List visitNamedParameter(HqlParser.NamedParameterContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.op)); - tokens.addAll(visit(ctx.expression())); + tokens.add(new JpaQueryParsingToken(ctx.COLON(), false)); + tokens.addAll(visit(ctx.identifier())); return tokens; } @Override - public List visitCaseExpression(HqlParser.CaseExpressionContext ctx) { - return visit(ctx.caseList()); - } - - @Override - public List visitLiteralExpression(HqlParser.LiteralExpressionContext ctx) { - return visit(ctx.literal()); - } + public List visitPositionalParameter(HqlParser.PositionalParameterContext ctx) { - @Override - public List visitParameterExpression(HqlParser.ParameterExpressionContext ctx) { - return visit(ctx.parameter()); - } + List tokens = new ArrayList<>(); - @Override - public List visitFunctionExpression(HqlParser.FunctionExpressionContext ctx) { - return visit(ctx.function()); - } + tokens.add(new JpaQueryParsingToken(ctx.QUESTION_MARK(), false)); + if (ctx.INTEGER_LITERAL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); + } - @Override - public List visitGeneralPathExpression(HqlParser.GeneralPathExpressionContext ctx) { - return visit(ctx.generalPathFragment()); + return tokens; } @Override - public List visitIdentificationVariable(HqlParser.IdentificationVariableContext ctx) { - - if (ctx.identifier() != null) { - return visit(ctx.identifier()); - } else if (ctx.simplePath() != null) { - return visit(ctx.simplePath()); + public List visitFunction(HqlParser.FunctionContext ctx) { + + if (ctx.standardFunction() != null) { + return visit(ctx.standardFunction()); + } else if (ctx.aggregateFunction() != null) { + return visit(ctx.aggregateFunction()); + } else if (ctx.collectionSizeFunction() != null) { + return visit(ctx.collectionSizeFunction()); + } else if (ctx.indexAggregateFunction() != null) { + return visit(ctx.indexAggregateFunction()); + } else if (ctx.elementAggregateFunction() != null) { + return visit(ctx.elementAggregateFunction()); + } else if (ctx.collectionFunctionMisuse() != null) { + return visit(ctx.collectionFunctionMisuse()); + } else if (ctx.jpaNonstandardFunction() != null) { + return visit(ctx.jpaNonstandardFunction()); + } else if (ctx.genericFunction() != null) { + return visit(ctx.genericFunction()); } else { return List.of(); } } @Override - public List visitPath(HqlParser.PathContext ctx) { + public List visitJpaNonstandardFunction(HqlParser.JpaNonstandardFunctionContext ctx) { List tokens = new ArrayList<>(); - if (ctx.treatedPath() != null) { - - tokens.addAll(visit(ctx.treatedPath())); + tokens.add(new JpaQueryParsingToken(ctx.FUNCTION(), false)); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.jpaNonstandardFunctionName())); + if (ctx.COMMA() != null) { - if (ctx.pathContinutation() != null) { - NOSPACE(tokens); - tokens.addAll(visit(ctx.pathContinutation())); - } - } else if (ctx.generalPathFragment() != null) { - tokens.addAll(visit(ctx.generalPathFragment())); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + tokens.addAll(visit(ctx.genericFunctionArguments())); } + NOSPACE(tokens); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitGeneralPathFragment(HqlParser.GeneralPathFragmentContext ctx) { + public List visitJpaNonstandardFunctionName(HqlParser.JpaNonstandardFunctionNameContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.STRING_LITERAL())); + } - List tokens = new ArrayList<>(); + @Override + public List visitGenericFunction(HqlParser.GenericFunctionContext ctx) { - tokens.addAll(visit(ctx.simplePath())); + List tokens = new ArrayList<>(); - if (ctx.indexedPathAccessFragment() != null) { - tokens.addAll(visit(ctx.indexedPathAccessFragment())); + tokens.addAll(visit(ctx.genericFunctionName())); + NOSPACE(tokens); + tokens.add(TOKEN_OPEN_PAREN); + if (ctx.genericFunctionArguments() != null) { + tokens.addAll(visit(ctx.genericFunctionArguments())); + } else if (ctx.ASTERISK() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ASTERISK())); + } + tokens.add(TOKEN_CLOSE_PAREN); + if (ctx.nthSideClause() != null) { + tokens.addAll(visit(ctx.nthSideClause())); + } + if (ctx.nullsClause() != null) { + tokens.addAll(visit(ctx.nullsClause())); + } + if (ctx.withinGroupClause() != null) { + tokens.addAll(visit(ctx.withinGroupClause())); + } + if (ctx.filterClause() != null) { + tokens.addAll(visit(ctx.filterClause())); + } + if (ctx.overClause() != null) { + tokens.addAll(visit(ctx.overClause())); } return tokens; } @Override - public List visitIndexedPathAccessFragment(HqlParser.IndexedPathAccessFragmentContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.add(TOKEN_OPEN_SQUARE_BRACKET); - tokens.addAll(visit(ctx.expression())); - tokens.add(TOKEN_CLOSE_SQUARE_BRACKET); - - if (ctx.generalPathFragment() != null) { - - tokens.add(TOKEN_DOT); - tokens.addAll(visit(ctx.generalPathFragment())); - } - - return tokens; + public List visitGenericFunctionName(HqlParser.GenericFunctionNameContext ctx) { + return visit(ctx.simplePath()); } @Override - public List visitSimplePath(HqlParser.SimplePathContext ctx) { + public List visitGenericFunctionArguments(HqlParser.GenericFunctionArgumentsContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.identifier())); - NOSPACE(tokens); + if (ctx.DISTINCT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.DISTINCT())); + } else if (ctx.datetimeField() != null) { - ctx.simplePathElement().forEach(simplePathElementContext -> { - tokens.addAll(visit(simplePathElementContext)); + tokens.addAll(visit(ctx.datetimeField())); + tokens.add(TOKEN_COMMA); + } + + ctx.expressionOrPredicate().forEach(expressionOrPredicateContext -> { + + tokens.addAll(visit(expressionOrPredicateContext)); NOSPACE(tokens); + tokens.add(TOKEN_COMMA); }); - SPACE(tokens); + CLIP(tokens); return tokens; } @Override - public List visitSimplePathElement(HqlParser.SimplePathElementContext ctx) { + public List visitCollectionSizeFunction(HqlParser.CollectionSizeFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.add(TOKEN_DOT); - tokens.addAll(visit(ctx.identifier())); + tokens.add(new JpaQueryParsingToken(ctx.SIZE())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitCaseList(HqlParser.CaseListContext ctx) { + public List visitIndexAggregateFunction(HqlParser.IndexAggregateFunctionContext ctx) { - if (ctx.simpleCaseExpression() != null) { - return visit(ctx.simpleCaseExpression()); - } else if (ctx.searchedCaseExpression() != null) { - return visit(ctx.searchedCaseExpression()); - } else { - return List.of(); - } - } + List tokens = new ArrayList<>(); - @Override - public List visitSimpleCaseExpression(HqlParser.SimpleCaseExpressionContext ctx) { + if (ctx.MAXINDEX() != null) { - List tokens = new ArrayList<>(); + tokens.add(new JpaQueryParsingToken(ctx.MAXINDEX())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.MININDEX() != null) { - tokens.add(new JpaQueryParsingToken(ctx.CASE())); - tokens.addAll(visit(ctx.expressionOrPredicate(0))); + tokens.add(new JpaQueryParsingToken(ctx.MININDEX())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.MAX() != null) { - ctx.caseWhenExpressionClause().forEach(caseWhenExpressionClauseContext -> { - tokens.addAll(visit(caseWhenExpressionClauseContext)); - }); + tokens.add(new JpaQueryParsingToken(ctx.MAX())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.MIN() != null) { - if (ctx.ELSE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.MIN())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.SUM() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ELSE())); - tokens.addAll(visit(ctx.expressionOrPredicate(1))); - } + tokens.add(new JpaQueryParsingToken(ctx.SUM())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.AVG() != null) { - tokens.add(new JpaQueryParsingToken(ctx.END())); + tokens.add(new JpaQueryParsingToken(ctx.AVG())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } return tokens; } @Override - public List visitSearchedCaseExpression(HqlParser.SearchedCaseExpressionContext ctx) { + public List visitElementAggregateFunction(HqlParser.ElementAggregateFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.CASE())); + if (ctx.MAXELEMENT() != null) { - ctx.caseWhenPredicateClause().forEach(caseWhenPredicateClauseContext -> { - tokens.addAll(visit(caseWhenPredicateClauseContext)); - }); + tokens.add(new JpaQueryParsingToken(ctx.MAXELEMENT())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.MINELEMENT() != null) { - if (ctx.ELSE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.MINELEMENT())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.MAX() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ELSE())); - tokens.addAll(visit(ctx.expressionOrPredicate())); - } + tokens.add(new JpaQueryParsingToken(ctx.MAX())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.MIN() != null) { - tokens.add(new JpaQueryParsingToken(ctx.END())); + tokens.add(new JpaQueryParsingToken(ctx.MIN())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.SUM() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.SUM())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.AVG() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.AVG())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } return tokens; } @Override - public List visitCaseWhenExpressionClause(HqlParser.CaseWhenExpressionClauseContext ctx) { + public List visitCollectionFunctionMisuse(HqlParser.CollectionFunctionMisuseContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.WHEN())); - tokens.addAll(visit(ctx.expression())); - tokens.add(new JpaQueryParsingToken(ctx.THEN())); - tokens.addAll(visit(ctx.expressionOrPredicate())); + if (ctx.ELEMENTS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); + } else if (ctx.INDICES() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + } + + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.path())); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitCaseWhenPredicateClause(HqlParser.CaseWhenPredicateClauseContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.add(new JpaQueryParsingToken(ctx.WHEN())); - tokens.addAll(visit(ctx.predicate())); - tokens.add(new JpaQueryParsingToken(ctx.THEN())); - tokens.addAll(visit(ctx.expressionOrPredicate())); + public List visitAggregateFunction(HqlParser.AggregateFunctionContext ctx) { - return tokens; + if (ctx.everyFunction() != null) { + return visit(ctx.everyFunction()); + } else if (ctx.anyFunction() != null) { + return visit(ctx.anyFunction()); + } else if (ctx.listaggFunction() != null) { + return visit(ctx.listaggFunction()); + } else { + return List.of(); + } } @Override - public List visitGenericFunction(HqlParser.GenericFunctionContext ctx) { + public List visitEveryFunction(HqlParser.EveryFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.functionName())); + if (ctx.EVERY() != null) { + tokens.add(new JpaQueryParsingToken(ctx.EVERY())); + } else if (ctx.ALL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ALL())); + } + + if (ctx.ELEMENTS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); + } else if (ctx.INDICES() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + } + NOSPACE(tokens); tokens.add(TOKEN_OPEN_PAREN); - if (ctx.functionArguments() != null) { - tokens.addAll(visit(ctx.functionArguments())); - } else if (ctx.ASTERISK() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ASTERISK())); + if (ctx.predicate() != null) { + tokens.addAll(visit(ctx.predicate())); + } else if (ctx.subquery() != null) { + tokens.addAll(visit(ctx.subquery())); + } else if (ctx.simplePath() != null) { + tokens.addAll(visit(ctx.simplePath())); } + NOSPACE(tokens); tokens.add(TOKEN_CLOSE_PAREN); - if (ctx.pathContinutation() != null) { - NOSPACE(tokens); - tokens.addAll(visit(ctx.pathContinutation())); - } - if (ctx.filterClause() != null) { tokens.addAll(visit(ctx.filterClause())); } - if (ctx.withinGroup() != null) { - tokens.addAll(visit(ctx.withinGroup())); - } - if (ctx.overClause() != null) { tokens.addAll(visit(ctx.overClause())); } @@ -1480,65 +2893,115 @@ public List visitGenericFunction(HqlParser.GenericFunction } @Override - public List visitFunctionWithSubquery(HqlParser.FunctionWithSubqueryContext ctx) { + public List visitAnyFunction(HqlParser.AnyFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.functionName())); + if (ctx.ANY() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ANY())); + } else if (ctx.SOME() != null) { + tokens.add(new JpaQueryParsingToken(ctx.SOME())); + } + + if (ctx.ELEMENTS() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); + } else if (ctx.INDICES() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + } + NOSPACE(tokens); tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.subquery())); + + if (ctx.predicate() != null) { + tokens.addAll(visit(ctx.predicate())); + } else if (ctx.subquery() != null) { + tokens.addAll(visit(ctx.subquery())); + } else if (ctx.simplePath() != null) { + tokens.addAll(visit(ctx.simplePath())); + } + NOSPACE(tokens); tokens.add(TOKEN_CLOSE_PAREN); + if (ctx.filterClause() != null) { + tokens.addAll(visit(ctx.filterClause())); + } + + if (ctx.overClause() != null) { + tokens.addAll(visit(ctx.overClause())); + } + return tokens; } @Override - public List visitCastFunctionInvocation(HqlParser.CastFunctionInvocationContext ctx) { - return visit(ctx.castFunction()); - } + public List visitListaggFunction(HqlParser.ListaggFunctionContext ctx) { - @Override - public List visitExtractFunctionInvocation(HqlParser.ExtractFunctionInvocationContext ctx) { - return visit(ctx.extractFunction()); - } + List tokens = new ArrayList<>(); - @Override - public List visitTrimFunctionInvocation(HqlParser.TrimFunctionInvocationContext ctx) { - return visit(ctx.trimFunction()); - } + tokens.add(new JpaQueryParsingToken(ctx.LISTAGG())); + tokens.add(TOKEN_OPEN_PAREN); + if (ctx.DISTINCT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.DISTINCT())); + } + tokens.addAll(visit(ctx.expressionOrPredicate(0))); + tokens.add(TOKEN_COMMA); + tokens.addAll(visit(ctx.expressionOrPredicate(1))); + if (ctx.onOverflowClause() != null) { + tokens.addAll(visit(ctx.onOverflowClause())); + } + tokens.add(TOKEN_CLOSE_PAREN); - @Override - public List visitEveryFunctionInvocation(HqlParser.EveryFunctionInvocationContext ctx) { - return visit(ctx.everyFunction()); - } + if (ctx.withinGroupClause() != null) { + tokens.addAll(visit(ctx.withinGroupClause())); + } + if (ctx.filterClause() != null) { + tokens.addAll(visit(ctx.filterClause())); + } + if (ctx.overClause() != null) { + tokens.addAll(visit(ctx.overClause())); + } - @Override - public List visitAnyFunctionInvocation(HqlParser.AnyFunctionInvocationContext ctx) { - return visit(ctx.anyFunction()); + return tokens; } @Override - public List visitTreatedPathInvocation(HqlParser.TreatedPathInvocationContext ctx) { - return visit(ctx.treatedPath()); + public List visitOnOverflowClause(HqlParser.OnOverflowClauseContext ctx) { + + List tokens = new ArrayList<>(); + + tokens.add(new JpaQueryParsingToken(ctx.ON())); + tokens.add(new JpaQueryParsingToken(ctx.OVERFLOW())); + + if (ctx.ERROR() != null) { + tokens.add(new JpaQueryParsingToken(ctx.ERROR())); + } else if (ctx.TRUNCATE() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.TRUNCATE())); + if (ctx.expression() != null) { + tokens.addAll(visit(ctx.expression())); + } + if (ctx.WITH() != null) { + tokens.add(new JpaQueryParsingToken(ctx.WITH())); + } else if (ctx.WITHOUT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.WITHOUT())); + } + tokens.add(new JpaQueryParsingToken(ctx.COUNT())); + } + + return tokens; } @Override - public List visitFunctionArguments(HqlParser.FunctionArgumentsContext ctx) { + public List visitWithinGroupClause(HqlParser.WithinGroupClauseContext ctx) { List tokens = new ArrayList<>(); - if (ctx.DISTINCT() != null) { - tokens.add(new JpaQueryParsingToken(ctx.DISTINCT())); - } - - ctx.expressionOrPredicate().forEach(expressionOrPredicateContext -> { - tokens.addAll(visit(expressionOrPredicateContext)); - NOSPACE(tokens); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + tokens.add(new JpaQueryParsingToken(ctx.WITHIN())); + tokens.add(new JpaQueryParsingToken(ctx.GROUP())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.orderByClause())); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @@ -1557,15 +3020,32 @@ public List visitFilterClause(HqlParser.FilterClauseContex } @Override - public List visitWithinGroup(HqlParser.WithinGroupContext ctx) { + public List visitNullsClause(HqlParser.NullsClauseContext ctx) { + + List tokens = new ArrayList<>(); + + if (ctx.RESPECT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.RESPECT())); + } else if (ctx.IGNORE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.IGNORE())); + } + tokens.add(new JpaQueryParsingToken(ctx.NULLS())); + + return tokens; + } + + @Override + public List visitNthSideClause(HqlParser.NthSideClauseContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.WITHIN())); - tokens.add(new JpaQueryParsingToken(ctx.GROUP())); - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.orderByClause())); - tokens.add(TOKEN_CLOSE_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.FROM())); + + if (ctx.FIRST() != null) { + tokens.add(new JpaQueryParsingToken(ctx.FIRST())); + } else if (ctx.LAST() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LAST())); + } return tokens; } @@ -1649,181 +3129,221 @@ public List visitFrameClause(HqlParser.FrameClauseContext } @Override - public List visitUnboundedPrecedingFrameStart( - HqlParser.UnboundedPrecedingFrameStartContext ctx) { + public List visitFrameStart(HqlParser.FrameStartContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.UNBOUNDED())); - tokens.add(new JpaQueryParsingToken(ctx.PRECEDING())); + if (ctx.PRECEDING() != null) { - return tokens; - } - - @Override - public List visitExpressionPrecedingFrameStart( - HqlParser.ExpressionPrecedingFrameStartContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.addAll(visit(ctx.expression())); - tokens.add(new JpaQueryParsingToken(ctx.PRECEDING())); - - return tokens; - } + if (ctx.UNBOUNDED() != null) { + tokens.add(new JpaQueryParsingToken(ctx.UNBOUNDED())); + } else { + tokens.addAll(visit(ctx.expression())); + } - @Override - public List visitCurrentRowFrameStart(HqlParser.CurrentRowFrameStartContext ctx) { + tokens.add(new JpaQueryParsingToken(ctx.PRECEDING())); + } else if (ctx.CURRENT() != null) { - List tokens = new ArrayList<>(); + tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); + tokens.add(new JpaQueryParsingToken(ctx.ROW())); + } else if (ctx.FOLLOWING() != null) { - tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); - tokens.add(new JpaQueryParsingToken(ctx.ROW())); + tokens.addAll(visit(ctx.expression())); + tokens.add(new JpaQueryParsingToken(ctx.FOLLOWING())); + } return tokens; } @Override - public List visitExpressionFollowingFrameStart( - HqlParser.ExpressionFollowingFrameStartContext ctx) { + public List visitFrameEnd(HqlParser.FrameEndContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.expression())); - tokens.add(new JpaQueryParsingToken(ctx.FOLLOWING())); + if (ctx.PRECEDING() != null) { - return tokens; - } + tokens.addAll(visit(ctx.expression())); + tokens.add(new JpaQueryParsingToken(ctx.PRECEDING())); + } else if (ctx.CURRENT() != null) { - @Override - public List visitCurrentRowFrameExclusion(HqlParser.CurrentRowFrameExclusionContext ctx) { + tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); + tokens.add(new JpaQueryParsingToken(ctx.ROW())); + } else if (ctx.FOLLOWING() != null) { - List tokens = new ArrayList<>(); + if (ctx.UNBOUNDED() == null) { + tokens.addAll(visit(ctx.expression())); + } else { + tokens.add(new JpaQueryParsingToken(ctx.UNBOUNDED())); + } - tokens.add(new JpaQueryParsingToken(ctx.EXCLUDE())); - tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); - tokens.add(new JpaQueryParsingToken(ctx.ROW())); + tokens.add(new JpaQueryParsingToken(ctx.FOLLOWING())); + } return tokens; } @Override - public List visitGroupFrameExclusion(HqlParser.GroupFrameExclusionContext ctx) { + public List visitFrameExclusion(HqlParser.FrameExclusionContext ctx) { List tokens = new ArrayList<>(); tokens.add(new JpaQueryParsingToken(ctx.EXCLUDE())); - tokens.add(new JpaQueryParsingToken(ctx.GROUP())); - return tokens; - } - - @Override - public List visitTiesFrameExclusion(HqlParser.TiesFrameExclusionContext ctx) { + if (ctx.CURRENT() != null) { - List tokens = new ArrayList<>(); + tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); + tokens.add(new JpaQueryParsingToken(ctx.ROW())); + } else if (ctx.GROUP() != null) { + tokens.add(new JpaQueryParsingToken(ctx.GROUP())); + } else if (ctx.TIES() != null) { + tokens.add(new JpaQueryParsingToken(ctx.TIES())); + } else if (ctx.NO() != null) { - tokens.add(new JpaQueryParsingToken(ctx.EXCLUDE())); - tokens.add(new JpaQueryParsingToken(ctx.TIES())); + tokens.add(new JpaQueryParsingToken(ctx.NO())); + tokens.add(new JpaQueryParsingToken(ctx.OTHERS())); + } return tokens; } @Override - public List visitNoOthersFrameExclusion(HqlParser.NoOthersFrameExclusionContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.add(new JpaQueryParsingToken(ctx.EXCLUDE())); - tokens.add(new JpaQueryParsingToken(ctx.NO())); - tokens.add(new JpaQueryParsingToken(ctx.OTHERS())); - - return tokens; + public List visitStandardFunction(HqlParser.StandardFunctionContext ctx) { + + if (ctx.castFunction() != null) { + return visit(ctx.castFunction()); + } else if (ctx.extractFunction() != null) { + return visit(ctx.extractFunction()); + } else if (ctx.truncFunction() != null) { + return visit(ctx.truncFunction()); + } else if (ctx.formatFunction() != null) { + return visit(ctx.formatFunction()); + } else if (ctx.collateFunction() != null) { + return visit(ctx.collateFunction()); + } else if (ctx.substringFunction() != null) { + return visit(ctx.substringFunction()); + } else if (ctx.overlayFunction() != null) { + return visit(ctx.overlayFunction()); + } else if (ctx.trimFunction() != null) { + return visit(ctx.trimFunction()); + } else if (ctx.padFunction() != null) { + return visit(ctx.padFunction()); + } else if (ctx.positionFunction() != null) { + return visit(ctx.positionFunction()); + } else if (ctx.currentDateFunction() != null) { + return visit(ctx.currentDateFunction()); + } else if (ctx.currentTimeFunction() != null) { + return visit(ctx.currentTimeFunction()); + } else if (ctx.currentTimestampFunction() != null) { + return visit(ctx.currentTimestampFunction()); + } else if (ctx.instantFunction() != null) { + return visit(ctx.instantFunction()); + } else if (ctx.localDateFunction() != null) { + return visit(ctx.localDateFunction()); + } else if (ctx.localTimeFunction() != null) { + return visit(ctx.localTimeFunction()); + } else if (ctx.localDateTimeFunction() != null) { + return visit(ctx.localDateTimeFunction()); + } else if (ctx.offsetDateTimeFunction() != null) { + return visit(ctx.offsetDateTimeFunction()); + } else if (ctx.cube() != null) { + return visit(ctx.cube()); + } else if (ctx.rollup() != null) { + return visit(ctx.rollup()); + } else { + return List.of(); + } } @Override - public List visitExpressionPrecedingFrameEnd(HqlParser.ExpressionPrecedingFrameEndContext ctx) { + public List visitCastFunction(HqlParser.CastFunctionContext ctx) { List tokens = new ArrayList<>(); + tokens.add(new JpaQueryParsingToken(ctx.CAST())); + tokens.add(TOKEN_OPEN_PAREN); tokens.addAll(visit(ctx.expression())); - tokens.add(new JpaQueryParsingToken(ctx.PRECEDING())); + tokens.add(TOKEN_AS); + tokens.addAll(visit(ctx.castTarget())); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitCurrentRowFrameEnd(HqlParser.CurrentRowFrameEndContext ctx) { + public List visitCastTarget(HqlParser.CastTargetContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); - tokens.add(new JpaQueryParsingToken(ctx.ROW())); - - return tokens; - } + tokens.addAll(visit(ctx.castTargetType())); - @Override - public List visitExpressionFollowingFrameEnd(HqlParser.ExpressionFollowingFrameEndContext ctx) { + if (ctx.LEFT_PAREN() != null) { - List tokens = new ArrayList<>(); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(new JpaQueryParsingToken(ctx.INTEGER_LITERAL(0))); - tokens.addAll(visit(ctx.expression())); - tokens.add(new JpaQueryParsingToken(ctx.FOLLOWING())); + if (ctx.COMMA() != null) { + tokens.add(TOKEN_COMMA); + tokens.add(new JpaQueryParsingToken(ctx.INTEGER_LITERAL(1))); + } + tokens.add(TOKEN_CLOSE_PAREN); + } return tokens; } @Override - public List visitUnboundedFollowingFrameEnd(HqlParser.UnboundedFollowingFrameEndContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.add(new JpaQueryParsingToken(ctx.UNBOUNDED())); - tokens.add(new JpaQueryParsingToken(ctx.FOLLOWING())); - - return tokens; + public List visitCastTargetType(HqlParser.CastTargetTypeContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.fullTargetName)); } @Override - public List visitCastFunction(HqlParser.CastFunctionContext ctx) { + public List visitSubstringFunction(HqlParser.SubstringFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.CAST())); + tokens.add(new JpaQueryParsingToken(ctx.SUBSTRING())); tokens.add(TOKEN_OPEN_PAREN); tokens.addAll(visit(ctx.expression())); - tokens.add(new JpaQueryParsingToken(ctx.AS())); - tokens.addAll(visit(ctx.identifier())); - tokens.add(TOKEN_CLOSE_PAREN); - return tokens; - } + if (ctx.COMMA() != null) { - @Override - public List visitExtractFunction(HqlParser.ExtractFunctionContext ctx) { + tokens.add(new JpaQueryParsingToken(ctx.COMMA(0))); + tokens.addAll(visit(ctx.substringFunctionStartArgument())); - List tokens = new ArrayList<>(); + if (ctx.COMMA(1) != null) { - if (ctx.EXTRACT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.COMMA(1))); + tokens.addAll(visit(ctx.substringFunctionLengthArgument())); + } + } else if (ctx.FROM() != null) { - tokens.add(new JpaQueryParsingToken(ctx.EXTRACT())); - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.expression(0))); tokens.add(new JpaQueryParsingToken(ctx.FROM())); - tokens.addAll(visit(ctx.expression(1))); - tokens.add(TOKEN_CLOSE_PAREN); - } else if (ctx.dateTimeFunction() != null) { + tokens.addAll(visit(ctx.substringFunctionStartArgument())); - tokens.addAll(visit(ctx.dateTimeFunction())); - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.expression(0))); - tokens.add(TOKEN_CLOSE_PAREN); + if (ctx.FOR() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.FOR())); + tokens.addAll(visit(ctx.substringFunctionLengthArgument())); + } } + tokens.add(TOKEN_CLOSE_PAREN); + return tokens; } + @Override + public List visitSubstringFunctionStartArgument( + HqlParser.SubstringFunctionStartArgumentContext ctx) { + return visit(ctx.expression()); + } + + @Override + public List visitSubstringFunctionLengthArgument( + HqlParser.SubstringFunctionLengthArgumentContext ctx) { + return visit(ctx.expression()); + } + @Override public List visitTrimFunction(HqlParser.TrimFunctionContext ctx) { @@ -1831,23 +3351,15 @@ public List visitTrimFunction(HqlParser.TrimFunctionContex tokens.add(new JpaQueryParsingToken(ctx.TRIM())); tokens.add(TOKEN_OPEN_PAREN); - - if (ctx.LEADING() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LEADING())); - } else if (ctx.TRAILING() != null) { - tokens.add(new JpaQueryParsingToken(ctx.TRAILING())); - } else if (ctx.BOTH() != null) { - tokens.add(new JpaQueryParsingToken(ctx.BOTH())); + if (ctx.trimSpecification() != null) { + tokens.addAll(visit(ctx.trimSpecification())); } - - if (ctx.stringLiteral() != null) { - tokens.addAll(visit(ctx.stringLiteral())); + if (ctx.trimCharacter() != null) { + tokens.addAll(visit(ctx.trimCharacter())); } - if (ctx.FROM() != null) { tokens.add(new JpaQueryParsingToken(ctx.FROM())); } - tokens.addAll(visit(ctx.expression())); tokens.add(TOKEN_CLOSE_PAREN); @@ -1855,556 +3367,884 @@ public List visitTrimFunction(HqlParser.TrimFunctionContex } @Override - public List visitDateTimeFunction(HqlParser.DateTimeFunctionContext ctx) { - return List.of(new JpaQueryParsingToken(ctx.d)); - } - - @Override - public List visitEveryFunction(HqlParser.EveryFunctionContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.add(new JpaQueryParsingToken(ctx.every)); - - if (ctx.ELEMENTS() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); - } else if (ctx.INDICES() != null) { - tokens.add(new JpaQueryParsingToken(ctx.INDICES())); - } - - tokens.add(TOKEN_OPEN_PAREN); + public List visitTrimSpecification(HqlParser.TrimSpecificationContext ctx) { - if (ctx.predicate() != null) { - tokens.addAll(visit(ctx.predicate())); - } else if (ctx.subquery() != null) { - tokens.addAll(visit(ctx.subquery())); - } else if (ctx.simplePath() != null) { - tokens.addAll(visit(ctx.simplePath())); + if (ctx.LEADING() != null) { + return List.of(new JpaQueryParsingToken(ctx.LEADING())); + } else if (ctx.TRAILING() != null) { + return List.of(new JpaQueryParsingToken(ctx.TRAILING())); + } else if (ctx.BOTH() != null) { + return List.of(new JpaQueryParsingToken(ctx.BOTH())); + } else { + return List.of(); } - - tokens.add(TOKEN_CLOSE_PAREN); - - return tokens; } @Override - public List visitAnyFunction(HqlParser.AnyFunctionContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.add(new JpaQueryParsingToken(ctx.any)); - - if (ctx.ELEMENTS() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); - } else if (ctx.INDICES() != null) { - tokens.add(new JpaQueryParsingToken(ctx.INDICES())); - } - - tokens.add(TOKEN_OPEN_PAREN); - - if (ctx.predicate() != null) { - tokens.addAll(visit(ctx.predicate())); - } else if (ctx.subquery() != null) { - tokens.addAll(visit(ctx.subquery())); - } else if (ctx.simplePath() != null) { - tokens.addAll(visit(ctx.simplePath())); - } - - tokens.add(TOKEN_CLOSE_PAREN); - - return tokens; + public List visitTrimCharacter(HqlParser.TrimCharacterContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.STRING_LITERAL())); } @Override - public List visitTreatedPath(HqlParser.TreatedPathContext ctx) { + public List visitPadFunction(HqlParser.PadFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.add(new JpaQueryParsingToken(ctx.TREAT(), false)); + tokens.add(new JpaQueryParsingToken(ctx.PAD())); tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.path())); - tokens.add(new JpaQueryParsingToken(ctx.AS())); - tokens.addAll(visit(ctx.simplePath())); - NOSPACE(tokens); - tokens.add(TOKEN_CLOSE_PAREN); - - if (ctx.pathContinutation() != null) { - NOSPACE(tokens); - tokens.addAll(visit(ctx.pathContinutation())); + tokens.addAll(visit(ctx.expression())); + tokens.add(TOKEN_WITH); + tokens.addAll(visit(ctx.padLength())); + tokens.addAll(visit(ctx.padSpecification())); + if (ctx.padCharacter() != null) { + tokens.addAll(visit(ctx.padCharacter())); } + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitPathContinutation(HqlParser.PathContinutationContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.add(TOKEN_DOT); - tokens.addAll(visit(ctx.simplePath())); + public List visitPadSpecification(HqlParser.PadSpecificationContext ctx) { - return tokens; + if (ctx.LEADING() != null) { + return List.of(new JpaQueryParsingToken(ctx.LEADING())); + } else if (ctx.TRAILING() != null) { + return List.of(new JpaQueryParsingToken(ctx.TRAILING())); + } else { + return List.of(); + } } @Override - public List visitNullExpressionPredicate(HqlParser.NullExpressionPredicateContext ctx) { - return visit(ctx.dealingWithNullExpression()); + public List visitPadCharacter(HqlParser.PadCharacterContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.STRING_LITERAL())); } @Override - public List visitBetweenPredicate(HqlParser.BetweenPredicateContext ctx) { - return visit(ctx.betweenExpression()); + public List visitPadLength(HqlParser.PadLengthContext ctx) { + return visit(ctx.expression()); } @Override - public List visitOrPredicate(HqlParser.OrPredicateContext ctx) { + public List visitOverlayFunction(HqlParser.OverlayFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.predicate(0))); - tokens.add(new JpaQueryParsingToken(ctx.OR())); - tokens.addAll(visit(ctx.predicate(1))); + tokens.add(new JpaQueryParsingToken(ctx.OVERLAY())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.overlayFunctionStringArgument())); + tokens.add(new JpaQueryParsingToken(ctx.PLACING())); + tokens.addAll(visit(ctx.overlayFunctionReplacementArgument())); + tokens.add(new JpaQueryParsingToken(ctx.FROM())); + tokens.addAll(visit(ctx.overlayFunctionStartArgument())); + if (ctx.FOR() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.FOR())); + tokens.addAll(visit(ctx.overlayFunctionLengthArgument())); + } + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitRelationalPredicate(HqlParser.RelationalPredicateContext ctx) { - return visit(ctx.relationalExpression()); + public List visitOverlayFunctionStringArgument( + HqlParser.OverlayFunctionStringArgumentContext ctx) { + return visit(ctx.expression()); } @Override - public List visitExistsPredicate(HqlParser.ExistsPredicateContext ctx) { - return visit(ctx.existsExpression()); + public List visitOverlayFunctionReplacementArgument( + HqlParser.OverlayFunctionReplacementArgumentContext ctx) { + return visit(ctx.expression()); } @Override - public List visitCollectionPredicate(HqlParser.CollectionPredicateContext ctx) { - return visit(ctx.collectionExpression()); + public List visitOverlayFunctionStartArgument( + HqlParser.OverlayFunctionStartArgumentContext ctx) { + return visit(ctx.expression()); } @Override - public List visitAndPredicate(HqlParser.AndPredicateContext ctx) { - - List tokens = new ArrayList<>(); - - tokens.addAll(visit(ctx.predicate(0))); - tokens.add(new JpaQueryParsingToken(ctx.AND())); - tokens.addAll(visit(ctx.predicate(1))); - - return tokens; + public List visitOverlayFunctionLengthArgument( + HqlParser.OverlayFunctionLengthArgumentContext ctx) { + return visit(ctx.expression()); } @Override - public List visitGroupedPredicate(HqlParser.GroupedPredicateContext ctx) { + public List visitCurrentDateFunction(HqlParser.CurrentDateFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.predicate())); - NOSPACE(tokens); - tokens.add(TOKEN_CLOSE_PAREN); + if (ctx.CURRENT_DATE() != null) { - return tokens; - } + tokens.add(new JpaQueryParsingToken(ctx.CURRENT_DATE())); + if (ctx.LEFT_PAREN() != null) { - @Override - public List visitLikePredicate(HqlParser.LikePredicateContext ctx) { - return visit(ctx.stringPatternMatching()); - } + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } + } else if (ctx.CURRENT() != null) { - @Override - public List visitInPredicate(HqlParser.InPredicateContext ctx) { - return visit(ctx.inExpression()); + tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); + tokens.add(new JpaQueryParsingToken(ctx.DATE())); + } + + return tokens; } @Override - public List visitNotPredicate(HqlParser.NotPredicateContext ctx) { + public List visitCurrentTimeFunction(HqlParser.CurrentTimeFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.add(TOKEN_NOT); - tokens.addAll(visit(ctx.predicate())); - - return tokens; - } + if (ctx.CURRENT_TIME() != null) { - @Override - public List visitExpressionPredicate(HqlParser.ExpressionPredicateContext ctx) { - return visit(ctx.expression()); - } + tokens.add(new JpaQueryParsingToken(ctx.CURRENT_TIME())); + if (ctx.LEFT_PAREN() != null) { - @Override - public List visitExpressionOrPredicate(HqlParser.ExpressionOrPredicateContext ctx) { + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } + } else if (ctx.CURRENT() != null) { - if (ctx.expression() != null) { - return visit(ctx.expression()); - } else if (ctx.predicate() != null) { - return visit(ctx.predicate()); - } else { - return List.of(); + tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); + tokens.add(new JpaQueryParsingToken(ctx.TIME())); } + + return tokens; } @Override - public List visitRelationalExpression(HqlParser.RelationalExpressionContext ctx) { + public List visitCurrentTimestampFunction(HqlParser.CurrentTimestampFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.expression(0))); - tokens.add(new JpaQueryParsingToken(ctx.op)); - tokens.addAll(visit(ctx.expression(1))); + if (ctx.CURRENT_TIMESTAMP() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.CURRENT_TIMESTAMP())); + if (ctx.LEFT_PAREN() != null) { + + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } + } else if (ctx.CURRENT() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.CURRENT())); + tokens.add(new JpaQueryParsingToken(ctx.TIMESTAMP())); + } return tokens; } @Override - public List visitBetweenExpression(HqlParser.BetweenExpressionContext ctx) { + public List visitInstantFunction(HqlParser.InstantFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.expression(0))); + if (ctx.CURRENT_INSTANT() != null) { - if (ctx.NOT() != null) { - tokens.add(TOKEN_NOT); - } + tokens.add(new JpaQueryParsingToken(ctx.CURRENT_INSTANT())); + if (ctx.LEFT_PAREN() != null) { - tokens.add(new JpaQueryParsingToken(ctx.BETWEEN())); - tokens.addAll(visit(ctx.expression(1))); - tokens.add(new JpaQueryParsingToken(ctx.AND())); - tokens.addAll(visit(ctx.expression(2))); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } + } else if (ctx.INSTANT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INSTANT())); + } return tokens; } @Override - public List visitDealingWithNullExpression(HqlParser.DealingWithNullExpressionContext ctx) { + public List visitLocalDateTimeFunction(HqlParser.LocalDateTimeFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.expression(0))); - tokens.add(new JpaQueryParsingToken(ctx.IS())); + if (ctx.LOCAL_DATETIME() != null) { - if (ctx.NOT() != null) { - tokens.add(TOKEN_NOT); - } + tokens.add(new JpaQueryParsingToken(ctx.LOCAL_DATETIME())); + if (ctx.LEFT_PAREN() != null) { - if (ctx.NULL() != null) { - tokens.add(new JpaQueryParsingToken(ctx.NULL())); - } else if (ctx.DISTINCT() != null) { + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } + } else if (ctx.LOCAL() != null) { - tokens.add(new JpaQueryParsingToken(ctx.DISTINCT())); - tokens.add(new JpaQueryParsingToken(ctx.FROM())); - tokens.addAll(visit(ctx.expression(1))); + tokens.add(new JpaQueryParsingToken(ctx.LOCAL())); + tokens.add(new JpaQueryParsingToken(ctx.DATETIME())); } return tokens; } @Override - public List visitStringPatternMatching(HqlParser.StringPatternMatchingContext ctx) { + public List visitOffsetDateTimeFunction(HqlParser.OffsetDateTimeFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.expression(0))); - - if (ctx.NOT() != null) { - tokens.add(TOKEN_NOT); - } - - if (ctx.LIKE() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LIKE())); - } else if (ctx.ILIKE() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ILIKE())); - } - - tokens.addAll(visit(ctx.expression(1))); + if (ctx.OFFSET_DATETIME() != null) { - if (ctx.ESCAPE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.OFFSET_DATETIME())); + if (ctx.LEFT_PAREN() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ESCAPE())); - if (ctx.character() != null) { - tokens.addAll(visit(ctx.character())); - } else if (ctx.parameter() != null) { - tokens.addAll(visit(ctx.parameter())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); } + } else if (ctx.OFFSET() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.OFFSET())); + tokens.add(new JpaQueryParsingToken(ctx.DATETIME())); } return tokens; } @Override - public List visitInExpression(HqlParser.InExpressionContext ctx) { + public List visitLocalDateFunction(HqlParser.LocalDateFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.expression())); + if (ctx.LOCAL_DATE() != null) { - if (ctx.NOT() != null) { - tokens.add(TOKEN_NOT); - } + tokens.add(new JpaQueryParsingToken(ctx.LOCAL_DATE())); + if (ctx.LEFT_PAREN() != null) { - tokens.add(new JpaQueryParsingToken(ctx.IN())); - tokens.addAll(visit(ctx.inList())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); + } + } else if (ctx.LOCAL() != null) { + + tokens.add(new JpaQueryParsingToken(ctx.LOCAL())); + tokens.add(new JpaQueryParsingToken(ctx.DATE())); + } return tokens; } @Override - public List visitInList(HqlParser.InListContext ctx) { + public List visitLocalTimeFunction(HqlParser.LocalTimeFunctionContext ctx) { List tokens = new ArrayList<>(); - if (ctx.simplePath() != null) { + if (ctx.LOCAL_TIME() != null) { - if (ctx.ELEMENTS() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); - } else if (ctx.INDICES() != null) { - tokens.add(new JpaQueryParsingToken(ctx.INDICES())); + tokens.add(new JpaQueryParsingToken(ctx.LOCAL_TIME())); + if (ctx.LEFT_PAREN() != null) { + + tokens.add(TOKEN_OPEN_PAREN); + tokens.add(TOKEN_CLOSE_PAREN); } + } else if (ctx.LOCAL() != null) { - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.simplePath())); - NOSPACE(tokens); - tokens.add(TOKEN_CLOSE_PAREN); - } else if (ctx.subquery() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LOCAL())); + tokens.add(new JpaQueryParsingToken(ctx.TIME())); + } - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.subquery())); - NOSPACE(tokens); - tokens.add(TOKEN_CLOSE_PAREN); - } else if (ctx.parameter() != null) { - tokens.addAll(visit(ctx.parameter())); - } else if (ctx.expressionOrPredicate() != null) { + return tokens; + } - tokens.add(TOKEN_OPEN_PAREN); + @Override + public List visitFormatFunction(HqlParser.FormatFunctionContext ctx) { - ctx.expressionOrPredicate().forEach(expressionOrPredicateContext -> { - tokens.addAll(visit(expressionOrPredicateContext)); - NOSPACE(tokens); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + List tokens = new ArrayList<>(); - tokens.add(TOKEN_CLOSE_PAREN); - } + tokens.add(new JpaQueryParsingToken(ctx.FORMAT())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.expression())); + tokens.add(new JpaQueryParsingToken(ctx.AS())); + tokens.addAll(visit(ctx.format())); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitExistsExpression(HqlParser.ExistsExpressionContext ctx) { - - List tokens = new ArrayList<>(); + public List visitFormat(HqlParser.FormatContext ctx) { + return List.of(new JpaQueryParsingToken(ctx.STRING_LITERAL())); + } - if (ctx.simplePath() != null) { + @Override + public List visitExtractFunction(HqlParser.ExtractFunctionContext ctx) { - tokens.add(new JpaQueryParsingToken(ctx.EXISTS())); + List tokens = new ArrayList<>(); - if (ctx.ELEMENTS() != null) { - tokens.add(new JpaQueryParsingToken(ctx.ELEMENTS())); - } else if (ctx.INDICES() != null) { - tokens.add(new JpaQueryParsingToken(ctx.INDICES())); - } + if (ctx.EXTRACT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.EXTRACT())); tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.simplePath())); + tokens.addAll(visit(ctx.extractField())); + tokens.add(new JpaQueryParsingToken(ctx.FROM())); + tokens.addAll(visit(ctx.expression())); tokens.add(TOKEN_CLOSE_PAREN); + } else if (ctx.datetimeField() != null) { - } else if (ctx.expression() != null) { - - tokens.add(new JpaQueryParsingToken(ctx.EXISTS())); + tokens.addAll(visit(ctx.datetimeField())); + tokens.add(TOKEN_OPEN_PAREN); tokens.addAll(visit(ctx.expression())); + tokens.add(TOKEN_CLOSE_PAREN); } return tokens; } @Override - public List visitCollectionExpression(HqlParser.CollectionExpressionContext ctx) { + public List visitTruncFunction(HqlParser.TruncFunctionContext ctx) { List tokens = new ArrayList<>(); - tokens.addAll(visit(ctx.expression())); - - if (ctx.IS() != null) { - - tokens.add(new JpaQueryParsingToken(ctx.IS())); - - if (ctx.NOT() != null) { - tokens.add(TOKEN_NOT); - } - - tokens.add(new JpaQueryParsingToken(ctx.EMPTY())); - } else if (ctx.MEMBER() != null) { - - if (ctx.NOT() != null) { - tokens.add(TOKEN_NOT); - } - - tokens.add(new JpaQueryParsingToken(ctx.MEMBER())); - tokens.add(new JpaQueryParsingToken(ctx.OF())); - tokens.addAll(visit(ctx.path())); + if (ctx.TRUNC() != null) { + tokens.add(new JpaQueryParsingToken(ctx.TRUNC())); + } else if (ctx.TRUNCATE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.TRUNCATE())); + } + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.expression(0))); + if (ctx.COMMA() != null) { + tokens.add(TOKEN_COMMA); + } + if (ctx.datetimeField() != null) { + tokens.addAll(visit(ctx.datetimeField())); + } + if (ctx.expression(1) != null) { + tokens.addAll(visit(ctx.expression(1))); } + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitInstantiationTarget(HqlParser.InstantiationTargetContext ctx) { + public List visitExtractField(HqlParser.ExtractFieldContext ctx) { - if (ctx.LIST() != null) { - return List.of(new JpaQueryParsingToken(ctx.LIST())); - } else if (ctx.MAP() != null) { - return List.of(new JpaQueryParsingToken(ctx.MAP())); - } else if (ctx.simplePath() != null) { + if (ctx.datetimeField() != null) { + return visit(ctx.datetimeField()); + } else if (ctx.dayField() != null) { + return visit(ctx.dayField()); + } else if (ctx.weekField() != null) { + return visit(ctx.weekField()); + } else if (ctx.timeZoneField() != null) { + return visit(ctx.timeZoneField()); + } else if (ctx.dateOrTimeField() != null) { + return visit(ctx.dateOrTimeField()); + } else { + return List.of(); + } + } - List tokens = visit(ctx.simplePath()); - NOSPACE(tokens); - return tokens; + @Override + public List visitDatetimeField(HqlParser.DatetimeFieldContext ctx) { + + if (ctx.YEAR() != null) { + return List.of(new JpaQueryParsingToken(ctx.YEAR())); + } else if (ctx.MONTH() != null) { + return List.of(new JpaQueryParsingToken(ctx.MONTH())); + } else if (ctx.DAY() != null) { + return List.of(new JpaQueryParsingToken(ctx.DAY())); + } else if (ctx.WEEK() != null) { + return List.of(new JpaQueryParsingToken(ctx.WEEK())); + } else if (ctx.QUARTER() != null) { + return List.of(new JpaQueryParsingToken(ctx.QUARTER())); + } else if (ctx.HOUR() != null) { + return List.of(new JpaQueryParsingToken(ctx.HOUR())); + } else if (ctx.MINUTE() != null) { + return List.of(new JpaQueryParsingToken(ctx.MINUTE())); + } else if (ctx.SECOND() != null) { + return List.of(new JpaQueryParsingToken(ctx.SECOND())); + } else if (ctx.NANOSECOND() != null) { + return List.of(new JpaQueryParsingToken(ctx.NANOSECOND())); + } else if (ctx.EPOCH() != null) { + return List.of(new JpaQueryParsingToken(ctx.EPOCH())); } else { return List.of(); } } @Override - public List visitInstantiationArguments(HqlParser.InstantiationArgumentsContext ctx) { + public List visitDayField(HqlParser.DayFieldContext ctx) { List tokens = new ArrayList<>(); - ctx.instantiationArgument().forEach(instantiationArgumentContext -> { - tokens.addAll(visit(instantiationArgumentContext)); - NOSPACE(tokens); - tokens.add(TOKEN_COMMA); - }); - CLIP(tokens); + tokens.add(new JpaQueryParsingToken(ctx.DAY())); + tokens.add(new JpaQueryParsingToken(ctx.OF())); + if (ctx.MONTH() != null) { + tokens.add(new JpaQueryParsingToken(ctx.MONTH())); + } else if (ctx.WEEK() != null) { + tokens.add(new JpaQueryParsingToken(ctx.WEEK())); + } else if (ctx.YEAR() != null) { + tokens.add(new JpaQueryParsingToken(ctx.YEAR())); + } return tokens; } @Override - public List visitInstantiationArgument(HqlParser.InstantiationArgumentContext ctx) { + public List visitWeekField(HqlParser.WeekFieldContext ctx) { List tokens = new ArrayList<>(); - if (ctx.expressionOrPredicate() != null) { - tokens.addAll(visit(ctx.expressionOrPredicate())); - } else if (ctx.instantiation() != null) { - tokens.addAll(visit(ctx.instantiation())); - } - - if (ctx.variable() != null) { - tokens.addAll(visit(ctx.variable())); + tokens.add(new JpaQueryParsingToken(ctx.WEEK())); + tokens.add(new JpaQueryParsingToken(ctx.OF())); + if (ctx.MONTH() != null) { + tokens.add(new JpaQueryParsingToken(ctx.MONTH())); + } else if (ctx.YEAR() != null) { + tokens.add(new JpaQueryParsingToken(ctx.YEAR())); } return tokens; } @Override - public List visitParameterOrIntegerLiteral(HqlParser.ParameterOrIntegerLiteralContext ctx) { + public List visitTimeZoneField(HqlParser.TimeZoneFieldContext ctx) { - if (ctx.parameter() != null) { - return visit(ctx.parameter()); - } else if (ctx.INTEGER_LITERAL() != null) { - return List.of(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); - } else { - return List.of(); + List tokens = new ArrayList<>(); + + if (ctx.OFFSET() != null) { + tokens.add(new JpaQueryParsingToken(ctx.OFFSET())); + if (ctx.HOUR() != null) { + tokens.add(new JpaQueryParsingToken(ctx.HOUR())); + } + if (ctx.MINUTE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.MINUTE())); + } + } else if (ctx.TIMEZONE_HOUR() != null) { + tokens.add(new JpaQueryParsingToken(ctx.TIMEZONE_HOUR())); + } else if (ctx.TIMEZONE_MINUTE() != null) { + tokens.add(new JpaQueryParsingToken(ctx.TIMEZONE_MINUTE())); } + + return tokens; } @Override - public List visitParameterOrNumberLiteral(HqlParser.ParameterOrNumberLiteralContext ctx) { + public List visitDateOrTimeField(HqlParser.DateOrTimeFieldContext ctx) { - if (ctx.parameter() != null) { - return visit(ctx.parameter()); - } else if (ctx.numericLiteral() != null) { - return visit(ctx.numericLiteral()); + if (ctx.DATE() != null) { + return List.of(new JpaQueryParsingToken(ctx.DATE())); + } else if (ctx.TIME() != null) { + return List.of(new JpaQueryParsingToken(ctx.TIME())); } else { return List.of(); } } @Override - public List visitVariable(HqlParser.VariableContext ctx) { + public List visitPositionFunction(HqlParser.PositionFunctionContext ctx) { List tokens = new ArrayList<>(); - if (ctx.identifier() != null) { - - tokens.add(new JpaQueryParsingToken(ctx.AS())); - tokens.addAll(visit(ctx.identifier())); - } else if (ctx.reservedWord() != null) { - tokens.addAll(visit(ctx.reservedWord())); - } + tokens.add(new JpaQueryParsingToken(ctx.POSITION())); + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.positionFunctionPatternArgument())); + tokens.add(new JpaQueryParsingToken(ctx.IN())); + tokens.addAll(visit(ctx.positionFunctionStringArgument())); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; + } @Override - public List visitParameter(HqlParser.ParameterContext ctx) { + public List visitPositionFunctionPatternArgument( + HqlParser.PositionFunctionPatternArgumentContext ctx) { + return visit(ctx.expression()); + } - List tokens = new ArrayList<>(); + @Override + public List visitPositionFunctionStringArgument( + HqlParser.PositionFunctionStringArgumentContext ctx) { + return visit(ctx.expression()); + } - if (ctx.prefix.getText().equals(":")) { + @Override + public List visitCube(HqlParser.CubeContext ctx) { - tokens.add(TOKEN_COLON); - tokens.addAll(visit(ctx.identifier())); - } else if (ctx.prefix.getText().equals("?")) { + List tokens = new ArrayList<>(); - tokens.add(TOKEN_QUESTION_MARK); + tokens.add(new JpaQueryParsingToken(ctx.CUBE())); + tokens.add(TOKEN_OPEN_PAREN); + ctx.expressionOrPredicate().forEach(expressionOrPredicateContext -> { - if (ctx.INTEGER_LITERAL() != null) { - tokens.add(new JpaQueryParsingToken(ctx.INTEGER_LITERAL())); - } - } + tokens.addAll(visit(expressionOrPredicateContext)); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + }); + CLIP(tokens); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitEntityName(HqlParser.EntityNameContext ctx) { + public List visitRollup(HqlParser.RollupContext ctx) { List tokens = new ArrayList<>(); - ctx.identifier().forEach(identifierContext -> { - tokens.addAll(visit(identifierContext)); + tokens.add(new JpaQueryParsingToken(ctx.ROLLUP())); + tokens.add(TOKEN_OPEN_PAREN); + ctx.expressionOrPredicate().forEach(expressionOrPredicateContext -> { + + tokens.addAll(visit(expressionOrPredicateContext)); NOSPACE(tokens); - tokens.add(TOKEN_DOT); + tokens.add(TOKEN_COMMA); }); CLIP(tokens); - SPACE(tokens); + tokens.add(TOKEN_CLOSE_PAREN); return tokens; } @Override - public List visitIdentifier(HqlParser.IdentifierContext ctx) { + public List visitNakedIdentifier(HqlParser.NakedIdentifierContext ctx) { - if (ctx.reservedWord() != null) { - return visit(ctx.reservedWord()); + if (ctx.IDENTIFIER() != null) { + return List.of(new JpaQueryParsingToken(ctx.IDENTIFIER())); + } else if (ctx.QUOTED_IDENTIFIER() != null) { + return List.of(new JpaQueryParsingToken(ctx.QUOTED_IDENTIFIER())); + } else if (ctx.ALL() != null) { + return List.of(new JpaQueryParsingToken(ctx.ALL())); + } else if (ctx.AND() != null) { + return List.of(new JpaQueryParsingToken(ctx.AND())); + } else if (ctx.ANY() != null) { + return List.of(new JpaQueryParsingToken(ctx.ANY())); + } else if (ctx.AS() != null) { + return List.of(new JpaQueryParsingToken(ctx.AS())); + } else if (ctx.ASC() != null) { + return List.of(new JpaQueryParsingToken(ctx.ASC())); + } else if (ctx.AVG() != null) { + return List.of(new JpaQueryParsingToken(ctx.AVG())); + } else if (ctx.BETWEEN() != null) { + return List.of(new JpaQueryParsingToken(ctx.BETWEEN())); + } else if (ctx.BOTH() != null) { + return List.of(new JpaQueryParsingToken(ctx.BOTH())); + } else if (ctx.BREADTH() != null) { + return List.of(new JpaQueryParsingToken(ctx.BREADTH())); + } else if (ctx.BY() != null) { + return List.of(new JpaQueryParsingToken(ctx.BY())); + } else if (ctx.CASE() != null) { + return List.of(new JpaQueryParsingToken(ctx.CASE())); + } else if (ctx.CAST() != null) { + return List.of(new JpaQueryParsingToken(ctx.CAST())); + } else if (ctx.COLLATE() != null) { + return List.of(new JpaQueryParsingToken(ctx.COLLATE())); + } else if (ctx.COUNT() != null) { + return List.of(new JpaQueryParsingToken(ctx.COUNT())); + } else if (ctx.CROSS() != null) { + return List.of(new JpaQueryParsingToken(ctx.CROSS())); + } else if (ctx.CUBE() != null) { + return List.of(new JpaQueryParsingToken(ctx.CUBE())); + } else if (ctx.CURRENT() != null) { + return List.of(new JpaQueryParsingToken(ctx.CURRENT())); + } else if (ctx.CURRENT_DATE() != null) { + return List.of(new JpaQueryParsingToken(ctx.CURRENT_DATE())); + } else if (ctx.CURRENT_INSTANT() != null) { + return List.of(new JpaQueryParsingToken(ctx.CURRENT_INSTANT())); + } else if (ctx.CURRENT_TIME() != null) { + return List.of(new JpaQueryParsingToken(ctx.CURRENT_TIME())); + } else if (ctx.CURRENT_TIMESTAMP() != null) { + return List.of(new JpaQueryParsingToken(ctx.CURRENT_TIMESTAMP())); + } else if (ctx.CYCLE() != null) { + return List.of(new JpaQueryParsingToken(ctx.CYCLE())); + } else if (ctx.DATE() != null) { + return List.of(new JpaQueryParsingToken(ctx.DATE())); + } else if (ctx.DATETIME() != null) { + return List.of(new JpaQueryParsingToken(ctx.DATETIME())); + } else if (ctx.DAY() != null) { + return List.of(new JpaQueryParsingToken(ctx.DAY())); + } else if (ctx.DEFAULT() != null) { + return List.of(new JpaQueryParsingToken(ctx.DEFAULT())); + } else if (ctx.DELETE() != null) { + return List.of(new JpaQueryParsingToken(ctx.DELETE())); + } else if (ctx.DEPTH() != null) { + return List.of(new JpaQueryParsingToken(ctx.DEPTH())); + } else if (ctx.DESC() != null) { + return List.of(new JpaQueryParsingToken(ctx.DESC())); + } else if (ctx.DISTINCT() != null) { + return List.of(new JpaQueryParsingToken(ctx.DISTINCT())); + } else if (ctx.ELEMENT() != null) { + return List.of(new JpaQueryParsingToken(ctx.ELEMENT())); + } else if (ctx.ELEMENTS() != null) { + return List.of(new JpaQueryParsingToken(ctx.ELEMENTS())); + } else if (ctx.ELSE() != null) { + return List.of(new JpaQueryParsingToken(ctx.ELSE())); + } else if (ctx.EMPTY() != null) { + return List.of(new JpaQueryParsingToken(ctx.EMPTY())); + } else if (ctx.END() != null) { + return List.of(new JpaQueryParsingToken(ctx.END())); + } else if (ctx.ENTRY() != null) { + return List.of(new JpaQueryParsingToken(ctx.ENTRY())); + } else if (ctx.EPOCH() != null) { + return List.of(new JpaQueryParsingToken(ctx.EPOCH())); + } else if (ctx.ERROR() != null) { + return List.of(new JpaQueryParsingToken(ctx.ERROR())); + } else if (ctx.ESCAPE() != null) { + return List.of(new JpaQueryParsingToken(ctx.ESCAPE())); + } else if (ctx.EVERY() != null) { + return List.of(new JpaQueryParsingToken(ctx.EVERY())); + } else if (ctx.EXCEPT() != null) { + return List.of(new JpaQueryParsingToken(ctx.EXCEPT())); + } else if (ctx.EXCLUDE() != null) { + return List.of(new JpaQueryParsingToken(ctx.EXCLUDE())); + } else if (ctx.EXISTS() != null) { + return List.of(new JpaQueryParsingToken(ctx.EXISTS())); + } else if (ctx.EXTRACT() != null) { + return List.of(new JpaQueryParsingToken(ctx.EXTRACT())); + } else if (ctx.FETCH() != null) { + return List.of(new JpaQueryParsingToken(ctx.FETCH())); + } else if (ctx.FILTER() != null) { + return List.of(new JpaQueryParsingToken(ctx.FILTER())); + } else if (ctx.FIRST() != null) { + return List.of(new JpaQueryParsingToken(ctx.FIRST())); + } else if (ctx.FOLLOWING() != null) { + return List.of(new JpaQueryParsingToken(ctx.FOLLOWING())); + } else if (ctx.FOR() != null) { + return List.of(new JpaQueryParsingToken(ctx.FOR())); + } else if (ctx.FORMAT() != null) { + return List.of(new JpaQueryParsingToken(ctx.FORMAT())); + } else if (ctx.FROM() != null) { + return List.of(new JpaQueryParsingToken(ctx.FROM())); + } else if (ctx.FUNCTION() != null) { + return List.of(new JpaQueryParsingToken(ctx.FUNCTION())); + } else if (ctx.GROUP() != null) { + return List.of(new JpaQueryParsingToken(ctx.GROUP())); + } else if (ctx.GROUPS() != null) { + return List.of(new JpaQueryParsingToken(ctx.GROUPS())); + } else if (ctx.HAVING() != null) { + return List.of(new JpaQueryParsingToken(ctx.HAVING())); + } else if (ctx.HOUR() != null) { + return List.of(new JpaQueryParsingToken(ctx.HOUR())); + } else if (ctx.ID() != null) { + return List.of(new JpaQueryParsingToken(ctx.ID())); + } else if (ctx.IGNORE() != null) { + return List.of(new JpaQueryParsingToken(ctx.IGNORE())); + } else if (ctx.ILIKE() != null) { + return List.of(new JpaQueryParsingToken(ctx.ILIKE())); + } else if (ctx.IN() != null) { + return List.of(new JpaQueryParsingToken(ctx.IN())); + } else if (ctx.INDEX() != null) { + return List.of(new JpaQueryParsingToken(ctx.INDEX())); + } else if (ctx.INDICES() != null) { + return List.of(new JpaQueryParsingToken(ctx.INDICES())); + } else if (ctx.INSERT() != null) { + return List.of(new JpaQueryParsingToken(ctx.INSERT())); + } else if (ctx.INSTANT() != null) { + return List.of(new JpaQueryParsingToken(ctx.INSTANT())); + } else if (ctx.INTERSECT() != null) { + return List.of(new JpaQueryParsingToken(ctx.INTERSECT())); + } else if (ctx.INTO() != null) { + return List.of(new JpaQueryParsingToken(ctx.INTO())); + } else if (ctx.IS() != null) { + return List.of(new JpaQueryParsingToken(ctx.IS())); + } else if (ctx.JOIN() != null) { + return List.of(new JpaQueryParsingToken(ctx.JOIN())); + } else if (ctx.KEY() != null) { + return List.of(new JpaQueryParsingToken(ctx.KEY())); + } else if (ctx.LAST() != null) { + return List.of(new JpaQueryParsingToken(ctx.LAST())); + } else if (ctx.LEADING() != null) { + return List.of(new JpaQueryParsingToken(ctx.LEADING())); + } else if (ctx.LIKE() != null) { + return List.of(new JpaQueryParsingToken(ctx.LIKE())); + } else if (ctx.LIMIT() != null) { + return List.of(new JpaQueryParsingToken(ctx.LIMIT())); + } else if (ctx.LIST() != null) { + return List.of(new JpaQueryParsingToken(ctx.LIST())); + } else if (ctx.LISTAGG() != null) { + return List.of(new JpaQueryParsingToken(ctx.LISTAGG())); + } else if (ctx.LOCAL() != null) { + return List.of(new JpaQueryParsingToken(ctx.LOCAL())); + } else if (ctx.LOCAL_DATE() != null) { + return List.of(new JpaQueryParsingToken(ctx.LOCAL_DATE())); + } else if (ctx.LOCAL_DATETIME() != null) { + return List.of(new JpaQueryParsingToken(ctx.LOCAL_DATETIME())); + } else if (ctx.LOCAL_TIME() != null) { + return List.of(new JpaQueryParsingToken(ctx.LOCAL_TIME())); + } else if (ctx.MAP() != null) { + return List.of(new JpaQueryParsingToken(ctx.MAP())); + } else if (ctx.MATERIALIZED() != null) { + return List.of(new JpaQueryParsingToken(ctx.MATERIALIZED())); + } else if (ctx.MAX() != null) { + return List.of(new JpaQueryParsingToken(ctx.MAX())); + } else if (ctx.MAXELEMENT() != null) { + return List.of(new JpaQueryParsingToken(ctx.MAXELEMENT())); + } else if (ctx.MAXINDEX() != null) { + return List.of(new JpaQueryParsingToken(ctx.MAXINDEX())); + } else if (ctx.MEMBER() != null) { + return List.of(new JpaQueryParsingToken(ctx.MEMBER())); + } else if (ctx.MICROSECOND() != null) { + return List.of(new JpaQueryParsingToken(ctx.MICROSECOND())); + } else if (ctx.MILLISECOND() != null) { + return List.of(new JpaQueryParsingToken(ctx.MILLISECOND())); + } else if (ctx.MIN() != null) { + return List.of(new JpaQueryParsingToken(ctx.MIN())); + } else if (ctx.MINELEMENT() != null) { + return List.of(new JpaQueryParsingToken(ctx.MINELEMENT())); + } else if (ctx.MININDEX() != null) { + return List.of(new JpaQueryParsingToken(ctx.MININDEX())); + } else if (ctx.MINUTE() != null) { + return List.of(new JpaQueryParsingToken(ctx.MINUTE())); + } else if (ctx.MONTH() != null) { + return List.of(new JpaQueryParsingToken(ctx.MONTH())); + } else if (ctx.NANOSECOND() != null) { + return List.of(new JpaQueryParsingToken(ctx.NANOSECOND())); + } else if (ctx.NATURALID() != null) { + return List.of(new JpaQueryParsingToken(ctx.NATURALID())); + } else if (ctx.NEW() != null) { + return List.of(new JpaQueryParsingToken(ctx.NEW())); + } else if (ctx.NEXT() != null) { + return List.of(new JpaQueryParsingToken(ctx.NEXT())); + } else if (ctx.NO() != null) { + return List.of(new JpaQueryParsingToken(ctx.NO())); + } else if (ctx.NOT() != null) { + return List.of(new JpaQueryParsingToken(ctx.NOT())); + } else if (ctx.NULLS() != null) { + return List.of(new JpaQueryParsingToken(ctx.NULLS())); + } else if (ctx.OBJECT() != null) { + return List.of(new JpaQueryParsingToken(ctx.OBJECT())); + } else if (ctx.OF() != null) { + return List.of(new JpaQueryParsingToken(ctx.OF())); + } else if (ctx.OFFSET() != null) { + return List.of(new JpaQueryParsingToken(ctx.OFFSET())); + } else if (ctx.OFFSET_DATETIME() != null) { + return List.of(new JpaQueryParsingToken(ctx.OFFSET_DATETIME())); + } else if (ctx.ON() != null) { + return List.of(new JpaQueryParsingToken(ctx.ON())); + } else if (ctx.ONLY() != null) { + return List.of(new JpaQueryParsingToken(ctx.ONLY())); + } else if (ctx.OR() != null) { + return List.of(new JpaQueryParsingToken(ctx.OR())); + } else if (ctx.ORDER() != null) { + return List.of(new JpaQueryParsingToken(ctx.ORDER())); + } else if (ctx.OTHERS() != null) { + return List.of(new JpaQueryParsingToken(ctx.OTHERS())); + } else if (ctx.OVER() != null) { + return List.of(new JpaQueryParsingToken(ctx.OVER())); + } else if (ctx.OVERFLOW() != null) { + return List.of(new JpaQueryParsingToken(ctx.OVERFLOW())); + } else if (ctx.OVERLAY() != null) { + return List.of(new JpaQueryParsingToken(ctx.OVERLAY())); + } else if (ctx.PAD() != null) { + return List.of(new JpaQueryParsingToken(ctx.PAD())); + } else if (ctx.PARTITION() != null) { + return List.of(new JpaQueryParsingToken(ctx.PARTITION())); + } else if (ctx.PERCENT() != null) { + return List.of(new JpaQueryParsingToken(ctx.PERCENT())); + } else if (ctx.PLACING() != null) { + return List.of(new JpaQueryParsingToken(ctx.PLACING())); + } else if (ctx.POSITION() != null) { + return List.of(new JpaQueryParsingToken(ctx.POSITION())); + } else if (ctx.PRECEDING() != null) { + return List.of(new JpaQueryParsingToken(ctx.PRECEDING())); + } else if (ctx.QUARTER() != null) { + return List.of(new JpaQueryParsingToken(ctx.QUARTER())); + } else if (ctx.RANGE() != null) { + return List.of(new JpaQueryParsingToken(ctx.RANGE())); + } else if (ctx.RESPECT() != null) { + return List.of(new JpaQueryParsingToken(ctx.RESPECT())); + } else if (ctx.ROLLUP() != null) { + return List.of(new JpaQueryParsingToken(ctx.ROLLUP())); + } else if (ctx.ROW() != null) { + return List.of(new JpaQueryParsingToken(ctx.ROW())); + } else if (ctx.ROWS() != null) { + return List.of(new JpaQueryParsingToken(ctx.ROWS())); + } else if (ctx.SEARCH() != null) { + return List.of(new JpaQueryParsingToken(ctx.SEARCH())); + } else if (ctx.SECOND() != null) { + return List.of(new JpaQueryParsingToken(ctx.SECOND())); + } else if (ctx.SELECT() != null) { + return List.of(new JpaQueryParsingToken(ctx.SELECT())); + } else if (ctx.SET() != null) { + return List.of(new JpaQueryParsingToken(ctx.SET())); + } else if (ctx.SIZE() != null) { + return List.of(new JpaQueryParsingToken(ctx.SIZE())); + } else if (ctx.SOME() != null) { + return List.of(new JpaQueryParsingToken(ctx.SOME())); + } else if (ctx.SUBSTRING() != null) { + return List.of(new JpaQueryParsingToken(ctx.SUBSTRING())); + } else if (ctx.SUM() != null) { + return List.of(new JpaQueryParsingToken(ctx.SUM())); + } else if (ctx.THEN() != null) { + return List.of(new JpaQueryParsingToken(ctx.THEN())); + } else if (ctx.TIES() != null) { + return List.of(new JpaQueryParsingToken(ctx.TIES())); + } else if (ctx.TIME() != null) { + return List.of(new JpaQueryParsingToken(ctx.TIME())); + } else if (ctx.TIMESTAMP() != null) { + return List.of(new JpaQueryParsingToken(ctx.TIMESTAMP())); + } else if (ctx.TIMEZONE_HOUR() != null) { + return List.of(new JpaQueryParsingToken(ctx.TIMEZONE_HOUR())); + } else if (ctx.TIMEZONE_MINUTE() != null) { + return List.of(new JpaQueryParsingToken(ctx.TIMEZONE_MINUTE())); + } else if (ctx.TO() != null) { + return List.of(new JpaQueryParsingToken(ctx.TO())); + } else if (ctx.TRAILING() != null) { + return List.of(new JpaQueryParsingToken(ctx.TRAILING())); + } else if (ctx.TREAT() != null) { + return List.of(new JpaQueryParsingToken(ctx.TREAT())); + } else if (ctx.TRIM() != null) { + return List.of(new JpaQueryParsingToken(ctx.TRIM())); + } else if (ctx.TRUNC() != null) { + return List.of(new JpaQueryParsingToken(ctx.TRUNC())); + } else if (ctx.TRUNCATE() != null) { + return List.of(new JpaQueryParsingToken(ctx.TRUNCATE())); + } else if (ctx.TYPE() != null) { + return List.of(new JpaQueryParsingToken(ctx.TYPE())); + } else if (ctx.UNBOUNDED() != null) { + return List.of(new JpaQueryParsingToken(ctx.UNBOUNDED())); + } else if (ctx.UNION() != null) { + return List.of(new JpaQueryParsingToken(ctx.UNION())); + } else if (ctx.UPDATE() != null) { + return List.of(new JpaQueryParsingToken(ctx.UPDATE())); + } else if (ctx.USING() != null) { + return List.of(new JpaQueryParsingToken(ctx.USING())); + } else if (ctx.VALUE() != null) { + return List.of(new JpaQueryParsingToken(ctx.VALUE())); + } else if (ctx.VALUES() != null) { + return List.of(new JpaQueryParsingToken(ctx.VALUES())); + } else if (ctx.VERSION() != null) { + return List.of(new JpaQueryParsingToken(ctx.VERSION())); + } else if (ctx.VERSIONED() != null) { + return List.of(new JpaQueryParsingToken(ctx.VERSIONED())); + } else if (ctx.WEEK() != null) { + return List.of(new JpaQueryParsingToken(ctx.WEEK())); + } else if (ctx.WHEN() != null) { + return List.of(new JpaQueryParsingToken(ctx.WHEN())); + } else if (ctx.WHERE() != null) { + return List.of(new JpaQueryParsingToken(ctx.WHERE())); + } else if (ctx.WITH() != null) { + return List.of(new JpaQueryParsingToken(ctx.WITH())); + } else if (ctx.WITHIN() != null) { + return List.of(new JpaQueryParsingToken(ctx.WITHIN())); + } else if (ctx.WITHOUT() != null) { + return List.of(new JpaQueryParsingToken(ctx.WITHOUT())); + } else if (ctx.YEAR() != null) { + return List.of(new JpaQueryParsingToken(ctx.YEAR())); } else { return List.of(); } } @Override - public List visitCharacter(HqlParser.CharacterContext ctx) { - return List.of(new JpaQueryParsingToken(ctx.CHARACTER())); - } - - @Override - public List visitFunctionName(HqlParser.FunctionNameContext ctx) { - return visit(ctx.reservedWord()); - } + public List visitIdentifier(HqlParser.IdentifierContext ctx) { - @Override - public List visitReservedWord(HqlParser.ReservedWordContext ctx) { + List tokens = new ArrayList<>(); - if (ctx.IDENTIFICATION_VARIABLE() != null) { - return List.of(new JpaQueryParsingToken(ctx.IDENTIFICATION_VARIABLE())); - } else { - return List.of(new JpaQueryParsingToken(ctx.f)); + if (ctx.nakedIdentifier() != null) { + tokens.addAll(visit(ctx.nakedIdentifier())); + } else if (ctx.FULL() != null) { + tokens.add(new JpaQueryParsingToken(ctx.FULL())); + } else if (ctx.INNER() != null) { + tokens.add(new JpaQueryParsingToken(ctx.INNER())); + } else if (ctx.LEFT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.LEFT())); + } else if (ctx.OUTER() != null) { + tokens.add(new JpaQueryParsingToken(ctx.OUTER())); + } else if (ctx.RIGHT() != null) { + tokens.add(new JpaQueryParsingToken(ctx.RIGHT())); } + + return tokens; } } diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryTransformer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryTransformer.java index 6afba0f1f7..1685229403 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryTransformer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryTransformer.java @@ -22,6 +22,7 @@ import java.util.List; import org.antlr.v4.runtime.ParserRuleContext; +import org.hibernate.grammars.hql.HqlParser; import org.springframework.data.domain.Sort; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -104,24 +105,37 @@ private static boolean isSubquery(ParserRuleContext ctx) { } @Override - public List visitOrderedQuery(HqlParser.OrderedQueryContext ctx) { + public List visitQuerySpecExpression(HqlParser.QuerySpecExpressionContext ctx) { - List tokens = newArrayList(); + List tokens = super.visitQuerySpecExpression(ctx); - if (ctx.query() != null) { - tokens.addAll(visit(ctx.query())); - } else if (ctx.queryExpression() != null) { + if (!countQuery && !isSubquery(ctx)) { - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.queryExpression())); - tokens.add(TOKEN_CLOSE_PAREN); - } + if (sort.isSorted()) { - if (!countQuery && !isSubquery(ctx)) { + if (ctx.queryOrder() != null) { + + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); + } else { - if (ctx.queryOrder() != null) { - tokens.addAll(visit(ctx.queryOrder())); + SPACE(tokens); + tokens.add(TOKEN_ORDER_BY); + } + + tokens.addAll(transformerSupport.generateOrderByArguments(primaryFromAlias, sort)); } + } + + return tokens; + } + + @Override + public List visitNestedQueryExpression(HqlParser.NestedQueryExpressionContext ctx) { + + List tokens = super.visitNestedQueryExpression(ctx); + + if (!countQuery && !isSubquery(ctx)) { if (sort.isSorted()) { @@ -137,55 +151,57 @@ public List visitOrderedQuery(HqlParser.OrderedQueryContex tokens.addAll(transformerSupport.generateOrderByArguments(primaryFromAlias, sort)); } - } else { - - if (ctx.queryOrder() != null) { - tokens.addAll(visit(ctx.queryOrder())); - } } return tokens; } @Override - public List visitFromQuery(HqlParser.FromQueryContext ctx) { + public List visitQuery(HqlParser.QueryContext ctx) { - List tokens = newArrayList(); + if (ctx.getChild(0) instanceof HqlParser.SelectClauseContext) { - if (countQuery && !isSubquery(ctx) && ctx.selectClause() == null) { + return super.visitQuery(ctx); - tokens.add(TOKEN_SELECT_COUNT); + } else { - if (countProjection != null) { - tokens.add(new JpaQueryParsingToken(countProjection)); - } else { - tokens.add(new JpaQueryParsingToken(() -> primaryFromAlias, false)); - } + List tokens = newArrayList(); - tokens.add(TOKEN_CLOSE_PAREN); - } + if (countQuery && !isSubquery(ctx) && ctx.selectClause() == null) { - if (ctx.fromClause() != null) { - tokens.addAll(visit(ctx.fromClause())); - } + tokens.add(TOKEN_SELECT_COUNT); - if (ctx.whereClause() != null) { - tokens.addAll(visit(ctx.whereClause())); - } + if (countProjection != null) { + tokens.add(new JpaQueryParsingToken(countProjection)); + } else { + tokens.add(new JpaQueryParsingToken(() -> primaryFromAlias, false)); + } - if (ctx.groupByClause() != null) { - tokens.addAll(visit(ctx.groupByClause())); - } + tokens.add(TOKEN_CLOSE_PAREN); - if (ctx.havingClause() != null) { - tokens.addAll(visit(ctx.havingClause())); - } + tokens.addAll(visit(ctx.fromClause())); - if (ctx.selectClause() != null) { - tokens.addAll(visit(ctx.selectClause())); - } + if (ctx.whereClause() != null) { + tokens.addAll(visit(ctx.whereClause())); + } - return tokens; + if (ctx.groupByClause() != null) { + tokens.addAll(visit(ctx.groupByClause())); + } + + if (ctx.havingClause() != null) { + tokens.addAll(visit(ctx.havingClause())); + } + + if (ctx.selectClause() != null) { + tokens.addAll(visit(ctx.selectClause())); + } + + return tokens; + } else { + return super.visitQuery(ctx); + } + } } @Override @@ -212,49 +228,63 @@ public List visitQueryOrder(HqlParser.QueryOrderContext ct } @Override - public List visitFromRoot(HqlParser.FromRootContext ctx) { + public List visitRootEntity(HqlParser.RootEntityContext ctx) { List tokens = newArrayList(); - if (ctx.entityName() != null) { + tokens.addAll(visit(ctx.entityName())); + + if (ctx.variable() != null) { + tokens.addAll(visit(ctx.variable())); + + if (primaryFromAlias == null && !isSubquery(ctx)) { + primaryFromAlias = tokens.get(tokens.size() - 1).getToken(); + } + } else { - tokens.addAll(visit(ctx.entityName())); + if (countQuery) { - if (ctx.variable() != null) { - tokens.addAll(visit(ctx.variable())); + tokens.add(TOKEN_AS); + tokens.add(TOKEN_DOUBLE_UNDERSCORE); if (primaryFromAlias == null && !isSubquery(ctx)) { - primaryFromAlias = tokens.get(tokens.size() - 1).getToken(); + primaryFromAlias = TOKEN_DOUBLE_UNDERSCORE.getToken(); } - } else { + } + } + NOSPACE(tokens); - if (countQuery) { + return tokens; + } - tokens.add(TOKEN_AS); - tokens.add(TOKEN_DOUBLE_UNDERSCORE); + @Override + public List visitRootSubquery(HqlParser.RootSubqueryContext ctx) { - if (primaryFromAlias == null && !isSubquery(ctx)) { - primaryFromAlias = TOKEN_DOUBLE_UNDERSCORE.getToken(); - } - } - } - } else if (ctx.subquery() != null) { + List tokens = newArrayList(); + + tokens.add(TOKEN_OPEN_PAREN); + tokens.addAll(visit(ctx.subquery())); + tokens.add(TOKEN_CLOSE_PAREN); + + if (ctx.variable() != null) { + tokens.addAll(visit(ctx.variable())); - if (ctx.LATERAL() != null) { - tokens.add(new JpaQueryParsingToken(ctx.LATERAL())); + if (primaryFromAlias == null && !isSubquery(ctx)) { + primaryFromAlias = tokens.get(tokens.size() - 1).getToken(); } - tokens.add(TOKEN_OPEN_PAREN); - tokens.addAll(visit(ctx.subquery())); - tokens.add(TOKEN_CLOSE_PAREN); + } else { - if (ctx.variable() != null) { - tokens.addAll(visit(ctx.variable())); + if (countQuery) { + + tokens.add(TOKEN_AS); + tokens.add(TOKEN_DOUBLE_UNDERSCORE); if (primaryFromAlias == null && !isSubquery(ctx)) { - primaryFromAlias = tokens.get(tokens.size() - 1).getToken(); + primaryFromAlias = TOKEN_DOUBLE_UNDERSCORE.getToken(); } } } + NOSPACE(tokens); return tokens; } @@ -262,7 +292,7 @@ public List visitFromRoot(HqlParser.FromRootContext ctx) { @Override public List visitJoin(HqlParser.JoinContext ctx) { - List tokens = new ArrayList<>(); + List tokens = newArrayList(); tokens.addAll(visit(ctx.joinType())); tokens.add(new JpaQueryParsingToken(ctx.JOIN())); @@ -282,18 +312,6 @@ public List visitJoin(HqlParser.JoinContext ctx) { return tokens; } - @Override - public List visitAlias(HqlParser.AliasContext ctx) { - - List tokens = super.visitAlias(ctx); - - if (primaryFromAlias == null && !isSubquery(ctx)) { - primaryFromAlias = tokens.get(tokens.size() - 1).getToken(); - } - - return tokens; - } - @Override public List visitVariable(HqlParser.VariableContext ctx) { diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryParsingToken.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryParsingToken.java index 59c409e9e3..a7ef4840c5 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryParsingToken.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryParsingToken.java @@ -48,6 +48,7 @@ class JpaQueryParsingToken { public static final JpaQueryParsingToken TOKEN_CLOSE_SQUARE_BRACKET = new JpaQueryParsingToken("]"); public static final JpaQueryParsingToken TOKEN_COLON = new JpaQueryParsingToken(":", false); public static final JpaQueryParsingToken TOKEN_QUESTION_MARK = new JpaQueryParsingToken("?", false); + public static final JpaQueryParsingToken TOKEN_OPEN_BRACE = new JpaQueryParsingToken("{", false); public static final JpaQueryParsingToken TOKEN_CLOSE_BRACE = new JpaQueryParsingToken("}"); public static final JpaQueryParsingToken TOKEN_CLOSE_SQUARE_BRACKET_BRACE = new JpaQueryParsingToken("]}"); public static final JpaQueryParsingToken TOKEN_CLOSE_PAREN_BRACE = new JpaQueryParsingToken(")}"); @@ -66,6 +67,8 @@ class JpaQueryParsingToken { public static final JpaQueryParsingToken TOKEN_MATERIALIZED = new JpaQueryParsingToken("materialized"); + public static final JpaQueryParsingToken TOKEN_SLASH = new JpaQueryParsingToken("/", false); + /** * The text value of the token. */ diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java index fb5a5ed923..019b2cfb8c 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java @@ -20,6 +20,8 @@ import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; +import org.hibernate.grammars.hql.HqlLexer; +import org.hibernate.grammars.hql.HqlParser; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -49,7 +51,7 @@ private static String parseWithoutChanges(String query) { parser.addErrorListener(new BadJpqlGrammarErrorListener(query)); - HqlParser.StartContext parsedQuery = parser.start(); + HqlParser.StatementContext parsedQuery = parser.statement(); return render(new HqlQueryRenderer().visit(parsedQuery)); } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java index e11dec1ebc..d08da45ca5 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java @@ -851,7 +851,7 @@ void countQueryShouldWorkEvenWithoutExplicitAlias() { @ParameterizedTest @MethodSource("queriesWithReservedWordsAsIdentifiers") // GH-2864 - void usingReservedWordAsRelationshipNameShouldWork(String relationshipName, String joinAlias) { + void usingReservedWordAsRelationshipNameShouldWork(String relationshipName) { HqlQueryParser.parseQuery(String.format(""" select u @@ -864,23 +864,23 @@ where exists ( join iu.roles u2r join u2r.role r join r.rights r2r - join r2r.%s %s + join r2r.%s rt where - %s.code = :rightCode + rt.code = :rightCode and iu = u ) and ct.id = :teamId - """, relationshipName, joinAlias, joinAlias)); + """, relationshipName)); } static Stream queriesWithReservedWordsAsIdentifiers() { return Stream.of( // - Arguments.of("right", "rt"), // - Arguments.of("left", "lt"), // - Arguments.of("outer", "ou"), // - Arguments.of("full", "full"), // - Arguments.of("inner", "inr")); + Arguments.of("right"), // + Arguments.of("left"), // + Arguments.of("outer"), // + Arguments.of("full"), // + Arguments.of("inner")); } @Test // GH-2508