Skip to content

Commit

Permalink
feature: support mysql update join sql (#4914)
Browse files Browse the repository at this point in the history
  • Loading branch information
renliangyu857 authored Oct 18, 2022
1 parent caeb231 commit 7f55c26
Show file tree
Hide file tree
Showing 20 changed files with 895 additions and 117 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
/*
* Copyright 1999-2019 Seata.io Group.
* Copyright 1999-2019 Seata.io Group.
*
* Licensed 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
* Licensed 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
* 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.
* 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 io.seata.discovery.registry;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeSet;
Expand Down Expand Up @@ -205,14 +204,43 @@ protected String getColumnNameInSQL(String columnName) {
return tableAlias == null ? columnName : tableAlias + "." + columnName;
}


/**
* Gets column name with table prefix
*
* @param table the table name
* @param tableAlias the tableAlias
* @param columnName the column name
* @return
*/
protected String getColumnNameWithTablePrefix(String table, String tableAlias, String columnName) {
return tableAlias == null ? (table == null ? columnName : table + "." + columnName) : (tableAlias + "." + columnName);
}

/**
* Gets column name with table prefix
*
* @param table the table name
* @param tableAlias the tableAlias
* @param columnNames the column names
* @return
*/
protected List<String> getColumnNamesWithTablePrefixList(String table,String tableAlias,List<String> columnNames) {
List<String> columnNameWithTablePrefix = new ArrayList<>();
for (String columnName : columnNames) {
columnNameWithTablePrefix.add(this.getColumnNameWithTablePrefix(table,tableAlias,columnName));
}
return columnNameWithTablePrefix;
}

/**
* Gets several column name in sql.
*
* @param columnNameList the column name
* @return the column name in sql
*/
protected String getColumnNamesInSQL(List<String> columnNameList) {
if (Objects.isNull(columnNameList) || columnNameList.isEmpty()) {
if (CollectionUtils.isEmpty(columnNameList)) {
return null;
}
StringBuilder columnNamesStr = new StringBuilder();
Expand All @@ -225,6 +253,28 @@ protected String getColumnNamesInSQL(List<String> columnNameList) {
return columnNamesStr.toString();
}

/**
* Gets several column name in sql.
*
* @param table the table
* @param tableAlias the table alias
* @param columnNameList the column name
* @return the column name in sql
*/
protected String getColumnNamesWithTablePrefix(String table,String tableAlias, List<String> columnNameList) {
if (CollectionUtils.isEmpty(columnNameList)) {
return null;
}
StringBuilder columnNamesStr = new StringBuilder();
for (int i = 0; i < columnNameList.size(); i++) {
if (i > 0) {
columnNamesStr.append(" , ");
}
columnNamesStr.append(getColumnNameWithTablePrefix(table,tableAlias, columnNameList.get(i)));
}
return columnNamesStr.toString();
}

/**
* Gets from table in sql.
*
Expand Down Expand Up @@ -268,13 +318,28 @@ protected TableMeta getTableMeta(String tableName) {
* @return true: contains pk false: not contains pk
*/
protected boolean containsPK(List<String> columns) {
if (columns == null || columns.isEmpty()) {
if (CollectionUtils.isEmpty(columns)) {
return false;
}
List<String> newColumns = ColumnUtils.delEscape(columns, getDbType());
return getTableMeta().containsPK(newColumns);
}

/**
* the columns contains table meta pk
*
* @param tableName the tableName
* @param columns the column name list
* @return true: contains pk false: not contains pk
*/
protected boolean containsPK(String tableName,List<String> columns) {
if (CollectionUtils.isEmpty(columns)) {
return false;
}
List<String> newColumns = ColumnUtils.delEscape(columns, getDbType());
return getTableMeta(tableName).containsPK(newColumns);
}


/**
* compare column name and primary key name
Expand Down Expand Up @@ -384,7 +449,6 @@ protected SQLUndoLog buildUndoItem(TableRecords beforeImage, TableRecords afterI
return sqlUndoLog;
}


/**
* build a BeforeImage
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
import io.seata.core.model.BranchType;
import io.seata.rm.datasource.StatementProxy;
import io.seata.rm.datasource.exec.mysql.MySQLInsertOnDuplicateUpdateExecutor;
import io.seata.rm.datasource.exec.mysql.MySQLUpdateJoinExecutor;
import io.seata.rm.datasource.sql.SQLVisitorFactory;
import io.seata.sqlparser.SQLRecognizer;
import io.seata.sqlparser.SQLType;
import io.seata.sqlparser.util.JdbcConstants;

/**
Expand Down Expand Up @@ -113,6 +115,15 @@ public static <T, S extends Statement> T execute(List<SQLRecognizer> sqlRecogniz
throw new NotSupportYetException(dbType + " not support to INSERT_ON_DUPLICATE_UPDATE");
}
break;
case UPDATE_JOIN:
switch (dbType) {
case JdbcConstants.MYSQL:
executor = new MySQLUpdateJoinExecutor<>(statementProxy,statementCallback,sqlRecognizer);
break;
default:
throw new NotSupportYetException(dbType + " not support to " + SQLType.UPDATE_JOIN.name());
}
break;
default:
executor = new PlainExecutor<>(statementProxy, statementCallback);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
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 All @@ -49,7 +50,7 @@ public class UpdateExecutor<T, S extends Statement> extends AbstractDMLBaseExecu
private static final Configuration CONFIG = ConfigurationFactory.getInstance();

private static final boolean ONLY_CARE_UPDATE_COLUMNS = CONFIG.getBoolean(
ConfigurationKeys.TRANSACTION_UNDO_ONLY_CARE_UPDATE_COLUMNS, DefaultValues.DEFAULT_ONLY_CARE_UPDATE_COLUMNS);
ConfigurationKeys.TRANSACTION_UNDO_ONLY_CARE_UPDATE_COLUMNS, DefaultValues.DEFAULT_ONLY_CARE_UPDATE_COLUMNS);

/**
* Instantiates a new Update executor.
Expand All @@ -59,7 +60,7 @@ public class UpdateExecutor<T, S extends Statement> extends AbstractDMLBaseExecu
* @param sqlRecognizer the sql recognizer
*/
public UpdateExecutor(StatementProxy<S> statementProxy, StatementCallback<T, S> statementCallback,
SQLRecognizer sqlRecognizer) {
SQLRecognizer sqlRecognizer) {
super(statementProxy, statementCallback, sqlRecognizer);
}

Expand All @@ -73,7 +74,6 @@ protected TableRecords beforeImage() throws SQLException {

private String buildBeforeImageSQL(TableMeta tableMeta, ArrayList<List<Object>> paramAppenderList) {
SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) sqlRecognizer;
List<String> updateColumns = recognizer.getUpdateColumnsIsSimplified();
StringBuilder prefix = new StringBuilder("SELECT ");
StringBuilder suffix = new StringBuilder(" FROM ").append(getFromTableInSQL());
String whereCondition = buildWhereCondition(recognizer, paramAppenderList);
Expand All @@ -90,24 +90,9 @@ private String buildBeforeImageSQL(TableMeta tableMeta, ArrayList<List<Object>>
}
suffix.append(" FOR UPDATE");
StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString());
if (ONLY_CARE_UPDATE_COLUMNS) {
if (!containsPK(updateColumns)) {
selectSQLJoin.add(getColumnNamesInSQL(tableMeta.getEscapePkNameList(getDbType())));
}
for (String columnName : updateColumns) {
selectSQLJoin.add(columnName);
}

// 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(updateColumns);
for (String onUpdateColumn : onUpdateColumns) {
selectSQLJoin.add(ColumnUtils.addEscape(onUpdateColumn, getDbType()));
}
} else {
for (String columnName : tableMeta.getAllColumns().keySet()) {
selectSQLJoin.add(ColumnUtils.addEscape(columnName, getDbType()));
}
List<String> needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsIsSimplified());
for (String needUpdateColumn : needUpdateColumns) {
selectSQLJoin.add(needUpdateColumn);
}
return selectSQLJoin.toString();
}
Expand All @@ -134,28 +119,37 @@ private String buildAfterImageSQL(TableMeta tableMeta, TableRecords beforeImage)
String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(tableMeta.getPrimaryKeyOnlyName(), beforeImage.pkRows().size(), getDbType());
String suffix = " FROM " + getFromTableInSQL() + " WHERE " + whereSql;
StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix);
SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) sqlRecognizer;
List<String> needUpdateColumns = getNeedUpdateColumns(tableMeta.getTableName(), sqlRecognizer.getTableAlias(), recognizer.getUpdateColumnsIsSimplified());
for (String needUpdateColumn : needUpdateColumns) {
selectSQLJoiner.add(needUpdateColumn);
}
return selectSQLJoiner.toString();
}

protected List<String> getNeedUpdateColumns(String table, String tableAlias, List<String> originUpdateColumns) {
List<String> needUpdateColumns = new ArrayList<>();
TableMeta tableMeta = getTableMeta(table);
if (ONLY_CARE_UPDATE_COLUMNS) {
SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) sqlRecognizer;
List<String> updateColumns = recognizer.getUpdateColumnsIsSimplified();
if (!containsPK(updateColumns)) {
selectSQLJoiner.add(getColumnNamesInSQL(tableMeta.getEscapePkNameList(getDbType())));
}
for (String columnName : updateColumns) {
selectSQLJoiner.add(columnName);
if (!containsPK(table, originUpdateColumns)) {
List<String> pkNameList = tableMeta.getEscapePkNameList(getDbType());
if (CollectionUtils.isNotEmpty(pkNameList)) {
needUpdateColumns.add(getColumnNamesWithTablePrefix(table,tableAlias,pkNameList));
}
}
needUpdateColumns.addAll(originUpdateColumns);

// 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(updateColumns);
onUpdateColumns.removeAll(originUpdateColumns);
for (String onUpdateColumn : onUpdateColumns) {
selectSQLJoiner.add(ColumnUtils.addEscape(onUpdateColumn, getDbType()));
needUpdateColumns.add(ColumnUtils.addEscape(onUpdateColumn, getDbType()));
}
} else {
for (String columnName : tableMeta.getAllColumns().keySet()) {
selectSQLJoiner.add(ColumnUtils.addEscape(columnName, getDbType()));
needUpdateColumns.add(ColumnUtils.addEscape(columnName, getDbType()));
}
}
return selectSQLJoiner.toString();
return needUpdateColumns;
}

}
}
Loading

0 comments on commit 7f55c26

Please sign in to comment.