From b41a93a8fffcf4d6fff8b3ff84afb65c8d0132cf Mon Sep 17 00:00:00 2001 From: FUNKYE <364176773@qq.com> Date: Tue, 29 Aug 2023 13:33:30 +0800 Subject: [PATCH] bugfix: insert executor keywords unescape (#5771) --- .../exec/BaseTransactionalExecutor.java | 53 +++++++++++++------ .../datasource/exec/MultiUpdateExecutor.java | 15 ++---- .../rm/datasource/exec/UpdateExecutor.java | 36 ++----------- .../exec/mysql/MySQLUpdateJoinExecutor.java | 4 +- 4 files changed, 47 insertions(+), 61 deletions(-) diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java index 0b8cf57cc4f..303cff94146 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java @@ -22,9 +22,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.StringJoiner; -import java.util.TreeSet; +import java.util.stream.Collectors; import io.seata.common.DefaultValues; import io.seata.common.exception.ShouldNeverHappenException; @@ -486,24 +485,17 @@ protected TableRecords buildTableRecords(TableMeta tableMeta, String selectSQL, protected TableRecords buildTableRecords(Map> pkValuesMap) throws SQLException { SQLInsertRecognizer recognizer = (SQLInsertRecognizer)sqlRecognizer; List pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); - StringBuilder prefix = new StringBuilder("SELECT "); + String prefix = "SELECT "; StringBuilder suffix = new StringBuilder(" FROM ").append(getFromTableInSQL()); // build check sql String firstKey = pkValuesMap.keySet().stream().findFirst().get(); int rowSize = pkValuesMap.get(firstKey).size(); suffix.append(WHERE).append(SqlGenerateUtils.buildWhereConditionByPKs(pkColumnNameList, rowSize, getDbType())); - StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString()); - List insertColumns = recognizer.getInsertColumns(); - if (ONLY_CARE_UPDATE_COLUMNS && CollectionUtils.isNotEmpty(insertColumns)) { - Set columns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - columns.addAll(recognizer.getInsertColumnsUnEscape()); - columns.addAll(pkColumnNameList); - for (String columnName : columns) { - selectSQLJoin.add(columnName); - } - } else { - selectSQLJoin.add(" * "); - } + StringJoiner selectSQLJoin = new StringJoiner(", ", prefix, suffix.toString()); + List insertColumnsUnEscape = recognizer.getInsertColumnsUnEscape(); + List needColumns = + getNeedColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), insertColumnsUnEscape); + needColumns.forEach(selectSQLJoin::add); ResultSet rs = null; try (PreparedStatement ps = statementProxy.getConnection().prepareStatement(selectSQLJoin.toString())) { @@ -523,6 +515,37 @@ protected TableRecords buildTableRecords(Map> pkValuesMap) } } + protected List getNeedColumns(String table, String tableAlias, List unescapeColumns) { + List needUpdateColumns = new ArrayList<>(); + TableMeta tableMeta = getTableMeta(table); + if (ONLY_CARE_UPDATE_COLUMNS && CollectionUtils.isNotEmpty(unescapeColumns)) { + if (!containsPK(table, unescapeColumns)) { + List pkNameList = tableMeta.getEscapePkNameList(getDbType()); + if (CollectionUtils.isNotEmpty(pkNameList)) { + if (StringUtils.isNotBlank(tableAlias)) { + needUpdateColumns.add(getColumnNamesWithTablePrefix(table, tableAlias, pkNameList)); + } else { + needUpdateColumns.add(getColumnNamesInSQL(pkNameList)); + } + } + } + needUpdateColumns.addAll(unescapeColumns.stream() + .map(unescapeUpdateColumn -> ColumnUtils.addEscape(unescapeUpdateColumn, getDbType(), tableMeta)).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(unescapeColumns); + needUpdateColumns.addAll(onUpdateColumns.stream() + .map(onUpdateColumn -> ColumnUtils.addEscape(onUpdateColumn, getDbType(), tableMeta)) + .collect(Collectors.toList())); + } else { + needUpdateColumns.addAll(tableMeta.getAllColumns().keySet().stream() + .map(columnName -> ColumnUtils.addEscape(columnName, getDbType(), tableMeta)).collect(Collectors.toList())); + } + return needUpdateColumns; + } + /** * get db type * diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java index 77ac5bceaae..40a2711cedf 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java @@ -113,18 +113,9 @@ protected TableRecords beforeImage() throws SQLException { } suffix.append(" FOR UPDATE"); final StringJoiner selectSQLAppender = new StringJoiner(", ", prefix, suffix.toString()); - if (ONLY_CARE_UPDATE_COLUMNS) { - if (!containsPK(new ArrayList<>(updateColumnsSet))) { - selectSQLAppender.add(getColumnNamesInSQL(tmeta.getEscapePkNameList(getDbType()))); - } - for (String updateCol : updateColumnsSet) { - selectSQLAppender.add(updateCol); - } - } else { - for (String columnName : tmeta.getAllColumns().keySet()) { - selectSQLAppender.add(ColumnUtils.addEscape(columnName, getDbType())); - } - } + List needColumns = + getNeedColumns(tmeta.getTableName(), sqlRecognizer.getTableAlias(), new ArrayList<>(updateColumnsSet)); + needColumns.forEach(selectSQLAppender::add); return buildTableRecords(tmeta, selectSQLAppender.toString(), paramAppenderList); } 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 17c83f44997..9729213c17f 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,7 +22,6 @@ 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; @@ -30,14 +29,12 @@ import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import io.seata.common.DefaultValues; -import io.seata.sqlparser.util.ColumnUtils; import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.StatementProxy; import io.seata.sqlparser.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.SQLUpdateRecognizer; -import io.seata.common.util.CollectionUtils; /** * The type Update executor. @@ -91,7 +88,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.getUpdateColumnsUnEscape()); + List needUpdateColumns = getNeedColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsUnEscape()); needUpdateColumns.forEach(selectSQLJoin::add); return selectSQLJoin.toString(); } @@ -114,39 +111,14 @@ protected TableRecords afterImage(TableRecords beforeImage) throws SQLException } private String buildAfterImageSQL(TableMeta tableMeta, TableRecords beforeImage) throws SQLException { - StringBuilder prefix = new StringBuilder("SELECT "); + String prefix = "SELECT "; String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(tableMeta.getPrimaryKeyOnlyName(), beforeImage.pkRows().size(), getDbType()); String suffix = " FROM " + getFromTableInSQL() + " WHERE " + whereSql; - StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix); + StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix, suffix); SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) sqlRecognizer; - List needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsUnEscape()); + List needUpdateColumns = getNeedColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsUnEscape()); needUpdateColumns.forEach(selectSQLJoiner::add); return selectSQLJoiner.toString(); } - 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, unescapeUpdateColumns)) { - List pkNameList = tableMeta.getEscapePkNameList(getDbType()); - if (CollectionUtils.isNotEmpty(pkNameList)) { - needUpdateColumns.add(getColumnNamesWithTablePrefix(table,tableAlias,pkNameList)); - } - } - needUpdateColumns.addAll(unescapeUpdateColumns.stream() - .map(unescapeUpdateColumn -> ColumnUtils.addEscape(unescapeUpdateColumn, getDbType(), tableMeta)).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(unescapeUpdateColumns); - needUpdateColumns.addAll(onUpdateColumns.stream() - .map(onUpdateColumn -> ColumnUtils.addEscape(onUpdateColumn, getDbType(), tableMeta)) - .collect(Collectors.toList())); - } else { - needUpdateColumns.addAll(tableMeta.getAllColumns().keySet().stream() - .map(columnName -> ColumnUtils.addEscape(columnName, getDbType(), tableMeta)).collect(Collectors.toList())); - } - return needUpdateColumns; - } } \ No newline at end of file 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 52f8eeb860c..68572533a3e 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 @@ -130,7 +130,7 @@ private String buildBeforeImageSQL(String joinTable, String itemTable,String suf //maybe duplicate row for select join sql.remove duplicate row by 'group by' condition suffix.append(GROUP_BY); List pkColumnNames = getColumnNamesWithTablePrefixList(itemTable, recognizer.getTableAlias(itemTable), itemTableMeta.getPrimaryKeyOnlyName()); - List needUpdateColumns = getNeedUpdateColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns); + List needUpdateColumns = getNeedColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns); suffix.append(buildGroupBy(pkColumnNames,needUpdateColumns)); suffix.append(" FOR UPDATE"); StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString()); @@ -200,7 +200,7 @@ private String buildAfterImageSQL(String joinTable, String itemTable, //maybe duplicate row for select join sql.remove duplicate row by 'group by' condition suffix += GROUP_BY; List itemTableUpdateColumns = getItemUpdateColumns(itemTableMeta, recognizer.getUpdateColumns()); - List needUpdateColumns = getNeedUpdateColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns); + List needUpdateColumns = getNeedColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns); suffix += buildGroupBy(pkColumns, needUpdateColumns); StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix); needUpdateColumns.forEach(selectSQLJoiner::add);