/* * Copyright 1999-2017 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.*; import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.*; 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.OracleLockTableStatement.LockMode; 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; import com.alibaba.druid.util.JdbcConstants; 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 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); } } public void parseStatementList(List<SQLStatement> statementList, int max, SQLObject parent) { 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)) { SQLSelectStatement stmt = new SQLSelectStatement(new OracleSelectParser(this.exprParser).select(), JdbcConstants.ORACLE); statementList.add(stmt); 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(), getDbType()); statementList.add(stmt); continue; } } accept(Token.COLONEQ); SQLExpr value = this.exprParser.expr(); SQLSetStatement stmt = new SQLSetStatement(variant, value, getDbType()); statementList.add(stmt); continue; } if (lexer.token() == Token.EXCEPTION) { OracleExceptionStatement stmt = this.parseException(); if (parent instanceof SQLBlockStatement) { ((SQLBlockStatement) parent).setException(stmt); } else { statementList.add(stmt); } 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 (lexer.token() == Token.CONTINUE) { lexer.nextToken(); OracleConntinueStatement stmt = new OracleConntinueStatement(); if (lexer.token() == Token.IDENTIFIER) { SQLName label = this.exprParser.name(); stmt.setLabel(label); } if (lexer.token() == Token.WHEN) { lexer.nextToken(); stmt.setWhen(this.exprParser.expr()); } statementList.add(stmt); continue; } if (lexer.token() == Token.FETCH || identifierEquals("FETCH")) { SQLStatement stmt = parseFetch(); statementList.add(stmt); continue; } if (identifierEquals("ROLLBACK")) { SQLRollbackStatement stmt = parseRollback(); stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.EXPLAIN) { OracleExplainStatement stmt = this.parseExplain(); stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.IDENTIFIER) { String strVal = lexer.stringVal(); if (strVal.equalsIgnoreCase("RAISE")) { statementList.add(this.parseRaise()); continue; } if (strVal.equalsIgnoreCase("FORALL")) { SQLStatement forAll = this.parseFor(); statementList.add(forAll); continue; } SQLExpr expr = exprParser.expr(); OracleExprStatement stmt = new OracleExprStatement(expr); stmt.setParent(parent); 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.REVOKE) { statementList.add(this.parseRevoke()); continue; } if (lexer.token() == Token.COMMENT) { statementList.add(this.parseComment()); continue; } if (lexer.token() == Token.FOR) { OracleForStatement forStatement = this.parseFor(); if (lexer.token() == Token.IDENTIFIER) { String strVal = lexer.stringVal(); int stmtListSize = statementList.size(); if (stmtListSize > 0) { SQLStatement lastStmt = statementList.get(stmtListSize - 1); if (lastStmt instanceof OracleLabelStatement) { if (((OracleLabelStatement) lastStmt).getLabel().getSimpleName().equalsIgnoreCase(strVal)) { SQLName endLabbel = this.exprParser.name(); forStatement.setEndLabel(endLabbel); } } } } statementList.add(forStatement); 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 (lexer.token() == Token.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 (lexer.token() == Token.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; } boolean isPublic = false; if (identifierEquals("PUBLIC")) { lexer.nextToken(); isPublic = true; } if (lexer.token() == Token.DATABASE) { lexer.nextToken(); if (identifierEquals("LINK")) { lexer.nextToken(); OracleDropDbLinkStatement stmt = new OracleDropDbLinkStatement(); if (isPublic) { stmt.setPublic(isPublic); } stmt.setName(this.exprParser.name()); statementList.add(stmt); continue; } } if (lexer.token() == Token.INDEX) { SQLStatement stmt = parseDropIndex(); statementList.add(stmt); continue; } if (lexer.token() == Token.VIEW) { SQLStatement stmt = parseDropView(false); statementList.add(stmt); continue; } if (lexer.token() == Token.SEQUENCE) { SQLDropSequenceStatement stmt = parseDropSequece(false); statementList.add(stmt); continue; } if (lexer.token() == Token.TRIGGER) { SQLDropTriggerStatement stmt = parseDropTrigger(false); statementList.add(stmt); continue; } if (lexer.token() == Token.USER) { SQLDropUserStatement stmt = parseDropUser(); statementList.add(stmt); continue; } if (lexer.token() == Token.PROCEDURE) { SQLDropProcedureStatement stmt = parseDropProcedure(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; } if (lexer.token() == Token.OPEN) { SQLStatement stmt = this.parseOpen(); statementList.add(stmt); continue; } if (lexer.token() == Token.CLOSE) { SQLStatement stmt = this.parseClose(); statementList.add(stmt); continue; } if (lexer.token() == Token.CASE) { SQLStatement stmt = this.parseCase(); statementList.add(stmt); continue; } if (lexer.token() == Token.PROCEDURE) { SQLStatement stmt = this.parseCreateProcedure(); statementList.add(stmt); continue; } if (lexer.token() == Token.ELSIF && parent instanceof SQLIfStatement) { break; } if (lexer.token() == Token.WHEN && parent instanceof OracleExceptionStatement.Item) { break; } throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } public SQLStatement parseRaise() { lexer.nextToken(); OracleRaiseStatement stmt = new OracleRaiseStatement(); if (lexer.token() != Token.SEMI) { stmt.setException(this.exprParser.expr()); } return stmt; } public SQLStatement parseCase() { SQLCaseStatement caseStmt = new SQLCaseStatement(); lexer.nextToken(); if (lexer.token() != Token.WHEN) { caseStmt.setValueExpr(this.exprParser.expr()); } accept(Token.WHEN); SQLExpr testExpr = this.exprParser.expr(); accept(Token.THEN); SQLStatement stmt = this.parseStatement(); if (lexer.token() == Token.SEMI) { lexer.nextToken(); } SQLCaseStatement.Item caseItem = new SQLCaseStatement.Item(testExpr, stmt); caseStmt.addItem(caseItem); while (lexer.token() == Token.WHEN) { lexer.nextToken(); testExpr = this.exprParser.expr(); accept(Token.THEN); stmt = this.parseStatement(); if (lexer.token() == Token.SEMI) { lexer.nextToken(); } caseItem = new SQLCaseStatement.Item(testExpr, stmt); caseStmt.addItem(caseItem); } if (lexer.token() == Token.ELSE) { lexer.nextToken(); this.parseStatementList(caseStmt.getElseStatements(), -1, caseStmt); } accept(Token.END); accept(Token.CASE); return caseStmt; } public SQLStatement parseIf() { accept(Token.IF); SQLIfStatement stmt = new SQLIfStatement(); stmt.setCondition(this.exprParser.expr()); accept(Token.THEN); this.parseStatementList(stmt.getStatements(), -1, stmt); while (lexer.token() == Token.ELSIF) { lexer.nextToken(); SQLIfStatement.ElseIf elseIf = new SQLIfStatement.ElseIf(); elseIf.setCondition(this.exprParser.expr()); accept(Token.THEN); this.parseStatementList(elseIf.getStatements(), -1, stmt); stmt.getElseIfList().add(elseIf); } while (lexer.token() == Token.ELSE) { lexer.nextToken(); if (lexer.token() == Token.IF) { lexer.nextToken(); SQLIfStatement.ElseIf elseIf = new SQLIfStatement.ElseIf(); elseIf.setCondition(this.exprParser.expr()); accept(Token.THEN); this.parseStatementList(elseIf.getStatements()); stmt.getElseIfList().add(elseIf); } else { SQLIfStatement.Else elseItem = new SQLIfStatement.Else(); this.parseStatementList(elseItem.getStatements()); stmt.setElseItem(elseItem); break; } } accept(Token.END); accept(Token.IF); return stmt; } public OracleForStatement parseFor() { OracleForStatement stmt = new OracleForStatement(); if (lexer.token() == Token.FOR) { lexer.nextToken(); } else { acceptIdentifier("FORALL"); stmt.setAll(true); } stmt.setIndex(this.exprParser.name()); accept(Token.IN); stmt.setRange(this.exprParser.expr()); if (stmt.isAll()) { SQLStatement itemStmt = this.parseStatement(); itemStmt.setParent(stmt); stmt.getStatements().add(itemStmt); } else { accept(Token.LOOP); this.parseStatementList(stmt.getStatements(), -1, stmt); accept(Token.END); accept(Token.LOOP); } return stmt; } public SQLLoopStatement parseLoop() { accept(Token.LOOP); SQLLoopStatement stmt = new SQLLoopStatement(); this.parseStatementList(stmt.getStatements(), -1, stmt); accept(Token.END); accept(Token.LOOP); 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 SQLStatement 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(), stmt); } 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(); accept(Token.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 (lexer.token() == Token.TRIGGER) { lexer.nextToken(); OracleAlterTriggerStatement stmt = new OracleAlterTriggerStatement(); stmt.setName(this.exprParser.name()); for (;;) { if (lexer.token() == Token.ENABLE) { lexer.nextToken(); stmt.setEnable(Boolean.TRUE); continue; } else if (lexer.token() == Token.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 (lexer.token() == Token.ENABLE) { lexer.nextToken(); stmt.setEnable(Boolean.TRUE); continue; } else if (lexer.token() == Token.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 (lexer.token() == Token.ENABLE) { lexer.nextToken(); stmt.setEnable(Boolean.TRUE); continue; } else if (lexer.token() == Token.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.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 SQLStatement parseAlterTable() { lexer.nextToken(); SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType()); stmt.setName(this.exprParser.name()); for (;;) { if (identifierEquals("ADD")) { lexer.nextToken(); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); SQLAlterTableAddColumn item = parseAlterTableAddColumn(); stmt.addItem(item); accept(Token.RPAREN); } else if (lexer.token() == Token.CONSTRAINT) { OracleConstraint constraint = ((OracleExprParser) this.exprParser).parseConstaint(); SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(); constraint.setParent(item); item.setParent(stmt); item.setConstraint(constraint); stmt.addItem(item); } else if (lexer.token() == Token.IDENTIFIER) { SQLAlterTableAddColumn item = parseAlterTableAddColumn(); stmt.addItem(item); } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } continue; } else if (identifierEquals("MOVE")) { lexer.nextToken(); if (lexer.token() == Token.TABLESPACE) { lexer.nextToken(); OracleAlterTableMoveTablespace item = new OracleAlterTableMoveTablespace(); item.setName(this.exprParser.name()); stmt.addItem(item); } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } else if (identifierEquals("RENAME")) { stmt.addItem(parseAlterTableRename()); } else if (identifierEquals("MODIFY")) { lexer.nextToken(); OracleAlterTableModify item = new OracleAlterTableModify(); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); for (;;) { SQLColumnDefinition columnDef = this.exprParser.parseColumn(); item.addColumn(columnDef); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } accept(Token.RPAREN); } else { SQLColumnDefinition columnDef = this.exprParser.parseColumn(); item.addColumn(columnDef); } stmt.addItem(item); 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.addItem(item); } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } continue; } else if (lexer.token() == Token.DROP) { parseAlterDrop(stmt); continue; } else if (lexer.token() == Token.DISABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); SQLAlterTableEnableConstraint item = new SQLAlterTableEnableConstraint(); item.setConstraintName(this.exprParser.name()); stmt.addItem(item); } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } else if (lexer.token() == Token.ENABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); SQLAlterTableDisableConstraint item = new SQLAlterTableDisableConstraint(); item.setConstraintName(this.exprParser.name()); stmt.addItem(item); } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } 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; } public void parseAlterDrop(SQLAlterTableStatement stmt) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); SQLAlterTableDropConstraint item = new SQLAlterTableDropConstraint(); item.setConstraintName(this.exprParser.name()); stmt.addItem(item); } else if (lexer.token() == Token.LPAREN) { lexer.nextToken(); SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem(); this.exprParser.names(item.getColumns()); stmt.addItem(item); accept(Token.RPAREN); } else if (lexer.token() == Token.COLUMN) { lexer.nextToken(); SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem(); this.exprParser.names(item.getColumns()); stmt.addItem(item); } else if (identifierEquals("PARTITION")) { lexer.nextToken(); OracleAlterTableDropPartition item = new OracleAlterTableDropPartition(); item.setName(this.exprParser.name()); stmt.addItem(item); } else if (lexer.token() == Token.INDEX) { lexer.nextToken(); SQLName indexName = this.exprParser.name(); SQLAlterTableDropIndex item = new SQLAlterTableDropIndex(); item.setIndexName(indexName); stmt.addItem(item); } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } private void parseAlterTableSplit(SQLAlterTableStatement 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(), item); 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 (lexer.token() == Token.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.addItem(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 SQLBlockStatement parseBlock() { SQLBlockStatement block = new SQLBlockStatement(); block.setDbType(JdbcConstants.ORACLE); if (lexer.token() == Token.DECLARE) { lexer.nextToken(); } if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.CURSOR) { parserParameters(block.getParameters(), block); for (SQLParameter param : block.getParameters()) { param.setParent(block); } } accept(Token.BEGIN); parseStatementList(block.getStatementList(), -1, block); accept(Token.END); return block; } private void parserParameters(List<SQLParameter> parameters, SQLObject parent) { for (;;) { SQLParameter parameter = new SQLParameter(); SQLName name; SQLDataType dataType; if (lexer.token() == Token.CURSOR) { lexer.nextToken(); name = this.exprParser.name(); accept(Token.IS); SQLSelect select = this.createSQLSelectParser().select(); dataType = new SQLDataTypeImpl(); dataType.setName("CURSOR"); parameter.setDefaultValue(new SQLQueryExpr(select)); } else if (lexer.token() == Token.PROCEDURE) { break; } else if (identifierEquals("TYPE")) { lexer.nextToken(); name = this.exprParser.name(); accept(Token.IS); if (identifierEquals("REF")) { lexer.nextToken(); accept(Token.CURSOR); dataType = new SQLDataTypeImpl("REF CURSOR"); } else if (lexer.token() == Token.TABLE) { lexer.nextToken(); accept(Token.OF); name = this.exprParser.name(); if (lexer.token() == Token.PERCENT) { lexer.nextToken(); acceptIdentifier("TYPE"); } String typeName = "TABLE OF " + name.toString() + "%TYPE"; dataType = new SQLDataTypeImpl(typeName); } else if (identifierEquals("VARRAY")) { lexer.nextToken(); accept(Token.LPAREN); int len = this.exprParser.acceptInteger(); accept(Token.RPAREN); accept(Token.OF); if (identifierEquals("NUMBER")) { lexer.nextToken(); String typeName = "VARRAY(" + len + ") OF NUMBER"; dataType = new SQLDataTypeImpl(typeName); } else { throw new ParserException("TODO : " + lexer.info()); } } else { throw new ParserException("TODO : " + lexer.info()); } } else { name = this.exprParser.name(); if (lexer.token() == Token.IN) { lexer.nextToken(); if (lexer.token() == Token.OUT) { lexer.nextToken(); parameter.setParamType(SQLParameter.ParameterType.INOUT); } else { parameter.setParamType(SQLParameter.ParameterType.IN); } } else if (lexer.token() == Token.OUT) { lexer.nextToken(); parameter.setParamType(SQLParameter.ParameterType.OUT); } if (identifierEquals("NOCOPY")) { lexer.nextToken(); parameter.setNoCopy(true); } if (identifierEquals("CONSTANT")) { lexer.nextToken(); parameter.setConstant(true); } dataType = this.exprParser.parseDataType(); if (lexer.token() == Token.COLONEQ) { lexer.nextToken(); parameter.setDefaultValue(this.exprParser.expr()); } } parameter.setName(name); parameter.setDataType(dataType); 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 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.addEntry(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.addItem(item); } if (lexer.token() == Token.ELSE) { lexer.nextToken(); OracleMultiInsertStatement.InsertIntoClause insertInto = new OracleMultiInsertStatement.InsertIntoClause(); parseInsert0(insertInto, false); clause.setElseItem(insertInto); } stmt.addEntry(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); this.parseStatementList(item.getStatements(), -1, item); stmt.addItem(item); if (lexer.token() == Token.SEMI) { lexer.nextToken(); } if (lexer.token() != Token.WHEN) { break; } } return stmt; } public OracleReturningClause parseReturningClause() { OracleReturningClause clause = null; if (lexer.token() == Token.RETURNING) { lexer.nextToken(); clause = new OracleReturningClause(); for (;;) { SQLExpr item = exprParser.expr(); clause.addItem(item); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } accept(Token.INTO); for (;;) { SQLExpr item = exprParser.expr(); clause.addValue(item); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } } return clause; } public OracleExplainStatement parseExplain() { accept(Token.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.setStatement(parseStatement()); return stmt; } public OracleDeleteStatement parseDeleteStatement() { OracleDeleteStatement deleteStatement = new OracleDeleteStatement(); if (lexer.token() == Token.DELETE) { lexer.nextToken(); if (lexer.token() == Token.COMMENT) { 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 if (lexer.token() == Token.LPAREN) { SQLTableSource tableSource = this.createSQLSelectParser().parseTableSource(); deleteStatement.setTableSource(tableSource); } else { SQLName tableName = exprParser.name(); deleteStatement.setTableName(tableName); } deleteStatement.setAlias(tableAlias()); } 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 SQLStatement parseCreateDbLink() { accept(Token.CREATE); OracleCreateDatabaseDbLinkStatement dbLink = new OracleCreateDatabaseDbLinkStatement(); if (identifierEquals("SHARED")) { dbLink.setShared(true); lexer.nextToken(); } if (identifierEquals("PUBLIC")) { dbLink.setPublic(true); lexer.nextToken(); } accept(Token.DATABASE); acceptIdentifier("LINK"); dbLink.setName(this.exprParser.name()); if (lexer.token() == Token.CONNECT) { lexer.nextToken(); accept(Token.TO); dbLink.setUser(this.exprParser.name()); if (lexer.token() == Token.IDENTIFIED) { lexer.nextToken(); accept(Token.BY); dbLink.setPassword(lexer.stringVal()); if (lexer.token() == Token.IDENTIFIER) { lexer.nextToken(); } else { accept(Token.LITERAL_ALIAS); } } } if (identifierEquals("AUTHENTICATED")) { lexer.nextToken(); accept(Token.BY); dbLink.setAuthenticatedUser(this.exprParser.name()); accept(Token.IDENTIFIED); accept(Token.BY); dbLink.setPassword(lexer.stringVal()); accept(Token.IDENTIFIER); } if (lexer.token() == Token.USING) { lexer.nextToken(); dbLink.setUsing(this.exprParser.expr()); } return dbLink; } 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.addItem(item); if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } break; } accept(Token.RPAREN); for (;;) { if (lexer.token() == Token.TABLESPACE) { lexer.nextToken(); stmt.setTablespace(this.exprParser.name()); continue; } else if (lexer.token() == Token.PCTFREE) { lexer.nextToken(); stmt.setPtcfree(this.exprParser.expr()); continue; } else if (lexer.token() == Token.INITRANS) { lexer.nextToken(); stmt.setInitrans(this.exprParser.expr()); continue; } else if (lexer.token() == Token.MAXTRANS) { lexer.nextToken(); stmt.setMaxtrans(this.exprParser.expr()); continue; } else if (lexer.token() == Token.COMPUTE) { lexer.nextToken(); acceptIdentifier("STATISTICS"); stmt.setComputeStatistics(true); continue; } else if (lexer.token() == Token.ENABLE) { lexer.nextToken(); stmt.setEnable(true); continue; } else if (lexer.token() == Token.DISABLE) { lexer.nextToken(); stmt.setEnable(false); 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 SQLCreateSequenceStatement parseCreateSequence(boolean acceptCreate) { if (acceptCreate) { accept(Token.CREATE); } accept(Token.SEQUENCE); SQLCreateSequenceStatement stmt = new SQLCreateSequenceStatement(); stmt.setDbType(JdbcConstants.ORACLE); 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 (lexer.token() == Token.CACHE) { lexer.nextToken(); stmt.setCache(Boolean.TRUE); continue; } else if (lexer.token() == Token.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; } else if (identifierEquals("MINVALUE")) { lexer.nextToken(); stmt.setMinValue(this.exprParser.expr()); continue; } else if (identifierEquals("MAXVALUE")) { lexer.nextToken(); stmt.setMaxValue(this.exprParser.expr()); continue; } else if (identifierEquals("NOMAXVALUE")) { lexer.nextToken(); stmt.setNoMaxValue(true); continue; } else if (identifierEquals("NOMINVALUE")) { lexer.nextToken(); stmt.setNoMinValue(true); continue; } break; } return stmt; } public SQLCreateProcedureStatement parseCreateProcedure() { SQLCreateProcedureStatement stmt = new SQLCreateProcedureStatement(); stmt.setDbType(dbType); if (lexer.token() == Token.CREATE) { lexer.nextToken(); if (lexer.token() == Token.OR) { lexer.nextToken(); accept(Token.REPLACE); stmt.setOrReplace(true); } } else { stmt.setCreate(false); } accept(Token.PROCEDURE); SQLName procedureName = this.exprParser.name(); stmt.setName(procedureName); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); parserParameters(stmt.getParameters(), stmt); accept(Token.RPAREN); } if (identifierEquals("AUTHID")) { lexer.nextToken(); String strVal = lexer.stringVal(); if (identifierEquals("CURRENT_USER")) { lexer.nextToken(); } else { acceptIdentifier("DEFINER"); } SQLName authid = new SQLIdentifierExpr(strVal); stmt.setAuthid(authid); } if (lexer.token() == Token.IS) { lexer.nextToken(); } else { accept(Token.AS); } if (identifierEquals("LANGUAGE")) { lexer.nextToken(); if (identifierEquals("JAVA")) { lexer.nextToken(); acceptIdentifier("NAME"); String javaCallSpec = lexer.stringVal(); accept(Token.LITERAL_CHARS); stmt.setJavaCallSpec(javaCallSpec); } else { throw new ParserException("TODO : " + lexer.info()); } return stmt; } SQLBlockStatement block = this.parseBlock(); stmt.setBlock(block); if (identifierEquals(procedureName.getSimpleName())) { lexer.nextToken(); } return stmt; } public SQLUpdateStatement parseUpdateStatement() { return new OracleUpdateParser(this.lexer).parseUpdateStatement(); } }