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 
&quot;t_order&quot; SET &quot;status&quot; = 'update' WHERE 
&quot;order_id&quot; = 1 AND &quot;user_id&quot; = 1" db-types="PostgreSQL, 
openGauss, Oracle" sql-case-types="LITERAL" />
+    <test-cases sql-case-id="update_without_alias" expected-sql="UPDATE 
&quot;t_order&quot; SET &quot;status&quot; = ? WHERE &quot;order_id&quot; = ? 
AND &quot;user_id&quot; = ?" db-types="PostgreSQL, openGauss, Oracle" 
sql-case-types="PLACEHOLDER" />
+</sql-node-converter-test-cases>

Reply via email to