Skip to content

Commit

Permalink
bugfix: insert executor keywords unescape (#5771)
Browse files Browse the repository at this point in the history
  • Loading branch information
funky-eyes authored Aug 29, 2023
1 parent 17b64fa commit b41a93a
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -486,24 +485,17 @@ protected TableRecords buildTableRecords(TableMeta tableMeta, String selectSQL,
protected TableRecords buildTableRecords(Map<String, List<Object>> pkValuesMap) throws SQLException {
SQLInsertRecognizer recognizer = (SQLInsertRecognizer)sqlRecognizer;
List<String> 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<String> insertColumns = recognizer.getInsertColumns();
if (ONLY_CARE_UPDATE_COLUMNS && CollectionUtils.isNotEmpty(insertColumns)) {
Set<String> 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<String> insertColumnsUnEscape = recognizer.getInsertColumnsUnEscape();
List<String> needColumns =
getNeedColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), insertColumnsUnEscape);
needColumns.forEach(selectSQLJoin::add);
ResultSet rs = null;
try (PreparedStatement ps = statementProxy.getConnection().prepareStatement(selectSQLJoin.toString())) {

Expand All @@ -523,6 +515,37 @@ protected TableRecords buildTableRecords(Map<String, List<Object>> pkValuesMap)
}
}

protected List<String> getNeedColumns(String table, String tableAlias, List<String> unescapeColumns) {
List<String> needUpdateColumns = new ArrayList<>();
TableMeta tableMeta = getTableMeta(table);
if (ONLY_CARE_UPDATE_COLUMNS && CollectionUtils.isNotEmpty(unescapeColumns)) {
if (!containsPK(table, unescapeColumns)) {
List<String> 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<String> 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
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> needColumns =
getNeedColumns(tmeta.getTableName(), sqlRecognizer.getTableAlias(), new ArrayList<>(updateColumnsSet));
needColumns.forEach(selectSQLAppender::add);
return buildTableRecords(tmeta, selectSQLAppender.toString(), paramAppenderList);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,19 @@
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;
import io.seata.config.Configuration;
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.
Expand Down Expand Up @@ -91,7 +88,7 @@ private String buildBeforeImageSQL(TableMeta tableMeta, ArrayList<List<Object>>
}
suffix.append(" FOR UPDATE");
StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString());
List<String> needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsUnEscape());
List<String> needUpdateColumns = getNeedColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsUnEscape());
needUpdateColumns.forEach(selectSQLJoin::add);
return selectSQLJoin.toString();
}
Expand All @@ -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<String> needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsUnEscape());
List<String> needUpdateColumns = getNeedColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsUnEscape());
needUpdateColumns.forEach(selectSQLJoiner::add);
return selectSQLJoiner.toString();
}

protected List<String> getNeedUpdateColumns(String table, String tableAlias, List<String> unescapeUpdateColumns) {
List<String> needUpdateColumns = new ArrayList<>();
TableMeta tableMeta = getTableMeta(table);
if (ONLY_CARE_UPDATE_COLUMNS) {
if (!containsPK(table, unescapeUpdateColumns)) {
List<String> 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<String> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> pkColumnNames = getColumnNamesWithTablePrefixList(itemTable, recognizer.getTableAlias(itemTable), itemTableMeta.getPrimaryKeyOnlyName());
List<String> needUpdateColumns = getNeedUpdateColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns);
List<String> needUpdateColumns = getNeedColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns);
suffix.append(buildGroupBy(pkColumnNames,needUpdateColumns));
suffix.append(" FOR UPDATE");
StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString());
Expand Down Expand Up @@ -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<String> itemTableUpdateColumns = getItemUpdateColumns(itemTableMeta, recognizer.getUpdateColumns());
List<String> needUpdateColumns = getNeedUpdateColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns);
List<String> needUpdateColumns = getNeedColumns(itemTable, recognizer.getTableAlias(itemTable), itemTableUpdateColumns);
suffix += buildGroupBy(pkColumns, needUpdateColumns);
StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix);
needUpdateColumns.forEach(selectSQLJoiner::add);
Expand Down

0 comments on commit b41a93a

Please sign in to comment.