Skip to content

Commit 0aa5be8

Browse files
committed
Properly handle EXTRACT function in HQL.
HQL's extract function supports things like "day of week", "day of month", and "week of year". Extend support to these alternate expressions. See #3219.
1 parent 018c2ac commit 0aa5be8

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,9 @@ expression
382382
| expression op=('*' | '/') expression # MultiplicationExpression
383383
| expression op=('+' | '-') expression # AdditionExpression
384384
| expression '||' expression # HqlConcatenationExpression
385+
| DAY OF WEEK # DayOfWeekExpression
386+
| DAY OF MONTH # DayOfMonthExpression
387+
| WEEK OF YEAR # WeekOfYearExpression
385388
;
386389

387390
primaryExpression

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,42 @@ public List<JpaQueryParsingToken> visitHqlConcatenationExpression(HqlParser.HqlC
12231223
return tokens;
12241224
}
12251225

1226+
@Override
1227+
public List<JpaQueryParsingToken> visitDayOfWeekExpression(HqlParser.DayOfWeekExpressionContext ctx) {
1228+
1229+
List<JpaQueryParsingToken> tokens = new ArrayList<>();
1230+
1231+
tokens.add(new JpaQueryParsingToken(ctx.DAY()));
1232+
tokens.add(new JpaQueryParsingToken(ctx.OF()));
1233+
tokens.add(new JpaQueryParsingToken(ctx.WEEK()));
1234+
1235+
return tokens;
1236+
}
1237+
1238+
@Override
1239+
public List<JpaQueryParsingToken> visitDayOfMonthExpression(HqlParser.DayOfMonthExpressionContext ctx) {
1240+
1241+
List<JpaQueryParsingToken> tokens = new ArrayList<>();
1242+
1243+
tokens.add(new JpaQueryParsingToken(ctx.DAY()));
1244+
tokens.add(new JpaQueryParsingToken(ctx.OF()));
1245+
tokens.add(new JpaQueryParsingToken(ctx.MONTH()));
1246+
1247+
return tokens;
1248+
}
1249+
1250+
@Override
1251+
public List<JpaQueryParsingToken> visitWeekOfYearExpression(HqlParser.WeekOfYearExpressionContext ctx) {
1252+
1253+
List<JpaQueryParsingToken> tokens = new ArrayList<>();
1254+
1255+
tokens.add(new JpaQueryParsingToken(ctx.WEEK()));
1256+
tokens.add(new JpaQueryParsingToken(ctx.OF()));
1257+
tokens.add(new JpaQueryParsingToken(ctx.YEAR()));
1258+
1259+
return tokens;
1260+
}
1261+
12261262
@Override
12271263
public List<JpaQueryParsingToken> visitGroupedExpression(HqlParser.GroupedExpressionContext ctx) {
12281264

@@ -1915,11 +1951,12 @@ public List<JpaQueryParsingToken> visitExtractFunction(HqlParser.ExtractFunction
19151951

19161952
if (ctx.EXTRACT() != null) {
19171953

1918-
tokens.add(new JpaQueryParsingToken(ctx.EXTRACT()));
1954+
tokens.add(new JpaQueryParsingToken(ctx.EXTRACT(), false));
19191955
tokens.add(TOKEN_OPEN_PAREN);
19201956
tokens.addAll(visit(ctx.expression(0)));
19211957
tokens.add(new JpaQueryParsingToken(ctx.FROM()));
19221958
tokens.addAll(visit(ctx.expression(1)));
1959+
NOSPACE(tokens);
19231960
tokens.add(TOKEN_CLOSE_PAREN);
19241961
} else if (ctx.dateTimeFunction() != null) {
19251962

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,4 +1605,34 @@ void newShouldBeLegalAsPartOfAStateFieldPathExpression() {
16051605
void powerShouldBeLegalInAQuery() {
16061606
assertQuery("select e.power.id from MyEntity e");
16071607
}
1608+
1609+
@Test // GH-3219
1610+
void extractFunctionShouldSupportAdditionalExtensions() {
1611+
1612+
assertQuery("""
1613+
select extract(day of week from departureTime) AS day, sum(duration) as duration from JourneyEntity
1614+
group by extract(day of week from departureTime)
1615+
""");
1616+
assertQuery("""
1617+
select extract(day of month from departureTime) AS day, sum(duration) as duration from JourneyEntity
1618+
group by extract(day of month from departureTime)
1619+
""");
1620+
assertQuery("""
1621+
select extract(week of year from departureTime) AS day, sum(duration) as duration from JourneyEntity
1622+
group by extract(week of year from departureTime)
1623+
""");
1624+
1625+
assertQuery("""
1626+
select extract(date from departureTime) AS date
1627+
group by extract(date from departureTime)
1628+
""");
1629+
assertQuery("""
1630+
select extract(time from departureTime) AS time
1631+
group by extract(time from departureTime)
1632+
""");
1633+
assertQuery("""
1634+
select extract(epoch from departureTime) AS epoch
1635+
group by extract(epoch from departureTime)
1636+
""");
1637+
}
16081638
}

0 commit comments

Comments
 (0)