From 9a298fd1af6f6e1eb25a04190329818e601ea47b Mon Sep 17 00:00:00 2001 From: FUNKYE <364176773@qq.com> Date: Tue, 7 Feb 2023 13:31:19 +0800 Subject: [PATCH] bugfix: that keywords don't add escaped characters (#5307) --- changes/en-us/develop.md | 1 + changes/zh-cn/develop.md | 2 +- .../rm/datasource/exec/UpdateExecutor.java | 30 +++++++++---------- .../exec/mysql/MySQLUpdateJoinExecutor.java | 10 ++----- .../datasource/exec/UpdateExecutorTest.java | 16 ++++++++-- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 531aa66ad5a..ae5e4336ca8 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -17,6 +17,7 @@ Add changes here for all PR submitted to the develop branch. - [[#5281](https://github.com/seata/seata/pull/5281)] parallel request handle throw IndexOutOfBoundsException - [[#5288](https://github.com/seata/seata/pull/5288)] fix auto-increment of pk columns in Oracle in AT mode - [[#5287](https://github.com/seata/seata/pull/5287)] fix auto-increment of pk columns in PostgreSQL in AT mode +- [[#5307](https://github.com/seata/seata/pull/5307)] fix that keywords don't add escaped characters ### optimize: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index c2d06243779..f2dce728093 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -17,7 +17,7 @@ - [[#5281](https://github.com/seata/seata/pull/5281)] 修复并行rm请求处理时数组索引越界问题 - [[#5288](https://github.com/seata/seata/pull/5288)] 修复AT模式下oracle的主键列自增的问题 - [[#5287](https://github.com/seata/seata/pull/5287)] 修复AT模式下pgsql的主键列自增的问题 - +- [[#5307](https://github.com/seata/seata/pull/5307)] 修复生成update前后镜像sql不对关键字转义的bug ### optimize: - [[#5208](https://github.com/seata/seata/pull/5208)] 优化多次重复获取Throwable#getCause问题 diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java index 491ea23017b..44dee4eca56 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; import java.util.StringJoiner; +import java.util.stream.Collectors; import io.seata.common.util.IOUtil; import io.seata.common.util.StringUtils; @@ -91,9 +92,7 @@ private String buildBeforeImageSQL(TableMeta tableMeta, ArrayList> suffix.append(" FOR UPDATE"); StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString()); List needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsIsSimplified()); - for (String needUpdateColumn : needUpdateColumns) { - selectSQLJoin.add(needUpdateColumn); - } + needUpdateColumns.forEach(selectSQLJoin::add); return selectSQLJoin.toString(); } @@ -121,34 +120,33 @@ private String buildAfterImageSQL(TableMeta tableMeta, TableRecords beforeImage) StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix); SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) sqlRecognizer; List needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsIsSimplified()); - for (String needUpdateColumn : needUpdateColumns) { - selectSQLJoiner.add(needUpdateColumn); - } + needUpdateColumns.forEach(selectSQLJoiner::add); return selectSQLJoiner.toString(); } - protected List getNeedUpdateColumns(String table, String tableAlias, List originUpdateColumns) { + protected List getNeedUpdateColumns(String table, String tableAlias, List unescapeUpdateColumns) { List needUpdateColumns = new ArrayList<>(); TableMeta tableMeta = getTableMeta(table); if (ONLY_CARE_UPDATE_COLUMNS) { - if (!containsPK(table, originUpdateColumns)) { + if (!containsPK(table, unescapeUpdateColumns)) { List pkNameList = tableMeta.getEscapePkNameList(getDbType()); if (CollectionUtils.isNotEmpty(pkNameList)) { needUpdateColumns.add(getColumnNamesWithTablePrefix(table,tableAlias,pkNameList)); } } - needUpdateColumns.addAll(originUpdateColumns); + needUpdateColumns.addAll(unescapeUpdateColumns.parallelStream() + .map(originUpdateColumn -> ColumnUtils.addEscape(originUpdateColumn, getDbType())) + .collect(Collectors.toList())); // The on update xxx columns will be auto update by db, so it's also the actually updated columns List onUpdateColumns = tableMeta.getOnUpdateColumnsOnlyName(); - onUpdateColumns.removeAll(originUpdateColumns); - for (String onUpdateColumn : onUpdateColumns) { - needUpdateColumns.add(ColumnUtils.addEscape(onUpdateColumn, getDbType())); - } + onUpdateColumns.removeAll(unescapeUpdateColumns); + needUpdateColumns.addAll(onUpdateColumns.parallelStream() + .map(onUpdateColumn -> ColumnUtils.addEscape(onUpdateColumn, getDbType())) + .collect(Collectors.toList())); } else { - for (String columnName : tableMeta.getAllColumns().keySet()) { - needUpdateColumns.add(ColumnUtils.addEscape(columnName, getDbType())); - } + needUpdateColumns.addAll(tableMeta.getAllColumns().keySet().parallelStream() + .map(columnName -> ColumnUtils.addEscape(columnName, getDbType())).collect(Collectors.toList())); } return needUpdateColumns; } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java index 19ba2443548..8077e51078e 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLUpdateJoinExecutor.java @@ -134,9 +134,7 @@ private String buildBeforeImageSQL(String joinTable, String itemTable,String suf suffix.append(buildGroupBy(pkColumnNames,needUpdateColumns)); suffix.append(" FOR UPDATE"); StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString()); - for (String needUpdateColumn : needUpdateColumns) { - selectSQLJoin.add(needUpdateColumn); - } + needUpdateColumns.forEach(selectSQLJoin::add); return selectSQLJoin.toString(); } @@ -203,11 +201,9 @@ private String buildAfterImageSQL(String joinTable, String itemTable, suffix += GROUP_BY; List itemTableUpdateColumns = getItemUpdateColumns(itemTableMeta, recognizer.getUpdateColumns()); List needUpdateColumns = getNeedUpdateColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns); - suffix += buildGroupBy(pkColumns,needUpdateColumns); + suffix += buildGroupBy(pkColumns, needUpdateColumns); StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix); - for (String needUpdateColumn : needUpdateColumns) { - selectSQLJoiner.add(needUpdateColumn); - } + needUpdateColumns.forEach(selectSQLJoiner::add); return selectSQLJoiner.toString(); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java index 33271227073..07d353effe4 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/UpdateExecutorTest.java @@ -49,14 +49,15 @@ public class UpdateExecutorTest { @BeforeAll public static void init() { - List returnValueColumnLabels = Lists.newArrayList("id", "name"); + List returnValueColumnLabels = Lists.newArrayList("id", "name", "all"); Object[][] returnValue = new Object[][] { - new Object[] {1, "Tom"}, - new Object[] {2, "Jack"}, + new Object[] {1, "Tom", "keyword"}, + new Object[] {2, "Jack", "keyword"}, }; Object[][] columnMetas = new Object[][] { new Object[] {"", "", "table_update_executor_test", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, new Object[] {"", "", "table_update_executor_test", "name", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, + new Object[] {"", "", "table_update_executor_test", "all", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, }; Object[][] indexMetas = new Object[][] { new Object[] {"PRIMARY", "id", false, "", 3, 1, "A", 34}, @@ -97,6 +98,15 @@ public void testBeforeImage() throws SQLException { Assertions.assertNotNull(updateExecutor.beforeImage()); } + @Test + public void testKeyword() throws SQLException { + String sql = "update table_update_executor_test set `all` = '1234' where id = 1"; + List asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0)); + updateExecutor = new UpdateExecutor(statementProxy, (statement, args) -> null, recognizer); + Assertions.assertNotNull(updateExecutor.beforeImage()); + } + @Test public void testAfterImage() throws SQLException { TableRecords beforeImage = updateExecutor.beforeImage();