use of io.seata.sqlparser.SQLRecognizer in project seata by seata.
the class MultiUpdateExecutor method buildAfterImageSQL.
private String buildAfterImageSQL(TableMeta tableMeta, TableRecords beforeImage) throws SQLException {
Set<String> updateColumnsSet = new HashSet<>();
for (SQLRecognizer recognizer : sqlRecognizers) {
sqlRecognizer = recognizer;
SQLUpdateRecognizer sqlUpdateRecognizer = (SQLUpdateRecognizer) sqlRecognizer;
updateColumnsSet.addAll(sqlUpdateRecognizer.getUpdateColumns());
}
StringBuilder prefix = new StringBuilder("SELECT ");
String suffix = " FROM " + getFromTableInSQL() + " WHERE " + SqlGenerateUtils.buildWhereConditionByPKs(tableMeta.getPrimaryKeyOnlyName(), beforeImage.pkRows().size(), getDbType());
StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix);
if (ONLY_CARE_UPDATE_COLUMNS) {
if (!containsPK(new ArrayList<>(updateColumnsSet))) {
selectSQLJoiner.add(getColumnNamesInSQL(tableMeta.getEscapePkNameList(getDbType())));
}
for (String updateCol : updateColumnsSet) {
selectSQLJoiner.add(updateCol);
}
} else {
for (String columnName : tableMeta.getAllColumns().keySet()) {
selectSQLJoiner.add(ColumnUtils.addEscape(columnName, getDbType()));
}
}
return selectSQLJoiner.toString();
}
use of io.seata.sqlparser.SQLRecognizer in project seata by seata.
the class MultiUpdateExecutor method beforeImage.
@Override
protected TableRecords beforeImage() throws SQLException {
if (sqlRecognizers.size() == 1) {
UpdateExecutor executor = new UpdateExecutor<>(statementProxy, statementCallback, sqlRecognizers.get(0));
return executor.beforeImage();
}
final TableMeta tmeta = getTableMeta(sqlRecognizers.get(0).getTableName());
final ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
Set<String> updateColumnsSet = new HashSet<>();
StringBuilder whereCondition = new StringBuilder();
boolean noWhereCondition = false;
for (SQLRecognizer recognizer : sqlRecognizers) {
sqlRecognizer = recognizer;
SQLUpdateRecognizer sqlUpdateRecognizer = (SQLUpdateRecognizer) recognizer;
ParametersHolder parametersHolder = statementProxy instanceof ParametersHolder ? (ParametersHolder) statementProxy : null;
if (StringUtils.isNotBlank(sqlUpdateRecognizer.getLimit(parametersHolder, paramAppenderList))) {
throw new NotSupportYetException("Multi update SQL with limit condition is not support yet !");
}
if (StringUtils.isNotBlank(sqlUpdateRecognizer.getOrderBy())) {
throw new NotSupportYetException("Multi update SQL with orderBy condition is not support yet !");
}
List<String> updateColumns = sqlUpdateRecognizer.getUpdateColumns();
updateColumnsSet.addAll(updateColumns);
if (noWhereCondition) {
continue;
}
String whereConditionStr = buildWhereCondition(sqlUpdateRecognizer, paramAppenderList);
if (StringUtils.isBlank(whereConditionStr)) {
noWhereCondition = true;
} else {
if (whereCondition.length() > 0) {
whereCondition.append(" OR ");
}
whereCondition.append(whereConditionStr);
}
}
StringBuilder prefix = new StringBuilder("SELECT ");
final StringBuilder suffix = new StringBuilder(" FROM ").append(getFromTableInSQL());
if (noWhereCondition) {
// select all rows
paramAppenderList.clear();
} else {
suffix.append(" WHERE ").append(whereCondition);
}
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()));
}
}
return buildTableRecords(tmeta, selectSQLAppender.toString(), paramAppenderList);
}
use of io.seata.sqlparser.SQLRecognizer in project seata by seata.
the class ExecuteTemplate method execute.
/**
* Execute t.
*
* @param <T> the type parameter
* @param <S> the type parameter
* @param sqlRecognizers the sql recognizer list
* @param statementProxy the statement proxy
* @param statementCallback the statement callback
* @param args the args
* @return the t
* @throws SQLException the sql exception
*/
public static <T, S extends Statement> T execute(List<SQLRecognizer> sqlRecognizers, StatementProxy<S> statementProxy, StatementCallback<T, S> statementCallback, Object... args) throws SQLException {
if (!RootContext.requireGlobalLock() && BranchType.AT != RootContext.getBranchType()) {
// Just work as original statement
return statementCallback.execute(statementProxy.getTargetStatement(), args);
}
String dbType = statementProxy.getConnectionProxy().getDbType();
if (CollectionUtils.isEmpty(sqlRecognizers)) {
sqlRecognizers = SQLVisitorFactory.get(statementProxy.getTargetSQL(), dbType);
}
Executor<T> executor;
if (CollectionUtils.isEmpty(sqlRecognizers)) {
executor = new PlainExecutor<>(statementProxy, statementCallback);
} else {
if (sqlRecognizers.size() == 1) {
SQLRecognizer sqlRecognizer = sqlRecognizers.get(0);
switch(sqlRecognizer.getSQLType()) {
case INSERT:
executor = EnhancedServiceLoader.load(InsertExecutor.class, dbType, new Class[] { StatementProxy.class, StatementCallback.class, SQLRecognizer.class }, new Object[] { statementProxy, statementCallback, sqlRecognizer });
break;
case UPDATE:
executor = new UpdateExecutor<>(statementProxy, statementCallback, sqlRecognizer);
break;
case DELETE:
executor = new DeleteExecutor<>(statementProxy, statementCallback, sqlRecognizer);
break;
case SELECT_FOR_UPDATE:
executor = new SelectForUpdateExecutor<>(statementProxy, statementCallback, sqlRecognizer);
break;
default:
executor = new PlainExecutor<>(statementProxy, statementCallback);
break;
}
} else {
executor = new MultiExecutor<>(statementProxy, statementCallback, sqlRecognizers);
}
}
T rs;
try {
rs = executor.execute(args);
} catch (Throwable ex) {
if (!(ex instanceof SQLException)) {
// Turn other exception into SQLException
ex = new SQLException(ex);
}
throw (SQLException) ex;
}
return rs;
}
use of io.seata.sqlparser.SQLRecognizer in project seata by seata.
the class MultiExecutor method afterImage.
@Override
protected TableRecords afterImage(TableRecords beforeImage) throws SQLException {
AbstractDMLBaseExecutor<T, S> executor = null;
for (List<SQLRecognizer> value : multiSqlGroup.values()) {
switch(value.get(0).getSQLType()) {
case UPDATE:
executor = new MultiUpdateExecutor<T, S>(statementProxy, statementCallback, value);
break;
case DELETE:
executor = new MultiDeleteExecutor<T, S>(statementProxy, statementCallback, value);
break;
default:
throw new UnsupportedOperationException("not support sql" + value.get(0).getOriginalSQL());
}
beforeImage = beforeImagesMap.get(value.get(0));
TableRecords afterImage = executor.afterImage(beforeImage);
afterImagesMap.put(value.get(0), afterImage);
}
return null;
}
use of io.seata.sqlparser.SQLRecognizer in project seata by seata.
the class MultiExecutor method beforeImage.
/**
* Before image table records. only support update or deleted
*
* @return the table records
* @throws SQLException the sql exception
* @see io.seata.rm.datasource.sql.SQLVisitorFactory#get(String, String) validate sqlType
*/
@Override
protected TableRecords beforeImage() throws SQLException {
// group by sqlType
multiSqlGroup = sqlRecognizers.stream().collect(Collectors.groupingBy(t -> t.getTableName()));
AbstractDMLBaseExecutor<T, S> executor = null;
for (List<SQLRecognizer> value : multiSqlGroup.values()) {
switch(value.get(0).getSQLType()) {
case UPDATE:
executor = new MultiUpdateExecutor<T, S>(statementProxy, statementCallback, value);
break;
case DELETE:
executor = new MultiDeleteExecutor<T, S>(statementProxy, statementCallback, value);
break;
default:
throw new UnsupportedOperationException("not support sql" + value.get(0).getOriginalSQL());
}
TableRecords beforeImage = executor.beforeImage();
beforeImagesMap.put(value.get(0), beforeImage);
}
return null;
}
Aggregations