diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlXAStatement.java b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlXAStatement.java new file mode 100644 index 0000000000..b815fc3bb6 --- /dev/null +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlXAStatement.java @@ -0,0 +1,71 @@ +package com.alibaba.druid.sql.dialect.mysql.ast.statement; + +import com.alibaba.druid.DruidRuntimeException; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; + +public class MySqlXAStatement extends MySqlStatementImpl { + private XAType type; + private SQLExpr id; + + public XAType getType() { + return type; + } + + public void setType(XAType type) { + this.type = type; + } + + public SQLExpr getId() { + return id; + } + + public void setId(SQLExpr x) { + if (x != null) { + x.setParent(this); + } + this.id = x; + } + + public void accept0(MySqlASTVisitor v) { + if (v.visit(this)) { + acceptChild(v, id); + } + v.endVisit(this); + } + + public enum XAType { + START, + BEGIN, + END, + PREPARE, + COMMIT, + ROLLBACK, + RECOVER; + + public static XAType of(String typeStr) { + if (typeStr == null || typeStr.isEmpty()) { + return null; + } + + switch (typeStr.toUpperCase()) { + case "START": + return XAType.START; + case "BEGIN": + return XAType.BEGIN; + case "END": + return XAType.END; + case "PREPARE": + return XAType.PREPARE; + case "COMMIT": + return XAType.COMMIT; + case "ROLLBACK": + return XAType.ROLLBACK; + case "RECOVER": + return XAType.RECOVER; + default: + throw new DruidRuntimeException("not support xa type " + typeStr); + } + } + } +} diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 2332d2b6cc..86691b66ef 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -1264,6 +1264,24 @@ public class MySqlStatementParser extends SQLStatementParser { return true; } + if (lexer.identifierEquals("XA")) { + lexer.nextToken(); + MySqlXAStatement stmt = new MySqlXAStatement(); + String typeStr = lexer.stringVal(); + stmt.setType( + MySqlXAStatement.XAType.of(typeStr) + ); + lexer.nextToken(); + + if (lexer.token() != EOF && lexer.token() != SEMI) { + SQLExpr xid = exprParser.expr(); + stmt.setId(xid); + } + + statementList.add(stmt); + return true; + } + if (lexer.token() == Token.EXPLAIN) { SQLStatement stmt = this.parseExplain(); statementList.add(stmt); diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index 2a62533c1a..7d2e8dc71c 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -1267,4 +1267,11 @@ public interface MySqlASTVisitor extends SQLASTVisitor { default void endVisit(MysqlAlterTableAlterCheck x) { } + + default boolean visit(MySqlXAStatement x) { + return true; + } + + default void endVisit(MySqlXAStatement x) { + } } // diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 59141b1e0b..bdf34c793f 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -5553,6 +5553,16 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV return false; } - public void endVisit(MysqlAlterTableAlterCheck x) { + public boolean visit(MySqlXAStatement x) { + print0(ucase ? "XA " : "xa "); + + MySqlXAStatement.XAType type = x.getType(); + print0(ucase ? type.name() : type.name().toLowerCase()); + SQLExpr id = x.getId(); + if (id != null) { + print(' '); + printExpr(id); + } + return false; } } // diff --git a/core/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlResourceTest.java b/core/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlResourceTest.java index 71626304a7..bdcee70cdc 100644 --- a/core/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlResourceTest.java +++ b/core/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlResourceTest.java @@ -126,6 +126,10 @@ public class MySqlResourceTest extends TestCase { exec_test("bvt/parser/mysql-33.txt"); } + public void test_34() throws Exception { + exec_test("bvt/parser/mysql-34.txt"); + } + public void exec_test(String resource) throws Exception { // System.out.println(resource); InputStream is = null; diff --git a/core/src/test/resources/bvt/parser/mysql-34.txt b/core/src/test/resources/bvt/parser/mysql-34.txt new file mode 100644 index 0000000000..e6fb9e745f --- /dev/null +++ b/core/src/test/resources/bvt/parser/mysql-34.txt @@ -0,0 +1,3 @@ +XA PREPARE xid +--------------------------- +XA PREPARE xid \ No newline at end of file