Search in sources :

Example 1 with SQLUndoLog

use of io.seata.rm.datasource.undo.SQLUndoLog 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 SQLUndoLog

use of io.seata.rm.datasource.undo.SQLUndoLog in project seata by seata.

the class ConnectionContextProxyTest method testRemoveSavepoint.

@Test
public void testRemoveSavepoint() {
    Savepoint sp1 = new MockSavepoint();
    connectionContext.appendSavepoint(sp1);
    connectionContext.appendUndoItem(new SQLUndoLog());
    connectionContext.appendLockKey("sp1-lock-key");
    Savepoint sp2 = new MockSavepoint();
    connectionContext.appendSavepoint(sp2);
    Savepoint sp3 = new MockSavepoint();
    connectionContext.appendSavepoint(sp3);
    connectionContext.appendLockKey("sp3-lock-key");
    connectionContext.appendUndoItem(new SQLUndoLog());
    Assertions.assertEquals(connectionContext.getUndoItems().size(), 2);
    Assertions.assertEquals(connectionContext.buildLockKeys(), "sp3-lock-key;sp1-lock-key");
    connectionContext.removeSavepoint(sp3);
    Assertions.assertEquals(connectionContext.getUndoItems().size(), 1);
    Assertions.assertEquals(connectionContext.buildLockKeys(), "sp1-lock-key");
    connectionContext.removeSavepoint(null);
    Assertions.assertEquals(connectionContext.getUndoItems().size(), 0);
    Assertions.assertNull(connectionContext.buildLockKeys());
}
Also used : MockSavepoint(com.alibaba.druid.mock.MockSavepoint) SQLUndoLog(io.seata.rm.datasource.undo.SQLUndoLog) MockSavepoint(com.alibaba.druid.mock.MockSavepoint) Savepoint(java.sql.Savepoint) Test(org.junit.jupiter.api.Test)

Example 3 with SQLUndoLog

use of io.seata.rm.datasource.undo.SQLUndoLog in project seata by seata.

the class ConnectionProxyTest method testLockRetryPolicyNotRollbackOnConflict.

@Test
public void testLockRetryPolicyNotRollbackOnConflict() throws Exception {
    boolean oldBranchRollbackFlag = (boolean) branchRollbackFlagField.get(null);
    branchRollbackFlagField.set(null, false);
    ConnectionProxy connectionProxy = new ConnectionProxy(dataSourceProxy, null);
    connectionProxy.bind(TEST_XID);
    connectionProxy.appendUndoLog(new SQLUndoLog());
    connectionProxy.appendLockKey(lockKey);
    Assertions.assertThrows(LockWaitTimeoutException.class, connectionProxy::commit);
    branchRollbackFlagField.set(null, oldBranchRollbackFlag);
}
Also used : SQLUndoLog(io.seata.rm.datasource.undo.SQLUndoLog) Test(org.junit.jupiter.api.Test)

Example 4 with SQLUndoLog

use of io.seata.rm.datasource.undo.SQLUndoLog in project seata by seata.

the class MySQLUndoLogManagerTest method testFlushUndoLogs.

@Test
public void testFlushUndoLogs() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
    connectionProxy.bind("xid");
    ConnectionContext context = connectionProxy.getContext();
    Method method = context.getClass().getDeclaredMethod("setBranchId", Long.class);
    method.setAccessible(true);
    method.invoke(context, 1L);
    SQLUndoLog undoLogItem = getUndoLogItem(1);
    undoLogItem.setTableName("test");
    Method appendUndoItemMethod = context.getClass().getDeclaredMethod("appendUndoItem", SQLUndoLog.class);
    appendUndoItemMethod.setAccessible(true);
    appendUndoItemMethod.invoke(context, undoLogItem);
    Assertions.assertDoesNotThrow(() -> undoLogManager.flushUndoLogs(connectionProxy));
}
Also used : SQLUndoLog(io.seata.rm.datasource.undo.SQLUndoLog) ConnectionContext(io.seata.rm.datasource.ConnectionContext) Method(java.lang.reflect.Method) Test(org.junit.jupiter.api.Test)

Example 5 with SQLUndoLog

use of io.seata.rm.datasource.undo.SQLUndoLog in project seata by seata.

the class MySQLUndoLogManagerTest method getUndoLogItem.

private SQLUndoLog getUndoLogItem(int size) throws NoSuchFieldException, IllegalAccessException {
    SQLUndoLog sqlUndoLog = new SQLUndoLog();
    sqlUndoLog.setTableName("table_plain_executor_test");
    sqlUndoLog.setSqlType(SQLType.INSERT);
    sqlUndoLog.setTableMeta(tableMeta);
    Field rowsField = TableRecords.class.getDeclaredField("rows");
    rowsField.setAccessible(true);
    List<Row> rows = new ArrayList<>(size);
    for (int i = 0; i < size; i++) {
        Row row = new Row();
        row.add(new io.seata.rm.datasource.sql.struct.Field("id", 1, "value_id_" + i));
        row.add(new io.seata.rm.datasource.sql.struct.Field("name", 1, "value_name_" + i));
        rows.add(row);
    }
    sqlUndoLog.setAfterImage(TableRecords.empty(tableMeta));
    TableRecords afterImage = new TableRecords(tableMeta);
    rowsField.set(afterImage, rows);
    sqlUndoLog.setAfterImage(afterImage);
    return sqlUndoLog;
}
Also used : TableRecords(io.seata.rm.datasource.sql.struct.TableRecords) Field(java.lang.reflect.Field) ArrayList(java.util.ArrayList) SQLUndoLog(io.seata.rm.datasource.undo.SQLUndoLog) Row(io.seata.rm.datasource.sql.struct.Row)

Aggregations

SQLUndoLog (io.seata.rm.datasource.undo.SQLUndoLog)22 TableRecords (io.seata.rm.datasource.sql.struct.TableRecords)13 Test (org.junit.jupiter.api.Test)12 Row (io.seata.rm.datasource.sql.struct.Row)11 ArrayList (java.util.ArrayList)9 TableMeta (io.seata.rm.datasource.sql.struct.TableMeta)6 Field (io.seata.rm.datasource.sql.struct.Field)4 BeforeAll (org.junit.jupiter.api.BeforeAll)4 UndoExecutorTest (io.seata.rm.datasource.undo.UndoExecutorTest)3 Savepoint (java.sql.Savepoint)3 MockSavepoint (com.alibaba.druid.mock.MockSavepoint)2 ShouldNeverHappenException (io.seata.common.exception.ShouldNeverHappenException)2 ConnectionProxy (io.seata.rm.datasource.ConnectionProxy)2 BranchUndoLog (io.seata.rm.datasource.undo.BranchUndoLog)2 SQLType (io.seata.sqlparser.SQLType)2 Field (java.lang.reflect.Field)2 Method (java.lang.reflect.Method)2 SQLException (java.sql.SQLException)2 List (java.util.List)2 Map (java.util.Map)2