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 0aa68f67b64 Support sql federation update (#28199)
0aa68f67b64 is described below
commit 0aa68f67b64ae0b67e018cf0884c22410ed28d6c
Author: niu niu <[email protected]>
AuthorDate: Mon Aug 21 16:44:06 2023 +0800
Support sql federation update (#28199)
---
.../compiler/converter/SQLNodeConverterEngine.java | 5 ++
.../statement/update/UpdateStatementConverter.java | 80 ++++++++++++++++++++++
.../sql/common/statement/dml/UpdateStatement.java | 9 +++
.../converter/SQLNodeConverterEngineIT.java | 5 +-
.../src/test/resources/converter/update.xml | 24 +++++++
5 files changed, 122 insertions(+), 1 deletion(-)
diff --git
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/SQLNodeConverterEngine.java
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/SQLNodeConverterEngine.java
index 92520797027..db559acb36f 100644
---
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/SQLNodeConverterEngine.java
+++
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/SQLNodeConverterEngine.java
@@ -24,8 +24,10 @@ import
org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dal.ExplainStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
import
org.apache.shardingsphere.sqlfederation.compiler.converter.statement.delete.DeleteStatementConverter;
import
org.apache.shardingsphere.sqlfederation.compiler.converter.statement.explain.ExplainStatementConverter;
+import
org.apache.shardingsphere.sqlfederation.compiler.converter.statement.update.UpdateStatementConverter;
import
org.apache.shardingsphere.sqlfederation.exception.OptimizationSQLNodeConvertException;
import
org.apache.shardingsphere.sqlfederation.compiler.converter.statement.select.SelectStatementConverter;
@@ -52,6 +54,9 @@ public final class SQLNodeConverterEngine {
if (statement instanceof ExplainStatement) {
return new ExplainStatementConverter().convert((ExplainStatement)
statement);
}
+ if (statement instanceof UpdateStatement) {
+ return new UpdateStatementConverter().convert((UpdateStatement)
statement);
+ }
throw new OptimizationSQLNodeConvertException(statement);
}
}
diff --git
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/statement/update/UpdateStatementConverter.java
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/statement/update/UpdateStatementConverter.java
new file mode 100644
index 00000000000..b4efca5e2bd
--- /dev/null
+++
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/statement/update/UpdateStatementConverter.java
@@ -0,0 +1,80 @@
+/*
+ * 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.sqlfederation.compiler.converter.statement.update;
+
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlOrderBy;
+import org.apache.calcite.sql.SqlUpdate;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
+import
org.apache.shardingsphere.sql.parser.sql.dialect.handler.dml.UpdateStatementHandler;
+import
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.ExpressionConverter;
+import
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.ColumnConverter;
+import
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.from.TableConverter;
+import
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.limit.PaginationValueSQLConverter;
+import
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.orderby.OrderByConverter;
+import
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.where.WhereConverter;
+import
org.apache.shardingsphere.sqlfederation.compiler.converter.statement.SQLStatementConverter;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * Update statement converter.
+ */
+public final class UpdateStatementConverter implements
SQLStatementConverter<UpdateStatement, SqlNode> {
+
+ @Override
+ public SqlNode convert(final UpdateStatement updateStatement) {
+ SqlUpdate sqlUpdate = convertUpdate(updateStatement);
+ SqlNodeList orderBy =
UpdateStatementHandler.getOrderBySegment(updateStatement).flatMap(optional ->
new OrderByConverter().convert(optional)).orElse(SqlNodeList.EMPTY);
+ Optional<LimitSegment> limit =
UpdateStatementHandler.getLimitSegment(updateStatement);
+ if (limit.isPresent()) {
+ SqlNode offset = limit.get().getOffset().flatMap(optional -> new
PaginationValueSQLConverter().convert(optional)).orElse(null);
+ SqlNode rowCount = limit.get().getRowCount().flatMap(optional ->
new PaginationValueSQLConverter().convert(optional)).orElse(null);
+ return new SqlOrderBy(SqlParserPos.ZERO, sqlUpdate, orderBy,
offset, rowCount);
+ }
+ return orderBy.isEmpty() ? sqlUpdate : new
SqlOrderBy(SqlParserPos.ZERO, sqlUpdate, orderBy, null, null);
+ }
+
+ private SqlUpdate convertUpdate(final UpdateStatement updateStatement) {
+ SqlNode table = new
TableConverter().convert(updateStatement.getTable()).orElseThrow(IllegalStateException::new);
+ SqlNode condition = updateStatement.getWhere().flatMap(optional -> new
WhereConverter().convert(optional)).orElse(null);
+ SqlNodeList columns = new SqlNodeList(SqlParserPos.ZERO);
+ SqlNodeList expressions = new SqlNodeList(SqlParserPos.ZERO);
+ for (AssignmentSegment each :
updateStatement.getAssignmentSegment().orElseThrow(IllegalStateException::new).getAssignments())
{
+ columns.addAll(convertColumn(each.getColumns()));
+ expressions.add(convertExpression(each.getValue()));
+ }
+ return new SqlUpdate(SqlParserPos.ZERO, table, columns, expressions,
condition, null, null);
+ }
+
+ private List<SqlNode> convertColumn(final List<ColumnSegment>
columnSegments) {
+ return columnSegments.stream().map(each -> new
ColumnConverter().convert(each).orElseThrow(IllegalStateException::new)).collect(Collectors.toList());
+ }
+
+ private SqlNode convertExpression(final ExpressionSegment
expressionSegment) {
+ return new
ExpressionConverter().convert(expressionSegment).orElseThrow(IllegalStateException::new);
+ }
+}
diff --git
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/statement/dml/UpdateStatement.java
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/statement/dml/UpdateStatement.java
index 424fa9141e3..633e405ec27 100644
---
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/statement/dml/UpdateStatement.java
+++
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/statement/dml/UpdateStatement.java
@@ -47,4 +47,13 @@ public abstract class UpdateStatement extends
AbstractSQLStatement implements DM
public Optional<WhereSegment> getWhere() {
return Optional.ofNullable(where);
}
+
+ /**
+ * Get assignment segment.
+ *
+ * @return assignment segment
+ */
+ public Optional<SetAssignmentSegment> getAssignmentSegment() {
+ return Optional.ofNullable(setAssignment);
+ }
}
diff --git
a/test/it/optimizer/src/test/java/org/apache/shardingsphere/test/it/optimizer/converter/SQLNodeConverterEngineIT.java
b/test/it/optimizer/src/test/java/org/apache/shardingsphere/test/it/optimizer/converter/SQLNodeConverterEngineIT.java
index d6d6b39a7b4..3f624e20616 100644
---
a/test/it/optimizer/src/test/java/org/apache/shardingsphere/test/it/optimizer/converter/SQLNodeConverterEngineIT.java
+++
b/test/it/optimizer/src/test/java/org/apache/shardingsphere/test/it/optimizer/converter/SQLNodeConverterEngineIT.java
@@ -62,6 +62,8 @@ class SQLNodeConverterEngineIT {
private static final String EXPLAIN_STATEMENT_PREFIX = "EXPLAIN";
+ private static final String UPDATE_STATEMENT_PREFIX = "UPDATE";
+
@ParameterizedTest(name = "{0} ({1}) -> {2}")
@ArgumentsSource(TestCaseArgumentsProvider.class)
void assertConvert(final String sqlCaseId, final SQLCaseType sqlCaseType,
final String databaseType) {
@@ -105,7 +107,8 @@ class SQLNodeConverterEngineIT {
private boolean isSupportedSQLCase(final
InternalSQLParserTestParameter testParam) {
return
testParam.getSqlCaseId().toUpperCase().startsWith(SELECT_STATEMENT_PREFIX)
||
testParam.getSqlCaseId().toUpperCase().startsWith(DELETE_STATEMENT_PREFIX)
- ||
testParam.getSqlCaseId().toUpperCase().startsWith(EXPLAIN_STATEMENT_PREFIX);
+ ||
testParam.getSqlCaseId().toUpperCase().startsWith(EXPLAIN_STATEMENT_PREFIX)
+ ||
testParam.getSqlCaseId().toUpperCase().startsWith(UPDATE_STATEMENT_PREFIX);
}
}
}
diff --git a/test/it/optimizer/src/test/resources/converter/update.xml
b/test/it/optimizer/src/test/resources/converter/update.xml
new file mode 100644
index 00000000000..d91fdd9054b
--- /dev/null
+++ b/test/it/optimizer/src/test/resources/converter/update.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<sql-node-converter-test-cases>
+ <test-cases sql-case-id="update_without_alias" expected-sql="UPDATE
`t_order` SET `status` = 'update' WHERE `order_id` = 1 AND `user_id` = 1"
db-types="MySQL" sql-case-types="LITERAL" />
+ <test-cases sql-case-id="update_without_alias" expected-sql="UPDATE
`t_order` SET `status` = ? WHERE `order_id` = ? AND `user_id` = ?"
db-types="MySQL" sql-case-types="PLACEHOLDER" />
+ <test-cases sql-case-id="update_without_alias" expected-sql="UPDATE
"t_order" SET "status" = 'update' WHERE
"order_id" = 1 AND "user_id" = 1" db-types="PostgreSQL,
openGauss, Oracle" sql-case-types="LITERAL" />
+ <test-cases sql-case-id="update_without_alias" expected-sql="UPDATE
"t_order" SET "status" = ? WHERE "order_id" = ?
AND "user_id" = ?" db-types="PostgreSQL, openGauss, Oracle"
sql-case-types="PLACEHOLDER" />
+</sql-node-converter-test-cases>