in core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java [1073:1704]
public boolean parseStatementListDialect(List<SQLStatement> statementList) {
if (lexer.identifierEquals("PREPARE")) {
MySqlPrepareStatement stmt = parsePrepare();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals("DEALLOCATE")) {
MysqlDeallocatePrepareStatement stmt = parseDeallocatePrepare();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals("LOAD")) {
SQLStatement stmt = parseLoad();
statementList.add(stmt);
return true;
}
if (lexer.token() == Token.REPLACE) {
SQLReplaceStatement stmt = parseReplace();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals("START")) {
SQLStartTransactionStatement stmt = parseStart();
statementList.add(stmt);
return true;
}
if (lexer.token() == Token.SHOW) {
SQLStatement stmt = parseShow();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals("CLEAR")) {
lexer.nextToken();
if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals("DDL")) {
// CLEAR DDL CACHE { ALL | <job_id> [ , <job_id> ] ... }
lexer.nextToken();
accept(Token.CACHE);
DrdsClearDDLJobCache stmt = new DrdsClearDDLJobCache();
if (Token.ALL == lexer.token()) {
lexer.nextToken();
stmt.setAllJobs(true);
statementList.add(stmt);
return true;
} else {
while (true) {
stmt.addJobId(lexer.integerValue().longValue());
accept(Token.LITERAL_INT);
if (Token.COMMA == lexer.token()) {
lexer.nextToken();
} else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {
break;
} else {
throw new ParserException("syntax error, expect job id, actual " + lexer.token() + ", " + lexer.info());
}
}
statementList.add(stmt);
return true;
}
}
acceptIdentifier("PLANCACHE");
statementList.add(new MySqlClearPlanCacheStatement());
return true;
}
if (lexer.identifierEquals("DISABLED")) {
lexer.nextToken();
acceptIdentifier("PLANCACHE");
statementList.add(new MySqlDisabledPlanCacheStatement());
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);
return true;
}
if (lexer.identifierEquals(BINLOG)) {
SQLStatement stmt = parseBinlog();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals(RESET)) {
SQLStatement stmt = parseReset();
statementList.add(stmt);
return true;
}
if (lexer.token() == Token.ANALYZE) {
SQLStatement stmt = parseAnalyze();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE)) {
SQLStatement stmt = parseArchive();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.BACKUP)) {
SQLStatement stmt = parseBackup();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.RESTORE)) {
SQLStatement stmt = parseRestore();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals("BUILD")) {
SQLStatement stmt = parseBuildTable();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals("CANCEL")) {
SQLStatement stmt = parseCancelJob();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.EXPORT)) {
lexer.nextToken();
if (lexer.token() == TABLE) {
SQLStatement stmt = parseExportTable();
statementList.add(stmt);
} else if (lexer.token() == Token.DATABASE) {
SQLStatement stmt = parseExportDB();
statementList.add(stmt);
}
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.IMPORT)) {
lexer.nextToken();
if (lexer.token() == TABLE) {
SQLStatement stmt = parseImportTable();
statementList.add(stmt);
} else if (lexer.token() == Token.DATABASE) {
SQLStatement stmt = parseImportDB();
statementList.add(stmt);
}
return true;
}
if (lexer.identifierEquals("SUBMIT")) {
lexer.nextToken();
acceptIdentifier("JOB");
SQLStatement stmt = parseSubmitJob();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.MIGRATE)) {
SQLStatement stmt = parseMigrate();
statementList.add(stmt);
return true;
}
if (lexer.token() == Token.OPTIMIZE) {
SQLStatement stmt = parseOptimize();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals("HELP")) {
lexer.nextToken();
MySqlHelpStatement stmt = new MySqlHelpStatement();
stmt.setContent(this.exprParser.primary());
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals("FLUSH")) {
SQLStatement stmt = parseFlush();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.SYNC)) {
SQLStatement stmt = parseSync();
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.INIT)) {
statementList.add(
new SQLExprStatement(
this.exprParser.expr()));
return true;
}
// DRDS async DDL.
if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(FnvHash.Constants.RECOVER)) {
// RECOVER DDL {ALL | <job_id> [, <job_id>] ...}
lexer.nextToken();
acceptIdentifier("DDL");
DrdsRecoverDDLJob stmt = new DrdsRecoverDDLJob();
if (Token.ALL == lexer.token()) {
lexer.nextToken();
stmt.setAllJobs(true);
statementList.add(stmt);
return true;
} else {
while (true) {
stmt.addJobId(lexer.integerValue().longValue());
accept(Token.LITERAL_INT);
if (Token.COMMA == lexer.token()) {
lexer.nextToken();
} else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {
break;
} else {
throw new ParserException("syntax error, expect job id, actual " + lexer.token() + ", " + lexer.info());
}
}
statementList.add(stmt);
return true;
}
}
if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(FnvHash.Constants.REMOVE)) {
// REMOVE DDL { ALL { COMPLETED | PENDING } | <job_id> [, <job_id>] ...}
lexer.nextToken();
acceptIdentifier("DDL");
DrdsRemoveDDLJob stmt = new DrdsRemoveDDLJob();
if (Token.ALL == lexer.token()) {
lexer.nextToken();
if (lexer.identifierEquals("COMPLETED")) {
lexer.nextToken();
stmt.setAllCompleted(true);
} else if (lexer.identifierEquals("PENDING")) {
lexer.nextToken();
stmt.setAllPending(true);
} else {
throw new ParserException("syntax error, expect COMPLETED or PENDING, actual " + lexer.token() + ", " + lexer.info());
}
} else {
while (true) {
stmt.addJobId(lexer.integerValue().longValue());
accept(Token.LITERAL_INT);
if (Token.COMMA == lexer.token()) {
lexer.nextToken();
} else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {
break;
} else {
throw new ParserException("syntax error, expect job id, actual " + lexer.token() + ", " + lexer.info());
}
}
}
statementList.add(stmt);
return true;
}
if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals("INSPECT")) {
// INSPECT DDL CACHE
lexer.nextToken();
acceptIdentifier("DDL");
accept(Token.CACHE);
statementList.add(new DrdsInspectDDLJobCache());
return true;
}
if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(FnvHash.Constants.CHANGE)) {
// CHANGE DDL <job_id> { SKIP | ADD } <group_and_table_name> [ , <group_and_table_name> ] ...
Lexer.SavePoint mark = lexer.mark();
lexer.nextToken();
if (lexer.identifierEquals("DDL")) {
lexer.nextToken();
DrdsChangeDDLJob stmt = new DrdsChangeDDLJob();
stmt.setJobId(lexer.integerValue().longValue());
accept(Token.LITERAL_INT);
if (lexer.identifierEquals("SKIP")) {
lexer.nextToken();
stmt.setSkip(true);
} else if (lexer.identifierEquals("ADD")) {
lexer.nextToken();
stmt.setAdd(true);
} else {
throw new ParserException("syntax error, expect SKIP or ADD, actual " + lexer.token() + ", " + lexer.info());
}
StringBuilder builder = new StringBuilder();
while (true) {
if (Token.COMMA == lexer.token()) {
lexer.nextToken();
stmt.addGroupAndTableNameList(builder.toString());
builder = new StringBuilder();
} else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {
stmt.addGroupAndTableNameList(builder.toString());
break;
} else if (lexer.token() == Token.COLON) {
builder.append(':');
lexer.nextToken();
} else if (lexer.token() == Token.DOT) {
builder.append('.');
lexer.nextToken();
} else {
builder.append(lexer.stringVal());
lexer.nextToken();
}
}
statementList.add(stmt);
return true;
}
lexer.reset(mark);
}
if (isEnabled(SQLParserFeature.DRDSBaseline) && lexer.identifierEquals("BASELINE")) {
lexer.nextToken();
DrdsBaselineStatement stmt = new DrdsBaselineStatement();
if (Token.EOF == lexer.token() || SEMI == lexer.token() ||
lexer.stringVal().isEmpty() || lexer.stringVal().equalsIgnoreCase("BASELINE")) {
throw new ParserException("syntax error, expect baseline operation, actual " + lexer.token() + ", " + lexer.info());
}
stmt.setOperation(lexer.stringVal());
lexer.setToken(Token.COMMA); // Hack here: Set previous comma to deal with negative number.
lexer.nextToken();
if (lexer.identifierEquals(FnvHash.Constants.SQL)) {
// Parse select.
lexer.nextToken();
if (lexer.token() == Token.HINT) {
stmt.setHeadHints(this.exprParser.parseHints());
}
MySqlSelectParser selectParser = createSQLSelectParser();
stmt.setSelect(selectParser.select());
} else {
// Parse id list.
while (lexer.token() != Token.EOF && lexer.token() != SEMI) {
stmt.addBaselineId(lexer.integerValue().longValue());
accept(Token.LITERAL_INT);
if (Token.COMMA == lexer.token()) {
lexer.nextToken();
}
}
}
statementList.add(stmt);
return true;
}
if (lexer.token() == Token.DESC || lexer.identifierEquals(DESCRIBE)) {
SQLStatement stmt = parseDescribe();
statementList.add(stmt);
return true;
}
if (lexer.token() == Token.LOCK) {
lexer.nextToken();
String val = lexer.stringVal();
boolean isLockTables = TABLES.equalsIgnoreCase(val) && lexer.token() == Token.IDENTIFIER;
boolean isLockTable = "TABLE".equalsIgnoreCase(val) && lexer.token() == TABLE;
if (isLockTables || isLockTable) {
lexer.nextToken();
} else {
setErrorEndPos(lexer.pos());
throw new ParserException("syntax error, expect TABLES or TABLE, actual " + lexer.token() + ", " + lexer.info());
}
MySqlLockTableStatement stmt = new MySqlLockTableStatement();
for (; ; ) {
MySqlLockTableStatement.Item item = new MySqlLockTableStatement.Item();
SQLExprTableSource tableSource = null;
SQLName tableName = this.exprParser.name();
if (lexer.token() == Token.AS) {
lexer.nextToken();
String as = lexer.stringVal();
tableSource = new SQLExprTableSource(tableName, as);
lexer.nextToken();
} else {
tableSource = new SQLExprTableSource(tableName);
}
item.setTableSource(tableSource);
stmt.getItems().add(item);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
if (lexer.identifierEquals(READ)) {
lexer.nextToken();
if (lexer.identifierEquals(LOCAL)) {
lexer.nextToken();
item.setLockType(LockType.READ_LOCAL);
} else {
item.setLockType(LockType.READ);
}
} else if (lexer.identifierEquals(WRITE)) {
lexer.nextToken();
item.setLockType(LockType.WRITE);
} else if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {
lexer.nextToken();
acceptIdentifier(WRITE);
lexer.nextToken();
item.setLockType(LockType.LOW_PRIORITY_WRITE);
} else {
throw new ParserException(
"syntax error, expect READ or WRITE OR AS, actual " + lexer.token() + ", " + lexer.info());
}
if (lexer.token() == Token.HINT) {
item.setHints(this.exprParser.parseHints());
}
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
statementList.add(stmt);
return true;
}
if (lexer.identifierEquals("UNLOCK")) {
lexer.nextToken();
String val = lexer.stringVal();
boolean isUnLockTables = TABLES.equalsIgnoreCase(val) && lexer.token() == Token.IDENTIFIER;
boolean isUnLockTable = "TABLE".equalsIgnoreCase(val) && lexer.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() + ", " + lexer.info());
}
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) {
statementList.add(this.parseChecksum());
return true;
}
if (lexer.token() == Token.HINT) {
List<SQLCommentHint> hints = this.exprParser.parseHints();
boolean tddlHints = false;
boolean accept = false;
boolean acceptHint = false;
switch (lexer.token()) {
case SELECT:
case WITH:
case DELETE:
case UPDATE:
case INSERT:
case SHOW:
case REPLACE:
case TRUNCATE:
case DROP:
case ALTER:
case CREATE:
case CHECK:
case SET:
case DESC:
case OPTIMIZE:
case ANALYZE:
case KILL:
case EXPLAIN:
case LPAREN:
acceptHint = true;
break;
case IDENTIFIER:
acceptHint = lexer.hashLCase() == FnvHash.Constants.DUMP
|| lexer.hashLCase() == FnvHash.Constants.RENAME
|| lexer.hashLCase() == FnvHash.Constants.DESCRIBE;
break;
default:
break;
}
if (hints.size() >= 1
&& statementList.isEmpty()
&& acceptHint) {
SQLCommentHint hint = hints.get(0);
String hintText = hint.getText().toUpperCase();
if (hintText.startsWith("+TDDL")
|| hintText.startsWith("+ TDDL")
|| hintText.startsWith("TDDL")
|| hintText.startsWith("!TDDL")) {
tddlHints = true;
} else if (hintText.startsWith("+")) {
accept = true;
}
}
if (tddlHints) {
SQLStatementImpl stmt = (SQLStatementImpl) this.parseStatement();
stmt.setHeadHints(hints);
statementList.add(stmt);
return true;
} else if (accept) {
SQLStatementImpl stmt = (SQLStatementImpl) this.parseStatement();
stmt.setHeadHints(hints);
statementList.add(stmt);
return true;
}
MySqlHintStatement stmt = new MySqlHintStatement();
stmt.setHints(hints);
statementList.add(stmt);
return true;
}
if (lexer.token() == Token.BEGIN) {
Lexer.SavePoint mark = lexer.mark();
lexer.nextToken();
if (lexer.token() == SEMI || lexer.token() == Token.EOF || lexer.token() == Token.IDENTIFIER) {
lexer.reset(mark);
statementList.add(this.parseTiDBBeginStatment());
return true;
} else {
lexer.reset(mark);
}
statementList.add(this.parseBlock());
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.ADD)) {
statementList.add(parseAddManageInstanceGroup());
return true;
}
if (lexer.token() == Token.IDENTIFIER) {
String label = lexer.stringVal();
Lexer.SavePoint savePoint = lexer.markOut();
lexer.nextToken();
if (lexer.token() == Token.VARIANT && lexer.stringVal().equals(":")) {
lexer.nextToken();
if (lexer.token() == Token.LOOP) {
// parse loop statement
statementList.add(this.parseLoop(label));
} else if (lexer.token() == Token.WHILE) {
// parse while statement with label
statementList.add(this.parseWhile(label));
} else if (lexer.token() == Token.BEGIN) {
// parse begin-end statement with label
SQLBlockStatement block = this.parseBlock(label);
statementList.add(block);
} else if (lexer.token() == Token.REPEAT) {
// parse repeat statement with label
statementList.add(this.parseRepeat(label));
}
return true;
} else {
lexer.reset(savePoint);
}
}
if (lexer.token() == Token.CHECK) {
final Lexer.SavePoint mark = lexer.mark();
lexer.nextToken();
if (lexer.token() == TABLE) {
lexer.nextToken();
MySqlCheckTableStatement stmt = new MySqlCheckTableStatement();
for (; ; ) {
SQLName table = this.exprParser.name();
stmt.addTable(new SQLExprTableSource(table));
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
statementList.add(stmt);
}
return true;
}
String strVal = lexer.stringVal();
if (strVal.equalsIgnoreCase("SPLIT")) {
TidbSplitTableStatement stmt = this.parseTiDBSplitTableStatement();
statementList.add(stmt);
return true;
}
return false;
}