Search in sources :

Example 1 with SQLRecognizer

use of io.seata.sqlparser.SQLRecognizer in project seata by seata.

the class MultiExecutorTest method testBeforeImageAndAfterImages.

@Test
public void testBeforeImageAndAfterImages() throws SQLException {
    // same table and same type
    String sql = "update table_update_executor_test set name = 'WILL' where id = 1;" + "update table_update_executor_test set name = 'WILL2' where id = 2";
    List<SQLRecognizer> multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL);
    executor = new MultiExecutor(statementProxy, (statement, args) -> {
        return null;
    }, multi);
    TableRecords beforeImage = executor.beforeImage();
    Map multiSqlGroup = executor.getMultiSqlGroup();
    Map beforeImagesMap = executor.getBeforeImagesMap();
    Assertions.assertEquals(multiSqlGroup.size(), 1);
    Assertions.assertEquals(beforeImagesMap.size(), 1);
    TableRecords afterImage = executor.afterImage(beforeImage);
    Assertions.assertEquals(executor.getAfterImagesMap().size(), 1);
    executor.prepareUndoLog(beforeImage, afterImage);
    List<SQLUndoLog> items = connectionProxy.getContext().getUndoItems();
    Assertions.assertTrue(items.stream().allMatch(t -> Objects.equals(t.getSqlType(), SQLType.UPDATE) && Objects.equals(t.getTableName(), "table_update_executor_test")));
    Assertions.assertEquals(items.size(), 1);
    connectionProxy.getContext().reset();
    // same table delete
    sql = "delete from table_update_executor_test where id = 2;" + "delete from table_update_executor_test where id = 3";
    multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL);
    executor = new MultiExecutor(statementProxy, (statement, args) -> {
        return null;
    }, multi);
    beforeImage = executor.beforeImage();
    multiSqlGroup = executor.getMultiSqlGroup();
    beforeImagesMap = executor.getBeforeImagesMap();
    Assertions.assertEquals(multiSqlGroup.size(), 1);
    Assertions.assertEquals(beforeImagesMap.size(), 1);
    afterImage = executor.afterImage(beforeImage);
    Assertions.assertEquals(executor.getAfterImagesMap().size(), 1);
    executor.prepareUndoLog(beforeImage, afterImage);
    items = connectionProxy.getContext().getUndoItems();
    Set<String> itemSet = items.stream().map(t -> t.getTableName()).collect(Collectors.toSet());
    Assertions.assertTrue(itemSet.contains("table_update_executor_test"));
    Assertions.assertEquals(items.size(), 1);
    connectionProxy.getContext().reset();
    // multi table update
    sql = "update table_update_executor_test set name = 'WILL' where id = 1;update table_update_executor_test2 set name = 'WILL' where id = 1;update table_update_executor_test2 set name = 'WILL' where id = 3;";
    multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL);
    executor = new MultiExecutor(statementProxy, (statement, args) -> {
        return null;
    }, multi);
    beforeImage = executor.beforeImage();
    multiSqlGroup = executor.getMultiSqlGroup();
    beforeImagesMap = executor.getBeforeImagesMap();
    Assertions.assertEquals(multiSqlGroup.size(), 2);
    Assertions.assertEquals(beforeImagesMap.size(), 2);
    afterImage = executor.afterImage(beforeImage);
    Assertions.assertEquals(executor.getAfterImagesMap().size(), 2);
    executor.prepareUndoLog(beforeImage, afterImage);
    items = connectionProxy.getContext().getUndoItems();
    itemSet = items.stream().map(t -> t.getTableName()).collect(Collectors.toSet());
    Assertions.assertTrue(itemSet.contains("table_update_executor_test"));
    Assertions.assertTrue(itemSet.contains("table_update_executor_test2"));
    Assertions.assertEquals(items.size(), 2);
    connectionProxy.getContext().reset();
    // multi table delete
    sql = "delete from table_update_executor_test2 where id = 2;delete from table_update_executor_test where id = 3;delete from table_update_executor_test where id = 4;delete from table_update_executor_test";
    multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL);
    executor = new MultiExecutor(statementProxy, (statement, args) -> {
        return null;
    }, multi);
    beforeImage = executor.beforeImage();
    multiSqlGroup = executor.getMultiSqlGroup();
    beforeImagesMap = executor.getBeforeImagesMap();
    Assertions.assertEquals(multiSqlGroup.size(), 2);
    Assertions.assertEquals(beforeImagesMap.size(), 2);
    afterImage = executor.afterImage(beforeImage);
    Assertions.assertEquals(executor.getAfterImagesMap().size(), 2);
    executor.prepareUndoLog(beforeImage, afterImage);
    items = connectionProxy.getContext().getUndoItems();
    itemSet = items.stream().map(t -> t.getTableName()).collect(Collectors.toSet());
    Assertions.assertTrue(itemSet.contains("table_update_executor_test"));
    Assertions.assertTrue(itemSet.contains("table_update_executor_test2"));
    Assertions.assertEquals(items.size(), 2);
    // contains limit delete
    sql = "delete from table_update_executor_test2 where id = 2;delete from table_update_executor_test2 where id = 2 limit 1;";
    multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL);
    executor = new MultiExecutor(statementProxy, (statement, args) -> {
        return null;
    }, multi);
    Assertions.assertThrows(NotSupportYetException.class, executor::beforeImage);
    // contains order by and limit delete
    sql = "delete from table_update_executor_test2 where id = 2;delete from table_update_executor_test2 where id = 2 order by id desc limit 1;";
    multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL);
    executor = new MultiExecutor(statementProxy, (statement, args) -> {
        return null;
    }, multi);
    Assertions.assertThrows(NotSupportYetException.class, executor::beforeImage);
    // contains order by update
    sql = "update table_update_executor_test set name = 'WILL' where id = 1;update table_update_executor_test set name = 'WILL' where id = 1 order by id desc;";
    multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL);
    executor = new MultiExecutor(statementProxy, (statement, args) -> {
        return null;
    }, multi);
    Assertions.assertThrows(NotSupportYetException.class, executor::beforeImage);
    // contains order by and limit update
    sql = "update table_update_executor_test set name = 'WILL' where id = 1;update table_update_executor_test set name = 'WILL' where id = 1 order by id desc limit 1;";
    multi = SQLVisitorFactory.get(sql, JdbcConstants.MYSQL);
    executor = new MultiExecutor(statementProxy, (statement, args) -> {
        return null;
    }, multi);
    Assertions.assertThrows(NotSupportYetException.class, executor::beforeImage);
}
Also used : StatementProxy(io.seata.rm.datasource.StatementProxy) SQLVisitorFactory(io.seata.rm.datasource.sql.SQLVisitorFactory) SQLRecognizer(io.seata.sqlparser.SQLRecognizer) MockStatementBase(com.alibaba.druid.mock.MockStatementBase) SQLType(io.seata.sqlparser.SQLType) SQLException(java.sql.SQLException) Lists(com.google.common.collect.Lists) MockExecuteHandlerImpl(io.seata.rm.datasource.mock.MockExecuteHandlerImpl) ConnectionProxy(io.seata.rm.datasource.ConnectionProxy) BeforeAll(org.junit.jupiter.api.BeforeAll) Map(java.util.Map) DataSourceProxy(io.seata.rm.datasource.DataSourceProxy) MockDriver(io.seata.rm.datasource.mock.MockDriver) SQLUtils(com.alibaba.druid.sql.SQLUtils) Set(java.util.Set) Field(java.lang.reflect.Field) Collectors(java.util.stream.Collectors) TableRecords(io.seata.rm.datasource.sql.struct.TableRecords) NotSupportYetException(io.seata.common.exception.NotSupportYetException) SQLUndoLog(io.seata.rm.datasource.undo.SQLUndoLog) Test(org.junit.jupiter.api.Test) Objects(java.util.Objects) List(java.util.List) MockStatement(com.alibaba.druid.mock.MockStatement) DruidDataSource(com.alibaba.druid.pool.DruidDataSource) JdbcConstants(com.alibaba.druid.util.JdbcConstants) Assertions(org.junit.jupiter.api.Assertions) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) Types(java.sql.Types) TableRecords(io.seata.rm.datasource.sql.struct.TableRecords) SQLRecognizer(io.seata.sqlparser.SQLRecognizer) SQLUndoLog(io.seata.rm.datasource.undo.SQLUndoLog) Map(java.util.Map) Test(org.junit.jupiter.api.Test)

Example 2 with SQLRecognizer

use of io.seata.sqlparser.SQLRecognizer in project seata by seata.

the class DruidSQLRecognizerFactoryImpl method create.

@Override
public List<SQLRecognizer> create(String sql, String dbType) {
    List<SQLStatement> asts = SQLUtils.parseStatements(sql, dbType);
    if (CollectionUtils.isEmpty(asts)) {
        throw new UnsupportedOperationException("Unsupported SQL: " + sql);
    }
    if (asts.size() > 1 && !(asts.stream().allMatch(statement -> statement instanceof SQLUpdateStatement) || asts.stream().allMatch(statement -> statement instanceof SQLDeleteStatement))) {
        throw new UnsupportedOperationException("ONLY SUPPORT SAME TYPE (UPDATE OR DELETE) MULTI SQL -" + sql);
    }
    List<SQLRecognizer> recognizers = null;
    SQLRecognizer recognizer = null;
    for (SQLStatement ast : asts) {
        SQLOperateRecognizerHolder recognizerHolder = SQLOperateRecognizerHolderFactory.getSQLRecognizerHolder(dbType.toLowerCase());
        if (ast instanceof SQLInsertStatement) {
            recognizer = recognizerHolder.getInsertRecognizer(sql, ast);
        } else if (ast instanceof SQLUpdateStatement) {
            recognizer = recognizerHolder.getUpdateRecognizer(sql, ast);
        } else if (ast instanceof SQLDeleteStatement) {
            recognizer = recognizerHolder.getDeleteRecognizer(sql, ast);
        } else if (ast instanceof SQLSelectStatement) {
            recognizer = recognizerHolder.getSelectForUpdateRecognizer(sql, ast);
        }
        if (recognizer != null) {
            if (recognizers == null) {
                recognizers = new ArrayList<>();
            }
            recognizers.add(recognizer);
        }
    }
    return recognizers;
}
Also used : SQLRecognizer(io.seata.sqlparser.SQLRecognizer) SQLDeleteStatement(com.alibaba.druid.sql.ast.statement.SQLDeleteStatement) SQLUpdateStatement(com.alibaba.druid.sql.ast.statement.SQLUpdateStatement) SQLInsertStatement(com.alibaba.druid.sql.ast.statement.SQLInsertStatement) SQLSelectStatement(com.alibaba.druid.sql.ast.statement.SQLSelectStatement) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement)

Example 3 with SQLRecognizer

use of io.seata.sqlparser.SQLRecognizer in project seata by seata.

the class SQLVisitorFactoryTest method testSqlRecognizerLoading.

@Test
public void testSqlRecognizerLoading() {
    List<SQLRecognizer> recognizers = SQLVisitorFactory.get("update t1 set name = 'test' where id = '1'", JdbcConstants.MYSQL);
    Assertions.assertNotNull(recognizers);
    Assertions.assertEquals(recognizers.size(), 1);
    SQLRecognizer recognizer = recognizers.get(0);
    Assertions.assertEquals(SQLType.UPDATE, recognizer.getSQLType());
    Assertions.assertEquals("t1", recognizer.getTableName());
}
Also used : SQLRecognizer(io.seata.sqlparser.SQLRecognizer) Test(org.junit.jupiter.api.Test)

Example 4 with SQLRecognizer

use of io.seata.sqlparser.SQLRecognizer in project seata by seata.

the class PostgresqlInsertRecognizerTest method testGetInsertColumns.

@Test
public void testGetInsertColumns() {
    // test for no column
    String sql = "insert into t values (?)";
    List<SQLRecognizer> sqlRecognizers = SQLVisitorFactory.get(sql, DB_TYPE);
    SQLInsertRecognizer recognizer = (SQLInsertRecognizer) sqlRecognizers.get(0);
    List<String> insertColumns = recognizer.getInsertColumns();
    Assertions.assertNull(insertColumns);
    // test for normal
    sql = "insert into t(a) values (?)";
    recognizer = (SQLInsertRecognizer) SQLVisitorFactory.get(sql, DB_TYPE).get(0);
    insertColumns = recognizer.getInsertColumns();
    Assertions.assertEquals(1, insertColumns.size());
    // test for exception
    Assertions.assertThrows(SQLParsingException.class, () -> {
        String s = "insert into t(a) values (?)";
        List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, DB_TYPE);
        SQLInsertStatement sqlInsertStatement = (SQLInsertStatement) sqlStatements.get(0);
        sqlInsertStatement.getColumns().add(new SQLBetweenExpr());
        PostgresqlInsertRecognizer postgresqlInsertRecognizer = new PostgresqlInsertRecognizer(s, sqlInsertStatement);
        postgresqlInsertRecognizer.getInsertColumns();
    });
}
Also used : SQLRecognizer(io.seata.sqlparser.SQLRecognizer) PostgresqlInsertRecognizer(io.seata.sqlparser.druid.postgresql.PostgresqlInsertRecognizer) SQLInsertStatement(com.alibaba.druid.sql.ast.statement.SQLInsertStatement) SQLBetweenExpr(com.alibaba.druid.sql.ast.expr.SQLBetweenExpr) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) SQLInsertRecognizer(io.seata.sqlparser.SQLInsertRecognizer) Test(org.junit.jupiter.api.Test)

Example 5 with SQLRecognizer

use of io.seata.sqlparser.SQLRecognizer in project seata by seata.

the class PostgresqlDeleteRecognizerTest method testGetWhereCondition_0.

@Test
public void testGetWhereCondition_0() {
    String sql = "delete from t";
    List<SQLRecognizer> sqlRecognizers = SQLVisitorFactory.get(sql, DB_TYPE);
    SQLDeleteRecognizer recognizer = (SQLDeleteRecognizer) sqlRecognizers.get(0);
    String whereCondition = recognizer.getWhereCondition(new ParametersHolder() {

        @Override
        public Map<Integer, ArrayList<Object>> getParameters() {
            return null;
        }
    }, new ArrayList<>());
    // test for no condition
    Assertions.assertEquals("", whereCondition);
}
Also used : ParametersHolder(io.seata.sqlparser.ParametersHolder) SQLRecognizer(io.seata.sqlparser.SQLRecognizer) SQLDeleteRecognizer(io.seata.sqlparser.SQLDeleteRecognizer) Map(java.util.Map) Test(org.junit.jupiter.api.Test)

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