This is an automated email from the ASF dual-hosted git repository. wuweijie 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 872763a5e4b Fix proxy MySQL 8.0.19 TABLE statement NPE (#26846) 872763a5e4b is described below commit 872763a5e4b343ace2fb524110fcb62a154e9c43 Author: niu niu <zihaoa...@aliyun.com> AuthorDate: Mon Jul 10 10:49:36 2023 +0800 Fix proxy MySQL 8.0.19 TABLE statement NPE (#26846) --- .../visitor/statement/MySQLStatementVisitor.java | 13 ++--- .../segment/dml/expr/ExplicitTableExpression.java | 41 +++++++++++++++ .../segment/expression/ExpressionAssert.java | 23 ++++++++- .../impl/expr/ExpectedExplicitTableExpression.java | 30 +++++++++++ .../jaxb/segment/impl/expr/ExpectedExpression.java | 3 ++ .../parser/src/main/resources/case/dal/explain.xml | 10 ++-- .../parser/src/main/resources/case/dml/table.xml | 60 ++++++++++++++++------ .../src/main/resources/sql/supported/dml/table.xml | 1 + 8 files changed, 155 insertions(+), 26 deletions(-) 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 8fe5fcd4f2b..86e4f97f680 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 @@ -169,6 +169,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhen import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CollateExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment; +import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExplicitTableExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression; @@ -808,12 +809,12 @@ public abstract class MySQLStatementVisitor extends MySQLStatementBaseVisitor<AS @Override public ASTNode visitTableStatement(final TableStatementContext ctx) { MySQLSelectStatement result = new MySQLSelectStatement(); - if (null != ctx.TABLE()) { - result.setFrom(new SimpleTableSegment(new TableNameSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), - new IdentifierValue(ctx.tableName().getText())))); - } else { - result.setTable((SimpleTableSegment) visit(ctx.tableName())); - } + int startIndex = ctx.getStart().getStartIndex(); + int stopIndex = ctx.getStop().getStopIndex(); + TableNameSegment tableNameSegment = new TableNameSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue(ctx.tableName().getText())); + ExplicitTableExpression explicitTableExpression = new ExplicitTableExpression(startIndex, stopIndex, tableNameSegment); + result.setProjections(new ProjectionsSegment(startIndex, stopIndex)); + result.getProjections().getProjections().add(new ExpressionProjectionSegment(startIndex, stopIndex, getOriginalText(ctx), explicitTableExpression)); return result; } diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ExplicitTableExpression.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ExplicitTableExpression.java new file mode 100644 index 00000000000..20803e1096e --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ExplicitTableExpression.java @@ -0,0 +1,41 @@ +/* + * 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.sql.parser.sql.common.segment.dml.expr; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment; + +/** + * Explicit table expression. + */ +@RequiredArgsConstructor +@Getter +public final class ExplicitTableExpression implements ExpressionSegment { + + private final int startIndex; + + private final int stopIndex; + + private final TableNameSegment tableNameSegment; + + @Override + public String getText() { + return tableNameSegment.getIdentifier().getValue(); + } +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java index 10fa5f77655..39027f2ad01 100644 --- a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java @@ -25,6 +25,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenE import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CollateExpression; +import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExplicitTableExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment; @@ -46,6 +47,7 @@ import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAsse import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.column.ColumnAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.generic.DataTypeAssert; +import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.identifier.IdentifierValueAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.insert.InsertValuesClauseAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.owner.OwnerAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.projection.ProjectionAssert; @@ -54,6 +56,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.expr.ExpectedBinaryOperationExpression; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedCaseWhenExpression; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedCollateExpression; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedExplicitTableExpression; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedExistsSubquery; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedExpression; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedInExpression; @@ -379,10 +382,10 @@ public final class ExpressionAssert { private static void assertValuesExpression(final SQLCaseAssertContext assertContext, final ValuesExpression actual, final ExpectedValuesExpression expected) { if (null == expected) { - assertNull(actual, assertContext.getText("Variable segment should not exist.")); + assertNull(actual, assertContext.getText("Values segment should not exist.")); return; } - assertNotNull(actual, assertContext.getText("Variable segment should exist.")); + assertNotNull(actual, assertContext.getText("Values segment should exist.")); if (null == expected.getInsertValuesClause()) { assertTrue(actual.getRowConstructorList().isEmpty(), "Values expression should not exist."); } else { @@ -391,6 +394,20 @@ public final class ExpressionAssert { } } + private static void assertExplicitExpression(final SQLCaseAssertContext assertContext, final ExplicitTableExpression actual, final ExpectedExplicitTableExpression expected) { + if (null == expected) { + assertNull(actual, assertContext.getText("Table segment should not exist.")); + return; + } + assertNotNull(actual, assertContext.getText("Table segment should exist.")); + if (null == expected.getName()) { + assertNull(actual.getTableNameSegment(), assertContext.getText("Table segment should not exist.")); + } else { + assertNotNull(actual.getTableNameSegment(), assertContext.getText("Table segment should exist.")); + IdentifierValueAssert.assertIs(assertContext, actual.getTableNameSegment().getIdentifier(), expected, "table"); + } + } + /** * Assert expression by actual expression segment class type. * @@ -446,6 +463,8 @@ public final class ExpressionAssert { assertVariableSegment(assertContext, (VariableSegment) actual, expected.getVariableSegment()); } else if (actual instanceof ValuesExpression) { assertValuesExpression(assertContext, (ValuesExpression) actual, expected.getValuesExpression()); + } else if (actual instanceof ExplicitTableExpression) { + assertExplicitExpression(assertContext, (ExplicitTableExpression) actual, expected.getExplicitTableExpression()); } else { throw new UnsupportedOperationException(String.format("Unsupported expression: %s", actual.getClass().getName())); } diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExplicitTableExpression.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExplicitTableExpression.java new file mode 100644 index 00000000000..7de8cb83675 --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExplicitTableExpression.java @@ -0,0 +1,30 @@ +/* + * 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.cases.parser.jaxb.segment.impl.expr; + +import lombok.Getter; +import lombok.Setter; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedIdentifierSQLSegment; + +/** + * Expected explicit table expression. + */ +@Getter +@Setter +public final class ExpectedExplicitTableExpression extends AbstractExpectedIdentifierSQLSegment { +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java index c8b4cd6bf3e..75a192ae6a5 100644 --- a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java @@ -98,4 +98,7 @@ public final class ExpectedExpression extends AbstractExpectedSQLSegment { @XmlElement(name = "values-expression") private ExpectedValuesExpression valuesExpression; + + @XmlElement(name = "explicit-table") + private ExpectedExplicitTableExpression explicitTableExpression; } diff --git a/test/it/parser/src/main/resources/case/dal/explain.xml b/test/it/parser/src/main/resources/case/dal/explain.xml index e7267a14bc6..36ff838ed9d 100644 --- a/test/it/parser/src/main/resources/case/dal/explain.xml +++ b/test/it/parser/src/main/resources/case/dal/explain.xml @@ -343,9 +343,13 @@ <offset value="2" literal-start-index="55" literal-stop-index="55" /> <row-count value="1" start-index="46" stop-index="46" /> </limit> - <from> - <simple-table name="t_order" start-index="8" stop-index="20" /> - </from> + <projections start-index="8" stop-index="20"> + <expression-projection text="TABLE t_order" start-index="8" stop-index="20"> + <expr> + <explicit-table start-index="8" stop-index="20" name="t_order" /> + </expr> + </expression-projection> + </projections> </select> </describe> diff --git a/test/it/parser/src/main/resources/case/dml/table.xml b/test/it/parser/src/main/resources/case/dml/table.xml index 69d94b8518f..300d37039dd 100644 --- a/test/it/parser/src/main/resources/case/dml/table.xml +++ b/test/it/parser/src/main/resources/case/dml/table.xml @@ -17,10 +17,24 @@ --> <sql-parser-test-cases> + <select sql-case-id="explicit_table"> + <projections start-index="0" stop-index="6"> + <expression-projection text="table f" start-index="0" stop-index="6"> + <expr> + <explicit-table start-index="0" stop-index="6" name="f" /> + </expr> + </expression-projection> + </projections> + </select> + <select sql-case-id="table_with_order_by_limit_offset"> - <from> - <simple-table name="t_order" start-index="0" stop-index="12" /> - </from> + <projections start-index="0" stop-index="12"> + <expression-projection text="TABLE t_order" start-index="0" stop-index="12"> + <expr> + <explicit-table start-index="0" stop-index="12" name="t_order" /> + </expr> + </expression-projection> + </projections> <order-by> <column-item name="order_id" start-index="23" stop-index="30" /> </order-by> @@ -31,19 +45,31 @@ </select> <select sql-case-id="table_union"> - <from> - <simple-table name="T1" start-index="0" stop-index="7" /> - </from> + <projections start-index="0" stop-index="7"> + <expression-projection text="TABLE T1" start-index="0" stop-index="7"> + <expr> + <explicit-table start-index="0" stop-index="7" name="T1" /> + </expr> + </expression-projection> + </projections> <combine combine-type="UNION" start-index="9" stop-index="22"> <left> - <from> - <simple-table name="T1" start-index="0" stop-index="7" /> - </from> + <projections start-index="0" stop-index="7"> + <expression-projection text="TABLE T1" start-index="0" stop-index="7"> + <expr> + <explicit-table start-index="0" stop-index="7" name="T1" /> + </expr> + </expression-projection> + </projections> </left> <right> - <from> - <simple-table name="T2" start-index="15" stop-index="22" /> - </from> + <projections start-index="15" stop-index="22"> + <expression-projection text="TABLE T2" start-index="15" stop-index="22"> + <expr> + <explicit-table start-index="15" stop-index="22" name="T2" /> + </expr> + </expression-projection> + </projections> </right> </combine> </select> @@ -56,9 +82,13 @@ <subquery-table alias="dt"> <subquery> <select> - <from> - <simple-table name="t0" start-index="15" stop-index="22" /> - </from> + <projections start-index="15" stop-index="22"> + <expression-projection text="TABLE t0" start-index="15" stop-index="22"> + <expr> + <explicit-table start-index="15" stop-index="22" name="t0" /> + </expr> + </expression-projection> + </projections> </select> </subquery> </subquery-table> diff --git a/test/it/parser/src/main/resources/sql/supported/dml/table.xml b/test/it/parser/src/main/resources/sql/supported/dml/table.xml index fc524e6fca5..c6f550d1357 100644 --- a/test/it/parser/src/main/resources/sql/supported/dml/table.xml +++ b/test/it/parser/src/main/resources/sql/supported/dml/table.xml @@ -17,6 +17,7 @@ --> <sql-cases> + <sql-case id="explicit_table" value="table f" db-types="MySQL" /> <sql-case id="table_with_order_by_limit_offset" value="TABLE t_order ORDER BY order_id LIMIT 1 OFFSET 2" db-types="MySQL" /> <sql-case id="table_union" value="TABLE T1 UNION TABLE T2" db-types="MySQL" /> <sql-case id="select_from_with_table" value="SELECT * FROM (TABLE t0) AS dt" db-types="MySQL" />