From f4e7606bd20d9b780ecc107e882c0541e5860fea Mon Sep 17 00:00:00 2001 From: qian0817 Date: Tue, 15 Apr 2025 16:08:37 +0800 Subject: [PATCH] feature: support has comma before grouping sets. --- .../ast/statement/SQLSelectGroupByClause.java | 9 ++++++++ .../druid/sql/parser/SQLSelectParser.java | 6 +++++ .../sql/visitor/SQLASTOutputVisitor.java | 18 +++++++-------- .../druid/bvt/sql/GroupingSetsTest.java | 22 +++++++++++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java b/core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java index 969ba700ff..7ebe402338 100644 --- a/core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java +++ b/core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java @@ -34,6 +34,7 @@ public class SQLSelectGroupByClause extends SQLObjectImpl implements SQLReplacea private boolean distinct; private boolean paren; + private boolean groupingSetsHaveComma; public SQLSelectGroupByClause() { } @@ -80,6 +81,14 @@ public void setWithCube(boolean withCube) { this.withCube = withCube; } + public boolean isGroupingSetsHaveComma() { + return groupingSetsHaveComma; + } + + public void setGroupingSetsHaveComma(boolean groupingSetsHaveComma) { + this.groupingSetsHaveComma = groupingSetsHaveComma; + } + public SQLExpr getHaving() { return this.having; } diff --git a/core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index 1467b6882e..7b2369a3b3 100644 --- a/core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -922,6 +922,7 @@ public void parseGroupBy(SQLSelectQueryBlock queryBlock) { groupBy.setWithCube(true); } + boolean hasComma = false; for (; ; ) { List comments = null; if (lexer.hasComment()) { @@ -931,6 +932,9 @@ public void parseGroupBy(SQLSelectQueryBlock queryBlock) { if (comments != null) { item.addBeforeComment(comments); } + if (item instanceof SQLGroupingSetExpr && hasComma) { + groupBy.setGroupingSetsHaveComma(true); + } item.setParent(groupBy); groupBy.addItem(item); @@ -946,8 +950,10 @@ public void parseGroupBy(SQLSelectQueryBlock queryBlock) { && lexer.line == line + 1) { item.addAfterComment(lexer.readAndResetComments()); } + hasComma = true; continue; } else if (lexer.identifierEquals(FnvHash.Constants.GROUPING)) { + hasComma = false; continue; } else { break; diff --git a/core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 5ae6cbcefe..f4bef554b3 100644 --- a/core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -51,13 +51,7 @@ import java.sql.Clob; import java.sql.NClob; import java.text.SimpleDateFormat; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.ZonedDateTime; +import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAmount; import java.util.*; @@ -2575,7 +2569,9 @@ public boolean visit(SQLSelectGroupByClause x) { if (i != 0) { if (groupItemSingleLine) { if (item instanceof SQLGroupingSetExpr) { - if (!item.hasBeforeComment()) { + if (x.isGroupingSetsHaveComma()) { + println(','); + } else if (!item.hasBeforeComment()) { println(); } } else { @@ -2583,7 +2579,11 @@ public boolean visit(SQLSelectGroupByClause x) { } } else { if (item instanceof SQLGroupingSetExpr) { - println(); + if (x.isGroupingSetsHaveComma()) { + println(','); + } else { + println(); + } } else { print(", "); } diff --git a/core/src/test/java/com/alibaba/druid/bvt/sql/GroupingSetsTest.java b/core/src/test/java/com/alibaba/druid/bvt/sql/GroupingSetsTest.java index e3b61b1f4f..ae5b48d3c7 100644 --- a/core/src/test/java/com/alibaba/druid/bvt/sql/GroupingSetsTest.java +++ b/core/src/test/java/com/alibaba/druid/bvt/sql/GroupingSetsTest.java @@ -17,4 +17,26 @@ public void test_groupingSets() throws Exception { + "\nFROM items_sold" + "\nGROUP BY GROUPING SETS ((brand), (size), ());", result); } + + public void test_groupingSetsHasComma() throws Exception { + String sql = "SELECT brand, size, sum(sales) FROM items_sold GROUP BY brand, size, GROUPING SETS ((brand), (size), ());"; + + String result = SQLUtils.format(sql, (DbType) null); + + Assert.assertEquals("SELECT brand, size, sum(sales)\n" + + "FROM items_sold\n" + + "GROUP BY brand, size,\n" + + "\tGROUPING SETS ((brand), (size), ());", result); + } + + public void test_groupingSetsNoComma() throws Exception { + String sql = "SELECT brand, size, sum(sales) FROM items_sold GROUP BY brand, size GROUPING SETS ((brand), (size), ());"; + + String result = SQLUtils.format(sql, (DbType) null); + + Assert.assertEquals("SELECT brand, size, sum(sales)\n" + + "FROM items_sold\n" + + "GROUP BY brand, size\n" + + "\tGROUPING SETS ((brand), (size), ());", result); + } }