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