From c5aa790e39fd5657ca8c25e1d5b2ae6de80547a0 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Wed, 29 Nov 2023 15:03:37 +0800 Subject: [PATCH] Upgrade to JSqlParser 4.8 Closes: #3340 Original Pull Request: #3248 --- pom.xml | 2 +- .../query/JSqlParserQueryEnhancer.java | 62 ++++++++----------- .../JSqlParserQueryEnhancerUnitTests.java | 4 +- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/pom.xml b/pom.xml index 4838c7bd5..11bf3f6ec 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ 6.4.3-SNAPSHOT 2.7.1

2.2.220

- 4.5 + 4.8 8.0.33 42.6.0 3.3.0-SNAPSHOT diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java index c377d666c..767e5cbf8 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java @@ -31,13 +31,10 @@ import net.sf.jsqlparser.statement.merge.Merge; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectBody; -import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SetOperationList; -import net.sf.jsqlparser.statement.select.WithItem; +import net.sf.jsqlparser.statement.select.Values; import net.sf.jsqlparser.statement.update.Update; -import net.sf.jsqlparser.statement.values.ValuesStatement; import java.util.ArrayList; import java.util.Collections; @@ -59,6 +56,7 @@ import org.springframework.util.StringUtils; * @author Diego Krupitza * @author Greg Turnquist * @author Geoffrey Deremetz + * @author Yanming Zhou * @since 2.7.0 */ public class JSqlParserQueryEnhancer implements QueryEnhancer { @@ -120,13 +118,13 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { Select selectStatement = parseSelectStatement(queryString); - if (selectStatement.getSelectBody()instanceof SetOperationList setOperationList) { + if (selectStatement instanceof SetOperationList setOperationList) { return applySortingToSetOperationList(setOperationList, sort); - } else if (!(selectStatement.getSelectBody() instanceof PlainSelect)) { - return queryString; } - PlainSelect selectBody = (PlainSelect) selectStatement.getSelectBody(); + if (!(selectStatement instanceof PlainSelect selectBody)) { + return queryString; + } Set joinAliases = getJoinAliases(selectBody); Set selectionAliases = getSelectionAliases(selectBody); @@ -155,7 +153,7 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { private String applySortingToSetOperationList(SetOperationList setOperationListStatement, Sort sort) { // special case: ValuesStatements are detected as nested OperationListStatements - if (setOperationListStatement.getSelects().stream().anyMatch(ValuesStatement.class::isInstance)) { + if (setOperationListStatement.getSelects().stream().anyMatch(Values.class::isInstance)) { return setOperationListStatement.toString(); } @@ -185,8 +183,8 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { } return selectBody.getSelectItems().stream() // - .filter(SelectExpressionItem.class::isInstance) // - .map(item -> ((SelectExpressionItem) item).getAlias()) // + .filter(SelectItem.class::isInstance) // + .map(item -> ((SelectItem) item).getAlias()) // .filter(Objects::nonNull) // .map(Alias::getName) // .collect(Collectors.toSet()); @@ -203,9 +201,7 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { return new HashSet<>(); } - Select selectStatement = (Select) statement; - PlainSelect selectBody = (PlainSelect) selectStatement.getSelectBody(); - return this.getSelectionAliases(selectBody); + return this.getSelectionAliases((PlainSelect) statement); } /** @@ -221,7 +217,7 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { } Select selectStatement = (Select) statement; - if (selectStatement.getSelectBody()instanceof PlainSelect selectBody) { + if (selectStatement instanceof PlainSelect selectBody) { return getJoinAliases(selectBody); } @@ -319,7 +315,7 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { * ValuesStatement has no alias * SetOperation can have multiple alias for each operation item */ - if (!(selectStatement.getSelectBody()instanceof PlainSelect selectBody)) { + if (!(selectStatement instanceof PlainSelect selectBody)) { return null; } @@ -374,7 +370,7 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { /* We only support count queries for {@link PlainSelect}. */ - if (!(selectStatement.getSelectBody()instanceof PlainSelect selectBody)) { + if (!(selectStatement instanceof PlainSelect selectBody)) { return this.query.getQueryString(); } @@ -384,7 +380,7 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { if (StringUtils.hasText(countProjection)) { Function jSqlCount = getJSqlCount(Collections.singletonList(countProjection), false); - selectBody.setSelectItems(Collections.singletonList(new SelectExpressionItem(jSqlCount))); + selectBody.setSelectItems(Collections.singletonList(new SelectItem(jSqlCount))); return selectBody.toString(); } @@ -394,34 +390,26 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { String tableAlias = detectAlias(selectBody); // is never null - List selectItems = selectBody.getSelectItems(); + List> selectItems = selectBody.getSelectItems(); if (onlyASingleColumnProjection(selectItems)) { - SelectExpressionItem singleProjection = (SelectExpressionItem) selectItems.get(0); + SelectItem singleProjection = (SelectItem) selectItems.get(0); Column column = (Column) singleProjection.getExpression(); String countProp = column.getFullyQualifiedName(); Function jSqlCount = getJSqlCount(Collections.singletonList(countProp), distinct); - selectBody.setSelectItems(Collections.singletonList(new SelectExpressionItem(jSqlCount))); + selectBody.setSelectItems(Collections.singletonList(new SelectItem<>(jSqlCount))); return selectBody.toString(); } String countProp = query.isNativeQuery() ? (distinct ? "*" : "1") : tableAlias == null ? "*" : tableAlias; Function jSqlCount = getJSqlCount(Collections.singletonList(countProp), distinct); - selectBody.setSelectItems(Collections.singletonList(new SelectExpressionItem(jSqlCount))); + selectBody.setSelectItems(Collections.singletonList(new SelectItem(jSqlCount))); - if (CollectionUtils.isEmpty(selectStatement.getWithItemsList())) { - return selectBody.toString(); - } - - String withStatements = selectStatement.getWithItemsList().stream() // - .map(WithItem::toString) // - .collect(Collectors.joining(",")); - - return "with " + withStatements + "\n" + selectBody; + return selectBody.toString(); } @Override @@ -435,13 +423,13 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { Select selectStatement = (Select) statement; - if (selectStatement.getSelectBody() instanceof ValuesStatement) { + if (selectStatement instanceof Values) { return ""; } - SelectBody selectBody = selectStatement.getSelectBody(); + Select selectBody = selectStatement; - if (selectStatement.getSelectBody()instanceof SetOperationList setOperationList) { + if (selectStatement instanceof SetOperationList setOperationList) { // using the first one since for setoperations the projection has to be the same selectBody = setOperationList.getSelects().get(0); @@ -493,11 +481,11 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { * @param projection the projection to analyse * @return true when the projection only contains a single column definition otherwise false */ - private boolean onlyASingleColumnProjection(List projection) { + private boolean onlyASingleColumnProjection(List> projection) { // this is unfortunately the only way to check without any hacky & hard string regex magic - return projection.size() == 1 && projection.get(0) instanceof SelectExpressionItem - && (((SelectExpressionItem) projection.get(0)).getExpression()) instanceof Column; + return projection.size() == 1 && projection.get(0) instanceof SelectItem + && (((SelectItem) projection.get(0)).getExpression()) instanceof Column; } @Override diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java index 639a156bf..58b5b6589 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java @@ -162,7 +162,7 @@ public class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests { assertThat(stringQuery.hasConstructorExpression()).isFalse(); assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase( - "with sample_data (day, value) AS (VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)))\n" + "with sample_data (day, value) AS (VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))) " + "SELECT count(1) FROM sample_data AS a"); assertThat(queryEnhancer.applySorting(Sort.by("day").descending())).endsWith("ORDER BY a.day DESC"); assertThat(queryEnhancer.getJoinAliases()).isEmpty(); @@ -185,7 +185,7 @@ public class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests { assertThat(stringQuery.hasConstructorExpression()).isFalse(); assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase( - "with sample_data (day, value) AS (VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))),test2 AS (VALUES (1, 2, 3))\n" + "with sample_data (day, value) AS (VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))), test2 AS (VALUES (1, 2, 3)) " + "SELECT count(1) FROM sample_data AS a"); assertThat(queryEnhancer.applySorting(Sort.by("day").descending())).endsWith("ORDER BY a.day DESC"); assertThat(queryEnhancer.getJoinAliases()).isEmpty();