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" />