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

jianbin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new fa6bdda3c3 bugfix: the failure of rollbacking back of the delete SQL 
at AT mode when using SQLServer (#6511)
fa6bdda3c3 is described below

commit fa6bdda3c33a7e49f2404faf2c375d1c59ed890f
Author: TakeActionNow2019 <55011193+takeactionnow2...@users.noreply.github.com>
AuthorDate: Wed Sep 11 10:01:43 2024 +0800

    bugfix: the failure of rollbacking back of the delete SQL at AT mode when 
using SQLServer (#6511)
---
 changes/en-us/2.x.md                               |  3 +
 changes/zh-cn/2.x.md                               |  3 +
 .../sql/struct/cache/SqlServerTableMetaCache.java  |  6 +-
 .../sqlserver/SqlServerUndoDeleteExecutor.java     | 92 +++++++++++++++++++---
 .../seata/sqlparser/struct/SqlServerTableMeta.java | 37 +++++++++
 5 files changed, 129 insertions(+), 12 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index d2df9011b8..f0ee86741f 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -24,6 +24,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#6707](https://github.com/apache/incubator-seata/pull/6707)] fix readonly 
branch commit errors in Oracle XA transactions
 - [[#6711](https://github.com/apache/incubator-seata/pull/6711)] fix dameng 
rollback info un compress fail
 - [[#6714](https://github.com/apache/incubator-seata/pull/6714)] fix dameng 
delete undo fail
+- [[#6511](https://github.com/apache/incubator-seata/pull/6511)] fix the 
failure of rollbacking back of the delete SQL at AT mode when using SQLServer
 - [[#6701](https://github.com/apache/incubator-seata/pull/6728)] fix support 
serialization for dm.jdbc.driver.DmdbTimestamp
 - [[#6757](https://github.com/apache/incubator-seata/pull/6757)] the bug where 
multiple nodes cannot be retrieved from the naming server
 - [[#6769](https://github.com/apache/incubator-seata/pull/6769)] fix tcc fence 
deadLock
@@ -133,6 +134,7 @@ Thanks to these contributors for their code commits. Please 
report an unintended
 - [GoodBoyCoder](https://github.com/GoodBoyCoder)
 - [liuqiufeng](https://github.com/liuqiufeng)
 - [caohdgege](https://github.com/caohdgege)
+- [TakeActionNow2019](https://github.com/TakeActionNow2019)
 - [imashimaro](https://github.com/hmj776521114)
 - [lyl2008dsg](https://github.com/lyl2008dsg)
 - [lightClouds917](https://github.com/lightClouds917)
@@ -143,4 +145,5 @@ Thanks to these contributors for their code commits. Please 
report an unintended
 - [LegGasai](https://github.com/LegGasai)
 - [yangli-stu](https://github.com/yangli-stu)
 
+
 Also, we receive many valuable issues, questions and advices from our 
community. Thanks for you all.
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index f7dd962f54..7489323f82 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -25,6 +25,7 @@
 - [[#6707](https://github.com/apache/incubator-seata/pull/6707)] 修复Oracle 
XA事务中只读分支提交出错的问题
 - [[#6711](https://github.com/apache/incubator-seata/pull/6711)] 
修复达梦数据库的getRollbackInfo没有解压缩的问题
 - [[#6714](https://github.com/apache/incubator-seata/pull/6714)] 
修复达梦数据库的delete sql回滚失败的问题
+- [[#6511](https://github.com/apache/incubator-seata/pull/6511)] 
修复在使用SQLServer时,AT模式delete语句无法正常回滚的问题
 - [[#6701](https://github.com/apache/incubator-seata/pull/6728)] 
修复达梦数据库的对dm.jdbc.driver.DmdbTimestamp的支持
 - [[#6757](https://github.com/apache/incubator-seata/pull/6757)] 
修复client通过namingserver只能获取到一个tc节点的bug
 - [[#6769](https://github.com/apache/incubator-seata/pull/6769)] 修复tcc fence死锁
@@ -134,6 +135,7 @@
 - [GoodBoyCoder](https://github.com/GoodBoyCoder)
 - [liuqiufeng](https://github.com/liuqiufeng)
 - [caohdgege](https://github.com/caohdgege)
+- [TakeActionNow2019](https://github.com/TakeActionNow2019)
 - [imashimaro](https://github.com/hmj776521114)
 - [lyl2008dsg](https://github.com/lyl2008dsg)
 - [lightClouds917](https://github.com/lightClouds917)
@@ -144,5 +146,6 @@
 - [LegGasai](https://github.com/LegGasai)
 - [yangli-stu](https://github.com/yangli-stu)
 
+
 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。
 
diff --git 
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/SqlServerTableMetaCache.java
 
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/SqlServerTableMetaCache.java
index 69c6fb08c4..dfe9813d30 100644
--- 
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/SqlServerTableMetaCache.java
+++ 
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/SqlServerTableMetaCache.java
@@ -28,6 +28,7 @@ import org.apache.seata.common.util.StringUtils;
 import org.apache.seata.sqlparser.struct.ColumnMeta;
 import org.apache.seata.sqlparser.struct.IndexMeta;
 import org.apache.seata.sqlparser.struct.IndexType;
+import org.apache.seata.sqlparser.struct.SqlServerTableMeta;
 import org.apache.seata.sqlparser.struct.TableMeta;
 import org.apache.seata.sqlparser.util.ColumnUtils;
 import org.apache.seata.sqlparser.util.JdbcConstants;
@@ -82,7 +83,7 @@ public class SqlServerTableMetaCache extends 
AbstractTableMetaCache {
     }
 
     private TableMeta resultSetMetaToSchema(Connection connection, String 
tableName) throws SQLException {
-        TableMeta tm = new TableMeta();
+        SqlServerTableMeta tm = new SqlServerTableMeta();
         tm.setTableName(tableName);
         tm.setOriginalTableName(tableName);
 
@@ -134,6 +135,9 @@ public class SqlServerTableMetaCache extends 
AbstractTableMetaCache {
                 col.setOrdinalPosition(rsColumns.getInt("ORDINAL_POSITION"));
                 col.setIsNullAble(rsColumns.getString("IS_NULLABLE"));
                 
col.setIsAutoincrement(rsColumns.getString("IS_AUTOINCREMENT"));
+                if (col.isAutoincrement()) {
+                    tm.setTableIdentifyExistence(true);
+                }
 
                 if (tm.getAllColumns().containsKey(col.getColumnName())) {
                     throw new NotSupportYetException("Not support the table 
has the same column name with different case yet");
diff --git 
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/sqlserver/SqlServerUndoDeleteExecutor.java
 
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/sqlserver/SqlServerUndoDeleteExecutor.java
index b579c599ab..caba81afa6 100644
--- 
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/sqlserver/SqlServerUndoDeleteExecutor.java
+++ 
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/sqlserver/SqlServerUndoDeleteExecutor.java
@@ -16,21 +16,33 @@
  */
 package org.apache.seata.rm.datasource.undo.sqlserver;
 
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
 import org.apache.seata.common.exception.ShouldNeverHappenException;
 import org.apache.seata.common.util.CollectionUtils;
+import org.apache.seata.common.util.IOUtil;
+import org.apache.seata.rm.datasource.ConnectionProxy;
 import org.apache.seata.rm.datasource.sql.struct.Field;
+import org.apache.seata.rm.datasource.sql.struct.KeyType;
 import org.apache.seata.rm.datasource.sql.struct.Row;
+import org.apache.seata.rm.datasource.sql.struct.TableMetaCacheFactory;
 import org.apache.seata.rm.datasource.sql.struct.TableRecords;
 import org.apache.seata.rm.datasource.undo.SQLUndoLog;
+import org.apache.seata.sqlparser.struct.SqlServerTableMeta;
+import org.apache.seata.sqlparser.struct.TableMeta;
 import org.apache.seata.sqlparser.util.ColumnUtils;
 import org.apache.seata.sqlparser.util.JdbcConstants;
 
 
 public class SqlServerUndoDeleteExecutor extends BaseSqlServerUndoExecutor {
+
+    private boolean tableIdentifyExistence = false;
+
     /**
      * Instantiates a new sql server delete undo executor.
      *
@@ -59,17 +71,75 @@ public class SqlServerUndoDeleteExecutor extends 
BaseSqlServerUndoExecutor {
         String insertValues = fields.stream().map(field -> "?")
                 .collect(Collectors.joining(", "));
 
-        return "SET IDENTITY_INSERT " +
-                sqlUndoLog.getTableName() +
-                " ON; INSERT INTO " +
-                sqlUndoLog.getTableName() +
-                " (" +
-                insertColumns +
-                ") VALUES (" +
-                insertValues +
-                "); SET IDENTITY_INSERT " +
-                sqlUndoLog.getTableName() +
-                " OFF;";
+        if (tableIdentifyExistence) {
+            return "begin " +
+                    "SET IDENTITY_INSERT " + sqlUndoLog.getTableName() + " 
ON;" +
+                    "INSERT INTO " + sqlUndoLog.getTableName() + "(" + 
insertColumns + ") VALUES (" + insertValues + ");" +
+                    "SET IDENTITY_INSERT " + sqlUndoLog.getTableName() + " 
OFF; " +
+                    "end";
+        }
+        return "INSERT INTO " + sqlUndoLog.getTableName() + "(" + 
insertColumns + ") VALUES (" + insertValues + ");";
+    }
+
+    /**
+     * Judge whether there is a column of a SQLServer table is with a 
"IDENTITY"
+     *
+     * @param connectionProxy
+     */
+    private void judgeTableIdentifyExistence(ConnectionProxy connectionProxy) {
+        TableMeta tableMeta = 
TableMetaCacheFactory.getTableMetaCache(connectionProxy.getDbType())
+                .getTableMeta(
+                        connectionProxy.getTargetConnection(),
+                        sqlUndoLog.getTableName(),
+                        connectionProxy.getDataSourceProxy().getResourceId()
+                );
+        tableIdentifyExistence = ((SqlServerTableMeta) 
tableMeta).isTableIdentifyExistence();
+    }
+
+    /**
+     * Execute on.
+     *
+     * @param connectionProxy the connection proxy
+     * @throws SQLException the sql exception
+     */
+    @Override
+    public void executeOn(ConnectionProxy connectionProxy) throws SQLException 
{
+        Connection conn = connectionProxy.getTargetConnection();
+        if (IS_UNDO_DATA_VALIDATION_ENABLE && 
!dataValidationAndGoOn(connectionProxy)) {
+            return;
+        }
+
+        judgeTableIdentifyExistence(connectionProxy);
+
+        PreparedStatement undoPST = null;
+        try {
+            String undoSQL = buildUndoSQL();
+            undoPST = conn.prepareStatement(undoSQL);
+            TableRecords undoRows = getUndoRows();
+            for (Row undoRow : undoRows.getRows()) {
+                ArrayList<Field> undoValues = new ArrayList<>();
+                List<Field> pkValueList = getOrderedPkList(undoRows, undoRow, 
connectionProxy.getDbType());
+                for (Field field : undoRow.getFields()) {
+                    if (field.getKeyType() != KeyType.PRIMARY_KEY) {
+                        undoValues.add(field);
+                    }
+                }
+
+                undoPrepare(undoPST, undoValues, pkValueList);
+
+                undoPST.executeUpdate();
+            }
+
+        } catch (Exception ex) {
+            if (ex instanceof SQLException) {
+                throw (SQLException) ex;
+            } else {
+                throw new SQLException(ex);
+            }
+        } finally {
+            IOUtil.close(undoPST);
+        }
+
     }
 
     @Override
diff --git 
a/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/struct/SqlServerTableMeta.java
 
b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/struct/SqlServerTableMeta.java
new file mode 100644
index 0000000000..8b6afbf215
--- /dev/null
+++ 
b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/struct/SqlServerTableMeta.java
@@ -0,0 +1,37 @@
+/*
+ * 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.seata.sqlparser.struct;
+
+/**
+ * The type Table meta of SqlServer.
+ */
+public class SqlServerTableMeta extends TableMeta {
+
+    /**
+     * Stands for whether there is a column of a SQLServer table with a 
"IDENTITY"
+     */
+    private boolean tableIdentifyExistence = false;
+
+    public boolean isTableIdentifyExistence() {
+        return tableIdentifyExistence;
+    }
+
+    public void setTableIdentifyExistence(boolean tableIdentifyExistence) {
+        this.tableIdentifyExistence = tableIdentifyExistence;
+    }
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org
For additional commands, e-mail: notifications-h...@seata.apache.org

Reply via email to