/* * Copyright 1999-2011 Alibaba Group Holding Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.druid.sql.parser; import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLListExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddColumn; import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddConstraint; import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddIndex; import com.alibaba.druid.sql.ast.statement.SQLAlterTableAlterColumn; import com.alibaba.druid.sql.ast.statement.SQLAlterTableDisableConstraint; import com.alibaba.druid.sql.ast.statement.SQLAlterTableDisableKeys; import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropColumnItem; import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropConstraint; import com.alibaba.druid.sql.ast.statement.SQLAlterTableEnableConstraint; import com.alibaba.druid.sql.ast.statement.SQLAlterTableEnableKeys; import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCommentStatement; import com.alibaba.druid.sql.ast.statement.SQLConstaint; import com.alibaba.druid.sql.ast.statement.SQLCreateDatabaseStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerEvent; import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType; import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLDropDatabaseStatement; import com.alibaba.druid.sql.ast.statement.SQLDropFunctionStatement; import com.alibaba.druid.sql.ast.statement.SQLDropIndexStatement; import com.alibaba.druid.sql.ast.statement.SQLDropProcedureStatement; import com.alibaba.druid.sql.ast.statement.SQLDropSequenceStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableSpaceStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTriggerStatement; import com.alibaba.druid.sql.ast.statement.SQLDropUserStatement; import com.alibaba.druid.sql.ast.statement.SQLDropViewStatement; import com.alibaba.druid.sql.ast.statement.SQLExplainStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLGrantStatement; import com.alibaba.druid.sql.ast.statement.SQLGrantStatement.ObjectType; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey; 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.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.ast.statement.SQLUseStatement; import com.alibaba.druid.sql.dialect.odps.parser.OdpsSelectParser; public class SQLStatementParser extends SQLParser { protected SQLExprParser exprParser; public SQLStatementParser(String sql){ this(new SQLExprParser(sql)); } public SQLStatementParser(SQLExprParser exprParser){ super(exprParser.getLexer()); this.exprParser = exprParser; } public SQLExprParser getExprParser() { return exprParser; } public List parseStatementList() { List statementList = new ArrayList(); parseStatementList(statementList); return statementList; } public void parseStatementList(List statementList) { parseStatementList(statementList, -1); } public void parseStatementList(List statementList, int max) { for (;;) { if (max != -1) { if (statementList.size() >= max) { return; } } if (lexer.token() == Token.EOF) { return; } if (lexer.token() == (Token.SEMI)) { lexer.nextToken(); continue; } if (lexer.token() == Token.SELECT) { statementList.add(parseSelect()); continue; } if (lexer.token() == (Token.UPDATE)) { statementList.add(parseUpdateStatement()); continue; } if (lexer.token() == (Token.CREATE)) { statementList.add(parseCreate()); continue; } if (lexer.token() == (Token.INSERT)) { SQLStatement insertStatement = parseInsert(); statementList.add(insertStatement); continue; } if (lexer.token() == (Token.DELETE)) { statementList.add(parseDeleteStatement()); continue; } if (lexer.token() == (Token.EXPLAIN)) { statementList.add(parseExplain()); continue; } if (lexer.token() == Token.SET) { statementList.add(parseSet()); continue; } if (lexer.token() == Token.ALTER) { statementList.add(parseAlter()); continue; } if (lexer.token() == Token.DROP) { lexer.nextToken(); if (lexer.token() == Token.TABLE || identifierEquals("TEMPORARY")) { SQLDropTableStatement stmt = parseDropTable(false); statementList.add(stmt); continue; } else if (lexer.token() == Token.USER) { SQLStatement stmt = parseDropUser(); statementList.add(stmt); continue; } else if (lexer.token() == Token.INDEX) { SQLStatement stmt = parseDropIndex(); statementList.add(stmt); continue; } else if (lexer.token() == Token.VIEW) { SQLStatement stmt = parseDropView(false); statementList.add(stmt); continue; } else if (lexer.token() == Token.TRIGGER) { SQLStatement stmt = parseDropTrigger(false); statementList.add(stmt); continue; } else if (lexer.token() == Token.DATABASE) { SQLStatement stmt = parseDropDatabase(false); statementList.add(stmt); continue; } else if (lexer.token() == Token.FUNCTION) { SQLStatement stmt = parseDropFunction(false); statementList.add(stmt); continue; } else if (lexer.token() == Token.TABLESPACE) { SQLStatement stmt = parseDropTablespace(false); statementList.add(stmt); continue; } else if (lexer.token() == Token.PROCEDURE) { SQLStatement stmt = parseDropProcedure(false); statementList.add(stmt); continue; } else { throw new ParserException("TODO " + lexer.token()); } } if (lexer.token() == Token.TRUNCATE) { SQLStatement stmt = parseTruncate(); statementList.add(stmt); continue; } if (lexer.token() == Token.USE) { SQLStatement stmt = parseUse(); statementList.add(stmt); continue; } if (lexer.token() == Token.GRANT) { SQLStatement stmt = parseGrant(); statementList.add(stmt); continue; } if (lexer.token() == Token.LBRACE || identifierEquals("CALL")) { SQLCallStatement stmt = parseCall(); statementList.add(stmt); continue; } if (identifierEquals("RENAME")) { SQLStatement stmt = parseRename(); statementList.add(stmt); continue; } if (identifierEquals("RELEASE")) { SQLStatement stmt = parseReleaseSavePoint(); statementList.add(stmt); continue; } if (identifierEquals("SAVEPOINT")) { SQLStatement stmt = parseSavePoint(); statementList.add(stmt); continue; } if (identifierEquals("ROLLBACK")) { SQLRollbackStatement stmt = parseRollback(); statementList.add(stmt); continue; } if (identifierEquals("COMMIT")) { SQLStatement stmt = parseCommit(); statementList.add(stmt); continue; } if (lexer.token() == Token.SHOW) { SQLStatement stmt = parseShow(); statementList.add(stmt); continue; } if (lexer.token() == Token.LPAREN) { char markChar = lexer.current(); int markBp = lexer.bp(); lexer.nextToken(); if (lexer.token() == Token.SELECT) { lexer.reset(markBp, markChar, Token.LPAREN); SQLStatement stmt = parseSelect(); statementList.add(stmt); continue; } } if (parseStatementListDialect(statementList)) { continue; } if (lexer.token() == Token.COMMENT) { statementList.add(this.parseComment()); continue; } // throw new ParserException("syntax error, " + lexer.token() + " " // + lexer.stringVal() + ", pos " // + lexer.pos()); printError(lexer.token()); } } public SQLRollbackStatement parseRollback() { lexer.nextToken(); if (identifierEquals("WORK")) { lexer.nextToken(); } SQLRollbackStatement stmt = new SQLRollbackStatement(); if (lexer.token() == Token.TO) { lexer.nextToken(); if (identifierEquals("SAVEPOINT")) { lexer.nextToken(); } stmt.setTo(this.exprParser.name()); } return stmt; } public SQLStatement parseCommit() { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } public SQLStatement parseShow() { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } public SQLUseStatement parseUse() { accept(Token.USE); SQLUseStatement stmt = new SQLUseStatement(); stmt.setDatabase(this.exprParser.name()); return stmt; } public SQLGrantStatement parseGrant() { accept(Token.GRANT); SQLGrantStatement stmt = new SQLGrantStatement(); for (;;) { String privilege = null; if (lexer.token() == Token.ALL) { lexer.nextToken(); if (identifierEquals("PRIVILEGES")) { privilege = "ALL PRIVILEGES"; } else { privilege = "ALL"; } } else if (lexer.token() == Token.SELECT) { privilege = "SELECT"; lexer.nextToken(); } else if (lexer.token() == Token.UPDATE) { privilege = "UPDATE"; lexer.nextToken(); } else if (lexer.token() == Token.DELETE) { privilege = "DELETE"; lexer.nextToken(); } else if (lexer.token() == Token.INSERT) { privilege = "INSERT"; lexer.nextToken(); } else if (lexer.token() == Token.INDEX) { lexer.nextToken(); privilege = "INDEX"; } else if (lexer.token() == Token.TRIGGER) { lexer.nextToken(); privilege = "TRIGGER"; } else if (lexer.token() == Token.REFERENCES) { privilege = "REFERENCES"; lexer.nextToken(); } else if (lexer.token() == Token.CREATE) { lexer.nextToken(); if (lexer.token() == Token.TABLE) { privilege = "CREATE TABLE"; lexer.nextToken(); } else if (lexer.token() == Token.SESSION) { privilege = "CREATE SESSION"; lexer.nextToken(); } else if (lexer.token() == Token.TABLESPACE) { privilege = "CREATE TABLESPACE"; lexer.nextToken(); } else if (lexer.token() == Token.USER) { privilege = "CREATE USER"; lexer.nextToken(); } else if (lexer.token() == Token.VIEW) { privilege = "CREATE VIEW"; lexer.nextToken(); } else if (lexer.token() == Token.ANY) { lexer.nextToken(); if (lexer.token() == Token.TABLE) { lexer.nextToken(); privilege = "CREATE ANY TABLE"; } else if (identifierEquals("MATERIALIZED")) { lexer.nextToken(); accept(Token.VIEW); privilege = "CREATE ANY MATERIALIZED VIEW"; } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } else if (identifierEquals("SYNONYM")) { privilege = "CREATE SYNONYM"; lexer.nextToken(); } else if (identifierEquals("ROUTINE")) { privilege = "CREATE ROUTINE"; lexer.nextToken(); } else if (identifierEquals("TEMPORARY")) { lexer.nextToken(); accept(Token.TABLE); privilege = "CREATE TEMPORARY TABLE"; } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } else if (lexer.token() == Token.ALTER) { lexer.nextToken(); if (lexer.token() == Token.TABLE) { privilege = "ALTER TABLE"; lexer.nextToken(); } else if (lexer.token() == Token.SESSION) { privilege = "ALTER SESSION"; lexer.nextToken(); } else if (lexer.token() == Token.ANY) { lexer.nextToken(); if (lexer.token() == Token.TABLE) { lexer.nextToken(); privilege = "ALTER ANY TABLE"; } else if (identifierEquals("MATERIALIZED")) { lexer.nextToken(); accept(Token.VIEW); privilege = "ALTER ANY MATERIALIZED VIEW"; } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } else if (lexer.token() == Token.DROP) { lexer.nextToken(); if (lexer.token() == Token.DROP) { privilege = "DROP TABLE"; lexer.nextToken(); } else if (lexer.token() == Token.SESSION) { privilege = "DROP SESSION"; lexer.nextToken(); } else if (lexer.token() == Token.ANY) { lexer.nextToken(); if (lexer.token() == Token.TABLE) { lexer.nextToken(); privilege = "DROP ANY TABLE"; } else if (identifierEquals("MATERIALIZED")) { lexer.nextToken(); accept(Token.VIEW); privilege = "DROP ANY MATERIALIZED VIEW"; } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } else { privilege = "DROP"; } } else if (identifierEquals("USAGE")) { privilege = "USAGE"; lexer.nextToken(); } else if (identifierEquals("EXECUTE")) { privilege = "EXECUTE"; lexer.nextToken(); } else if (identifierEquals("PROXY")) { privilege = "PROXY"; lexer.nextToken(); } else if (identifierEquals("QUERY")) { lexer.nextToken(); acceptIdentifier("REWRITE"); privilege = "QUERY REWRITE"; } else if (identifierEquals("GLOBAL")) { lexer.nextToken(); acceptIdentifier("QUERY"); acceptIdentifier("REWRITE"); privilege = "GLOBAL QUERY REWRITE"; } else if (identifierEquals("INHERIT")) { lexer.nextToken(); acceptIdentifier("PRIVILEGES"); privilege = "INHERIT PRIVILEGES"; } else if (identifierEquals("EVENT")) { lexer.nextToken(); privilege = "EVENT"; } else if (identifierEquals("FILE")) { lexer.nextToken(); privilege = "FILE"; } else if (lexer.token() == Token.GRANT) { lexer.nextToken(); acceptIdentifier("OPTION"); privilege = "GRANT OPTION"; } else if (lexer.token() == Token.LOCK) { lexer.nextToken(); acceptIdentifier("TABLES"); privilege = "LOCK TABLES"; } else if (identifierEquals("PROCESS")) { lexer.nextToken(); privilege = "PROCESS"; } else if (identifierEquals("RELOAD")) { lexer.nextToken(); privilege = "RELOAD"; } else if (identifierEquals("REPLICATION")) { lexer.nextToken(); if (identifierEquals("SLAVE")) { lexer.nextToken(); privilege = "REPLICATION SLAVE"; } else { acceptIdentifier("CLIENT"); privilege = "REPLICATION CLIENT"; } } else if (lexer.token() == Token.SHOW) { lexer.nextToken(); if (lexer.token() == Token.VIEW) { lexer.nextToken(); privilege = "SHOW VIEW"; } else { acceptIdentifier("DATABASES"); privilege = "SHOW DATABASES"; } } else if (identifierEquals("SHUTDOWN")) { lexer.nextToken(); privilege = "SHUTDOWN"; } else if (identifierEquals("SUPER")) { lexer.nextToken(); privilege = "SUPER"; } if (privilege != null) { SQLExpr expr = new SQLIdentifierExpr(privilege); if (lexer.token() == Token.LPAREN) { expr = this.exprParser.primaryRest(expr); } expr.setParent(stmt); stmt.getPrivileges().add(expr); } if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } if (lexer.token() == Token.ON) { lexer.nextToken(); if (lexer.token() == Token.PROCEDURE) { lexer.nextToken(); stmt.setObjectType(ObjectType.PROCEDURE); } else if (lexer.token() == Token.FUNCTION) { lexer.nextToken(); stmt.setObjectType(ObjectType.FUNCTION); } else if (lexer.token() == Token.TABLE) { lexer.nextToken(); stmt.setObjectType(ObjectType.TABLE); } else if (lexer.token() == Token.USER) { lexer.nextToken(); stmt.setObjectType(ObjectType.USER); } stmt.setOn(this.exprParser.expr()); } if (lexer.token() == Token.TO) { lexer.nextToken(); stmt.setTo(this.exprParser.expr()); } if (lexer.token() == Token.WITH) { lexer.nextToken(); for (;;) { if (identifierEquals("MAX_QUERIES_PER_HOUR")) { lexer.nextToken(); stmt.setMaxQueriesPerHour(this.exprParser.primary()); continue; } if (identifierEquals("MAX_UPDATES_PER_HOUR")) { lexer.nextToken(); stmt.setMaxUpdatesPerHour(this.exprParser.primary()); continue; } if (identifierEquals("MAX_CONNECTIONS_PER_HOUR")) { lexer.nextToken(); stmt.setMaxConnectionsPerHour(this.exprParser.primary()); continue; } if (identifierEquals("MAX_USER_CONNECTIONS")) { lexer.nextToken(); stmt.setMaxUserConnections(this.exprParser.primary()); continue; } break; } } if (identifierEquals("ADMIN")) { lexer.nextToken(); acceptIdentifier("OPTION"); stmt.setAdminOption(true); } if (lexer.token() == Token.IDENTIFIED) { lexer.nextToken(); accept(Token.BY); stmt.setIdentifiedBy(this.exprParser.expr()); } return stmt; } public SQLStatement parseSavePoint() { acceptIdentifier("SAVEPOINT"); SQLSavePointStatement stmt = new SQLSavePointStatement(); stmt.setName(this.exprParser.name()); 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); if (lexer.token() == Token.TABLE) { lexer.nextToken(); SQLAlterTableStatement stmt = new SQLAlterTableStatement(); stmt.setName(this.exprParser.name()); for (;;) { if (lexer.token() == Token.DROP) { parseAlterDrop(stmt); } else if (identifierEquals("ADD")) { lexer.nextToken(); if (lexer.token() == Token.PRIMARY) { SQLPrimaryKey primaryKey = this.exprParser.parsePrimaryKey(); SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(primaryKey); stmt.getItems().add(item); } else if (lexer.token() == Token.IDENTIFIER) { SQLAlterTableAddColumn item = parseAlterTableAddColumn(); stmt.getItems().add(item); } else { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } } else if (lexer.token() == Token.DISABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); SQLAlterTableDisableConstraint item = new SQLAlterTableDisableConstraint(); item.setConstraintName(this.exprParser.name()); stmt.getItems().add(item); } else { acceptIdentifier("KEYS"); SQLAlterTableDisableKeys item = new SQLAlterTableDisableKeys(); stmt.getItems().add(item); } } else if (lexer.token() == Token.ENABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); SQLAlterTableEnableConstraint item = new SQLAlterTableEnableConstraint(); item.setConstraintName(this.exprParser.name()); stmt.getItems().add(item); } else { acceptIdentifier("KEYS"); SQLAlterTableEnableKeys item = new SQLAlterTableEnableKeys(); stmt.getItems().add(item); } } else if (lexer.token() == Token.ALTER) { lexer.nextToken(); if (lexer.token() == Token.COLUMN) { lexer.nextToken(); SQLColumnDefinition column = this.exprParser.parseColumn(); SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn(); alterColumn.setColumn(column); stmt.getItems().add(alterColumn); } else { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } } else if (lexer.token() == Token.WITH) { lexer.nextToken(); acceptIdentifier("NOCHECK"); acceptIdentifier("ADD"); SQLConstaint check = this.exprParser.parseConstaint(); SQLAlterTableAddConstraint addCheck = new SQLAlterTableAddConstraint(); addCheck.setWithNoCheck(true); addCheck.setConstraint(check); stmt.getItems().add(addCheck); } else { break; } } return stmt; } throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } public void parseAlterDrop(SQLAlterTableStatement stmt) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); SQLAlterTableDropConstraint item = new SQLAlterTableDropConstraint(); item.setConstraintName(this.exprParser.name()); stmt.getItems().add(item); } else if (lexer.token() == Token.COLUMN) { lexer.nextToken(); SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem(); this.exprParser.names(item.getColumns()); stmt.getItems().add(item); } else { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } } public SQLStatement parseRename() { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } protected SQLDropTableStatement parseDropTable(boolean acceptDrop) { if (acceptDrop) { accept(Token.DROP); } SQLDropTableStatement stmt = new SQLDropTableStatement(); if (identifierEquals("TEMPORARY")) { lexer.nextToken(); stmt.setTemporary(true); } accept(Token.TABLE); if (lexer.token() == Token.IF) { lexer.nextToken(); accept(Token.EXISTS); stmt.setIfExists(true); } for (;;) { SQLName name = this.exprParser.name(); stmt.getTableSources().add(new SQLExprTableSource(name)); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } for (;;) { if (identifierEquals("RESTRICT")) { lexer.nextToken(); stmt.setRestrict(true); continue; } if (identifierEquals("CASCADE")) { lexer.nextToken(); stmt.setCascade(true); if (identifierEquals("CONSTRAINTS")) { // for oracle lexer.nextToken(); } continue; } if (lexer.token() == Token.PURGE) { lexer.nextToken(); stmt.setPurge(true); continue; } break; } return stmt; } protected SQLDropSequenceStatement parseDropSequece(boolean acceptDrop) { if (acceptDrop) { accept(Token.DROP); } lexer.nextToken(); SQLName name = this.exprParser.name(); SQLDropSequenceStatement stmt = new SQLDropSequenceStatement(); stmt.setName(name); return stmt; } protected SQLDropTriggerStatement parseDropTrigger(boolean acceptDrop) { if (acceptDrop) { accept(Token.DROP); } lexer.nextToken(); SQLName name = this.exprParser.name(); SQLDropTriggerStatement stmt = new SQLDropTriggerStatement(); stmt.setName(name); return stmt; } protected SQLDropViewStatement parseDropView(boolean acceptDrop) { if (acceptDrop) { accept(Token.DROP); } SQLDropViewStatement stmt = new SQLDropViewStatement(); accept(Token.VIEW); if (lexer.token() == Token.IF) { lexer.nextToken(); accept(Token.EXISTS); stmt.setIfExists(true); } for (;;) { SQLName name = this.exprParser.name(); stmt.getTableSources().add(new SQLExprTableSource(name)); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } if (identifierEquals("RESTRICT")) { lexer.nextToken(); stmt.setRestrict(true); } else if (identifierEquals("CASCADE")) { lexer.nextToken(); if (identifierEquals("CONSTRAINTS")) { // for oracle lexer.nextToken(); } stmt.setCascade(true); } return stmt; } protected SQLDropDatabaseStatement parseDropDatabase(boolean acceptDrop) { if (acceptDrop) { accept(Token.DROP); } SQLDropDatabaseStatement stmt = new SQLDropDatabaseStatement(); accept(Token.DATABASE); if (lexer.token() == Token.IF) { lexer.nextToken(); accept(Token.EXISTS); stmt.setIfExists(true); } SQLName name = this.exprParser.name(); stmt.setDatabase(name); return stmt; } protected SQLDropFunctionStatement parseDropFunction(boolean acceptDrop) { if (acceptDrop) { accept(Token.DROP); } SQLDropFunctionStatement stmt = new SQLDropFunctionStatement(); accept(Token.FUNCTION); if (lexer.token() == Token.IF) { lexer.nextToken(); accept(Token.EXISTS); stmt.setIfExists(true); } SQLName name = this.exprParser.name(); stmt.setName(name); return stmt; } protected SQLDropTableSpaceStatement parseDropTablespace(boolean acceptDrop) { if (acceptDrop) { accept(Token.DROP); } SQLDropTableSpaceStatement stmt = new SQLDropTableSpaceStatement(); accept(Token.TABLESPACE); if (lexer.token() == Token.IF) { lexer.nextToken(); accept(Token.EXISTS); stmt.setIfExists(true); } SQLName name = this.exprParser.name(); stmt.setName(name); return stmt; } protected SQLDropProcedureStatement parseDropProcedure(boolean acceptDrop) { if (acceptDrop) { accept(Token.DROP); } SQLDropProcedureStatement stmt = new SQLDropProcedureStatement(); accept(Token.PROCEDURE); if (lexer.token() == Token.IF) { lexer.nextToken(); accept(Token.EXISTS); stmt.setIfExists(true); } SQLName name = this.exprParser.name(); stmt.setName(name); return stmt; } public SQLStatement parseTruncate() { accept(Token.TRUNCATE); if (lexer.token() == Token.TABLE) { lexer.nextToken(); } SQLTruncateStatement stmt = new SQLTruncateStatement(); if (lexer.token() == Token.ONLY) { lexer.nextToken(); stmt.setOnly(true); } for (;;) { SQLName name = this.exprParser.name(); stmt.addTableSource(name); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } for (;;) { if (lexer.token() == Token.PURGE) { lexer.nextToken(); if (identifierEquals("SNAPSHOT")) { lexer.nextToken(); acceptIdentifier("LOG"); stmt.setPurgeSnapshotLog(true); } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } continue; } if (lexer.token() == Token.RESTART) { lexer.nextToken(); accept(Token.IDENTITY); stmt.setRestartIdentity(Boolean.TRUE); continue; } else if (lexer.token() == Token.SHARE) { lexer.nextToken(); accept(Token.IDENTITY); stmt.setRestartIdentity(Boolean.FALSE); continue; } if (lexer.token() == Token.CASCADE) { lexer.nextToken(); stmt.setCascade(Boolean.TRUE); continue; } else if (lexer.token() == Token.RESTRICT) { lexer.nextToken(); stmt.setCascade(Boolean.FALSE); continue; } break; } return stmt; } public SQLStatement parseInsert() { SQLInsertStatement insertStatement = new SQLInsertStatement(); if (lexer.token() == Token.INSERT) { accept(Token.INSERT); } parseInsert0(insertStatement); return insertStatement; } protected void parseInsert0(SQLInsertInto insertStatement) { parseInsert0(insertStatement, true); } protected void parseInsert0_hinits(SQLInsertInto insertStatement) { } protected void parseInsert0(SQLInsertInto insertStatement, boolean acceptSubQuery) { if (lexer.token() == Token.INTO) { lexer.nextToken(); SQLName tableName = this.exprParser.name(); insertStatement.setTableName(tableName); if (lexer.token() == Token.LITERAL_ALIAS) { insertStatement.setAlias(as()); } parseInsert0_hinits(insertStatement); if (lexer.token() == Token.IDENTIFIER) { insertStatement.setAlias(lexer.stringVal()); lexer.nextToken(); } } if (lexer.token() == (Token.LPAREN)) { lexer.nextToken(); this.exprParser.exprList(insertStatement.getColumns()); accept(Token.RPAREN); } if (lexer.token() == Token.VALUES) { lexer.nextToken(); accept(Token.LPAREN); SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(); this.exprParser.exprList(values.getValues()); insertStatement.setValues(values); accept(Token.RPAREN); } else if (acceptSubQuery && (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN)) { SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr(); insertStatement.setQuery(queryExpr.getSubQuery()); } } public boolean parseStatementListDialect(List statementList) { return false; } public SQLDropUserStatement parseDropUser() { accept(Token.USER); SQLDropUserStatement stmt = new SQLDropUserStatement(); for (;;) { SQLExpr expr = this.exprParser.expr(); stmt.getUsers().add(expr); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } return stmt; } public SQLStatement parseDropIndex() { accept(Token.INDEX); SQLDropIndexStatement stmt = new SQLDropIndexStatement(); stmt.setIndexName(this.exprParser.name()); if (lexer.token() == Token.ON) { lexer.nextToken(); stmt.setTableName(this.exprParser.name()); } return stmt; } public SQLCallStatement parseCall() { boolean brace = false; if (lexer.token() == Token.LBRACE) { lexer.nextToken(); brace = true; } SQLCallStatement stmt = new SQLCallStatement(); if (lexer.token() == Token.QUES) { lexer.nextToken(); accept(Token.EQ); stmt.setOutParameter(new SQLVariantRefExpr("?")); } acceptIdentifier("CALL"); stmt.setProcedureName(exprParser.name()); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); exprParser.exprList(stmt.getParameters()); accept(Token.RPAREN); } if (brace) { accept(Token.RBRACE); stmt.setBrace(true); } return stmt; } public SQLStatement parseSet() { accept(Token.SET); SQLSetStatement stmt = new SQLSetStatement(); parseAssignItems(stmt.getItems(), stmt); return stmt; } public void parseAssignItems(List items, SQLObject parent) { for (;;) { SQLAssignItem item = exprParser.parseAssignItem(); item.setParent(parent); items.add(item); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } else { break; } } } public SQLStatement parseCreate() { char markChar = lexer.current(); int markBp = lexer.bp(); accept(Token.CREATE); Token token = lexer.token(); if (token == Token.TABLE || identifierEquals("GLOBAL")) { SQLCreateTableParser createTableParser = getSQLCreateTableParser(); return createTableParser.parseCrateTable(false); } else if (token == Token.INDEX // || token == Token.UNIQUE // || identifierEquals("NONCLUSTERED") // sql server ) { return parseCreateIndex(false); } else if (lexer.token() == Token.SEQUENCE) { return parseCreateSequence(false); } else if (token == Token.OR) { lexer.nextToken(); accept(Token.REPLACE); if (lexer.token() == Token.PROCEDURE) { lexer.reset(markBp, markChar, Token.CREATE); return parseCreateProcedure(); } // lexer.reset(mark_bp, mark_ch, Token.CREATE); throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } else if (token == Token.DATABASE) { lexer.nextToken(); if (identifierEquals("LINK")) { lexer.reset(markBp, markChar, Token.CREATE); return parseCreateDbLink(); } lexer.reset(markBp, markChar, Token.CREATE); return parseCreateDatabase(); } else if (identifierEquals("PUBLIC") || identifierEquals("SHARE")) { lexer.reset(markBp, markChar, Token.CREATE); return parseCreateDbLink(); } else if (token == Token.VIEW) { return parseCreateView(); } else if (token == Token.TRIGGER) { return parseCreateTrigger(); } throw new ParserException("TODO " + lexer.token()); } public SQLStatement parseCreateDbLink() { throw new ParserException("TODO " + lexer.token()); } public SQLStatement parseCreateTrigger() { accept(Token.TRIGGER); SQLCreateTriggerStatement stmt = new SQLCreateTriggerStatement(); stmt.setName(this.exprParser.name()); if (identifierEquals("BEFORE")) { stmt.setTriggerType(TriggerType.BEFORE); lexer.nextToken(); } else if (identifierEquals("AFTER")) { stmt.setTriggerType(TriggerType.AFTER); lexer.nextToken(); } else if (identifierEquals("INSTEAD")) { lexer.nextToken(); accept(Token.OF); stmt.setTriggerType(TriggerType.INSTEAD_OF); } for (;;) { if (lexer.token() == Token.INSERT) { lexer.nextToken(); stmt.getTriggerEvents().add(TriggerEvent.INSERT); continue; } if (lexer.token() == Token.UPDATE) { lexer.nextToken(); stmt.getTriggerEvents().add(TriggerEvent.UPDATE); continue; } if (lexer.token() == Token.DELETE) { lexer.nextToken(); stmt.getTriggerEvents().add(TriggerEvent.DELETE); continue; } break; } accept(Token.ON); stmt.setOn(this.exprParser.name()); if (lexer.token() == Token.FOR) { lexer.nextToken(); acceptIdentifier("EACH"); accept(Token.ROW); stmt.setForEachRow(true); } SQLStatement body = this.parseBlock(); stmt.setBody(body); return stmt; } public SQLStatement parseBlock() { throw new ParserException("TODO " + lexer.token()); } public SQLStatement parseCreateDatabase() { if (lexer.token() == Token.CREATE) { lexer.nextToken(); } accept(Token.DATABASE); SQLCreateDatabaseStatement stmt = new SQLCreateDatabaseStatement(); stmt.setName(this.exprParser.name()); return stmt; } public SQLStatement parseCreateProcedure() { throw new ParserException("TODO " + lexer.token()); } public SQLStatement parseCreateSequence(boolean acceptCreate) { throw new ParserException("TODO " + lexer.token()); } public SQLStatement parseCreateIndex(boolean acceptCreate) { if (acceptCreate) { accept(Token.CREATE); } SQLCreateIndexStatement stmt = new SQLCreateIndexStatement(); if (lexer.token() == Token.UNIQUE) { lexer.nextToken(); if (identifierEquals("CLUSTERED")) { lexer.nextToken(); stmt.setType("UNIQUE CLUSTERED"); } else { stmt.setType("UNIQUE"); } } else if (identifierEquals("FULLTEXT")) { stmt.setType("FULLTEXT"); lexer.nextToken(); } else if (identifierEquals("NONCLUSTERED")) { stmt.setType("NONCLUSTERED"); lexer.nextToken(); } accept(Token.INDEX); stmt.setName(this.exprParser.name()); accept(Token.ON); stmt.setTable(this.exprParser.name()); accept(Token.LPAREN); for (;;) { SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem(); item.setParent(stmt); stmt.getItems().add(item); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } accept(Token.RPAREN); return stmt; } public SQLCreateTableParser getSQLCreateTableParser() { return new SQLCreateTableParser(this.exprParser); } public SQLSelectStatement parseSelect() { SQLSelectParser selectParser = createSQLSelectParser(); SQLSelect select = selectParser.select(); return new SQLSelectStatement(select); } public SQLSelectParser createSQLSelectParser() { return new OdpsSelectParser(this.exprParser); } public SQLUpdateStatement parseUpdateStatement() { SQLUpdateStatement udpateStatement = createUpdateStatement(); if (lexer.token() == Token.UPDATE) { lexer.nextToken(); SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource(); udpateStatement.setTableSource(tableSource); } parseUpdateSet(udpateStatement); if (lexer.token() == (Token.WHERE)) { lexer.nextToken(); udpateStatement.setWhere(this.exprParser.expr()); } return udpateStatement; } protected void parseUpdateSet(SQLUpdateStatement update) { accept(Token.SET); for (;;) { SQLUpdateSetItem item = new SQLUpdateSetItem(); if (lexer.token() == (Token.LPAREN)) { lexer.nextToken(); SQLListExpr list = new SQLListExpr(); this.exprParser.exprList(list.getItems()); accept(Token.RPAREN); item.setColumn(list); } else { item.setColumn(this.exprParser.primary()); } accept(Token.EQ); item.setValue(this.exprParser.expr()); update.getItems().add(item); if (lexer.token() != Token.COMMA) { break; } lexer.nextToken(); } } protected SQLUpdateStatement createUpdateStatement() { return new SQLUpdateStatement(); } public SQLDeleteStatement parseDeleteStatement() { SQLDeleteStatement deleteStatement = new SQLDeleteStatement(); if (lexer.token() == Token.DELETE) { lexer.nextToken(); if (lexer.token() == (Token.FROM)) { lexer.nextToken(); } if (lexer.token() == Token.COMMENT) { lexer.nextToken(); } SQLName tableName = exprParser.name(); deleteStatement.setTableName(tableName); } if (lexer.token() == (Token.WHERE)) { lexer.nextToken(); SQLExpr where = this.exprParser.expr(); deleteStatement.setWhere(where); } return deleteStatement; } public SQLCreateTableStatement parseCreateTable() { // SQLCreateTableParser parser = new SQLCreateTableParser(this.lexer); // return parser.parseCrateTable(); throw new ParserException("TODO"); } public SQLCreateViewStatement parseCreateView() { SQLCreateViewStatement createView = new SQLCreateViewStatement(); if (lexer.token() == Token.CREATE) { lexer.nextToken(); } if (lexer.token() == Token.OR) { lexer.nextToken(); accept(Token.REPLACE); createView.setOrReplace(true); } this.accept(Token.VIEW); createView.setName(exprParser.name()); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); this.exprParser.exprList(createView.getColumns()); accept(Token.RPAREN); } this.accept(Token.AS); createView.setSubQuery(new SQLSelectParser(this.exprParser).select()); return createView; } public SQLCommentStatement parseComment() { accept(Token.COMMENT); SQLCommentStatement stmt = new SQLCommentStatement(); accept(Token.ON); if (lexer.token() == Token.TABLE) { stmt.setType(SQLCommentStatement.Type.TABLE); lexer.nextToken(); } else if (lexer.token() == Token.COLUMN) { stmt.setType(SQLCommentStatement.Type.COLUMN); lexer.nextToken(); } stmt.setOn(this.exprParser.name()); accept(Token.IS); stmt.setComment(this.exprParser.expr()); return stmt; } protected SQLAlterTableAddColumn parseAlterTableAddColumn() { SQLAlterTableAddColumn item = new SQLAlterTableAddColumn(); for (;;) { SQLColumnDefinition columnDef = this.exprParser.parseColumn(); item.getColumns().add(columnDef); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } return item; } public SQLStatement parseStatement() { List list = new ArrayList(); this.parseStatementList(list, 1); return list.get(0); } public SQLExplainStatement parseExplain() { accept(Token.EXPLAIN); if (identifierEquals("PLAN")) { lexer.nextToken(); } if (lexer.token() == Token.FOR) { lexer.nextToken(); } SQLExplainStatement explain = new SQLExplainStatement(); explain.setStatement(parseStatement()); return explain; } protected SQLAlterTableAddIndex parseAlterTableAddIndex() { SQLAlterTableAddIndex item = new SQLAlterTableAddIndex(); if (lexer.token() == Token.UNIQUE) { item.setUnique(true); lexer.nextToken(); if (lexer.token() == Token.INDEX) { lexer.nextToken(); } } else { accept(Token.INDEX); } if (lexer.token() == Token.LPAREN) { lexer.nextToken(); } else { item.setName(this.exprParser.name()); accept(Token.LPAREN); } for (;;) { SQLSelectOrderByItem column = this.exprParser.parseSelectOrderByItem(); item.getItems().add(column); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } accept(Token.RPAREN); return item; } }