/** * Alipay.com Inc. * Copyright (c) 2004-2012 All Rights Reserved. */ package com.alipay.zdal.parser.sql.dialect.oracle.parser; import java.util.ArrayList; import java.util.List; import com.alipay.zdal.parser.sql.ast.SQLDataTypeImpl; import com.alipay.zdal.parser.sql.ast.SQLExpr; import com.alipay.zdal.parser.sql.ast.SQLHint; import com.alipay.zdal.parser.sql.ast.SQLName; import com.alipay.zdal.parser.sql.ast.SQLStatement; import com.alipay.zdal.parser.sql.ast.expr.SQLBinaryOpExpr; import com.alipay.zdal.parser.sql.ast.expr.SQLBinaryOperator; import com.alipay.zdal.parser.sql.ast.expr.SQLCharExpr; import com.alipay.zdal.parser.sql.ast.expr.SQLNullExpr; import com.alipay.zdal.parser.sql.ast.expr.SQLQueryExpr; import com.alipay.zdal.parser.sql.ast.statement.SQLAlterTableAddColumn; import com.alipay.zdal.parser.sql.ast.statement.SQLColumnDefinition; import com.alipay.zdal.parser.sql.ast.statement.SQLConstaint; import com.alipay.zdal.parser.sql.ast.statement.SQLDropTableStatement; import com.alipay.zdal.parser.sql.ast.statement.SQLInsertInto; import com.alipay.zdal.parser.sql.ast.statement.SQLSelect; import com.alipay.zdal.parser.sql.ast.statement.SQLSelectOrderByItem; import com.alipay.zdal.parser.sql.ast.statement.SQLSelectStatement; import com.alipay.zdal.parser.sql.ast.statement.SQLSetStatement; import com.alipay.zdal.parser.sql.ast.statement.SQLTableSource; import com.alipay.zdal.parser.sql.ast.statement.SQLUpdateSetItem; import com.alipay.zdal.parser.sql.ast.statement.SQLUpdateStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.OracleParameter; import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterIndexStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterProcedureStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterSynonymStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableAddConstaint; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableDropPartition; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableItem; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableModify; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableMoveTablespace; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableRenameTo; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.NestedTablePartitionSpec; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.TableSpaceItem; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.UpdateIndexesClause; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTableTruncatePartition; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTablespaceAddDataFile; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTablespaceStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterTriggerStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleAlterViewStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleCommitStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleCreateIndexStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleCreateProcedureStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleExceptionStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleExitStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleExplainStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleExprStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleFetchStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleFileSpecification; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleForStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleGotoStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleGrantStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleIfStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleLabelStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleLockTableStatement.LockMode; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleLoopStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSavePointStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSetTransactionStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleStatement; import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleTruncateStatement; import com.alipay.zdal.parser.sql.parser.Lexer; import com.alipay.zdal.parser.sql.parser.ParserException; import com.alipay.zdal.parser.sql.parser.SQLStatementParser; import com.alipay.zdal.parser.sql.parser.Token; /** * * @author ���� * @version $Id: OracleStatementParser.java, v 0.1 2012-11-17 ����3:52:17 Exp $ */ 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 parseInsert0Hinits(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) throws ParserException { parseStatementList(statementList, -1); } public void parseStatementList(List<SQLStatement> statementList, int max) throws ParserException { 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 (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() throws ParserException { 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() throws ParserException { 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() throws ParserException { return new OracleUpdateParser(this.lexer).parseUpdateStatement(); } }