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);
}
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);
}
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);
}
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);
}
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;
}
Aggregations