use of io.seata.rm.datasource.sql.struct.TableRecords in project seata by seata.
the class MySQLUndoUpdateExecutor method buildUndoSQL.
/**
* Undo Update.
*
* @return sql
*/
@Override
protected String buildUndoSQL() {
TableRecords beforeImage = sqlUndoLog.getBeforeImage();
List<Row> beforeImageRows = beforeImage.getRows();
if (CollectionUtils.isEmpty(beforeImageRows)) {
// TODO
throw new ShouldNeverHappenException("Invalid UNDO LOG");
}
Row row = beforeImageRows.get(0);
List<Field> nonPkFields = row.nonPrimaryKeys();
// update sql undo log before image all field come from table meta. need add escape.
// see BaseTransactionalExecutor#buildTableRecords
String updateColumns = nonPkFields.stream().map(field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.MYSQL) + " = ?").collect(Collectors.joining(", "));
List<String> pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.MYSQL).stream().map(e -> e.getName()).collect(Collectors.toList());
String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.MYSQL);
return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, whereSql);
}
use of io.seata.rm.datasource.sql.struct.TableRecords in project seata by seata.
the class BaseTransactionalExecutorTest method testBuildLockKey.
@Test
public void testBuildLockKey() {
// build expect data
String tableName = "test_name";
String fieldOne = "1";
String fieldTwo = "2";
String split1 = ":";
String split2 = ",";
String pkColumnName = "id";
// test_name:1,2
String buildLockKeyExpect = tableName + split1 + fieldOne + split2 + fieldTwo;
// mock field
Field field1 = mock(Field.class);
when(field1.getValue()).thenReturn(fieldOne);
Field field2 = mock(Field.class);
when(field2.getValue()).thenReturn(fieldTwo);
List<Map<String, Field>> pkRows = new ArrayList<>();
pkRows.add(Collections.singletonMap(pkColumnName, field1));
pkRows.add(Collections.singletonMap(pkColumnName, field2));
// mock tableMeta
TableMeta tableMeta = mock(TableMeta.class);
when(tableMeta.getTableName()).thenReturn(tableName);
when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[] { pkColumnName }));
// mock tableRecords
TableRecords tableRecords = mock(TableRecords.class);
when(tableRecords.getTableMeta()).thenReturn(tableMeta);
when(tableRecords.size()).thenReturn(pkRows.size());
when(tableRecords.pkRows()).thenReturn(pkRows);
// mock executor
BaseTransactionalExecutor executor = mock(BaseTransactionalExecutor.class);
when(executor.buildLockKey(tableRecords)).thenCallRealMethod();
when(executor.getTableMeta()).thenReturn(tableMeta);
assertThat(executor.buildLockKey(tableRecords)).isEqualTo(buildLockKeyExpect);
}
use of io.seata.rm.datasource.sql.struct.TableRecords in project seata by seata.
the class BaseTransactionalExecutorTest method testBuildLockKeyWithMultiPk.
@Test
public void testBuildLockKeyWithMultiPk() {
// build expect data
String tableName = "test_name";
String pkOneValue1 = "1";
String pkOneValue2 = "2";
String pkTwoValue1 = "one";
String pkTwoValue2 = "two";
String split1 = ":";
String split2 = ",";
String split3 = "_";
String pkOneColumnName = "id";
String pkTwoColumnName = "userId";
// test_name:1_one,2_two
String buildLockKeyExpect = tableName + split1 + pkOneValue1 + split3 + pkTwoValue1 + split2 + pkOneValue2 + split3 + pkTwoValue2;
// mock field
Field pkOneField1 = mock(Field.class);
when(pkOneField1.getValue()).thenReturn(pkOneValue1);
Field pkOneField2 = mock(Field.class);
when(pkOneField2.getValue()).thenReturn(pkOneValue2);
Field pkTwoField1 = mock(Field.class);
when(pkTwoField1.getValue()).thenReturn(pkTwoValue1);
Field pkTwoField2 = mock(Field.class);
when(pkTwoField2.getValue()).thenReturn(pkTwoValue2);
List<Map<String, Field>> pkRows = new ArrayList<>();
Map<String, Field> row1 = new HashMap<String, Field>() {
{
put(pkOneColumnName, pkOneField1);
put(pkTwoColumnName, pkTwoField1);
}
};
pkRows.add(row1);
Map<String, Field> row2 = new HashMap<String, Field>() {
{
put(pkOneColumnName, pkOneField2);
put(pkTwoColumnName, pkTwoField2);
}
};
pkRows.add(row2);
// mock tableMeta
TableMeta tableMeta = mock(TableMeta.class);
when(tableMeta.getTableName()).thenReturn(tableName);
when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[] { pkOneColumnName, pkTwoColumnName }));
// mock tableRecords
TableRecords tableRecords = mock(TableRecords.class);
when(tableRecords.getTableMeta()).thenReturn(tableMeta);
when(tableRecords.size()).thenReturn(pkRows.size());
when(tableRecords.pkRows()).thenReturn(pkRows);
// mock executor
BaseTransactionalExecutor executor = mock(BaseTransactionalExecutor.class);
when(executor.buildLockKey(tableRecords)).thenCallRealMethod();
when(executor.getTableMeta()).thenReturn(tableMeta);
assertThat(executor.buildLockKey(tableRecords)).isEqualTo(buildLockKeyExpect);
}
use of io.seata.rm.datasource.sql.struct.TableRecords in project seata by seata.
the class DeleteExecutorTest method testAfterImage.
@Test
public void testAfterImage() throws SQLException {
TableRecords tableRecords = deleteExecutor.beforeImage();
Assertions.assertEquals(0, deleteExecutor.afterImage(tableRecords).size());
}
use of io.seata.rm.datasource.sql.struct.TableRecords in project seata by seata.
the class MySQLInsertExecutorTest method testAfterImage_Exception.
@Test
public void testAfterImage_Exception() {
Assertions.assertThrows(SQLException.class, () -> {
doReturn(false).when(insertExecutor).containsPK();
doReturn(true).when(insertExecutor).containsColumns();
Map<String, List<Object>> pkValuesMap = new HashMap<>();
pkValuesMap.put("id", Arrays.asList(new Object[] { PK_VALUE }));
doReturn(pkValuesMap).when(insertExecutor).getPkValuesByAuto();
doReturn(null).when(insertExecutor).buildTableRecords(pkValuesMap);
doReturn(tableMeta).when(insertExecutor).getTableMeta();
when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[] { ID_COLUMN }));
insertExecutor.afterImage(new TableRecords());
});
}
Aggregations