From 7ef6fab1e34258266c55319afecf9b5e8cba53d3 Mon Sep 17 00:00:00 2001 From: jianbin Date: Sun, 18 Feb 2024 18:13:08 +0800 Subject: [PATCH 1/6] bugfix: the problem that the number of mirrors before and after may be inconsistent --- .../exec/AbstractDMLBaseExecutor.java | 12 ++++ .../rm/datasource/exec/UpdateExecutor.java | 25 +++++--- .../mysql/AntlrMySQLUpdateRecognizer.java | 22 +++++++ .../seata/sqlparser/SQLUpdateRecognizer.java | 8 +++ .../seata/sqlparser/druid/BaseRecognizer.java | 63 +++++++++++++++++++ .../druid/dm/DmUpdateRecognizer.java | 7 +++ .../druid/mysql/MySQLUpdateRecognizer.java | 8 +++ .../druid/oracle/OracleUpdateRecognizer.java | 7 +++ .../PostgresqlUpdateRecognizer.java | 6 ++ .../sqlserver/SqlServerUpdateRecognizer.java | 7 +++ .../druid/MySQLUpdateRecognizerTest.java | 30 +++++++++ 11 files changed, 186 insertions(+), 9 deletions(-) diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java index 3ba490a0e82..f0d6fb4a82f 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java @@ -26,6 +26,7 @@ import java.util.function.Predicate; import java.util.stream.Collectors; +import org.apache.seata.common.exception.ShouldNeverHappenException; import org.apache.seata.common.util.CollectionUtils; import org.apache.seata.rm.datasource.AbstractConnectionProxy; import org.apache.seata.rm.datasource.ConnectionContext; @@ -34,6 +35,7 @@ import org.apache.seata.rm.datasource.exception.TableMetaException; import org.apache.seata.rm.datasource.sql.struct.TableRecords; import org.apache.seata.sqlparser.SQLRecognizer; +import org.apache.seata.sqlparser.SQLType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -97,6 +99,16 @@ protected T executeAutoCommitFalse(Object[] args) throws Exception { try { TableRecords beforeImage = beforeImage(); T result = statementCallback.execute(statementProxy.getTargetStatement(), args); + int updateCount = statementProxy.getUpdateCount(); + if (updateCount > 0) { + if (SQLType.UPDATE == sqlRecognizer.getSQLType()) { + if (updateCount > beforeImage.size()) { + String errorMsg = + "Before image size is not equaled to after image size, probably because you use read committed, please retry transaction."; + throw new ShouldNeverHappenException(errorMsg); + } + } + } TableRecords afterImage = afterImage(beforeImage); prepareUndoLog(beforeImage, afterImage); return result; diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/UpdateExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/UpdateExecutor.java index 5459f13abbd..955e5294a19 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/UpdateExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/UpdateExecutor.java @@ -95,20 +95,27 @@ protected String buildBeforeImageSQL(TableMeta tableMeta, ArrayList @Override protected TableRecords afterImage(TableRecords beforeImage) throws SQLException { - TableMeta tmeta = getTableMeta(); if (beforeImage == null || beforeImage.size() == 0) { return TableRecords.empty(getTableMeta()); } - String selectSQL = buildAfterImageSQL(tmeta, beforeImage); + TableMeta tmeta = getTableMeta(); PreparedStatement pst = null; ResultSet rs = null; - try { - pst = statementProxy.getConnection().prepareStatement(selectSQL); - SqlGenerateUtils.setParamForPk(beforeImage.pkRows(), getTableMeta().getPrimaryKeyOnlyName(), pst); - rs = pst.executeQuery(); - return TableRecords.buildRecords(tmeta, rs); - } finally { - IOUtil.close(rs, pst); + SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer)sqlRecognizer; + List whereColumns = recognizer.getWhereColumns(); + boolean contain = tmeta.containsPK(whereColumns); + if (contain) { + String selectSQL = buildAfterImageSQL(tmeta, beforeImage); + try { + pst = statementProxy.getConnection().prepareStatement(selectSQL); + SqlGenerateUtils.setParamForPk(beforeImage.pkRows(), getTableMeta().getPrimaryKeyOnlyName(), pst); + rs = pst.executeQuery(); + return TableRecords.buildRecords(tmeta, rs); + } finally { + IOUtil.close(rs, pst); + } + } else { + return beforeImage(); } } diff --git a/sqlparser/seata-sqlparser-antlr/src/main/java/org/apache/seata/sqlparser/antlr/mysql/AntlrMySQLUpdateRecognizer.java b/sqlparser/seata-sqlparser-antlr/src/main/java/org/apache/seata/sqlparser/antlr/mysql/AntlrMySQLUpdateRecognizer.java index d7b99f79727..6990d97632b 100644 --- a/sqlparser/seata-sqlparser-antlr/src/main/java/org/apache/seata/sqlparser/antlr/mysql/AntlrMySQLUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-antlr/src/main/java/org/apache/seata/sqlparser/antlr/mysql/AntlrMySQLUpdateRecognizer.java @@ -16,6 +16,7 @@ */ package org.apache.seata.sqlparser.antlr.mysql; +import org.apache.seata.common.util.CollectionUtils; import org.apache.seata.sqlparser.util.ColumnUtils; import org.apache.seata.sqlparser.ParametersHolder; import org.apache.seata.sqlparser.SQLType; @@ -29,6 +30,7 @@ import org.antlr.v4.runtime.tree.ParseTreeWalker; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -129,4 +131,24 @@ public String getTableName() { public String getOriginalSQL() { return sqlContext.getOriginalSQL(); } + + @Override + public List getWhereColumns() { + List sqls = sqlContext.getUpdateForWhereColumnNames(); + if (CollectionUtils.isNotEmpty(sqls)) { + List list = new ArrayList<>(sqls.size()); + for (MySqlContext.SQL sql : sqls) { + String column = sql.getUpdateWhereColumnName(); + int index = column.indexOf("."); + if (index > 0) { + // table.column -> column name + column = column.substring(index + 1); + } + list.add(column); + } + return list; + } + return Collections.emptyList(); + } + } diff --git a/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/SQLUpdateRecognizer.java b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/SQLUpdateRecognizer.java index da5733a0726..17395d0910f 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/SQLUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/SQLUpdateRecognizer.java @@ -55,4 +55,12 @@ default String getTableAlias(String tableName) { * @return (`a`, `b`, `c`) -> (a, b, c) */ List getUpdateColumnsUnEscape(); + + /** + * Gets update where columns. + * + * @return the update where columns + */ + List getWhereColumns(); + } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/BaseRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/BaseRecognizer.java index 71afd726584..714cabe1c84 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/BaseRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/BaseRecognizer.java @@ -16,16 +16,22 @@ */ package org.apache.seata.sqlparser.druid; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLLimit; +import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLExistsExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLMergeStatement; import com.alibaba.druid.sql.ast.statement.SQLReplaceStatement; @@ -33,6 +39,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.common.util.CollectionUtils; import org.apache.seata.sqlparser.SQLParsingException; import org.apache.seata.sqlparser.SQLRecognizer; @@ -160,4 +167,60 @@ public boolean visit(SQLInsertStatement x) { getAst().accept(visitor); return true; } + + public List getWhereColumns(SQLExpr sqlExpr) { + // single condition + if (sqlExpr instanceof SQLBinaryOpExpr) { + return getWhereColumns(Collections.singletonList(sqlExpr)); + } else { + // multiple conditions + return getWhereColumns(sqlExpr.getChildren()); + } + } + + public List getWhereColumns(List list) { + if (CollectionUtils.isNotEmpty(list)) { + List columns = new ArrayList<>(list.size()); + for (SQLObject sqlObject : list) { + if (sqlObject instanceof SQLIdentifierExpr) { + columns.add(((SQLIdentifierExpr)sqlObject).getName()); + } else { + getWhereColumns(sqlObject, columns); + } + } + return columns; + } + return Collections.emptyList(); + } + + public void getWhereColumns(SQLObject sqlExpr, List list) { + if (sqlExpr instanceof SQLBinaryOpExpr) { + SQLExpr left = ((SQLBinaryOpExpr)sqlExpr).getLeft(); + getWhereColumn(left, list); + SQLExpr right = ((SQLBinaryOpExpr)sqlExpr).getRight(); + getWhereColumn(right, list); + } + } + + public void getWhereColumn(SQLExpr left, List list) { + if (left instanceof SQLBetweenExpr) { + SQLExpr expr = ((SQLBetweenExpr)left).getTestExpr(); + if (expr instanceof SQLIdentifierExpr) { + list.add(((SQLIdentifierExpr)expr).getName()); + } + if (expr instanceof SQLPropertyExpr) { + list.add(((SQLPropertyExpr)expr).getName()); + } + } else if (left instanceof SQLIdentifierExpr) { + list.add(((SQLIdentifierExpr)left).getName()); + } else if (left instanceof SQLInListExpr) { + SQLExpr expr = ((SQLInListExpr)left).getExpr(); + if (expr instanceof SQLIdentifierExpr) { + list.add(((SQLIdentifierExpr)expr).getName()); + } + } else if (left instanceof SQLBinaryOpExpr) { + getWhereColumns(left, list); + } + } + } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/dm/DmUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/dm/DmUpdateRecognizer.java index cd6f0c7a270..4231170bb85 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/dm/DmUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/dm/DmUpdateRecognizer.java @@ -173,6 +173,13 @@ public List getUpdateColumnsUnEscape() { return ColumnUtils.delEscape(updateColumns, getDbType()); } + + @Override + public List getWhereColumns() { + SQLExpr where = ast.getWhere(); + return super.getWhereColumns(where); + } + @Override protected SQLStatement getAst() { return this.ast; diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java index 8eae8c2e740..737aaa18331 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java @@ -249,4 +249,12 @@ public boolean visit(SQLExprTableSource x) { visitor.visit(tableSource); return tableName.toString(); } + + + @Override + public List getWhereColumns() { + SQLExpr where = ast.getWhere(); + return super.getWhereColumns(where); + } + } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java index b5e567a39d2..983855d6c83 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java @@ -176,6 +176,13 @@ public boolean visit(SQLJoinTableSource x) { return sb.toString(); } + + @Override + public List getWhereColumns() { + SQLExpr where = ast.getWhere(); + return super.getWhereColumns(where); + } + @Override protected SQLStatement getAst() { return ast; diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java index 877c00be6f5..b99345628a6 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java @@ -173,6 +173,12 @@ public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList getWhereColumns() { + SQLExpr where = ast.getWhere(); + return super.getWhereColumns(where); + } + @Override protected SQLStatement getAst() { return ast; diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/sqlserver/SqlServerUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/sqlserver/SqlServerUpdateRecognizer.java index 4c674c01290..cbd0dd22a26 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/sqlserver/SqlServerUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/sqlserver/SqlServerUpdateRecognizer.java @@ -201,6 +201,13 @@ public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList getWhereColumns() { + SQLExpr where = ast.getWhere(); + return super.getWhereColumns(where); + } + @Override protected SQLStatement getAst() { return ast; diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java index 02dd7627e29..94257df927a 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java @@ -375,4 +375,34 @@ public void testGetUpdateColumns_2() { Assertions.assertTrue(updateColumn.contains("`")); } } + + @Test + public void testGetWhereColumns() { + String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE t1.id between ? and ? or name1= ? and name2= ?"; + + SQLStatement statement = getSQLStatement(sql); + + MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement); + List whereColumns = mySQLUpdateRecognizer.getWhereColumns(); + Assertions.assertEquals("id", whereColumns.get(0)); + Assertions.assertEquals("name1", whereColumns.get(1)); + Assertions.assertEquals("name2", whereColumns.get(2)); + sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id between ? and ?"; + + statement = getSQLStatement(sql); + + mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement); + whereColumns = mySQLUpdateRecognizer.getWhereColumns(); + Assertions.assertEquals("id", whereColumns.get(0)); + + sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id in(?,? ) and createTime between ? and ?"; + + statement = getSQLStatement(sql); + + mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement); + whereColumns = mySQLUpdateRecognizer.getWhereColumns(); + Assertions.assertEquals("id", whereColumns.get(0)); + Assertions.assertEquals("createTime", whereColumns.get(1)); + } + } From 6cbcff45131b3c46a18bbce1372949631f0a13e2 Mon Sep 17 00:00:00 2001 From: jianbin Date: Mon, 19 Feb 2024 09:28:41 +0800 Subject: [PATCH 2/6] bugfix: the problem that the number of mirrors before and after may be inconsistent --- .../org/apache/seata/sqlparser/SQLUpdateRecognizer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/SQLUpdateRecognizer.java b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/SQLUpdateRecognizer.java index 17395d0910f..325693cd130 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/SQLUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/SQLUpdateRecognizer.java @@ -57,10 +57,10 @@ default String getTableAlias(String tableName) { List getUpdateColumnsUnEscape(); /** - * Gets update where columns. + * Gets where columns. * - * @return the update where columns + * @return the where columns */ - List getWhereColumns(); + List getWhereColumns(); } From 914b8e1f22f37e3c12e51196dbc8f113cee8941b Mon Sep 17 00:00:00 2001 From: jianbin Date: Mon, 19 Feb 2024 09:54:10 +0800 Subject: [PATCH 3/6] bugfix: the problem that the number of mirrors before and after may be inconsistent --- .../seata/rm/datasource/exec/AbstractDMLBaseExecutor.java | 2 +- .../seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java index f0d6fb4a82f..ddcb7124b42 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java @@ -105,7 +105,7 @@ protected T executeAutoCommitFalse(Object[] args) throws Exception { if (updateCount > beforeImage.size()) { String errorMsg = "Before image size is not equaled to after image size, probably because you use read committed, please retry transaction."; - throw new ShouldNeverHappenException(errorMsg); + throw new ShouldNeverHappenException(errorMsg); } } } diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java index 3d3fd79c99a..2c65cdfa10c 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java @@ -20,10 +20,6 @@ import org.apache.seata.rm.datasource.ConnectionContext; import org.apache.seata.rm.datasource.ConnectionProxy; import org.apache.seata.rm.datasource.PreparedStatementProxy; -import org.apache.seata.rm.datasource.exec.AbstractDMLBaseExecutor; -import org.apache.seata.rm.datasource.exec.LockConflictException; -import org.apache.seata.rm.datasource.exec.LockWaitTimeoutException; -import org.apache.seata.rm.datasource.exec.StatementCallback; import org.apache.seata.rm.datasource.exec.mysql.MySQLInsertExecutor; import org.apache.seata.rm.datasource.exec.oracle.OracleInsertExecutor; import org.apache.seata.sqlparser.struct.TableMeta; From c701c9d8d24c032d921b091e187ba3bc91a299ba Mon Sep 17 00:00:00 2001 From: jianbin Date: Mon, 19 Feb 2024 10:36:39 +0800 Subject: [PATCH 4/6] update --- changes/en-us/2.x.md | 1 + changes/zh-cn/2.x.md | 1 + 2 files changed, 2 insertions(+) diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index 08cf23609b9..4e80a5dbd00 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. - [[#6232](https://github.com/apache/incubator-seata/pull/6232)] convert to utf8mb4 if mysql column is json type - [[#6278](https://github.com/apache/incubator-seata/pull/6278)] fix ProtocolV1SerializerTest failed - [[#6324](https://github.com/apache/incubator-seata/pull/6324)] fix Parse protocol file failed +- [[#6348](https://github.com/apache/incubator-seata/pull/6348)] fix the problem that the number of mirrors before and after may be inconsisten ### optimize: diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index 8f850c36acb..e803840ef1f 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -24,6 +24,7 @@ - [[#6232](https://github.com/apache/incubator-seata/pull/6232)] 修复在mysql的json类型下出现Cannot create a JSON value from a string with CHARACTER SET 'binary'问题 - [[#6278](https://github.com/apache/incubator-seata/pull/6278)] 修复 ProtocolV1SerializerTest 失败问题 - [[#6324](https://github.com/apache/incubator-seata/pull/6324)] 修复 Parse protocol file failed +- [[#6348](https://github.com/apache/incubator-seata/pull/6348)] 修复读已提交隔离级别下前镜像可能跟后镜像数据行不同的问题 ### optimize: - [[#6031](https://github.com/apache/incubator-seata/pull/6031)] 添加undo_log表的存在性校验 From f11c64d582a4a85f369de64376718ce0944d318a Mon Sep 17 00:00:00 2001 From: jianbin Date: Mon, 19 Feb 2024 14:08:31 +0800 Subject: [PATCH 5/6] update test case --- .../sql/handler/EscapeHandlerTest.java | 31 +++++++++++++++++++ .../druid/dm/DmUpdateRecognizer.java | 2 +- .../druid/mysql/MySQLUpdateRecognizer.java | 2 +- .../druid/oracle/OracleUpdateRecognizer.java | 2 +- .../PostgresqlUpdateRecognizer.java | 2 +- .../sqlserver/SqlServerUpdateRecognizer.java | 2 +- .../druid/MySQLUpdateRecognizerTest.java | 2 +- 7 files changed, 37 insertions(+), 6 deletions(-) diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/handler/EscapeHandlerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/handler/EscapeHandlerTest.java index 9f8f55e5f29..f73db665e4b 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/handler/EscapeHandlerTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/handler/EscapeHandlerTest.java @@ -125,4 +125,35 @@ public void testInsertColumnsEscape() { Assertions.assertTrue(insertCol.contains("\"")); } } + + + @Test + public void testGetWhereColumns() { + String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE t1.id between ? and ? or `name1`= ? and name2= ?"; + + SQLStatement statement = SQLUtils.parseStatements(sql, "mysql").get(0); + + MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement); + List whereColumns = mySQLUpdateRecognizer.getWhereColumns(); + Assertions.assertEquals("id", whereColumns.get(0)); + Assertions.assertEquals("name1", whereColumns.get(1)); + Assertions.assertEquals("name2", whereColumns.get(2)); + sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id between ? and ?"; + + statement = SQLUtils.parseStatements(sql, "mysql").get(0); + + mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement); + whereColumns = mySQLUpdateRecognizer.getWhereColumns(); + Assertions.assertEquals("id", whereColumns.get(0)); + + sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id in(?,? ) and createTime between ? and ?"; + + statement = SQLUtils.parseStatements(sql, "mysql").get(0); + + mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement); + whereColumns = mySQLUpdateRecognizer.getWhereColumns(); + Assertions.assertEquals("id", whereColumns.get(0)); + Assertions.assertEquals("createTime", whereColumns.get(1)); + } + } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/dm/DmUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/dm/DmUpdateRecognizer.java index 4231170bb85..345333c2ab3 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/dm/DmUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/dm/DmUpdateRecognizer.java @@ -177,7 +177,7 @@ public List getUpdateColumnsUnEscape() { @Override public List getWhereColumns() { SQLExpr where = ast.getWhere(); - return super.getWhereColumns(where); + return ColumnUtils.delEscape(super.getWhereColumns(where), getDbType()); } @Override diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java index 737aaa18331..cf6905b0239 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/mysql/MySQLUpdateRecognizer.java @@ -254,7 +254,7 @@ public boolean visit(SQLExprTableSource x) { @Override public List getWhereColumns() { SQLExpr where = ast.getWhere(); - return super.getWhereColumns(where); + return ColumnUtils.delEscape(super.getWhereColumns(where), getDbType()); } } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java index 983855d6c83..93fe31b90e4 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleUpdateRecognizer.java @@ -180,7 +180,7 @@ public boolean visit(SQLJoinTableSource x) { @Override public List getWhereColumns() { SQLExpr where = ast.getWhere(); - return super.getWhereColumns(where); + return ColumnUtils.delEscape(super.getWhereColumns(where), getDbType()); } @Override diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java index b99345628a6..bb83d093de7 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/postgresql/PostgresqlUpdateRecognizer.java @@ -176,7 +176,7 @@ public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList getWhereColumns() { SQLExpr where = ast.getWhere(); - return super.getWhereColumns(where); + return ColumnUtils.delEscape(super.getWhereColumns(where), getDbType()); } @Override diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/sqlserver/SqlServerUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/sqlserver/SqlServerUpdateRecognizer.java index cbd0dd22a26..2fd6ce03d76 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/sqlserver/SqlServerUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/sqlserver/SqlServerUpdateRecognizer.java @@ -205,7 +205,7 @@ public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList getWhereColumns() { SQLExpr where = ast.getWhere(); - return super.getWhereColumns(where); + return ColumnUtils.delEscape(super.getWhereColumns(where), getDbType()); } @Override diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java index 94257df927a..d8fdefb80b7 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java @@ -378,7 +378,7 @@ public void testGetUpdateColumns_2() { @Test public void testGetWhereColumns() { - String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE t1.id between ? and ? or name1= ? and name2= ?"; + String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE t1.id between ? and ? or `name1`= ? and name2= ?"; SQLStatement statement = getSQLStatement(sql); From 20039b9cf431e5c626a86dd2eb5ac4f0c1ad703d Mon Sep 17 00:00:00 2001 From: jianbin Date: Mon, 19 Feb 2024 15:29:52 +0800 Subject: [PATCH 6/6] update test case --- .../druid/MySQLUpdateRecognizerTest.java | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java index d8fdefb80b7..ad16c5bfea9 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java @@ -376,33 +376,4 @@ public void testGetUpdateColumns_2() { } } - @Test - public void testGetWhereColumns() { - String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE t1.id between ? and ? or `name1`= ? and name2= ?"; - - SQLStatement statement = getSQLStatement(sql); - - MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement); - List whereColumns = mySQLUpdateRecognizer.getWhereColumns(); - Assertions.assertEquals("id", whereColumns.get(0)); - Assertions.assertEquals("name1", whereColumns.get(1)); - Assertions.assertEquals("name2", whereColumns.get(2)); - sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id between ? and ?"; - - statement = getSQLStatement(sql); - - mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement); - whereColumns = mySQLUpdateRecognizer.getWhereColumns(); - Assertions.assertEquals("id", whereColumns.get(0)); - - sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id in(?,? ) and createTime between ? and ?"; - - statement = getSQLStatement(sql); - - mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement); - whereColumns = mySQLUpdateRecognizer.getWhereColumns(); - Assertions.assertEquals("id", whereColumns.get(0)); - Assertions.assertEquals("createTime", whereColumns.get(1)); - } - }