diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 64ce2ad047..7b2dbc246f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -675,8 +675,16 @@ public class MySqlStatementParser extends SQLStatementParser { if (lexer.token() == Token.LOCK) { lexer.nextToken(); - acceptIdentifier(TABLES); - + String val = lexer.stringVal(); + boolean isLockTables = TABLES.equalsIgnoreCase(val) && lexer.token() == Token.IDENTIFIER; + boolean isLockTable = "TABLE".equalsIgnoreCase(val) && lexer.token() == Token.TABLE; + if (isLockTables || isLockTable) { + lexer.nextToken(); + } else { + setErrorEndPos(lexer.pos()); + throw new ParserException("syntax error, expect TABLES or TABLE, actual " + lexer.token()); + } + MySqlLockTableStatement stmt = new MySqlLockTableStatement(); stmt.setTableSource(this.exprParser.name()); @@ -694,6 +702,8 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); acceptIdentifier(WRITE); stmt.setLockType(LockType.LOW_PRIORITY_WRITE); + } else { + throw new ParserException("syntax error, expect READ or WRITE, actual " + lexer.token()); } if (lexer.token() == Token.HINT) { @@ -705,8 +715,16 @@ public class MySqlStatementParser extends SQLStatementParser { if (identifierEquals("UNLOCK")) { lexer.nextToken(); - acceptIdentifier(TABLES); + String val = lexer.stringVal(); + boolean isUnLockTables = TABLES.equalsIgnoreCase(val) && lexer.token() == Token.IDENTIFIER; + boolean isUnLockTable = "TABLE".equalsIgnoreCase(val) && lexer.token() == Token.TABLE; statementList.add(new MySqlUnlockTablesStatement()); + if (isUnLockTables || isUnLockTable) { + lexer.nextToken(); + } else { + setErrorEndPos(lexer.pos()); + throw new ParserException("syntax error, expect TABLES or TABLE, actual " + lexer.token()); + } return true; } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index cb2a5f3493..5d61b7293e 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -397,13 +397,8 @@ public class Lexer { scanChar(); token = COLONCOLON; } else { - if (isDigit(ch)) { - unscan(); - scanVariable(); - } else { - unscan(); - scanVariable(); - } + unscan(); + scanVariable(); } return; case '#': @@ -455,8 +450,7 @@ public class Lexer { scanVariable(); return; case '-': - int subNextChar = charAt(pos + 1); - if (subNextChar == '-') { + if (charAt(pos +1) == '-') { scanComment(); if ((token() == Token.LINE_COMMENT || token() == Token.MULTI_LINE_COMMENT) && skipComment) { bufPos = 0; 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 11d59be845..d1a02dbf0b 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -306,7 +306,7 @@ public enum Token { TILDE_EQ("~="), QUES("?"), COLON(":"), - COLONCOLON(":"), + COLONCOLON("::"), COLONEQ(":="), EQEQ("=="), LTEQ("<="), diff --git a/src/test/java/com/alibaba/druid/sql/parser/MySQLLockTableTest.java b/src/test/java/com/alibaba/druid/sql/parser/MySQLLockTableTest.java new file mode 100644 index 0000000000..c48a60b325 --- /dev/null +++ b/src/test/java/com/alibaba/druid/sql/parser/MySQLLockTableTest.java @@ -0,0 +1,50 @@ +package com.alibaba.druid.sql.parser; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlLockTableStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlLockTableStatement.LockType; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnlockTablesStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; + +public class MySQLLockTableTest extends TestCase { + + public void testLockTables() { + String stmt1 = "lock tables tt_table read"; + MySqlStatementParser parser1 = new MySqlStatementParser(stmt1); + MySqlLockTableStatement statment1 = (MySqlLockTableStatement) parser1.parseStatement(); + Assert.assertTrue("tt_table".equalsIgnoreCase(statment1.getTableSource().toString())); + Assert.assertTrue(LockType.READ == statment1.getLockType()); + + String stmt2 = "lock tables tt_table write"; + MySqlStatementParser parser2 = new MySqlStatementParser(stmt2); + MySqlLockTableStatement statment2 = (MySqlLockTableStatement) parser2.parseStatement(); + Assert.assertTrue("tt_table".equalsIgnoreCase(statment2.getTableSource().toString())); + Assert.assertTrue(LockType.WRITE == statment2.getLockType()); + + String stmt3 = "lock table tt_table read"; + MySqlStatementParser parser3 = new MySqlStatementParser(stmt3); + MySqlLockTableStatement statment3 = (MySqlLockTableStatement) parser3.parseStatement(); + Assert.assertTrue("tt_table".equalsIgnoreCase(statment3.getTableSource().toString())); + Assert.assertTrue(LockType.READ == statment3.getLockType()); + + String stmt4 = "lock table tt_table write"; + MySqlStatementParser parser4 = new MySqlStatementParser(stmt4); + MySqlLockTableStatement statment4 = (MySqlLockTableStatement) parser4.parseStatement(); + Assert.assertTrue("tt_table".equalsIgnoreCase(statment4.getTableSource().toString())); + Assert.assertTrue(LockType.WRITE == statment4.getLockType()); + } + + public void testUnlockTables() { + String stmt1 = "unlock tables"; + String stmt2 = "unlock table"; + MySqlStatementParser parser1 = new MySqlStatementParser(stmt1); + MySqlStatementParser parser2 = new MySqlStatementParser(stmt2); + MySqlUnlockTablesStatement statment1 = (MySqlUnlockTablesStatement)parser1.parseStatement(); + MySqlUnlockTablesStatement statment2 = (MySqlUnlockTablesStatement)parser2.parseStatement(); + Assert.assertTrue(true); + } + +}