/*
* 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.dialect.oracle.parser;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLHint;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddColumn;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLConstaint;
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLInsertInto;
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.SQLUpdateSetItem;
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleParameter;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterIndexStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterProcedureStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSynonymStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableAddConstaint;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableDropPartition;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableItem;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableModify;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableMoveTablespace;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableRenameTo;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.NestedTablePartitionSpec;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.TableSpaceItem;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.UpdateIndexesClause;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableTruncatePartition;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTablespaceAddDataFile;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTablespaceStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTriggerStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterViewStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCommitStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateIndexStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateProcedureStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExceptionStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExitStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExplainStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExprStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleFetchStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleFileSpecification;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleForStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleGotoStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleGrantStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleIfStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLabelStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement.LockMode;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLoopStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSavePointStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSetTransactionStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleTruncateStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
public class OracleStatementParser extends SQLStatementParser {
public OracleStatementParser(String sql){
super(new OracleExprParser(sql));
}
public OracleStatementParser(Lexer lexer){
super(new OracleExprParser(lexer));
}
@Override
public OracleExprParser getExprParser() {
return (OracleExprParser) exprParser;
}
public void parseHints(List<SQLHint> hints) {
this.getExprParser().parseHints(hints);
}
public OracleCreateTableParser getSQLCreateTableParser() {
return new OracleCreateTableParser(lexer);
}
protected void parseInsert0_hinits(SQLInsertInto insertStatement) {
if (insertStatement instanceof OracleInsertStatement) {
OracleInsertStatement stmt = (OracleInsertStatement) insertStatement;
this.getExprParser().parseHints(stmt.getHints());
} else {
List<SQLHint> hints = new ArrayList<SQLHint>(1);
this.getExprParser().parseHints(hints);
}
}
@Override
public void parseStatementList(List<SQLStatement> statementList) {
parseStatementList(statementList, -1);
}
public void parseStatementList(List<SQLStatement> statementList, int max) {
for (;;) {
if (max != -1) {
if (statementList.size() >= max) {
return;
}
}
if (lexer.token() == Token.EOF) {
return;
}
if (lexer.token() == Token.END) {
return;
}
if (lexer.token() == Token.ELSE) {
return;
}
if (lexer.token() == (Token.SEMI)) {
lexer.nextToken();
continue;
}
if (lexer.token() == (Token.SELECT)) {
statementList.add(new SQLSelectStatement(new OracleSelectParser(this.exprParser).select()));
continue;
}
if (lexer.token() == (Token.UPDATE)) {
statementList.add(parseUpdateStatement());
continue;
}
if (lexer.token() == (Token.CREATE)) {
statementList.add(parseCreate());
continue;
}
if (lexer.token() == Token.INSERT) {
statementList.add(parseInsert());
continue;
}
if (lexer.token() == (Token.DELETE)) {
statementList.add(parseDeleteStatement());
continue;
}
if (lexer.token() == (Token.SLASH)) {
lexer.nextToken();
statementList.add(new OraclePLSQLCommitStatement());
continue;
}
if (lexer.token() == Token.ALTER) {
statementList.add(parserAlter());
continue;
}
if (lexer.token() == Token.WITH) {
statementList.add(new SQLSelectStatement(new OracleSelectParser(this.exprParser).select()));
continue;
}
if (lexer.token() == Token.LBRACE || identifierEquals("CALL")) {
statementList.add(this.parseCall());
continue;
}
if (lexer.token() == Token.MERGE) {
statementList.add(this.parseMerge());
continue;
}
if (lexer.token() == Token.BEGIN) {
statementList.add(this.parseBlock());
continue;
}
if (lexer.token() == Token.DECLARE) {
statementList.add(this.parseBlock());
continue;
}
if (lexer.token() == Token.LOCK) {
statementList.add(this.parseLock());
continue;
}
if (lexer.token() == Token.TRUNCATE) {
statementList.add(this.parseTruncate());
continue;
}
if (lexer.token() == Token.VARIANT) {
SQLExpr variant = this.exprParser.primary();
if (variant instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) variant;
if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) {
SQLSetStatement stmt = new SQLSetStatement(binaryOpExpr.getLeft(), binaryOpExpr.getRight());
statementList.add(stmt);
continue;
}
}
accept(Token.COLONEQ);
SQLExpr value = this.exprParser.expr();
SQLSetStatement stmt = new SQLSetStatement(variant, value);
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.EXCEPTION) {
statementList.add(this.parseException());
continue;
}
if (identifierEquals("EXIT")) {
lexer.nextToken();
OracleExitStatement stmt = new OracleExitStatement();
if (lexer.token() == Token.WHEN) {
lexer.nextToken();
stmt.setWhen(this.exprParser.expr());
}
statementList.add(stmt);
continue;
}
if (identifierEquals("FETCH")) {
lexer.nextToken();
OracleFetchStatement stmt = new OracleFetchStatement();
stmt.setCursorName(this.exprParser.name());
accept(Token.INTO);
for (;;) {
stmt.getInto().add(this.exprParser.name());
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.IDENTIFIER) {
if (identifierEquals("EXPLAIN")) {
statementList.add(this.parseExplain());
continue;
}
SQLExpr expr = exprParser.expr();
OracleExprStatement stmt = new OracleExprStatement(expr);
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.LPAREN) {
char ch = lexer.current();
int bp = lexer.bp();
lexer.nextToken();
if (lexer.token() == Token.SELECT) {
lexer.reset(bp, ch, Token.LPAREN);
statementList.add(this.parseSelect());
continue;
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
if (lexer.token() == Token.SET) {
statementList.add(this.parseSet());
continue;
}
if (lexer.token() == Token.GRANT) {
statementList.add(this.parseGrant());
continue;
}
if (lexer.token() == Token.COMMENT) {
statementList.add(this.parseComment());
continue;
}
if (lexer.token() == Token.FOR) {
statementList.add(this.parseFor());
continue;
}
if (lexer.token() == Token.LOOP) {
statementList.add(this.parseLoop());
continue;
}
if (lexer.token() == Token.IF) {
statementList.add(this.parseIf());
continue;
}
if (lexer.token() == Token.GOTO) {
lexer.nextToken();
SQLName label = this.exprParser.name();
OracleGotoStatement stmt = new OracleGotoStatement(label);
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.COMMIT) {
lexer.nextToken();
if (identifierEquals("WORK")) {
lexer.nextToken();
}
OracleCommitStatement stmt = new OracleCommitStatement();
if (identifierEquals("WRITE")) {
stmt.setWrite(true);
lexer.nextToken();
for (;;) {
if (lexer.token() == Token.WAIT) {
lexer.nextToken();
stmt.setWait(Boolean.TRUE);
continue;
} else if (lexer.token() == Token.NOWAIT) {
lexer.nextToken();
stmt.setWait(Boolean.FALSE);
continue;
} else if (identifierEquals("IMMEDIATE")) {
lexer.nextToken();
stmt.setImmediate(Boolean.TRUE);
continue;
} else if (identifierEquals("BATCH")) {
lexer.nextToken();
stmt.setImmediate(Boolean.FALSE);
continue;
}
break;
}
}
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.SAVEPOINT) {
lexer.nextToken();
OracleSavePointStatement stmt = new OracleSavePointStatement();
if (identifierEquals("TO")) {
lexer.nextToken();
stmt.setTo(this.exprParser.name());
}
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.LTLT) {
lexer.nextToken();
SQLName label = this.exprParser.name();
OracleLabelStatement stmt = new OracleLabelStatement(label);
accept(Token.GTGT);
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.DROP) {
lexer.nextToken();
if (lexer.token() == Token.TABLE) {
SQLDropTableStatement stmt = parseDropTable(false);
statementList.add(stmt);
continue;
}
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
if (lexer.token() == Token.NULL) {
lexer.nextToken();
OracleExprStatement stmt = new OracleExprStatement(new SQLNullExpr());
statementList.add(stmt);
continue;
}
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
public SQLStatement parseIf() {
accept(Token.IF);
OracleIfStatement stmt = new OracleIfStatement();
stmt.setCondition(this.exprParser.expr());
accept(Token.THEN);
this.parseStatementList(stmt.getStatements());
while (lexer.token() == Token.ELSE) {
lexer.nextToken();
if (lexer.token() == Token.IF) {
lexer.nextToken();
OracleIfStatement.ElseIf elseIf = new OracleIfStatement.ElseIf();
elseIf.setCondition(this.exprParser.expr());
accept(Token.THEN);
this.parseStatementList(elseIf.getStatements());
stmt.getElseIfList().add(elseIf);
} else {
OracleIfStatement.Else elseItem = new OracleIfStatement.Else();
this.parseStatementList(elseItem.getStatements());
stmt.setElseItem(elseItem);
break;
}
}
accept(Token.END);
accept(Token.IF);
return stmt;
}
public OracleForStatement parseFor() {
accept(Token.FOR);
OracleForStatement stmt = new OracleForStatement();
stmt.setIndex(this.exprParser.name());
accept(Token.IN);
stmt.setRange(this.exprParser.expr());
accept(Token.LOOP);
this.parseStatementList(stmt.getStatements());
accept(Token.END);
accept(Token.LOOP);
return stmt;
}
public OracleLoopStatement parseLoop() {
accept(Token.LOOP);
OracleLoopStatement stmt = new OracleLoopStatement();
this.parseStatementList(stmt.getStatements());
accept(Token.END);
accept(Token.LOOP);
return stmt;
}
public SQLStatement parseGrant() {
accept(Token.GRANT);
OracleGrantStatement stmt = new OracleGrantStatement();
for (;;) {
if (lexer.token() == Token.ALL) {
lexer.nextToken();
if (identifierEquals("PRIVILEGES")) {
lexer.nextToken();
}
stmt.getPrivileges().add("ALL");
} else if (lexer.token() == Token.SELECT) {
stmt.getPrivileges().add("SELECT");
lexer.nextToken();
} else if (lexer.token() == Token.UPDATE) {
stmt.getPrivileges().add("UPDATE");
lexer.nextToken();
} else if (lexer.token() == Token.DELETE) {
stmt.getPrivileges().add("DELETE");
lexer.nextToken();
} else if (lexer.token() == Token.INSERT) {
stmt.getPrivileges().add("INSERT");
lexer.nextToken();
} else if (lexer.token() == Token.CREATE) {
lexer.nextToken();
if (lexer.token() == Token.TABLE) {
stmt.getPrivileges().add("CREATE TABLE");
lexer.nextToken();
} else if (identifierEquals("SYNONYM")) {
stmt.getPrivileges().add("CREATE SYNONYM");
lexer.nextToken();
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
if (lexer.token() == Token.ON) {
lexer.nextToken();
stmt.setOn(this.exprParser.expr());
}
return stmt;
}
public SQLStatement parseSet() {
accept(Token.SET);
acceptIdentifier("TRANSACTION");
OracleSetTransactionStatement stmt = new OracleSetTransactionStatement();
if (identifierEquals("READ")) {
lexer.nextToken();
acceptIdentifier("ONLY");
stmt.setReadOnly(true);
}
acceptIdentifier("NAME");
stmt.setName(this.exprParser.expr());
return stmt;
}
public OracleTruncateStatement parseTruncate() {
accept(Token.TRUNCATE);
accept(Token.TABLE);
OracleTruncateStatement stmt = new OracleTruncateStatement();
SQLName name = this.exprParser.name();
stmt.addTableSource(name);
if (identifierEquals("PURGE")) {
lexer.nextToken();
if (identifierEquals("SNAPSHOT")) {
lexer.nextToken();
acceptIdentifier("LOG");
stmt.setPurgeSnapshotLog(true);
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
return stmt;
}
public OracleStatement parserAlter() {
accept(Token.ALTER);
if (lexer.token() == Token.SESSION) {
lexer.nextToken();
OracleAlterSessionStatement stmt = new OracleAlterSessionStatement();
if (lexer.token() == Token.SET) {
lexer.nextToken();
parseAssignItems(stmt.getItems());
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
return stmt;
} else if (lexer.token() == Token.PROCEDURE) {
lexer.nextToken();
OracleAlterProcedureStatement stmt = new OracleAlterProcedureStatement();
stmt.setName(this.exprParser.name());
if (identifierEquals("COMPILE")) {
lexer.nextToken();
stmt.setCompile(true);
}
if (identifierEquals("REUSE")) {
lexer.nextToken();
acceptIdentifier("SETTINGS");
stmt.setReuseSettings(true);
}
return stmt;
} else if (lexer.token() == Token.TABLE) {
return parseAlterTable();
} else if (lexer.token() == Token.INDEX) {
lexer.nextToken();
OracleAlterIndexStatement stmt = new OracleAlterIndexStatement();
stmt.setName(this.exprParser.name());
if (identifierEquals("RENAME")) {
lexer.nextToken();
acceptIdentifier("TO");
stmt.setRenameTo(this.exprParser.name());
}
for (;;) {
if (identifierEquals("rebuild")) {
lexer.nextToken();
OracleAlterIndexStatement.Rebuild rebuild = new OracleAlterIndexStatement.Rebuild();
stmt.setRebuild(rebuild);
continue;
} else if (identifierEquals("MONITORING")) {
lexer.nextToken();
acceptIdentifier("USAGE");
stmt.setMonitoringUsage(Boolean.TRUE);
continue;
} else if (identifierEquals("PARALLEL")) {
lexer.nextToken();
stmt.setParallel(this.exprParser.expr());
}
break;
}
return stmt;
} else if (identifierEquals("TRIGGER")) {
lexer.nextToken();
OracleAlterTriggerStatement stmt = new OracleAlterTriggerStatement();
stmt.setName(this.exprParser.name());
for (;;) {
if (identifierEquals("ENABLE")) {
lexer.nextToken();
stmt.setEnable(Boolean.TRUE);
continue;
} else if (identifierEquals("DISABLE")) {
lexer.nextToken();
stmt.setEnable(Boolean.FALSE);
continue;
} else if (identifierEquals("COMPILE")) {
lexer.nextToken();
stmt.setCompile(true);
continue;
}
break;
}
return stmt;
} else if (identifierEquals("SYNONYM")) {
lexer.nextToken();
OracleAlterSynonymStatement stmt = new OracleAlterSynonymStatement();
stmt.setName(this.exprParser.name());
for (;;) {
if (identifierEquals("ENABLE")) {
lexer.nextToken();
stmt.setEnable(Boolean.TRUE);
continue;
} else if (identifierEquals("DISABLE")) {
lexer.nextToken();
stmt.setEnable(Boolean.FALSE);
continue;
} else if (identifierEquals("COMPILE")) {
lexer.nextToken();
stmt.setCompile(true);
continue;
}
break;
}
return stmt;
} else if (lexer.token() == Token.VIEW) {
lexer.nextToken();
OracleAlterViewStatement stmt = new OracleAlterViewStatement();
stmt.setName(this.exprParser.name());
for (;;) {
if (identifierEquals("ENABLE")) {
lexer.nextToken();
stmt.setEnable(Boolean.TRUE);
continue;
} else if (identifierEquals("DISABLE")) {
lexer.nextToken();
stmt.setEnable(Boolean.FALSE);
continue;
} else if (identifierEquals("COMPILE")) {
lexer.nextToken();
stmt.setCompile(true);
continue;
}
break;
}
return stmt;
} else if (identifierEquals("TABLESPACE")) {
lexer.nextToken();
OracleAlterTablespaceStatement stmt = new OracleAlterTablespaceStatement();
stmt.setName(this.exprParser.name());
if (identifierEquals("ADD")) {
lexer.nextToken();
if (identifierEquals("DATAFILE")) {
lexer.nextToken();
OracleAlterTablespaceAddDataFile item = new OracleAlterTablespaceAddDataFile();
for (;;) {
OracleFileSpecification file = new OracleFileSpecification();
for (;;) {
SQLExpr fileName = this.exprParser.expr();
file.getFileNames().add(fileName);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
if (identifierEquals("SIZE")) {
lexer.nextToken();
file.setSize(this.exprParser.expr());
}
if (identifierEquals("AUTOEXTEND")) {
lexer.nextToken();
if (identifierEquals("OFF")) {
lexer.nextToken();
file.setAutoExtendOff(true);
} else if (identifierEquals("ON")) {
lexer.nextToken();
file.setAutoExtendOn(this.exprParser.expr());
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
item.getFiles().add(file);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
stmt.setItem(item);
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
return stmt;
}
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
private OracleStatement parseAlterTable() {
lexer.nextToken();
OracleAlterTableStatement stmt = new OracleAlterTableStatement();
stmt.setName(this.exprParser.name());
for (;;) {
if (identifierEquals("ADD")) {
lexer.nextToken();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
SQLAlterTableAddColumn item = new SQLAlterTableAddColumn();
for (;;) {
SQLColumnDefinition columnDef = this.exprParser.parseColumn();
item.getColumns().add(columnDef);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
stmt.getItems().add(item);
} else if (lexer.token() == Token.CONSTRAINT) {
stmt.getItems().add(parseConstaint());
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
continue;
} else if (identifierEquals("MOVE")) {
lexer.nextToken();
if (identifierEquals("TABLESPACE")) {
lexer.nextToken();
OracleAlterTableMoveTablespace item = new OracleAlterTableMoveTablespace();
item.setName(this.exprParser.name());
stmt.getItems().add(item);
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
} else if (identifierEquals("RENAME")) {
stmt.getItems().add(parseAlterTableRename());
} else if (identifierEquals("MODIFY")) {
lexer.nextToken();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
OracleAlterTableModify item = new OracleAlterTableModify();
for (;;) {
SQLColumnDefinition columnDef = this.exprParser.parseColumn();
item.getColumns().add(columnDef);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
stmt.getItems().add(item);
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
continue;
} else if (identifierEquals("SPLIT")) {
parseAlterTableSplit(stmt);
continue;
} else if (lexer.token() == Token.TRUNCATE) {
lexer.nextToken();
if (identifierEquals("PARTITION")) {
lexer.nextToken();
OracleAlterTableTruncatePartition item = new OracleAlterTableTruncatePartition();
item.setName(this.exprParser.name());
stmt.getItems().add(item);
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
continue;
} else if (lexer.token() == Token.DROP) {
parseAlterTableDrop(stmt);
continue;
}
break;
}
if (lexer.token() == Token.UPDATE) {
lexer.nextToken();
if (identifierEquals("GLOBAL")) {
lexer.nextToken();
acceptIdentifier("INDEXES");
stmt.setUpdateGlobalIndexes(true);
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
return stmt;
}
private OracleAlterTableItem parseAlterTableRename() {
acceptIdentifier("RENAME");
if (identifierEquals("TO")) {
lexer.nextToken();
OracleAlterTableRenameTo item = new OracleAlterTableRenameTo();
item.setTo(this.exprParser.name());
return item;
}
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
private OracleAlterTableAddConstaint parseConstaint() {
accept(Token.CONSTRAINT);
OracleAlterTableAddConstaint item = new OracleAlterTableAddConstaint();
SQLName name = this.exprParser.name();
SQLConstaint constraint;
if (lexer.token() == Token.PRIMARY) {
constraint = exprParser.parsePrimaryKey();
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
constraint.setName(name);
item.setConstraint(constraint);
return item;
}
private void parseAlterTableDrop(OracleAlterTableStatement stmt) {
lexer.nextToken();
if (identifierEquals("PARTITION")) {
lexer.nextToken();
OracleAlterTableDropPartition item = new OracleAlterTableDropPartition();
item.setName(this.exprParser.name());
stmt.getItems().add(item);
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
private void parseAlterTableSplit(OracleAlterTableStatement stmt) {
lexer.nextToken();
if (identifierEquals("PARTITION")) {
lexer.nextToken();
OracleAlterTableSplitPartition item = new OracleAlterTableSplitPartition();
item.setName(this.exprParser.name());
if (identifierEquals("AT")) {
lexer.nextToken();
accept(Token.LPAREN);
this.exprParser.exprList(item.getAt());
accept(Token.RPAREN);
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
if (lexer.token() == Token.INTO) {
lexer.nextToken();
accept(Token.LPAREN);
for (;;) {
NestedTablePartitionSpec spec = new NestedTablePartitionSpec();
acceptIdentifier("PARTITION");
spec.setPartition(this.exprParser.name());
for (;;) {
if (identifierEquals("TABLESPACE")) {
lexer.nextToken();
SQLName tablespace = this.exprParser.name();
spec.getSegmentAttributeItems().add(new TableSpaceItem(tablespace));
continue;
} else if (identifierEquals("PCTREE")) {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
} else if (identifierEquals("PCTUSED")) {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
} else if (identifierEquals("INITRANS")) {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
} else if (identifierEquals("STORAGE")) {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
} else if (identifierEquals("LOGGING")) {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
} else if (identifierEquals("NOLOGGING")) {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
} else if (identifierEquals("FILESYSTEM_LIKE_LOGGING")) {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
break;
}
item.getInto().add(spec);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
}
if (lexer.token() == Token.UPDATE) {
lexer.nextToken();
acceptIdentifier("INDEXES");
UpdateIndexesClause updateIndexes = new UpdateIndexesClause();
item.setUpdateIndexes(updateIndexes);
}
stmt.getItems().add(item);
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
public OracleLockTableStatement parseLock() {
accept(Token.LOCK);
accept(Token.TABLE);
OracleLockTableStatement stmt = new OracleLockTableStatement();
stmt.setTable(this.exprParser.name());
accept(Token.IN);
if (lexer.token() == Token.SHARE) {
stmt.setLockMode(LockMode.SHARE);
lexer.nextToken();
} else if (lexer.token() == Token.EXCLUSIVE) {
stmt.setLockMode(LockMode.EXCLUSIVE);
lexer.nextToken();
}
accept(Token.MODE);
if (lexer.token() == Token.NOWAIT) {
lexer.nextToken();
} else if (lexer.token() == Token.WAIT) {
lexer.nextToken();
stmt.setWait(exprParser.expr());
}
return stmt;
}
public OracleBlockStatement parseBlock() {
OracleBlockStatement block = new OracleBlockStatement();
if (lexer.token() == Token.DECLARE) {
lexer.nextToken();
parserParameters(block.getParameters());
for (OracleParameter param : block.getParameters()) {
param.setParent(block);
}
}
accept(Token.BEGIN);
parseStatementList(block.getStatementList());
accept(Token.END);
return block;
}
private void parserParameters(List<OracleParameter> parameters) {
for (;;) {
OracleParameter parameter = new OracleParameter();
if (lexer.token() == Token.CURSOR) {
lexer.nextToken();
parameter.setName(this.exprParser.name());
accept(Token.IS);
SQLSelect select = this.createSQLSelectParser().select();
SQLDataTypeImpl dataType = new SQLDataTypeImpl();
dataType.setName("CURSOR");
parameter.setDataType(dataType);
parameter.setDefaultValue(new SQLQueryExpr(select));
} else {
parameter.setName(this.exprParser.name());
parameter.setDataType(this.exprParser.parseDataType());
if (lexer.token() == Token.COLONEQ) {
lexer.nextToken();
parameter.setDefaultValue(this.exprParser.expr());
}
}
parameters.add(parameter);
if (lexer.token() == Token.COMMA || lexer.token() == Token.SEMI) {
lexer.nextToken();
}
if (lexer.token() != Token.BEGIN && lexer.token() != Token.RPAREN) {
continue;
}
break;
}
}
public OracleSelectParser createSQLSelectParser() {
return new OracleSelectParser(this.exprParser);
}
public OracleMergeStatement parseMerge() {
accept(Token.MERGE);
OracleMergeStatement stmt = new OracleMergeStatement();
parseHints(stmt.getHints());
accept(Token.INTO);
stmt.setInto(exprParser.name());
stmt.setAlias(as());
accept(Token.USING);
SQLTableSource using = this.createSQLSelectParser().parseTableSource();
stmt.setUsing(using);
accept(Token.ON);
stmt.setOn(exprParser.expr());
boolean insertFlag = false;
if (lexer.token() == Token.WHEN) {
lexer.nextToken();
if (lexer.token() == Token.MATCHED) {
OracleMergeStatement.MergeUpdateClause updateClause = new OracleMergeStatement.MergeUpdateClause();
lexer.nextToken();
accept(Token.THEN);
accept(Token.UPDATE);
accept(Token.SET);
for (;;) {
SQLUpdateSetItem item = new SQLUpdateSetItem();
item.setColumn(this.exprParser.name());
accept(Token.EQ);
item.setValue(this.exprParser.expr());
updateClause.getItems().add(item);
if (lexer.token() == (Token.COMMA)) {
lexer.nextToken();
continue;
}
break;
}
if (lexer.token() == Token.WHERE) {
lexer.nextToken();
updateClause.setWhere(exprParser.expr());
}
if (lexer.token() == Token.DELETE) {
lexer.nextToken();
accept(Token.WHERE);
updateClause.setWhere(exprParser.expr());
}
stmt.setUpdateClause(updateClause);
} else if (lexer.token() == Token.NOT) {
lexer.nextToken();
insertFlag = true;
}
}
if (!insertFlag) {
if (lexer.token() == Token.WHEN) {
lexer.nextToken();
}
if (lexer.token() == Token.NOT) {
lexer.nextToken();
insertFlag = true;
}
}
if (insertFlag) {
OracleMergeStatement.MergeInsertClause insertClause = new OracleMergeStatement.MergeInsertClause();
accept(Token.MATCHED);
accept(Token.THEN);
accept(Token.INSERT);
if (lexer.token() == Token.LPAREN) {
accept(Token.LPAREN);
exprParser.exprList(insertClause.getColumns());
accept(Token.RPAREN);
}
accept(Token.VALUES);
accept(Token.LPAREN);
exprParser.exprList(insertClause.getValues());
accept(Token.RPAREN);
if (lexer.token() == Token.WHERE) {
lexer.nextToken();
insertClause.setWhere(exprParser.expr());
}
stmt.setInsertClause(insertClause);
}
OracleErrorLoggingClause errorClause = parseErrorLoggingClause();
stmt.setErrorLoggingClause(errorClause);
return stmt;
}
public OracleStatement parseInsert() {
if (lexer.token() == Token.LPAREN) {
OracleInsertStatement stmt = new OracleInsertStatement();
parseInsert0(stmt, false);
stmt.setReturning(parseReturningClause());
stmt.setErrorLogging(parseErrorLoggingClause());
return stmt;
}
accept(Token.INSERT);
List<SQLHint> hints = new ArrayList<SQLHint>();
parseHints(hints);
if (lexer.token() == Token.INTO) {
OracleInsertStatement stmt = new OracleInsertStatement();
stmt.setHints(hints);
parseInsert0(stmt);
stmt.setReturning(parseReturningClause());
stmt.setErrorLogging(parseErrorLoggingClause());
return stmt;
}
OracleMultiInsertStatement stmt = parseMultiInsert();
stmt.setHints(hints);
return stmt;
}
public OracleMultiInsertStatement parseMultiInsert() {
OracleMultiInsertStatement stmt = new OracleMultiInsertStatement();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
stmt.setOption(OracleMultiInsertStatement.Option.ALL);
} else if (lexer.token() == Token.FIRST) {
lexer.nextToken();
stmt.setOption(OracleMultiInsertStatement.Option.FIRST);
}
while (lexer.token() == Token.INTO) {
OracleMultiInsertStatement.InsertIntoClause clause = new OracleMultiInsertStatement.InsertIntoClause();
parseInsert0(clause);
clause.setReturning(parseReturningClause());
clause.setErrorLogging(parseErrorLoggingClause());
stmt.getEntries().add(clause);
}
if (lexer.token() == Token.WHEN) {
OracleMultiInsertStatement.ConditionalInsertClause clause = new OracleMultiInsertStatement.ConditionalInsertClause();
while (lexer.token() == Token.WHEN) {
lexer.nextToken();
OracleMultiInsertStatement.ConditionalInsertClauseItem item = new OracleMultiInsertStatement.ConditionalInsertClauseItem();
item.setWhen(this.exprParser.expr());
accept(Token.THEN);
OracleMultiInsertStatement.InsertIntoClause insertInto = new OracleMultiInsertStatement.InsertIntoClause();
parseInsert0(insertInto);
item.setThen(insertInto);
clause.getItems().add(item);
}
if (lexer.token() == Token.ELSE) {
lexer.nextToken();
OracleMultiInsertStatement.InsertIntoClause insertInto = new OracleMultiInsertStatement.InsertIntoClause();
parseInsert0(insertInto, false);
clause.setElseItem(insertInto);
}
stmt.getEntries().add(clause);
}
SQLSelect subQuery = this.createSQLSelectParser().select();
stmt.setSubQuery(subQuery);
return stmt;
}
private OracleExceptionStatement parseException() {
accept(Token.EXCEPTION);
OracleExceptionStatement stmt = new OracleExceptionStatement();
for (;;) {
accept(Token.WHEN);
OracleExceptionStatement.Item item = new OracleExceptionStatement.Item();
item.setWhen(this.exprParser.expr());
accept(Token.THEN);
parseStatementList(item.getStatements());
stmt.getItems().add(item);
if (lexer.token() != Token.WHEN) {
break;
}
}
return stmt;
}
private OracleErrorLoggingClause parseErrorLoggingClause() {
if (identifierEquals("LOG")) {
OracleErrorLoggingClause errorClause = new OracleErrorLoggingClause();
lexer.nextToken();
accept(Token.ERRORS);
if (lexer.token() == Token.INTO) {
lexer.nextToken();
errorClause.setInto(exprParser.name());
}
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
errorClause.setSimpleExpression(exprParser.expr());
accept(Token.RPAREN);
}
if (lexer.token() == Token.REJECT) {
lexer.nextToken();
accept(Token.LIMIT);
errorClause.setLimit(exprParser.expr());
}
return errorClause;
}
return null;
}
public OracleReturningClause parseReturningClause() {
OracleReturningClause clause = null;
if (lexer.token() == Token.RETURNING) {
lexer.nextToken();
clause = new OracleReturningClause();
for (;;) {
SQLExpr item = exprParser.expr();
clause.getItems().add(item);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.INTO);
for (;;) {
SQLExpr item = exprParser.expr();
clause.getValues().add(item);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
}
return clause;
}
public SQLStatement parseStatement() {
List<SQLStatement> list = new ArrayList<SQLStatement>();
this.parseStatementList(list, 1);
return list.get(0);
}
public OracleExplainStatement parseExplain() {
acceptIdentifier("EXPLAIN");
acceptIdentifier("PLAN");
OracleExplainStatement stmt = new OracleExplainStatement();
if (lexer.token() == Token.SET) {
lexer.nextToken();
acceptIdentifier("STATEMENT_ID");
accept(Token.EQ);
stmt.setStatementId((SQLCharExpr) this.exprParser.primary());
}
if (lexer.token() == Token.INTO) {
lexer.nextToken();
stmt.setInto(this.exprParser.name());
}
accept(Token.FOR);
stmt.setForStatement(parseStatement());
return stmt;
}
public OracleDeleteStatement parseDeleteStatement() {
OracleDeleteStatement deleteStatement = new OracleDeleteStatement();
if (lexer.token() == Token.DELETE) {
lexer.nextToken();
parseHints(deleteStatement.getHints());
if (lexer.token() == (Token.FROM)) {
lexer.nextToken();
}
if (identifierEquals("ONLY")) {
lexer.nextToken();
accept(Token.LPAREN);
SQLName tableName = exprParser.name();
deleteStatement.setTableName(tableName);
accept(Token.RPAREN);
} else {
SQLName tableName = exprParser.name();
deleteStatement.setTableName(tableName);
}
deleteStatement.setAlias(as());
}
if (lexer.token() == (Token.WHERE)) {
lexer.nextToken();
deleteStatement.setWhere(this.exprParser.expr());
}
if (lexer.token() == Token.RETURNING) {
OracleReturningClause clause = this.parseReturningClause();
deleteStatement.setReturning(clause);
}
if (identifierEquals("RETURN") || identifierEquals("RETURNING")) {
throw new ParserException("TODO");
}
if (identifierEquals("LOG")) {
throw new ParserException("TODO");
}
return deleteStatement;
}
public OracleCreateIndexStatement parseCreateIndex(boolean acceptCreate) {
if (acceptCreate) {
accept(Token.CREATE);
}
OracleCreateIndexStatement stmt = new OracleCreateIndexStatement();
if (lexer.token() == Token.UNIQUE) {
stmt.setType("UNIQUE");
lexer.nextToken();
} else if (identifierEquals("BITMAP")) {
stmt.setType("BITMAP");
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();
stmt.getItems().add(item);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
for (;;) {
if (identifierEquals("TABLESPACE")) {
lexer.nextToken();
stmt.setTablespace(this.exprParser.name());
continue;
} else if (identifierEquals("ONLINE")) {
lexer.nextToken();
stmt.setOnline(true);
continue;
} else if (identifierEquals("NOPARALLEL")) {
lexer.nextToken();
stmt.setNoParallel(true);
continue;
} else if (identifierEquals("PARALLEL")) {
lexer.nextToken();
stmt.setParallel(this.exprParser.expr());
continue;
} else if (lexer.token() == Token.INDEX) {
lexer.nextToken();
acceptIdentifier("ONLY");
acceptIdentifier("TOPLEVEL");
stmt.setIndexOnlyTopLevel(true);
continue;
} else {
break;
}
}
return stmt;
}
public OracleCreateSequenceStatement parseCreateSequence(boolean acceptCreate) {
if (acceptCreate) {
accept(Token.CREATE);
}
acceptIdentifier("SEQUENCE");
OracleCreateSequenceStatement stmt = new OracleCreateSequenceStatement();
stmt.setName(this.exprParser.name());
for (;;) {
if (lexer.token() == Token.START) {
lexer.nextToken();
accept(Token.WITH);
stmt.setStartWith(this.exprParser.expr());
continue;
} else if (identifierEquals("INCREMENT")) {
lexer.nextToken();
accept(Token.BY);
stmt.setIncrementBy(this.exprParser.expr());
continue;
} else if (identifierEquals("CACHE")) {
lexer.nextToken();
stmt.setCache(Boolean.TRUE);
continue;
} else if (identifierEquals("NOCACHE")) {
lexer.nextToken();
stmt.setCache(Boolean.FALSE);
continue;
} else if (identifierEquals("CYCLE")) {
lexer.nextToken();
stmt.setCycle(Boolean.TRUE);
continue;
} else if (identifierEquals("NOCYCLE")) {
lexer.nextToken();
stmt.setCycle(Boolean.FALSE);
continue;
}
break;
}
return stmt;
}
public OracleCreateProcedureStatement parseCreateProcedure() {
OracleCreateProcedureStatement stmt = new OracleCreateProcedureStatement();
accept(Token.CREATE);
if (lexer.token() == Token.OR) {
lexer.nextToken();
acceptIdentifier("REPLACE");
stmt.setOrReplace(true);
}
accept(Token.PROCEDURE);
stmt.setName(this.exprParser.name());
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
parserParameters(stmt.getParameters());
accept(Token.RPAREN);
}
accept(Token.AS);
OracleBlockStatement block = this.parseBlock();
stmt.setBlock(block);
return stmt;
}
public SQLUpdateStatement parseUpdateStatement() {
return new OracleUpdateParser(this.lexer).parseUpdateStatement();
}
}