This is an automated email from the ASF dual-hosted git repository.

duanzhengqiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 453aab30fc2 support parse parentheses (#29725)
453aab30fc2 is described below

commit 453aab30fc28d7d8e27b20d796c9b191bc722ce2
Author: Chuxin Chen <[email protected]>
AuthorDate: Mon Jan 15 12:47:42 2024 +0800

    support parse parentheses (#29725)
    
    * support chinese whitespace for oracle
    
    * support parse parentheses
---
 .../expression/impl/ColumnSegmentBinder.java       |  1 +
 .../visitor/statement/MySQLStatementVisitor.java   | 14 +++----
 .../common/segment/dml/column/ColumnSegment.java   |  4 ++
 .../common/segment/generic/ParenthesesSegment.java | 25 +++++-------
 .../asserts/segment/generic/ParenthesesAssert.java | 47 ++++++++++++++++++++++
 .../segment/projection/ProjectionAssert.java       |  8 ++++
 .../ExpectedParentheses.java}                      | 18 +++------
 .../impl/column/ExpectedColumnProjection.java      |  6 +++
 .../parser/src/main/resources/case/dml/select.xml  | 12 ++++++
 .../sql/supported/dml/select-distinct.xml          |  1 +
 10 files changed, 102 insertions(+), 34 deletions(-)

diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
index e2cd1ca9632..4c02e220911 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
@@ -82,6 +82,7 @@ public final class ColumnSegmentBinder {
         Optional<ColumnSegment> inputColumnSegment = 
findInputColumnSegment(segment, parentSegmentType, tableBinderContextValues, 
outerTableBinderContexts, statementBinderContext);
         inputColumnSegment.ifPresent(optional -> 
result.setVariable(optional.isVariable()));
         result.setColumnBoundedInfo(createColumnSegmentBoundedInfo(segment, 
inputColumnSegment.orElse(null)));
+        segment.getParentheses().forEach(each -> 
result.getParentheses().add(each));
         return result;
     }
     
diff --git 
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
 
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
index 216179598bd..31a8bcda719 100644
--- 
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
+++ 
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
@@ -163,6 +163,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSe
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParenthesesSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.InsertColumnsSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.OnDuplicateKeyColumnsSegment;
@@ -645,7 +646,12 @@ public abstract class MySQLStatementVisitor extends 
MySQLStatementBaseVisitor<AS
             return new NotExpression(startIndex, stopIndex, 
(ExpressionSegment) expression, 
"!".equalsIgnoreCase(ctx.notOperator().getText()));
         }
         if (null != ctx.LP_() && 1 == ctx.expr().size()) {
-            return visit(ctx.expr(0));
+            ASTNode result = visit(ctx.expr(0));
+            if (result instanceof ColumnSegment) {
+                ((ColumnSegment) result).getParentheses().add(new 
ParenthesesSegment(ctx.LP_().getSymbol().getStartIndex(), 
ctx.LP_().getSymbol().getStopIndex(), true));
+                ((ColumnSegment) result).getParentheses().add(new 
ParenthesesSegment(ctx.RP_().getSymbol().getStartIndex(), 
ctx.RP_().getSymbol().getStopIndex(), false));
+            }
+            return result;
         }
         if (null != ctx.VERTICAL_BAR_() && 2 == ctx.VERTICAL_BAR_().size()) {
             ExpressionSegment left = (ExpressionSegment) 
visit(ctx.simpleExpr(0));
@@ -1986,12 +1992,6 @@ public abstract class MySQLStatementVisitor extends 
MySQLStatementBaseVisitor<AS
         return new EngineSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), 
SQLUtils.getExactlyValue(ctx.textOrIdentifier().getText()));
     }
     
-    /**
-     * Get original text.
-     *
-     * @param ctx context
-     * @return original text
-     */
     protected String getOriginalText(final ParserRuleContext ctx) {
         return ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
     }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/column/ColumnSegment.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/column/ColumnSegment.java
index f7269bb1f9d..61dfe16bd85 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/column/ColumnSegment.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/column/ColumnSegment.java
@@ -20,11 +20,13 @@ package 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column;
 import lombok.Getter;
 import lombok.Setter;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParenthesesSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.bounded.ColumnSegmentBoundedInfo;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -52,6 +54,8 @@ public final class ColumnSegment implements 
ExpressionSegment, OwnerAvailable {
     
     private boolean isVariable;
     
+    private List<ParenthesesSegment> parentheses = new LinkedList<>();
+    
     public ColumnSegment(final int startIndex, final int stopIndex, final 
IdentifierValue identifier) {
         this.startIndex = startIndex;
         this.stopIndex = stopIndex;
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/ParenthesesSegment.java
similarity index 50%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
copy to 
parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/ParenthesesSegment.java
index 6141bb8adab..6dec1393932 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/ParenthesesSegment.java
@@ -15,27 +15,22 @@
  * limitations under the License.
  */
 
-package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.projection.impl.column;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic;
 
 import lombok.Getter;
-import lombok.Setter;
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedIdentifierSQLSegment;
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.projection.ExpectedProjection;
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedOwner;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
 
 /**
- * Expected column projection.
+ * Parentheses segment.
  */
+@RequiredArgsConstructor
 @Getter
-@Setter
-public final class ExpectedColumnProjection extends 
AbstractExpectedIdentifierSQLSegment implements ExpectedProjection {
+public final class ParenthesesSegment implements SQLSegment {
+    
+    private final int startIndex;
     
-    @XmlAttribute
-    private String alias;
+    private final int stopIndex;
     
-    @XmlElement
-    private ExpectedOwner owner;
+    private final boolean left;
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/generic/ParenthesesAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/generic/ParenthesesAssert.java
new file mode 100644
index 00000000000..b943d98c8b3
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/generic/ParenthesesAssert.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *     http://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.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.generic;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParenthesesSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.generic.ExpectedParentheses;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Parentheses assert.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ParenthesesAssert {
+    
+    /**
+     * Assert actual brackets segment is correct with expected parentheses.
+     *
+     * @param assertContext assert context
+     * @param actual actual brackets segment
+     * @param expected expected parentheses
+     */
+    public static void assertIs(final SQLCaseAssertContext assertContext, 
final ParenthesesSegment actual, final ExpectedParentheses expected) {
+        assertThat(assertContext.getText("Left brackets assertion error: "), 
actual.isLeft(), is(expected.isLeft()));
+        SQLSegmentAssert.assertIs(assertContext, actual, expected);
+    }
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/projection/ProjectionAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/projection/ProjectionAssert.java
index 257fe519796..24197f25c5b 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/projection/ProjectionAssert.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/projection/ProjectionAssert.java
@@ -30,9 +30,11 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.Subquery
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.rownum.NumberLiteralRowNumberValueSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.rownum.ParameterMarkerRowNumberValueSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.top.TopProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParenthesesSegment;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.expression.ExpressionAssert;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.generic.ParenthesesAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.identifier.IdentifierValueAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.owner.OwnerAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dml.impl.SelectStatementAssert;
@@ -47,6 +49,7 @@ import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.s
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.projection.impl.top.ExpectedTopProjection;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.sql.type.SQLCaseType;
 
+import java.util.Iterator;
 import java.util.List;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
@@ -136,6 +139,11 @@ public final class ProjectionAssert {
         } else {
             IdentifierValueAssert.assertIs(assertContext, 
actual.getColumn().getIdentifier(), expected, "Column projection");
         }
+        if (!expected.getParentheses().isEmpty()) {
+            assertThat(expected.getParentheses().size(), 
is(actual.getColumn().getParentheses().size()));
+            Iterator<ParenthesesSegment> iterator = 
actual.getColumn().getParentheses().iterator();
+            expected.getParentheses().forEach(each -> 
ParenthesesAssert.assertIs(assertContext, iterator.next(), each));
+        }
         if (null == expected.getOwner()) {
             assertFalse(actual.getColumn().getOwner().isPresent(), 
assertContext.getText("Actual owner should not exist."));
         } else {
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/generic/ExpectedParentheses.java
similarity index 62%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
copy to 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/generic/ExpectedParentheses.java
index 6141bb8adab..cb3c8f44358 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/generic/ExpectedParentheses.java
@@ -15,27 +15,21 @@
  * limitations under the License.
  */
 
-package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.projection.impl.column;
+package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.generic;
 
 import lombok.Getter;
 import lombok.Setter;
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedIdentifierSQLSegment;
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.projection.ExpectedProjection;
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedOwner;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
 
 import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
 
 /**
- * Expected column projection.
+ * Expected parentheses.
  */
 @Getter
 @Setter
-public final class ExpectedColumnProjection extends 
AbstractExpectedIdentifierSQLSegment implements ExpectedProjection {
+public final class ExpectedParentheses extends AbstractExpectedSQLSegment {
     
-    @XmlAttribute
-    private String alias;
-    
-    @XmlElement
-    private ExpectedOwner owner;
+    @XmlAttribute(name = "left")
+    private boolean left;
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
index 6141bb8adab..ef22e08dd2a 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/projection/impl/column/ExpectedColumnProjection.java
@@ -20,11 +20,14 @@ package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.
 import lombok.Getter;
 import lombok.Setter;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedIdentifierSQLSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.generic.ExpectedParentheses;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.projection.ExpectedProjection;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedOwner;
 
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Expected column projection.
@@ -38,4 +41,7 @@ public final class ExpectedColumnProjection extends 
AbstractExpectedIdentifierSQ
     
     @XmlElement
     private ExpectedOwner owner;
+    
+    @XmlElement(name = "parentheses")
+    private List<ExpectedParentheses> parentheses = new LinkedList<>();
 }
diff --git a/test/it/parser/src/main/resources/case/dml/select.xml 
b/test/it/parser/src/main/resources/case/dml/select.xml
index f1ebf7bebd3..74af7bda52a 100644
--- a/test/it/parser/src/main/resources/case/dml/select.xml
+++ b/test/it/parser/src/main/resources/case/dml/select.xml
@@ -2867,6 +2867,18 @@
         </projections>
     </select>
 
+    <select sql-case-id="select_distinct_with_brackets" >
+        <from>
+            <simple-table name="t_order_item" start-index="31" stop-index="42" 
/>
+        </from>
+        <projections start-index="16" stop-index="24" distinct-row="true">
+            <column-projection name="item_id" start-index="17" stop-index="23">
+                <parentheses left = "true" start-index = "16" stop-index = 
"16" />
+                <parentheses left = "false" start-index = "24" stop-index = 
"24" />
+            </column-projection>
+        </projections>
+    </select>
+
     <select sql-case-id="select_unique_with_single_column_without_order_by" >
         <from>
             <simple-table name="t_order_item" start-index="27" stop-index="38" 
/>
diff --git 
a/test/it/parser/src/main/resources/sql/supported/dml/select-distinct.xml 
b/test/it/parser/src/main/resources/sql/supported/dml/select-distinct.xml
index 38c5c312d31..92c9e835ce0 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/select-distinct.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/select-distinct.xml
@@ -24,6 +24,7 @@
     <sql-case id="select_unique_with_multi_column_without_order_by" 
value="SELECT UNIQUE order_id, user_id, status FROM t_order" db-types="Oracle" 
/>
 
     <sql-case id="select_distinct_with_owner_column_without_order_by" 
value="SELECT DISTINCT t_order.order_id FROM t_order order by t_order.order_id" 
db-types="MySQL" />
+    <sql-case id="select_distinct_with_brackets" value="SELECT DISTINCT 
(item_id) FROM t_order_item" db-types="MySQL" />
     <sql-case id="select_distinct_with_owner_star_without_order_by" 
value="SELECT DISTINCT t_order.*, t_order_item.order_id FROM t_order, 
t_order_item WHERE t_order.order_id = t_order_item.order_id" db-types="MySQL" />
     <!-- for with owner column with group by without order by  -->
     <sql-case id="select_distinct_with_owner_column_with_group_by" 
value="SELECT DISTINCT t_order.order_id FROM t_order GROUP BY t_order.order_id" 
db-types="MySQL" />

Reply via email to