Skip to content

Commit 262e05e

Browse files
christophstroblmp911de
authored andcommitted
Add support for JPA 3.2 additions to EQL.
See: #3136 Original Pull Request: #3695
1 parent ebda35d commit 262e05e

File tree

9 files changed

+345
-18
lines changed

9 files changed

+345
-18
lines changed

spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ scalar_expression
309309
| datetime_expression
310310
| boolean_expression
311311
| case_expression
312+
| cast_function
312313
| entity_type_expression
313314
;
314315

@@ -458,6 +459,7 @@ string_expression
458459
| string_cast_function
459460
| type_cast_function
460461
| '(' subquery ')'
462+
| string_expression '||' string_expression
461463
;
462464

463465
datetime_expression
@@ -542,6 +544,9 @@ functions_returning_strings
542544
| TRIM '(' ((trim_specification)? (trim_character)? FROM)? string_expression ')'
543545
| LOWER '(' string_expression ')'
544546
| UPPER '(' string_expression ')'
547+
| REPLACE '(' string_expression ',' string_expression ',' string_expression ')'
548+
| LEFT '(' string_expression ',' arithmetic_expression ')'
549+
| RIGHT '(' string_expression ',' arithmetic_expression ')'
545550
;
546551

547552
trim_specification
@@ -625,6 +630,14 @@ nullif_expression
625630
: NULLIF '(' scalar_expression ',' scalar_expression ')'
626631
;
627632

633+
type_literal
634+
: STRING
635+
| INTEGER
636+
| LONG
637+
| FLOAT
638+
| DOUBLE
639+
;
640+
628641
/*******************
629642
Gaps in the spec.
630643
*******************/
@@ -637,6 +650,7 @@ trim_character
637650
identification_variable
638651
: IDENTIFICATION_VARIABLE
639652
| f=(COUNT
653+
| AS
640654
| DATE
641655
| FROM
642656
| INNER
@@ -646,11 +660,13 @@ identification_variable
646660
| ORDER
647661
| OUTER
648662
| POWER
663+
| RIGHT
649664
| FLOOR
650665
| SIGN
651666
| TIME
652667
| TYPE
653668
| VALUE)
669+
| type_literal
654670
;
655671

656672
constructor_name
@@ -832,6 +848,8 @@ reserved_word
832848
|OR
833849
|ORDER
834850
|OUTER
851+
|REPLACE
852+
|RIGHT
835853
|POWER
836854
|ROUND
837855
|SELECT
@@ -928,6 +946,7 @@ EXTRACT : E X T R A C T;
928946
FALSE : F A L S E;
929947
FETCH : F E T C H;
930948
FIRST : F I R S T;
949+
FLOAT : F L O A T;
931950
FLOOR : F L O O R;
932951
FLOAT : F L O A T;
933952
FROM : F R O M;
@@ -937,6 +956,7 @@ HAVING : H A V I N G;
937956
IN : I N;
938957
INDEX : I N D E X;
939958
INNER : I N N E R;
959+
INTEGER : I N T E G E R;
940960
INTERSECT : I N T E R S E C T;
941961
IS : I S;
942962
INTEGER : I N T E G E R;
@@ -969,13 +989,16 @@ ORDER : O R D E R;
969989
OUTER : O U T E R;
970990
POWER : P O W E R;
971991
REGEXP : R E G E X P;
992+
REPLACE : R E P L A C E;
993+
RIGHT : R I G H T;
972994
ROUND : R O U N D;
973995
SELECT : S E L E C T;
974996
SET : S E T;
975997
SIGN : S I G N;
976998
SIZE : S I Z E;
977999
SOME : S O M E;
9781000
SQRT : S Q R T;
1001+
STRING : S T R I N G;
9791002
SUBSTRING : S U B S T R I N G;
9801003
STRING : S T R I N G;
9811004
SUM : S U M;
@@ -996,7 +1019,6 @@ WHERE : W H E R E;
9961019
EQUAL : '=' ;
9971020
NOT_EQUAL : '<>' | '!=' ;
9981021

999-
10001022
CHARACTER : '\'' (~ ('\'' | '\\')) '\'' ;
10011023
IDENTIFICATION_VARIABLE : ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '$' | '_') ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '0' .. '9' | '$' | '_')* ;
10021024
STRINGLITERAL : '\'' (~ ('\'' | '\\')|'\\')* '\'' ;

spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Jpql.g4

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,25 @@ ql_statement
4343
;
4444

4545
select_statement
46-
: select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)? (setOperator_with_select_statement)*
46+
: select_query
4747
;
4848

49-
setOperator_with_select_statement
50-
: INTERSECT select_statement
51-
| UNION select_statement
52-
| EXCEPT select_statement
49+
select_query
50+
: select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)? (set_fuction)?
51+
;
52+
53+
setOperator
54+
: UNION ALL?
55+
| INTERSECT ALL?
56+
| EXCEPT ALL?
57+
;
58+
59+
set_fuction
60+
: setOperator set_function_select
61+
;
62+
63+
set_function_select
64+
: select_query
5365
;
5466

5567
update_statement
@@ -303,6 +315,7 @@ scalar_expression
303315
| datetime_expression
304316
| boolean_expression
305317
| case_expression
318+
| cast_expression
306319
| entity_type_expression
307320
;
308321

@@ -453,6 +466,7 @@ string_expression
453466
| string_cast_function
454467
| type_cast_function
455468
| '(' subquery ')'
469+
| string_expression '||' string_expression
456470
;
457471

458472
datetime_expression
@@ -536,7 +550,10 @@ functions_returning_strings
536550
| SUBSTRING '(' string_expression ',' arithmetic_expression (',' arithmetic_expression)? ')'
537551
| TRIM '(' ((trim_specification)? (trim_character)? FROM)? string_expression ')'
538552
| LOWER '(' string_expression ')'
553+
| REPLACE '(' string_expression ',' string_expression ',' string_expression ')'
539554
| UPPER '(' string_expression ')'
555+
| LEFT '(' string_expression ',' arithmetic_expression ')'
556+
| RIGHT '(' string_expression ',' arithmetic_expression ')'
540557
;
541558

542559
trim_specification
@@ -620,6 +637,10 @@ nullif_expression
620637
: NULLIF '(' scalar_expression ',' scalar_expression ')'
621638
;
622639

640+
cast_expression
641+
: CAST '(' string_expression AS type_literal ')'
642+
;
643+
623644
/*******************
624645
Gaps in the spec.
625646
*******************/
@@ -641,6 +662,7 @@ identification_variable
641662
| ORDER
642663
| OUTER
643664
| POWER
665+
| RIGHT
644666
| FLOOR
645667
| SIGN
646668
| TIME
@@ -691,6 +713,14 @@ numeric_literal
691713
| LONGLITERAL
692714
;
693715

716+
type_literal
717+
: STRING
718+
| INTEGER
719+
| LONG
720+
| FLOAT
721+
| DOUBLE
722+
;
723+
694724
boolean_literal
695725
: TRUE
696726
| FALSE
@@ -827,6 +857,8 @@ reserved_word
827857
|ORDER
828858
|OUTER
829859
|POWER
860+
|REPLACE
861+
|RIGHT
830862
|ROUND
831863
|SELECT
832864
|SET
@@ -922,6 +954,7 @@ EXTRACT : E X T R A C T;
922954
FALSE : F A L S E;
923955
FETCH : F E T C H;
924956
FIRST : F I R S T;
957+
FLOAT : F L O A T;
925958
FLOOR : F L O O R;
926959
FLOAT : F L O A T;
927960
FROM : F R O M;
@@ -931,6 +964,7 @@ HAVING : H A V I N G;
931964
IN : I N;
932965
INDEX : I N D E X;
933966
INNER : I N N E R;
967+
INTEGER : I N T E G E R;
934968
INTERSECT : I N T E R S E C T;
935969
IS : I S;
936970
INTEGER : I N T E G E R;
@@ -961,6 +995,8 @@ ON : O N;
961995
OR : O R;
962996
ORDER : O R D E R;
963997
OUTER : O U T E R;
998+
REPLACE : R E P L A C E;
999+
RIGHT : R I G H T;
9641000
POWER : P O W E R;
9651001
REGEXP : R E G E X P;
9661002
ROUND : R O U N D;
@@ -970,6 +1006,7 @@ SIGN : S I G N;
9701006
SIZE : S I Z E;
9711007
SOME : S O M E;
9721008
SQRT : S Q R T;
1009+
STRING : S T R I N G;
9731010
SUBSTRING : S U B S T R I N G;
9741011
STRING : S T R I N G;
9751012
SUM : S U M;

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryRenderer.java

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.springframework.data.jpa.repository.query.QueryRenderer.QueryRendererBuilder;
2626
import org.springframework.util.CollectionUtils;
27+
import org.springframework.util.ObjectUtils;
2728

2829
/**
2930
* An ANTLR {@link org.antlr.v4.runtime.tree.ParseTreeVisitor} that renders an EQL query without making any changes.
@@ -1009,6 +1010,8 @@ public QueryTokenStream visitScalar_expression(EqlParser.Scalar_expressionContex
10091010
builder.append(visit(ctx.case_expression()));
10101011
} else if (ctx.entity_type_expression() != null) {
10111012
builder.append(visit(ctx.entity_type_expression()));
1013+
} else if (ctx.cast_function() != null) {
1014+
return (visit(ctx.cast_function()));
10121015
}
10131016

10141017
return builder;
@@ -1610,6 +1613,11 @@ public QueryTokenStream visitString_expression(EqlParser.String_expressionContex
16101613
builder.append(TOKEN_OPEN_PAREN);
16111614
builder.appendInline(visit(ctx.subquery()));
16121615
builder.append(TOKEN_CLOSE_PAREN);
1616+
} else if (!ObjectUtils.isEmpty(ctx.string_expression())) {
1617+
1618+
builder.appendInline(visit(ctx.string_expression(0)));
1619+
builder.append(TOKEN_DOUBLE_PIPE);
1620+
builder.appendExpression(visit(ctx.string_expression(1)));
16131621
}
16141622

16151623
return builder;
@@ -1941,6 +1949,32 @@ public QueryTokenStream visitFunctions_returning_strings(EqlParser.Functions_ret
19411949
builder.append(TOKEN_OPEN_PAREN);
19421950
builder.appendInline(visit(ctx.string_expression(0)));
19431951
builder.append(TOKEN_CLOSE_PAREN);
1952+
} else if (ctx.LEFT() != null) {
1953+
1954+
builder.append(QueryTokens.token(ctx.LEFT()));
1955+
builder.append(TOKEN_OPEN_PAREN);
1956+
builder.appendInline(visit(ctx.string_expression(0)));
1957+
builder.append(TOKEN_COMMA);
1958+
builder.appendInline(visit(ctx.arithmetic_expression(0)));
1959+
builder.append(TOKEN_CLOSE_PAREN);
1960+
} else if (ctx.RIGHT() != null) {
1961+
1962+
builder.append(QueryTokens.token(ctx.RIGHT()));
1963+
builder.append(TOKEN_OPEN_PAREN);
1964+
builder.appendInline(visit(ctx.string_expression(0)));
1965+
builder.append(TOKEN_COMMA);
1966+
builder.appendInline(visit(ctx.arithmetic_expression(0)));
1967+
builder.append(TOKEN_CLOSE_PAREN);
1968+
} else if (ctx.REPLACE() != null) {
1969+
1970+
builder.append(QueryTokens.token(ctx.REPLACE()));
1971+
builder.append(TOKEN_OPEN_PAREN);
1972+
builder.appendInline(visit(ctx.string_expression(0)));
1973+
builder.append(TOKEN_COMMA);
1974+
builder.appendInline(visit(ctx.string_expression(1)));
1975+
builder.append(TOKEN_COMMA);
1976+
builder.appendInline(visit(ctx.string_expression(2)));
1977+
builder.append(TOKEN_CLOSE_PAREN);
19441978
}
19451979

19461980
return builder;
@@ -1986,7 +2020,7 @@ public QueryTokenStream visitType_cast_function(EqlParser.Type_cast_functionCont
19862020
if (ctx.AS() != null) {
19872021
builder.append(QueryTokens.expression(ctx.AS()));
19882022
}
1989-
builder.appendInline(visit(ctx.identification_variable()));
2023+
builder.appendInline(QueryTokenStream.concat(ctx.identification_variable(), this::visit, TOKEN_SPACE));
19902024

19912025
if (!CollectionUtils.isEmpty(ctx.numeric_literal())) {
19922026

@@ -2106,6 +2140,14 @@ public QueryTokenStream visitCase_expression(EqlParser.Case_expressionContext ct
21062140
}
21072141
}
21082142

2143+
@Override
2144+
public QueryRendererBuilder visitType_literal(EqlParser.Type_literalContext ctx) {
2145+
2146+
QueryRendererBuilder builder = QueryRenderer.builder();
2147+
ctx.children.forEach(it -> builder.append(QueryTokens.expression(it.getText())));
2148+
return builder;
2149+
}
2150+
21092151
@Override
21102152
public QueryTokenStream visitGeneral_case_expression(EqlParser.General_case_expressionContext ctx) {
21112153

@@ -2226,9 +2268,11 @@ public QueryTokenStream visitIdentification_variable(EqlParser.Identification_va
22262268
return QueryRendererBuilder.from(QueryTokens.expression(ctx.IDENTIFICATION_VARIABLE()));
22272269
} else if (ctx.f != null) {
22282270
return QueryRendererBuilder.from(QueryTokens.expression(ctx.f));
2229-
} else {
2230-
return QueryRenderer.builder();
2271+
} else if (ctx.type_literal() != null) {
2272+
return visit(ctx.type_literal());
22312273
}
2274+
2275+
return QueryRenderer.builder();
22322276
}
22332277

22342278
@Override

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpqlCountQueryTransformer.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,17 @@ class JpqlCountQueryTransformer extends JpqlQueryRenderer {
4242
}
4343

4444
@Override
45-
public QueryRenderer.QueryRendererBuilder visitSelect_statement(JpqlParser.Select_statementContext ctx) {
45+
public QueryTokenStream visitSelect_statement(JpqlParser.Select_statementContext ctx) {
46+
47+
if(ctx.select_query() != null) {
48+
return visitSelect_query(ctx.select_query());
49+
}
50+
51+
return QueryTokenStream.empty();
52+
}
53+
54+
@Override
55+
public QueryTokenStream visitSelect_query(JpqlParser.Select_queryContext ctx) {
4656

4757
QueryRendererBuilder builder = QueryRenderer.builder();
4858

0 commit comments

Comments
 (0)