-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement support for EclipseLink Query Language (EQL), handling the various extensions it offers. See #3170
- Loading branch information
Showing
12 changed files
with
6,963 additions
and
1 deletion.
There are no files selected for viewing
897 changes: 897 additions & 0 deletions
897
spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4
Large diffs are not rendered by default.
Oops, something went wrong.
132 changes: 132 additions & 0 deletions
132
...-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/* | ||
* Copyright 2022-2023 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 java.util.List; | ||
|
||
import org.antlr.v4.runtime.CharStreams; | ||
import org.antlr.v4.runtime.CommonTokenStream; | ||
import org.antlr.v4.runtime.ParserRuleContext; | ||
import org.springframework.data.domain.Sort; | ||
import org.springframework.lang.Nullable; | ||
|
||
/** | ||
* Implements the {@code EQL} parsing operations of a {@link JpaQueryParserSupport} using the ANTLR-generated | ||
* {@link EqlParser} and {@link EqlQueryTransformer}. | ||
* | ||
* @author Greg Turnquist | ||
* @since 3.2 | ||
*/ | ||
class EqlQueryParser extends JpaQueryParserSupport { | ||
|
||
EqlQueryParser(String query) { | ||
super(query); | ||
} | ||
|
||
/** | ||
* Convenience method to parse a EQL query. Will throw a {@link BadJpqlGrammarException} if the query is invalid. | ||
* | ||
* @param query | ||
* @return a parsed query, ready for postprocessing | ||
*/ | ||
public static ParserRuleContext parseQuery(String query) { | ||
|
||
EqlLexer lexer = new EqlLexer(CharStreams.fromString(query)); | ||
EqlParser parser = new EqlParser(new CommonTokenStream(lexer)); | ||
|
||
configureParser(query, lexer, parser); | ||
|
||
return parser.start(); | ||
} | ||
|
||
/** | ||
* Parse the query using {@link #parseQuery(String)}. | ||
* | ||
* @return a parsed query | ||
*/ | ||
@Override | ||
protected ParserRuleContext parse(String query) { | ||
return parseQuery(query); | ||
} | ||
|
||
/** | ||
* Use the {@link EqlQueryTransformer} to transform the original query into a query with the {@link Sort} applied. | ||
* | ||
* @param parsedQuery | ||
* @param sort can be {@literal null} | ||
* @return list of {@link JpaQueryParsingToken}s | ||
*/ | ||
@Override | ||
protected List<JpaQueryParsingToken> applySort(ParserRuleContext parsedQuery, Sort sort) { | ||
return new EqlQueryTransformer(sort).visit(parsedQuery); | ||
} | ||
|
||
/** | ||
* Use the {@link EqlQueryTransformer} to transform the original query into a count query. | ||
* | ||
* @param parsedQuery | ||
* @param countProjection | ||
* @return list of {@link JpaQueryParsingToken}s | ||
*/ | ||
@Override | ||
protected List<JpaQueryParsingToken> doCreateCountQuery(ParserRuleContext parsedQuery, | ||
@Nullable String countProjection) { | ||
return new EqlQueryTransformer(true, countProjection).visit(parsedQuery); | ||
} | ||
|
||
/** | ||
* Run the parsed query through {@link EqlQueryTransformer} to find the primary FROM clause's alias. | ||
* | ||
* @param parsedQuery | ||
* @return can be {@literal null} | ||
*/ | ||
@Override | ||
protected String doFindAlias(ParserRuleContext parsedQuery) { | ||
|
||
EqlQueryTransformer transformVisitor = new EqlQueryTransformer(); | ||
transformVisitor.visit(parsedQuery); | ||
return transformVisitor.getAlias(); | ||
} | ||
|
||
/** | ||
* Use {@link EqlQueryTransformer} to find the projection of the query. | ||
* | ||
* @param parsedQuery | ||
* @return | ||
*/ | ||
@Override | ||
protected List<JpaQueryParsingToken> doFindProjection(ParserRuleContext parsedQuery) { | ||
|
||
EqlQueryTransformer transformVisitor = new EqlQueryTransformer(); | ||
transformVisitor.visit(parsedQuery); | ||
return transformVisitor.getProjection(); | ||
} | ||
|
||
/** | ||
* Use {@link EqlQueryTransformer} to detect if the query uses a {@code new com.example.Dto()} DTO constructor in the | ||
* primary select clause. | ||
* | ||
* @param parsedQuery | ||
* @return Guaranteed to be {@literal true} or {@literal false}. | ||
*/ | ||
@Override | ||
protected boolean doCheckForConstructor(ParserRuleContext parsedQuery) { | ||
|
||
EqlQueryTransformer transformVisitor = new EqlQueryTransformer(); | ||
transformVisitor.visit(parsedQuery); | ||
return transformVisitor.hasConstructorExpression(); | ||
} | ||
} |
Oops, something went wrong.