diff --git a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4 b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4 index a0aa24491..9bbf47a86 100644 --- a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4 +++ b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4 @@ -23,6 +23,7 @@ grammar Eql; * * https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL * * @author Greg Turnquist + * @author Christoph Strobl * @since 3.2 */ } @@ -509,7 +510,7 @@ functions_returning_numerics | LN '(' arithmetic_expression ')' | SIGN '(' arithmetic_expression ')' | SQRT '(' arithmetic_expression ')' - | MOD '(' arithmetic_expression '/' arithmetic_expression ')' + | MOD '(' arithmetic_expression ',' arithmetic_expression ')' | POWER '(' arithmetic_expression ',' arithmetic_expression ')' | ROUND '(' arithmetic_expression ',' arithmetic_expression ')' | SIZE '(' collection_valued_path_expression ')' @@ -894,4 +895,4 @@ INTLITERAL : ('0' .. '9')+ ; LONGLITERAL : ('0' .. '9')+ L; DATELITERAL : '{' D STRINGLITERAL '}'; TIMELITERAL : '{' T STRINGLITERAL '}'; -TIMESTAMPLITERAL : '{' T S STRINGLITERAL '}'; \ No newline at end of file +TIMESTAMPLITERAL : '{' T S STRINGLITERAL '}'; diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryRenderer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryRenderer.java index 07201fd20..6688d78f0 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryRenderer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryRenderer.java @@ -24,6 +24,7 @@ import java.util.List; * An ANTLR {@link org.antlr.v4.runtime.tree.ParseTreeVisitor} that renders an EQL query without making any changes. * * @author Greg Turnquist + * @author Christoph Strobl * @since 3.2 */ @SuppressWarnings({ "ConstantConditions", "DuplicatedCode" }) @@ -1912,7 +1913,8 @@ class EqlQueryRenderer extends EqlBaseVisitor> { tokens.add(new JpaQueryParsingToken(ctx.MOD(), false)); tokens.add(TOKEN_OPEN_PAREN); tokens.addAll(visit(ctx.arithmetic_expression(0))); - tokens.add(new JpaQueryParsingToken("/")); + NOSPACE(tokens); + tokens.add(TOKEN_COMMA); tokens.addAll(visit(ctx.arithmetic_expression(1))); NOSPACE(tokens); tokens.add(TOKEN_CLOSE_PAREN); diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EqlComplianceTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EqlComplianceTests.java index aacf1e6c5..67cbf2237 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EqlComplianceTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EqlComplianceTests.java @@ -25,10 +25,13 @@ import org.junit.jupiter.api.Test; /** * Tests built around examples of EQL found in the EclipseLink's docs at * https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL
+ * With the exception of {@literal MOD} which is defined as {@literal MOD(arithmetic_expression , arithmetic_expression)}, + * but shown in tests as {@literal MOD(arithmetic_expression ? arithmetic_expression)}. *
* IMPORTANT: Purely verifies the parser without any transformations. * * @author Greg Turnquist + * @author Christoph Strobl */ class EqlComplianceTests { @@ -214,7 +217,7 @@ class EqlComplianceTests { assertQuery("SELECT e.name, CURRENT_TIMESTAMP FROM Employee e"); assertQuery("SELECT LENGTH(e.lastName) FROM Employee e"); assertQuery("SELECT LOWER(e.lastName) FROM Employee e"); - assertQuery("SELECT MOD(e.hoursWorked / 8) FROM Employee e"); + assertQuery("SELECT MOD(e.hoursWorked, 8) FROM Employee e"); assertQuery("SELECT NULLIF(e.salary, 0) FROM Employee e"); assertQuery("SELECT SQRT(o.RESULT) FROM Output o"); assertQuery("SELECT SUBSTRING(e.lastName, 0, 2) FROM Employee e"); @@ -243,7 +246,7 @@ class EqlComplianceTests { assertQuery("SELECT e FROM Employee e WHERE CURRENT_TIME > CURRENT_TIMESTAMP"); assertQuery("SELECT e FROM Employee e WHERE LENGTH(e.lastName) > 0"); assertQuery("SELECT e FROM Employee e WHERE LOWER(e.lastName) = 'bilbo'"); - assertQuery("SELECT e FROM Employee e WHERE MOD(e.hoursWorked / 8) > 0"); + assertQuery("SELECT e FROM Employee e WHERE MOD(e.hoursWorked, 8) > 0"); assertQuery("SELECT e FROM Employee e WHERE NULLIF(e.salary, 0) is null"); assertQuery("SELECT e FROM Employee e WHERE SQRT(o.RESULT) > 0.0"); assertQuery("SELECT e FROM Employee e WHERE SUBSTRING(e.lastName, 0, 2) = 'Bilbo'"); @@ -272,7 +275,7 @@ class EqlComplianceTests { assertQuery("SELECT e FROM Employee e ORDER BY CURRENT_TIMESTAMP"); assertQuery("SELECT e FROM Employee e ORDER BY LENGTH(e.lastName)"); assertQuery("SELECT e FROM Employee e ORDER BY LOWER(e.lastName)"); - assertQuery("SELECT e FROM Employee e ORDER BY MOD(e.hoursWorked / 8)"); + assertQuery("SELECT e FROM Employee e ORDER BY MOD(e.hoursWorked, 8)"); assertQuery("SELECT e FROM Employee e ORDER BY NULLIF(e.salary, 0)"); assertQuery("SELECT e FROM Employee e ORDER BY SQRT(o.RESULT)"); assertQuery("SELECT e FROM Employee e ORDER BY SUBSTRING(e.lastName, 0, 2)"); @@ -301,7 +304,7 @@ class EqlComplianceTests { assertQuery("SELECT e FROM Employee e GROUP BY CURRENT_TIMESTAMP"); assertQuery("SELECT e FROM Employee e GROUP BY LENGTH(e.lastName)"); assertQuery("SELECT e FROM Employee e GROUP BY LOWER(e.lastName)"); - assertQuery("SELECT e FROM Employee e GROUP BY MOD(e.hoursWorked / 8)"); + assertQuery("SELECT e FROM Employee e GROUP BY MOD(e.hoursWorked, 8)"); assertQuery("SELECT e FROM Employee e GROUP BY NULLIF(e.salary, 0)"); assertQuery("SELECT e FROM Employee e GROUP BY SQRT(o.RESULT)"); assertQuery("SELECT e FROM Employee e GROUP BY SUBSTRING(e.lastName, 0, 2)"); @@ -329,7 +332,7 @@ class EqlComplianceTests { assertQuery("SELECT e FROM Employee e GROUP BY e.salary HAVING CURRENT_TIME > CURRENT_TIMESTAMP"); assertQuery("SELECT e FROM Employee e GROUP BY e.salary HAVING LENGTH(e.lastName) > 0"); assertQuery("SELECT e FROM Employee e GROUP BY e.salary HAVING LOWER(e.lastName) = 'bilbo'"); - assertQuery("SELECT e FROM Employee e GROUP BY e.salary HAVING MOD(e.hoursWorked / 8) > 0"); + assertQuery("SELECT e FROM Employee e GROUP BY e.salary HAVING MOD(e.hoursWorked, 8) > 0"); assertQuery("SELECT e FROM Employee e GROUP BY e.salary HAVING NULLIF(e.salary, 0) is null"); assertQuery("SELECT e FROM Employee e GROUP BY e.salary HAVING SQRT(o.RESULT) > 0.0"); assertQuery("SELECT e FROM Employee e GROUP BY e.salary HAVING SUBSTRING(e.lastName, 0, 2) = 'Bilbo'");