Skip to content

Commit b888bac

Browse files
committed
Add support for IS TRUE|FALSE|EMPTY and CONTAINS|INCLUDES|INTERSECTS HQL predicates.
Closes #3628
1 parent 7a00b28 commit b888bac

File tree

3 files changed

+187
-78
lines changed

3 files changed

+187
-78
lines changed

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

+12-14
Original file line numberDiff line numberDiff line change
@@ -571,13 +571,15 @@ pathContinutation
571571
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-conditional-expressions
572572
predicate
573573
: '(' predicate ')' # GroupedPredicate
574-
| dealingWithNullExpression # NullExpressionPredicate
574+
| expression IS NOT? (NULL|EMPTY|TRUE|FALSE) # IsBooleanPredicate
575+
| expression IS NOT? DISTINCT FROM expression # IsDistinctFromPredicate
576+
| expression NOT? MEMBER OF? path # MemberOfPredicate
575577
| inExpression # InPredicate
576578
| betweenExpression # BetweenPredicate
579+
| expression NOT? (CONTAINS|INCLUDES|INTERSECTS) expression # ContainsPredicate
577580
| relationalExpression # RelationalPredicate
578581
| stringPatternMatching # LikePredicate
579582
| existsExpression # ExistsPredicate
580-
| collectionExpression # CollectionPredicate
581583
| NOT predicate # NotPredicate
582584
| predicate AND predicate # AndPredicate
583585
| predicate OR predicate # OrPredicate
@@ -600,12 +602,6 @@ betweenExpression
600602
: expression NOT? BETWEEN expression AND expression
601603
;
602604

603-
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-null-predicate
604-
dealingWithNullExpression
605-
: expression IS NOT? NULL
606-
| expression IS NOT? DISTINCT FROM expression
607-
;
608-
609605
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-like-predicate
610606
stringPatternMatching
611607
: expression NOT? (LIKE | ILIKE) expression (ESCAPE (stringLiteral|parameter))?
@@ -632,12 +628,6 @@ existsExpression
632628
| EXISTS expression
633629
;
634630

635-
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-collection-operators
636-
collectionExpression
637-
: expression IS NOT? EMPTY
638-
| expression NOT? MEMBER OF path
639-
;
640-
641631
// Projection
642632
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-select-new
643633
instantiationTarget
@@ -707,6 +697,7 @@ reservedWord
707697
| CASE
708698
| CAST
709699
| COLLATE
700+
| CONTAINS
710701
| COUNT
711702
| CROSS
712703
| CUBE
@@ -739,6 +730,7 @@ reservedWord
739730
| EXISTS
740731
| EXP
741732
| EXTRACT
733+
| FALSE
742734
| FETCH
743735
| FILTER
744736
| FIRST
@@ -757,12 +749,14 @@ reservedWord
757749
| IGNORE
758750
| ILIKE
759751
| IN
752+
| INCLUDES
760753
| INDEX
761754
| INDICES
762755
| INNER
763756
| INSERT
764757
| INSTANT
765758
| INTERSECT
759+
| INTERSECTS
766760
| INTO
767761
| IS
768762
| JOIN
@@ -834,6 +828,7 @@ reservedWord
834828
| SOME
835829
| SUBSTRING
836830
| SUM
831+
| TRUE
837832
| THEN
838833
| TIES
839834
| TIME
@@ -917,6 +912,7 @@ CASE : C A S E;
917912
CAST : C A S T;
918913
CEILING : C E I L I N G;
919914
COLLATE : C O L L A T E;
915+
CONTAINS : C O N T A I N S;
920916
COUNT : C O U N T;
921917
CROSS : C R O S S;
922918
CUBE : C U B E;
@@ -969,12 +965,14 @@ ID : I D;
969965
IGNORE : I G N O R E;
970966
ILIKE : I L I K E;
971967
IN : I N;
968+
INCLUDES : I N C L U D E S;
972969
INDEX : I N D E X;
973970
INDICES : I N D I C E S;
974971
INNER : I N N E R;
975972
INSERT : I N S E R T;
976973
INSTANT : I N S T A N T;
977974
INTERSECT : I N T E R S E C T;
975+
INTERSECTS : I N T E R S E C T S;
978976
INTO : I N T O;
979977
IS : I S;
980978
JOIN : J O I N;

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

+98-61
Original file line numberDiff line numberDiff line change
@@ -2094,15 +2094,111 @@ public List<JpaQueryParsingToken> visitPathContinutation(HqlParser.PathContinuta
20942094
}
20952095

20962096
@Override
2097-
public List<JpaQueryParsingToken> visitNullExpressionPredicate(HqlParser.NullExpressionPredicateContext ctx) {
2098-
return visit(ctx.dealingWithNullExpression());
2097+
public List<JpaQueryParsingToken> visitIsBooleanPredicate(HqlParser.IsBooleanPredicateContext ctx) {
2098+
2099+
List<JpaQueryParsingToken> tokens = new ArrayList<>();
2100+
2101+
tokens.addAll(visit(ctx.expression()));
2102+
tokens.add(new JpaQueryParsingToken(ctx.IS()));
2103+
2104+
if (ctx.NOT() != null) {
2105+
tokens.add(new JpaQueryParsingToken(ctx.NOT()));
2106+
}
2107+
2108+
if (ctx.NULL() != null) {
2109+
tokens.add(new JpaQueryParsingToken(ctx.NULL()));
2110+
}
2111+
2112+
if (ctx.TRUE() != null) {
2113+
tokens.add(new JpaQueryParsingToken(ctx.TRUE()));
2114+
}
2115+
2116+
if (ctx.FALSE() != null) {
2117+
tokens.add(new JpaQueryParsingToken(ctx.FALSE()));
2118+
}
2119+
2120+
if (ctx.EMPTY() != null) {
2121+
tokens.add(new JpaQueryParsingToken(ctx.EMPTY()));
2122+
}
2123+
2124+
return tokens;
2125+
}
2126+
2127+
@Override
2128+
public List<JpaQueryParsingToken> visitMemberOfPredicate(HqlParser.MemberOfPredicateContext ctx) {
2129+
2130+
List<JpaQueryParsingToken> tokens = new ArrayList<>();
2131+
2132+
tokens.addAll(visit(ctx.expression()));
2133+
if (ctx.NOT() != null) {
2134+
tokens.add(new JpaQueryParsingToken(ctx.NOT()));
2135+
}
2136+
if (ctx.MEMBER() != null) {
2137+
tokens.add(new JpaQueryParsingToken(ctx.MEMBER()));
2138+
}
2139+
if (ctx.OF() != null) {
2140+
tokens.add(new JpaQueryParsingToken(ctx.OF()));
2141+
}
2142+
2143+
tokens.addAll(visit(ctx.path()));
2144+
2145+
return tokens;
2146+
}
2147+
2148+
@Override
2149+
public List<JpaQueryParsingToken> visitIsDistinctFromPredicate(HqlParser.IsDistinctFromPredicateContext ctx) {
2150+
2151+
List<JpaQueryParsingToken> tokens = new ArrayList<>(16);
2152+
2153+
tokens.addAll(visit(ctx.expression(0)));
2154+
tokens.add(new JpaQueryParsingToken(ctx.IS()));
2155+
2156+
if (ctx.NOT() != null) {
2157+
tokens.add(new JpaQueryParsingToken(ctx.NOT()));
2158+
}
2159+
2160+
if (ctx.DISTINCT() != null) {
2161+
2162+
tokens.add(new JpaQueryParsingToken(ctx.DISTINCT()));
2163+
tokens.add(new JpaQueryParsingToken(ctx.FROM()));
2164+
tokens.addAll(visit(ctx.expression(1)));
2165+
}
2166+
2167+
return tokens;
20992168
}
21002169

21012170
@Override
21022171
public List<JpaQueryParsingToken> visitBetweenPredicate(HqlParser.BetweenPredicateContext ctx) {
21032172
return visit(ctx.betweenExpression());
21042173
}
21052174

2175+
@Override
2176+
public List<JpaQueryParsingToken> visitContainsPredicate(HqlParser.ContainsPredicateContext ctx) {
2177+
2178+
List<JpaQueryParsingToken> tokens = new ArrayList<>();
2179+
2180+
tokens.addAll(visit(ctx.expression(0)));
2181+
2182+
if (ctx.NOT() != null) {
2183+
tokens.add(new JpaQueryParsingToken(ctx.NOT()));
2184+
}
2185+
2186+
if (ctx.CONTAINS() != null) {
2187+
tokens.add(new JpaQueryParsingToken(ctx.CONTAINS()));
2188+
}
2189+
if (ctx.INCLUDES() != null) {
2190+
tokens.add(new JpaQueryParsingToken(ctx.INCLUDES()));
2191+
}
2192+
if (ctx.INTERSECTS() != null) {
2193+
tokens.add(new JpaQueryParsingToken(ctx.INTERSECTS()));
2194+
}
2195+
2196+
tokens.addAll(visit(ctx.expression(1)));
2197+
2198+
return tokens;
2199+
2200+
}
2201+
21062202
@Override
21072203
public List<JpaQueryParsingToken> visitOrPredicate(HqlParser.OrPredicateContext ctx) {
21082204

@@ -2125,11 +2221,6 @@ public List<JpaQueryParsingToken> visitExistsPredicate(HqlParser.ExistsPredicate
21252221
return visit(ctx.existsExpression());
21262222
}
21272223

2128-
@Override
2129-
public List<JpaQueryParsingToken> visitCollectionPredicate(HqlParser.CollectionPredicateContext ctx) {
2130-
return visit(ctx.collectionExpression());
2131-
}
2132-
21332224
@Override
21342225
public List<JpaQueryParsingToken> visitAndPredicate(HqlParser.AndPredicateContext ctx) {
21352226

@@ -2224,30 +2315,6 @@ public List<JpaQueryParsingToken> visitBetweenExpression(HqlParser.BetweenExpres
22242315
return tokens;
22252316
}
22262317

2227-
@Override
2228-
public List<JpaQueryParsingToken> visitDealingWithNullExpression(HqlParser.DealingWithNullExpressionContext ctx) {
2229-
2230-
List<JpaQueryParsingToken> tokens = new ArrayList<>();
2231-
2232-
tokens.addAll(visit(ctx.expression(0)));
2233-
tokens.add(new JpaQueryParsingToken(ctx.IS()));
2234-
2235-
if (ctx.NOT() != null) {
2236-
tokens.add(TOKEN_NOT);
2237-
}
2238-
2239-
if (ctx.NULL() != null) {
2240-
tokens.add(new JpaQueryParsingToken(ctx.NULL()));
2241-
} else if (ctx.DISTINCT() != null) {
2242-
2243-
tokens.add(new JpaQueryParsingToken(ctx.DISTINCT()));
2244-
tokens.add(new JpaQueryParsingToken(ctx.FROM()));
2245-
tokens.addAll(visit(ctx.expression(1)));
2246-
}
2247-
2248-
return tokens;
2249-
}
2250-
22512318
@Override
22522319
public List<JpaQueryParsingToken> visitStringPatternMatching(HqlParser.StringPatternMatchingContext ctx) {
22532320

@@ -2368,36 +2435,6 @@ public List<JpaQueryParsingToken> visitExistsExpression(HqlParser.ExistsExpressi
23682435
return tokens;
23692436
}
23702437

2371-
@Override
2372-
public List<JpaQueryParsingToken> visitCollectionExpression(HqlParser.CollectionExpressionContext ctx) {
2373-
2374-
List<JpaQueryParsingToken> tokens = new ArrayList<>();
2375-
2376-
tokens.addAll(visit(ctx.expression()));
2377-
2378-
if (ctx.IS() != null) {
2379-
2380-
tokens.add(new JpaQueryParsingToken(ctx.IS()));
2381-
2382-
if (ctx.NOT() != null) {
2383-
tokens.add(TOKEN_NOT);
2384-
}
2385-
2386-
tokens.add(new JpaQueryParsingToken(ctx.EMPTY()));
2387-
} else if (ctx.MEMBER() != null) {
2388-
2389-
if (ctx.NOT() != null) {
2390-
tokens.add(TOKEN_NOT);
2391-
}
2392-
2393-
tokens.add(new JpaQueryParsingToken(ctx.MEMBER()));
2394-
tokens.add(new JpaQueryParsingToken(ctx.OF()));
2395-
tokens.addAll(visit(ctx.path()));
2396-
}
2397-
2398-
return tokens;
2399-
}
2400-
24012438
@Override
24022439
public List<JpaQueryParsingToken> visitInstantiationTarget(HqlParser.InstantiationTargetContext ctx) {
24032440

0 commit comments

Comments
 (0)