Search in sources :

Example 16 with SQLRecognizer

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();
}
Also used : SQLRecognizer(io.seata.sqlparser.SQLRecognizer) SQLUpdateRecognizer(io.seata.sqlparser.SQLUpdateRecognizer) ArrayList(java.util.ArrayList) StringJoiner(java.util.StringJoiner) HashSet(java.util.HashSet)

Example 17 with SQLRecognizer

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);
}
Also used : ArrayList(java.util.ArrayList) SQLUpdateRecognizer(io.seata.sqlparser.SQLUpdateRecognizer) ParametersHolder(io.seata.sqlparser.ParametersHolder) SQLRecognizer(io.seata.sqlparser.SQLRecognizer) ArrayList(java.util.ArrayList) List(java.util.List) TableMeta(io.seata.rm.datasource.sql.struct.TableMeta) NotSupportYetException(io.seata.common.exception.NotSupportYetException) StringJoiner(java.util.StringJoiner) HashSet(java.util.HashSet)

Example 18 with SQLRecognizer

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;
}
Also used : SQLException(java.sql.SQLException) SQLRecognizer(io.seata.sqlparser.SQLRecognizer) StatementProxy(io.seata.rm.datasource.StatementProxy)

Example 19 with SQLRecognizer

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;
}
Also used : TableRecords(io.seata.rm.datasource.sql.struct.TableRecords) SQLRecognizer(io.seata.sqlparser.SQLRecognizer)

Example 20 with SQLRecognizer

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;
}
Also used : TableRecords(io.seata.rm.datasource.sql.struct.TableRecords) SQLRecognizer(io.seata.sqlparser.SQLRecognizer)

Aggregations

SQLRecognizer (io.seata.sqlparser.SQLRecognizer)23 Test (org.junit.jupiter.api.Test)13 SQLDeleteRecognizer (io.seata.sqlparser.SQLDeleteRecognizer)6 SQLStatement (com.alibaba.druid.sql.ast.SQLStatement)4 TableRecords (io.seata.rm.datasource.sql.struct.TableRecords)4 SQLInsertRecognizer (io.seata.sqlparser.SQLInsertRecognizer)4 NotSupportYetException (io.seata.common.exception.NotSupportYetException)3 TableMeta (io.seata.rm.datasource.sql.struct.TableMeta)3 ParametersHolder (io.seata.sqlparser.ParametersHolder)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 Map (java.util.Map)3 StringJoiner (java.util.StringJoiner)3 SQLInsertStatement (com.alibaba.druid.sql.ast.statement.SQLInsertStatement)2 StatementProxy (io.seata.rm.datasource.StatementProxy)2 SQLUpdateRecognizer (io.seata.sqlparser.SQLUpdateRecognizer)2 SQLException (java.sql.SQLException)2 HashSet (java.util.HashSet)2 MockStatement (com.alibaba.druid.mock.MockStatement)1 MockStatementBase (com.alibaba.druid.mock.MockStatementBase)1