From 20290e845f717ecd279a79b18596450fcdd45ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Sat, 12 Dec 2020 15:26:09 +0800 Subject: [PATCH] improved mysq 8 support, support for update skip locked / for share --- .../ast/statement/SQLSelectQueryBlock.java | 22 ++++++++++++- .../mysql/parser/MySqlSelectParser.java | 31 +++++++++++++------ .../mysql/visitor/MySqlOutputVisitor.java | 9 ++++++ .../sql/mysql/visitor/MySqlResourceTest.java | 9 ++++++ src/test/resources/bvt/parser/mysql-18.txt | 8 +++++ src/test/resources/bvt/parser/mysql-19.txt | 6 ++++ 6 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 src/test/resources/bvt/parser/mysql-18.txt create mode 100644 src/test/resources/bvt/parser/mysql-19.txt diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java index 26245e8db9..ebc935497d 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java @@ -53,6 +53,8 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery protected boolean parenthesized = false; protected boolean forUpdate = false; protected boolean noWait = false; + protected boolean skipLocked = false; + protected boolean forShare = false; protected SQLExpr waitTime; protected SQLLimit limit; @@ -534,7 +536,23 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery public void setNoWait(boolean noWait) { this.noWait = noWait; } - + + public boolean isSkipLocked() { + return skipLocked; + } + + public void setSkipLocked(boolean skipLocked) { + this.skipLocked = skipLocked; + } + + public boolean isForShare() { + return forShare; + } + + public void setForShare(boolean forShare) { + this.forShare = forShare; + } + public SQLExpr getWaitTime() { return waitTime; } @@ -986,6 +1004,8 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery x.parenthesized = parenthesized; x.forUpdate = forUpdate; x.noWait = noWait; + x.skipLocked = skipLocked; + x.forShare = forShare; if (waitTime != null) { x.setWaitTime(waitTime.clone()); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java index 05fc9050bf..f1cde216d5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java @@ -292,17 +292,28 @@ public class MySqlSelectParser extends SQLSelectParser { if (lexer.token() == Token.FOR) { lexer.nextToken(); - accept(Token.UPDATE); - queryBlock.setForUpdate(true); - - if (lexer.identifierEquals(FnvHash.Constants.NO_WAIT) || lexer.identifierEquals(FnvHash.Constants.NOWAIT)) { - lexer.nextToken(); - queryBlock.setNoWait(true); - } else if (lexer.identifierEquals(FnvHash.Constants.WAIT)) { - lexer.nextToken(); - SQLExpr waitTime = this.exprParser.primary(); - queryBlock.setWaitTime(waitTime); + if (lexer.token() == Token.UPDATE) { + queryBlock.setForUpdate(true); + + if (lexer.identifierEquals(FnvHash.Constants.NO_WAIT) + || lexer.identifierEquals(FnvHash.Constants.NOWAIT)) { + lexer.nextToken(); + queryBlock.setNoWait(true); + } else if (lexer.identifierEquals(FnvHash.Constants.WAIT)) { + lexer.nextToken(); + SQLExpr waitTime = this.exprParser.primary(); + queryBlock.setWaitTime(waitTime); + } + + if (lexer.identifierEquals(FnvHash.Constants.SKIP)) { + lexer.nextToken(); + acceptIdentifier("LOCKED"); + queryBlock.setSkipLocked(true); + } + } else { + acceptIdentifier("SHARE"); + queryBlock.setForShare(true); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index fba5a274f6..57e757399e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -238,6 +238,15 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? " WAIT " : " wait "); x.getWaitTime().accept(this); } + + if (x.isSkipLocked()) { + print0(ucase ? " SKIP LOCKED" : " skip locked"); + } + } + + if (x.isForShare()) { + println(); + print0(ucase ? "FOR SHARE" : "for share"); } if (x.isLockInShareMode()) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlResourceTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlResourceTest.java index 602a803ee6..6a07cd794d 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlResourceTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlResourceTest.java @@ -58,10 +58,19 @@ public class MySqlResourceTest extends TestCase { public void test_16() throws Exception { exec_test("bvt/parser/mysql-16.txt"); } + public void test_17() throws Exception { exec_test("bvt/parser/mysql-17.txt"); } + public void test_18() throws Exception { + exec_test("bvt/parser/mysql-18.txt"); + } + + public void test_19() throws Exception { + exec_test("bvt/parser/mysql-19.txt"); + } + public void exec_test(String resource) throws Exception { // System.out.println(resource); InputStream is = null; diff --git a/src/test/resources/bvt/parser/mysql-18.txt b/src/test/resources/bvt/parser/mysql-18.txt new file mode 100644 index 0000000000..8cb6aa140a --- /dev/null +++ b/src/test/resources/bvt/parser/mysql-18.txt @@ -0,0 +1,8 @@ +SELECT * FROM table_name WHERE ref = ? AND flag = 0 LIMIT ? FOR UPDATE SKIP LOCKED +--------------------------- +SELECT * +FROM table_name +WHERE ref = ? + AND flag = 0 +LIMIT ? +FOR UPDATE SKIP LOCKED \ No newline at end of file diff --git a/src/test/resources/bvt/parser/mysql-19.txt b/src/test/resources/bvt/parser/mysql-19.txt new file mode 100644 index 0000000000..ba9e617a10 --- /dev/null +++ b/src/test/resources/bvt/parser/mysql-19.txt @@ -0,0 +1,6 @@ +SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE; +--------------------------- +SELECT * +FROM parent +WHERE NAME = 'Jones' +FOR SHARE; \ No newline at end of file