Skip to content

Commit bf16a88

Browse files
gderemetzgregturn
authored andcommitted
Detect alias for merge statement for JSqlParserQueryEnhancer.
Related: #2641.
1 parent e589265 commit bf16a88

File tree

2 files changed

+60
-22
lines changed

2 files changed

+60
-22
lines changed

src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java

+44-18
Original file line numberDiff line numberDiff line change
@@ -307,24 +307,28 @@ public String detectAlias() {
307307
@Nullable
308308
private String detectAlias(String query) {
309309

310-
if (this.parsedType != ParsedType.SELECT) {
311-
return null;
312-
}
313-
314-
Select selectStatement = parseSelectStatement(query);
310+
if (ParsedType.MERGE.equals(this.parsedType)) {
311+
Merge mergeStatement = parseSelectStatement(query, Merge.class);
312+
return detectAlias(mergeStatement);
313+
314+
} else if (ParsedType.SELECT.equals(this.parsedType)) {
315+
Select selectStatement = parseSelectStatement(query);
316+
317+
/*
318+
For all the other types ({@link ValuesStatement} and {@link SetOperationList}) it does not make sense to provide
319+
alias since:
320+
* ValuesStatement has no alias
321+
* SetOperation can have multiple alias for each operation item
322+
*/
323+
if (!(selectStatement.getSelectBody() instanceof PlainSelect)) {
324+
return null;
325+
}
315326

316-
/*
317-
For all the other types ({@link ValuesStatement} and {@link SetOperationList}) it does not make sense to provide
318-
alias since:
319-
* ValuesStatement has no alias
320-
* SetOperation can have multiple alias for each operation item
321-
*/
322-
if (!(selectStatement.getSelectBody() instanceof PlainSelect)) {
323-
return null;
327+
PlainSelect selectBody = (PlainSelect) selectStatement.getSelectBody();
328+
return detectAlias(selectBody);
324329
}
325330

326-
PlainSelect selectBody = (PlainSelect) selectStatement.getSelectBody();
327-
return detectAlias(selectBody);
331+
return null;
328332
}
329333

330334
/**
@@ -335,7 +339,7 @@ For all the other types ({@link ValuesStatement} and {@link SetOperationList}) i
335339
* @return Might return {@literal null}.
336340
*/
337341
@Nullable
338-
private static String detectAlias(PlainSelect selectBody) {
342+
private String detectAlias(PlainSelect selectBody) {
339343

340344
if (selectBody.getFromItem() == null) {
341345
return null;
@@ -345,6 +349,18 @@ private static String detectAlias(PlainSelect selectBody) {
345349
return alias == null ? null : alias.getName();
346350
}
347351

352+
/**
353+
* Resolves the alias for the given {@link Merge} statement.
354+
*
355+
* @param mergeStatement must not be {@literal null}.
356+
* @return Might return {@literal null}.
357+
*/
358+
@Nullable
359+
private String detectAlias(Merge mergeStatement) {
360+
Alias alias = mergeStatement.getUsingAlias();
361+
return alias == null ? null : alias.getName();
362+
}
363+
348364
@Override
349365
public String createCountQueryFor(@Nullable String countProjection) {
350366

@@ -453,15 +469,25 @@ public Set<String> getJoinAliases() {
453469
* @param query the query to parse
454470
* @return the parsed query
455471
*/
456-
private static Select parseSelectStatement(String query) {
472+
private <T extends Statement> T parseSelectStatement(String query, Class<T> classOfT) {
457473

458474
try {
459-
return (Select) CCJSqlParserUtil.parse(query);
475+
return classOfT.cast(CCJSqlParserUtil.parse(query));
460476
} catch (JSQLParserException e) {
461477
throw new IllegalArgumentException("The query you provided is not a valid SQL Query!", e);
462478
}
463479
}
464480

481+
/**
482+
* Parses a query string with JSqlParser.
483+
*
484+
* @param query the query to parse
485+
* @return the parsed query
486+
*/
487+
private Select parseSelectStatement(String query) {
488+
return parseSelectStatement(query, Select.class);
489+
}
490+
465491
/**
466492
* Checks whether a given projection only contains a single column definition (aka without functions, etc.)
467493
*

src/test/java/org/springframework/data/jpa/repository/query/QueryEnhancerUnitTests.java

+16-4
Original file line numberDiff line numberDiff line change
@@ -923,14 +923,17 @@ void insertStatementIsProcessedSameAsDefault(String insertQuery) {
923923
assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
924924
}
925925

926-
@Test // GH-2641
927-
void mergeStatementWorksWithJSqlParser() {
928-
String query = "merge into a using (select id, value from b) query on (a.id = query.id) when matched then update set a.value = value";
926+
@ParameterizedTest // GH-2641
927+
@MethodSource("mergeStatementWorksWithJSqlParserSource")
928+
void mergeStatementWorksWithJSqlParser(String query, String alias) {
929929
StringQuery stringQuery = new StringQuery(query, true);
930930
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
931931

932+
assertThat(queryEnhancer.detectAlias()).isEqualTo(alias);
933+
assertThat(QueryUtils.detectAlias(query)).isNull();
934+
932935
assertThat(queryEnhancer.getJoinAliases()).isEmpty();
933-
assertThat(queryEnhancer.detectAlias()).isNull();
936+
assertThat(queryEnhancer.detectAlias()).isEqualTo(alias);
934937
assertThat(queryEnhancer.getProjection()).isEmpty();
935938
assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
936939
}
@@ -942,6 +945,15 @@ public static Stream<Arguments> insertStatementIsProcessedSameAsDefaultSource()
942945
);
943946
}
944947

948+
public static Stream<Arguments> mergeStatementWorksWithJSqlParserSource() {
949+
return Stream.of(Arguments.of(
950+
"merge into a using (select id, value from b) query on (a.id = query.id) when matched then update set a.value = value",
951+
"query"),
952+
Arguments.of(
953+
"merge into a using (select id2, value from b) on (id = id2) when matched then update set a.value = value",
954+
null));
955+
}
956+
945957
public static Stream<Arguments> detectsJoinAliasesCorrectlySource() {
946958

947959
return Stream.of( //

0 commit comments

Comments
 (0)