diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReleaseSavePointStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReleaseSavePointStatement.java new file mode 100644 index 0000000000..388473f5ca --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReleaseSavePointStatement.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.sql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLReleaseSavePointStatement extends SQLStatementImpl { + + private static final long serialVersionUID = 1L; + private SQLExpr name; + + public SQLExpr getName() { + return name; + } + + public void setName(SQLExpr name) { + this.name = name; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + } + visitor.endVisit(this); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java index 68bd59770c..e0da7f3583 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java @@ -127,7 +127,6 @@ public class OracleLexer extends Lexer { map.put("ELSE", Token.ELSE); map.put("GOTO", Token.GOTO); map.put("COMMIT", Token.COMMIT); - map.put("ROLLBACK", Token.ROLLBACK); map.put("SAVEPOINT", Token.SAVEPOINT); map.put("CROSS", Token.CROSS); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index 6799aa55d3..6bc911dae6 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -33,7 +33,6 @@ import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLConstaint; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; -import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; @@ -383,20 +382,6 @@ public class OracleStatementParser extends SQLStatementParser { continue; } - if (lexer.token() == Token.ROLLBACK) { - lexer.nextToken(); - - SQLRollbackStatement stmt = new SQLRollbackStatement(); - - if (identifierEquals("TO")) { - lexer.nextToken(); - stmt.setTo(this.exprParser.name()); - } - - statementList.add(stmt); - continue; - } - if (lexer.token() == Token.SAVEPOINT) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java index 6fa1154555..0b870e1b14 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java @@ -16,7 +16,6 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr; -import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java index 872df73f45..8eb1ce6d4a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java @@ -1,7 +1,6 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr; -import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 5fef48c04f..3db6ef8126 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -34,8 +34,8 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableItem; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; -import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; +import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index d00c11c7f8..5f2ac6c9ab 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -16,7 +16,6 @@ import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; -import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLTableSource; diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 2260d695ef..986fd538e7 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -34,6 +34,8 @@ import com.alibaba.druid.sql.ast.statement.SQLDropViewStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLReleaseSavePointStatement; +import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; @@ -166,12 +168,41 @@ public class SQLStatementParser extends SQLParser { continue; } + if (identifierEquals("RELEASE")) { + SQLStatement stmt = parseReleaseSavePoint(); + statementList.add(stmt); + continue; + } + if (identifierEquals("SAVEPOINT")) { SQLStatement stmt = parseSavePoint(); statementList.add(stmt); continue; } + if (identifierEquals("ROLLBACK")) { + lexer.nextToken(); + + if (identifierEquals("WORK")) { + lexer.nextToken(); + } + + SQLRollbackStatement stmt = new SQLRollbackStatement(); + + if (identifierEquals("TO")) { + lexer.nextToken(); + + if (identifierEquals("SAVEPOINT")) { + lexer.nextToken(); + } + + stmt.setTo(this.exprParser.name()); + } + + statementList.add(stmt); + continue; + } + if (parseStatementListDialect(statementList)) { continue; } @@ -206,6 +237,14 @@ public class SQLStatementParser extends SQLParser { return stmt; } + public SQLStatement parseReleaseSavePoint() { + acceptIdentifier("RELEASE"); + acceptIdentifier("SAVEPOINT"); + SQLReleaseSavePointStatement stmt = new SQLReleaseSavePointStatement(); + stmt.setName(this.exprParser.name()); + return stmt; + } + public SQLStatement parseAlter() { accept(Token.ALTER); throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index acb4bd8bb5..3173dfb66a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -160,7 +160,6 @@ public enum Token { LOOP("LOOP"), GOTO("GOTO"), COMMIT("COMMIT"), - ROLLBACK("ROLLBACK"), SAVEPOINT("SAVEPOINT"), CROSS("CROSS"), diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index f1645dce43..62b145ce54 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -69,11 +69,12 @@ import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDropViewStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; -import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; -import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; +import com.alibaba.druid.sql.ast.statement.SQLReleaseSavePointStatement; +import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; +import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; @@ -1072,6 +1073,13 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { return false; } + @Override + public boolean visit(SQLReleaseSavePointStatement x) { + print("RELEASE SAVEPOINT "); + x.getName().accept(this); + return false; + } + @Override public boolean visit(SQLRollbackStatement x) { print("ROLLBACK"); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 1fb26789e5..664c14ead3 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -66,6 +66,7 @@ import com.alibaba.druid.sql.ast.statement.SQLDropViewStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLReleaseSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; @@ -365,4 +366,8 @@ public interface SQLASTVisitor { boolean visit(SQLRollbackStatement x); void endVisit(SQLRollbackStatement x); + + boolean visit(SQLReleaseSavePointStatement x); + + void endVisit(SQLReleaseSavePointStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index 182e6e5e07..7494e81abf 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -67,6 +67,7 @@ import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLReleaseSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; @@ -650,4 +651,13 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { public void endVisit(SQLRollbackStatement x) { } + + @Override + public boolean visit(SQLReleaseSavePointStatement x) { + return true; + } + + @Override + public void endVisit(SQLReleaseSavePointStatement x) { + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/cobar/MTSParserTest.java b/src/test/java/com/alibaba/druid/bvt/sql/cobar/MTSParserTest.java index dc4f907780..0576ce94f3 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/cobar/MTSParserTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/cobar/MTSParserTest.java @@ -8,8 +8,8 @@ import com.alibaba.druid.sql.parser.Token; import junit.framework.Assert; import junit.framework.TestCase; - public class MTSParserTest extends TestCase { + public void test_mts_0() throws Exception { String sql = " savepoint xx"; MySqlStatementParser parser = new MySqlStatementParser(sql); @@ -18,4 +18,58 @@ public class MTSParserTest extends TestCase { String output = SQLUtils.toMySqlString(stmt); Assert.assertEquals("SAVEPOINT xx", output); } + + public void test_mts_1() throws Exception { + String sql = " savepoint SAVEPOINT"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("SAVEPOINT SAVEPOINT", output); + } + + public void test_mts_2() throws Exception { + String sql = " savepoInt `select`"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("SAVEPOINT `select`", output); + } + + public void test_mts_3() throws Exception { + String sql = "Release sAVEPOINT xx "; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("RELEASE SAVEPOINT xx", output); + } + + public void test_rollback_0() throws Exception { + String sql = "rollBack to x1"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ROLLBACK TO x1", output); + } + + public void test_rollback_1() throws Exception { + String sql = "rollBack work to x1"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ROLLBACK TO x1", output); + } + + public void test_rollback_2() throws Exception { + String sql = "rollBack work to savepoint x1"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ROLLBACK TO x1", output); + } }