use of io.seata.sqlparser.SQLRecognizer 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.sqlparser.SQLRecognizer in project seata by seata.
the class DruidSQLRecognizerFactoryImpl method create.
@Override
public List<SQLRecognizer> create(String sql, String dbType) {
List<SQLStatement> asts = SQLUtils.parseStatements(sql, dbType);
if (CollectionUtils.isEmpty(asts)) {
throw new UnsupportedOperationException("Unsupported SQL: " + sql);
}
if (asts.size() > 1 && !(asts.stream().allMatch(statement -> statement instanceof SQLUpdateStatement) || asts.stream().allMatch(statement -> statement instanceof SQLDeleteStatement))) {
throw new UnsupportedOperationException("ONLY SUPPORT SAME TYPE (UPDATE OR DELETE) MULTI SQL -" + sql);
}
List<SQLRecognizer> recognizers = null;
SQLRecognizer recognizer = null;
for (SQLStatement ast : asts) {
SQLOperateRecognizerHolder recognizerHolder = SQLOperateRecognizerHolderFactory.getSQLRecognizerHolder(dbType.toLowerCase());
if (ast instanceof SQLInsertStatement) {
recognizer = recognizerHolder.getInsertRecognizer(sql, ast);
} else if (ast instanceof SQLUpdateStatement) {
recognizer = recognizerHolder.getUpdateRecognizer(sql, ast);
} else if (ast instanceof SQLDeleteStatement) {
recognizer = recognizerHolder.getDeleteRecognizer(sql, ast);
} else if (ast instanceof SQLSelectStatement) {
recognizer = recognizerHolder.getSelectForUpdateRecognizer(sql, ast);
}
if (recognizer != null) {
if (recognizers == null) {
recognizers = new ArrayList<>();
}
recognizers.add(recognizer);
}
}
return recognizers;
}
use of io.seata.sqlparser.SQLRecognizer in project seata by seata.
the class SQLVisitorFactoryTest method testSqlRecognizerLoading.
@Test
public void testSqlRecognizerLoading() {
List<SQLRecognizer> recognizers = SQLVisitorFactory.get("update t1 set name = 'test' where id = '1'", JdbcConstants.MYSQL);
Assertions.assertNotNull(recognizers);
Assertions.assertEquals(recognizers.size(), 1);
SQLRecognizer recognizer = recognizers.get(0);
Assertions.assertEquals(SQLType.UPDATE, recognizer.getSQLType());
Assertions.assertEquals("t1", recognizer.getTableName());
}
use of io.seata.sqlparser.SQLRecognizer in project seata by seata.
the class PostgresqlInsertRecognizerTest method testGetInsertColumns.
@Test
public void testGetInsertColumns() {
// test for no column
String sql = "insert into t values (?)";
List<SQLRecognizer> sqlRecognizers = SQLVisitorFactory.get(sql, DB_TYPE);
SQLInsertRecognizer recognizer = (SQLInsertRecognizer) sqlRecognizers.get(0);
List<String> insertColumns = recognizer.getInsertColumns();
Assertions.assertNull(insertColumns);
// test for normal
sql = "insert into t(a) values (?)";
recognizer = (SQLInsertRecognizer) SQLVisitorFactory.get(sql, DB_TYPE).get(0);
insertColumns = recognizer.getInsertColumns();
Assertions.assertEquals(1, insertColumns.size());
// test for exception
Assertions.assertThrows(SQLParsingException.class, () -> {
String s = "insert into t(a) values (?)";
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, DB_TYPE);
SQLInsertStatement sqlInsertStatement = (SQLInsertStatement) sqlStatements.get(0);
sqlInsertStatement.getColumns().add(new SQLBetweenExpr());
PostgresqlInsertRecognizer postgresqlInsertRecognizer = new PostgresqlInsertRecognizer(s, sqlInsertStatement);
postgresqlInsertRecognizer.getInsertColumns();
});
}
use of io.seata.sqlparser.SQLRecognizer in project seata by seata.
the class PostgresqlDeleteRecognizerTest method testGetWhereCondition_0.
@Test
public void testGetWhereCondition_0() {
String sql = "delete from t";
List<SQLRecognizer> sqlRecognizers = SQLVisitorFactory.get(sql, DB_TYPE);
SQLDeleteRecognizer recognizer = (SQLDeleteRecognizer) sqlRecognizers.get(0);
String whereCondition = recognizer.getWhereCondition(new ParametersHolder() {
@Override
public Map<Integer, ArrayList<Object>> getParameters() {
return null;
}
}, new ArrayList<>());
// test for no condition
Assertions.assertEquals("", whereCondition);
}
Aggregations