Search in sources :

Example 1 with TableRecords

use of io.seata.rm.datasource.sql.struct.TableRecords 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 TableRecords

use of io.seata.rm.datasource.sql.struct.TableRecords in project seata by seata.

the class AbstractDMLBaseExecutorTest method initBeforeEach.

@BeforeEach
public void initBeforeEach() throws Exception {
    branchRollbackFlagField = ConnectionProxy.LockRetryPolicy.class.getDeclaredField("LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT");
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(branchRollbackFlagField, branchRollbackFlagField.getModifiers() & ~Modifier.FINAL);
    branchRollbackFlagField.setAccessible(true);
    boolean branchRollbackFlag = (boolean) branchRollbackFlagField.get(null);
    Assertions.assertTrue(branchRollbackFlag);
    Connection targetConnection = Mockito.mock(Connection.class);
    connectionProxy = Mockito.mock(ConnectionProxy.class);
    Mockito.doThrow(new LockConflictException()).when(connectionProxy).commit();
    Mockito.when(connectionProxy.getAutoCommit()).thenReturn(Boolean.TRUE);
    Mockito.when(connectionProxy.getTargetConnection()).thenReturn(targetConnection);
    Mockito.when(connectionProxy.getContext()).thenReturn(new ConnectionContext());
    PreparedStatementProxy statementProxy = Mockito.mock(PreparedStatementProxy.class);
    Mockito.when(statementProxy.getConnectionProxy()).thenReturn(connectionProxy);
    StatementCallback statementCallback = Mockito.mock(StatementCallback.class);
    SQLInsertRecognizer sqlInsertRecognizer = Mockito.mock(SQLInsertRecognizer.class);
    TableMeta tableMeta = Mockito.mock(TableMeta.class);
    executor = Mockito.spy(new MySQLInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer));
    Mockito.doReturn(tableMeta).when(executor).getTableMeta();
    TableRecords tableRecords = new TableRecords();
    Mockito.doReturn(tableRecords).when(executor).beforeImage();
    Mockito.doReturn(tableRecords).when(executor).afterImage(tableRecords);
}
Also used : Connection(java.sql.Connection) ConnectionProxy(io.seata.rm.datasource.ConnectionProxy) TableRecords(io.seata.rm.datasource.sql.struct.TableRecords) Field(java.lang.reflect.Field) MySQLInsertExecutor(io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor) ConnectionContext(io.seata.rm.datasource.ConnectionContext) TableMeta(io.seata.rm.datasource.sql.struct.TableMeta) PreparedStatementProxy(io.seata.rm.datasource.PreparedStatementProxy) SQLInsertRecognizer(io.seata.sqlparser.SQLInsertRecognizer) BeforeEach(org.junit.jupiter.api.BeforeEach)

Example 3 with TableRecords

use of io.seata.rm.datasource.sql.struct.TableRecords in project seata by seata.

the class MySQLInsertExecutorTest method testAfterImage_ByColumn.

@Test
public void testAfterImage_ByColumn() throws SQLException {
    doReturn(true).when(insertExecutor).containsPK();
    Map<String, List<Object>> pkValuesMap = new HashMap<>();
    pkValuesMap.put("id", Arrays.asList(new Object[] { PK_VALUE }));
    doReturn(pkValuesMap).when(insertExecutor).getPkValuesByColumn();
    TableRecords tableRecords = new TableRecords();
    doReturn(tableRecords).when(insertExecutor).buildTableRecords(pkValuesMap);
    doReturn(tableMeta).when(insertExecutor).getTableMeta();
    when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[] { ID_COLUMN }));
    TableRecords resultTableRecords = insertExecutor.afterImage(new TableRecords());
    Assertions.assertEquals(resultTableRecords, tableRecords);
}
Also used : TableRecords(io.seata.rm.datasource.sql.struct.TableRecords) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) List(java.util.List) Mockito.anyString(org.mockito.Mockito.anyString) Test(org.junit.jupiter.api.Test)

Example 4 with TableRecords

use of io.seata.rm.datasource.sql.struct.TableRecords in project seata by seata.

the class PostgresqlUndoInsertExecutor method buildUndoSQL.

@Override
protected String buildUndoSQL() {
    TableRecords afterImage = sqlUndoLog.getAfterImage();
    List<Row> afterImageRows = afterImage.getRows();
    if (CollectionUtils.isEmpty(afterImageRows)) {
        throw new ShouldNeverHappenException("Invalid UNDO LOG");
    }
    return generateDeleteSql(afterImageRows, afterImage);
}
Also used : TableRecords(io.seata.rm.datasource.sql.struct.TableRecords) ShouldNeverHappenException(io.seata.common.exception.ShouldNeverHappenException) Row(io.seata.rm.datasource.sql.struct.Row)

Example 5 with TableRecords

use of io.seata.rm.datasource.sql.struct.TableRecords 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

TableRecords (io.seata.rm.datasource.sql.struct.TableRecords)52 Row (io.seata.rm.datasource.sql.struct.Row)29 Test (org.junit.jupiter.api.Test)25 ArrayList (java.util.ArrayList)23 Field (io.seata.rm.datasource.sql.struct.Field)21 SQLUndoLog (io.seata.rm.datasource.undo.SQLUndoLog)19 TableMeta (io.seata.rm.datasource.sql.struct.TableMeta)14 List (java.util.List)13 ShouldNeverHappenException (io.seata.common.exception.ShouldNeverHappenException)12 SQLException (java.sql.SQLException)9 Collectors (java.util.stream.Collectors)7 CollectionUtils (io.seata.common.util.CollectionUtils)6 ColumnUtils (io.seata.rm.datasource.ColumnUtils)6 AbstractUndoExecutor (io.seata.rm.datasource.undo.AbstractUndoExecutor)6 JdbcConstants (io.seata.sqlparser.util.JdbcConstants)6 SQLRecognizer (io.seata.sqlparser.SQLRecognizer)4 BeforeAll (org.junit.jupiter.api.BeforeAll)4 ConnectionProxy (io.seata.rm.datasource.ConnectionProxy)3 SqlGenerateUtils (io.seata.rm.datasource.SqlGenerateUtils)3 UndoExecutorTest (io.seata.rm.datasource.undo.UndoExecutorTest)3