Skip to content

Commit 13319bb

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 872ba73 commit 13319bb

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
@@ -1222,6 +1222,42 @@ public List<JpaQueryParsingToken> visitHqlConcatenationExpression(HqlParser.HqlC
12221222
return tokens;
12231223
}
12241224

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

@@ -1914,11 +1950,12 @@ public List<JpaQueryParsingToken> visitExtractFunction(HqlParser.ExtractFunction
19141950

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

1917-
tokens.add(new JpaQueryParsingToken(ctx.EXTRACT()));
1953+
tokens.add(new JpaQueryParsingToken(ctx.EXTRACT(), false));
19181954
tokens.add(TOKEN_OPEN_PAREN);
19191955
tokens.addAll(visit(ctx.expression(0)));
19201956
tokens.add(new JpaQueryParsingToken(ctx.FROM()));
19211957
tokens.addAll(visit(ctx.expression(1)));
1958+
NOSPACE(tokens);
19221959
tokens.add(TOKEN_CLOSE_PAREN);
19231960
} else if (ctx.dateTimeFunction() != null) {
19241961

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)