Skip to content

Commit

Permalink
Update JPQL grammar to support F and D suffixes.
Browse files Browse the repository at this point in the history
See #3277
Original pull request: #3280
  • Loading branch information
christophstrobl authored and mp911de committed Jan 10, 2024
1 parent dd04ad0 commit dbb62c8
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ constructor_item
| scalar_expression
| aggregate_expression
| identification_variable
| literal
;

aggregate_expression
Expand Down Expand Up @@ -620,6 +621,7 @@ constructor_name

literal
: STRINGLITERAL
| JAVASTRINGLITERAL
| INTLITERAL
| FLOATLITERAL
| LONGLITERAL
Expand Down Expand Up @@ -852,10 +854,10 @@ WHERE : W H E R E;
EQUAL : '=' ;
NOT_EQUAL : '<>' | '!=' ;


CHARACTER : '\'' (~ ('\'' | '\\')) '\'' ;
IDENTIFICATION_VARIABLE : ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '$' | '_') ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '0' .. '9' | '$' | '_')* ;
STRINGLITERAL : '\'' (~ ('\'' | '\\'))* '\'' ;
FLOATLITERAL : ('0' .. '9')* '.' ('0' .. '9')+ (E '0' .. '9')* ;
JAVASTRINGLITERAL : '"' ( ('\\' [btnfr"']) | ~('"'))* '"';
FLOATLITERAL : ('0' .. '9')* '.' ('0' .. '9')+ (E ('0' .. '9')+)* (F|D)?;
INTLITERAL : ('0' .. '9')+ ;
LONGLITERAL : ('0' .. '9')+L ;
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,8 @@ public List<JpaQueryParsingToken> visitConstructor_item(JpqlParser.Constructor_i
tokens.addAll(visit(ctx.aggregate_expression()));
} else if (ctx.identification_variable() != null) {
tokens.addAll(visit(ctx.identification_variable()));
} else if (ctx.literal() != null) {
tokens.addAll(visit(ctx.literal()));
}

return tokens;
Expand Down Expand Up @@ -2153,6 +2155,8 @@ public List<JpaQueryParsingToken> visitLiteral(JpqlParser.LiteralContext ctx) {

if (ctx.STRINGLITERAL() != null) {
tokens.add(new JpaQueryParsingToken(ctx.STRINGLITERAL()));
} else if (ctx.JAVASTRINGLITERAL() != null) {
tokens.add(new JpaQueryParsingToken(ctx.JAVASTRINGLITERAL()));
} else if (ctx.INTLITERAL() != null) {
tokens.add(new JpaQueryParsingToken(ctx.INTLITERAL()));
} else if (ctx.FLOATLITERAL() != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.jpa.repository.query;

import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.jpa.repository.query.JpaQueryParsingToken.*;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.junit.jupiter.api.Test;

/**
* Test to verify compliance of {@link JpqlParser} with standard SQL. Other than {@link JpqlSpecificationTests} tests in
* this class check that the parser follows a lenient approach and does not error on well known concepts like numeric
* suffix.
*
* @author Christoph Strobl
*/
class JpqlComplianceTests {

private static String parseWithoutChanges(String query) {

JpqlLexer lexer = new JpqlLexer(CharStreams.fromString(query));
JpqlParser parser = new JpqlParser(new CommonTokenStream(lexer));

parser.addErrorListener(new BadJpqlGrammarErrorListener(query));

JpqlParser.StartContext parsedQuery = parser.start();

return render(new JpqlQueryRenderer().visit(parsedQuery));
}

private void assertQuery(String query) {

String slimmedDownQuery = reduceWhitespace(query);
assertThat(parseWithoutChanges(slimmedDownQuery)).isEqualTo(slimmedDownQuery);
}

private String reduceWhitespace(String original) {

return original //
.replaceAll("[ \\t\\n]{1,}", " ") //
.trim();
}

@Test // GH-3277
void numericLiterals() {

assertQuery("SELECT e FROM Employee e WHERE e.id = 1234");
assertQuery("SELECT e FROM Employee e WHERE e.id = 1234L");
assertQuery("SELECT s FROM Stat s WHERE s.ratio > 3.14");
assertQuery("SELECT s FROM Stat s WHERE s.ratio > 3.14F");
assertQuery("SELECT s FROM Stat s WHERE s.ratio > 3.14e32D");
}

@Test // GH-3308
void newWithStrings() {
assertQuery("select new com.example.demo.SampleObject(se.id, se.sampleValue, \"java\") from SampleEntity se");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,12 @@ static Stream<Arguments> jpqlCountQueries() {

Arguments.of( //
"select distinct m.genre from Media m where m.user = ?1 order by m.genre asc", //
"select count(distinct m.genre) from Media m where m.user = ?1"));
"select count(distinct m.genre) from Media m where m.user = ?1"),

Arguments.of( //
"select u from User u where MOD(u.age, 10L) = 2", //
"select count(u) from User u where MOD(u.age, 10L) = 2")
);
}

@ParameterizedTest // GH-2511, GH-2773
Expand Down

0 comments on commit dbb62c8

Please sign in to comment.