/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.parser.sql.dialect.oracle.parser;
import com.alipay.zdal.parser.sql.ast.SQLExpr;
import com.alipay.zdal.parser.sql.ast.SQLSetQuantifier;
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.SQLIdentifierExpr;
import com.alipay.zdal.parser.sql.ast.expr.SQLListExpr;
import com.alipay.zdal.parser.sql.ast.statement.SQLSelectGroupByClause;
import com.alipay.zdal.parser.sql.ast.statement.SQLSelectQuery;
import com.alipay.zdal.parser.sql.ast.statement.SQLTableSource;
import com.alipay.zdal.parser.sql.ast.statement.SQLUnionOperator;
import com.alipay.zdal.parser.sql.ast.statement.SQLUnionQuery;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.CycleClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.FlashbackQueryClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.GroupingSetExpr;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.PartitionExtensionClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.SampleClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.SearchClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.SubqueryFactoringClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfSnapshotClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleOrderByItem;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelect;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectForUpdate;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectHierachicalQueryClause;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectJoin;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectPivot;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectRestriction;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSource;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectTableSource;
import com.alipay.zdal.parser.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot;
import com.alipay.zdal.parser.sql.parser.ParserException;
import com.alipay.zdal.parser.sql.parser.SQLExprParser;
import com.alipay.zdal.parser.sql.parser.SQLParserException;
import com.alipay.zdal.parser.sql.parser.SQLSelectParser;
import com.alipay.zdal.parser.sql.parser.Token;
/**
*
* @author ����
* @version $Id: OracleSelectParser.java, v 0.1 2012-11-17 ����3:52:07 Exp $
*/
public class OracleSelectParser extends SQLSelectParser {
public OracleSelectParser(String sql) {
super(new OracleExprParser(sql));
}
public OracleSelectParser(SQLExprParser exprParser) {
super(exprParser);
}
@Override
public OracleSelect select() {
OracleSelect select = new OracleSelect();
if (lexer.token() == Token.WITH) {
lexer.nextToken();
SubqueryFactoringClause subqueryFactoringClause = new SubqueryFactoringClause();
for (;;) {
SubqueryFactoringClause.Entry entry = new SubqueryFactoringClause.Entry();
entry.setName((SQLIdentifierExpr) this.exprParser.name());
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
exprParser.names(entry.getColumns());
accept(Token.RPAREN);
}
accept(Token.AS);
accept(Token.LPAREN);
entry.setSubQuery(query());
accept(Token.RPAREN);
if (identifierEquals("SEARCH")) {
lexer.nextToken();
SearchClause searchClause = new SearchClause();
if (lexer.token() != Token.IDENTIFIER) {
throw new SQLParserException("syntax erorr : " + lexer.token());
}
searchClause.setType(SearchClause.Type.valueOf(lexer.stringVal()));
lexer.nextToken();
acceptIdentifier("FIRST");
accept(Token.BY);
searchClause.getItems().add(
(OracleOrderByItem) exprParser.parseSelectOrderByItem());
while (lexer.token() == (Token.COMMA)) {
lexer.nextToken();
searchClause.getItems().add(
(OracleOrderByItem) exprParser.parseSelectOrderByItem());
}
accept(Token.SET);
searchClause.setOrderingColumn((SQLIdentifierExpr) exprParser.name());
entry.setSearchClause(searchClause);
}
if (identifierEquals("CYCLE")) {
lexer.nextToken();
CycleClause cycleClause = new CycleClause();
exprParser.exprList(cycleClause.getAliases());
accept(Token.SET);
cycleClause.setMark(exprParser.expr());
acceptIdentifier("TO");
cycleClause.setValue(exprParser.expr());
accept(Token.DEFAULT);
cycleClause.setDefaultValue(exprParser.expr());
entry.setCycleClause(cycleClause);
}
subqueryFactoringClause.getEntries().add(entry);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
select.setFactoring(subqueryFactoringClause);
}
select.setQuery(query());
select.setOrderBy(this.parseOrderBy());
if (lexer.token() == (Token.FOR)) {
lexer.nextToken();
accept(Token.UPDATE);
OracleSelectForUpdate forUpdate = new OracleSelectForUpdate();
if (lexer.token() == Token.OF) {
lexer.nextToken();
this.exprParser.exprList(forUpdate.getOf());
}
if (lexer.token() == Token.NOWAIT) {
lexer.nextToken();
forUpdate.setNotWait(true);
} else if (lexer.token() == Token.WAIT) {
lexer.nextToken();
forUpdate.setWait(this.exprParser.primary());
} else if (identifierEquals("SKIP")) {
lexer.nextToken();
acceptIdentifier("LOCKED");
forUpdate.setSkipLocked(true);
}
select.setForUpdate(forUpdate);
}
if (select.getOrderBy() == null) {
select.setOrderBy(this.exprParser.parseOrderBy());
}
if (lexer.token() == Token.WITH) {
lexer.nextToken();
if (identifierEquals("READ")) {
lexer.nextToken();
if (identifierEquals("ONLY"))
lexer.nextToken();
else {
throw new ParserException("syntax error");
}
select.setRestriction(new OracleSelectRestriction.ReadOnly());
} else if (lexer.token() == (Token.CHECK)) {
lexer.nextToken();
if (identifierEquals("OPTION"))
lexer.nextToken();
else {
throw new ParserException("syntax error");
}
OracleSelectRestriction.CheckOption checkOption = new OracleSelectRestriction.CheckOption();
if (lexer.token() == Token.CONSTRAINT) {
lexer.nextToken();
throw new ParserException("TODO");
}
select.setRestriction(checkOption);
} else if (lexer.token() == Token.RR) {
lexer.nextToken();
} else if (lexer.token() == Token.RS) {
lexer.nextToken();
} else if (lexer.token() == Token.UR) {
lexer.nextToken();
} else {
throw new ParserException("syntax error");
}
}
return select;
}
@Override
public SQLSelectQuery query() {
if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
SQLSelectQuery select = query();
accept(Token.RPAREN);
return queryRest(select);
}
OracleSelectQueryBlock queryBlock = new OracleSelectQueryBlock();
if (lexer.token() == Token.SELECT) {
lexer.nextToken();
parseHints(queryBlock);
if (lexer.token() == (Token.DISTINCT)) {
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
lexer.nextToken();
} else if (lexer.token() == (Token.UNIQUE)) {
queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);
lexer.nextToken();
} else if (lexer.token() == (Token.ALL)) {
queryBlock.setDistionOption(SQLSetQuantifier.ALL);
lexer.nextToken();
}
this.exprParser.parseHints(queryBlock.getHints());
parseSelectList(queryBlock);
}
parseInto(queryBlock);
parseFrom(queryBlock);
parseWhere(queryBlock);
parseHierachical(queryBlock);
parseGroupBy(queryBlock);
// parseModelClause(queryBlock);
return queryRest(queryBlock);
}
@Override
public SQLSelectQuery queryRest(SQLSelectQuery selectQuery) {
if (lexer.token() == (Token.UNION)) {
SQLUnionQuery union = new SQLUnionQuery();
union.setLeft(selectQuery);
lexer.nextToken();
if (lexer.token() == (Token.ALL)) {
union.setOperator(SQLUnionOperator.UNION_ALL);
lexer.nextToken();
} else if (lexer.token() == (Token.DISTINCT)) {
union.setOperator(SQLUnionOperator.DISTINCT);
lexer.nextToken();
}
SQLSelectQuery right = query();
union.setRight(right);
return queryRest(union);
}
if (lexer.token() == Token.INTERSECT) {
lexer.nextToken();
SQLUnionQuery union = new SQLUnionQuery();
union.setLeft(selectQuery);
union.setOperator(SQLUnionOperator.INTERSECT);
SQLSelectQuery right = this.query();
union.setRight(right);
return union;
}
if (lexer.token() == Token.MINUS) {
lexer.nextToken();
SQLUnionQuery union = new SQLUnionQuery();
union.setLeft(selectQuery);
union.setOperator(SQLUnionOperator.MINUS);
SQLSelectQuery right = this.query();
union.setRight(right);
return union;
}
return selectQuery;
}
// private void parseModelClause(OracleSelectQueryBlock queryBlock) {
// if (lexer.token() != Token.MODEL) {
// return;
// }
//
// lexer.nextToken();
//
// ModelClause model = new ModelClause();
// parseCellReferenceOptions(model.getCellReferenceOptions());
//
// if (identifierEquals("RETURN")) {
// lexer.nextToken();
// ReturnRowsClause returnRowsClause = new ReturnRowsClause();
// if (lexer.token() == Token.ALL) {
// lexer.nextToken();
// returnRowsClause.setAll(true);
// } else {
// acceptIdentifier("UPDATED");
// }
// acceptIdentifier("ROWS");
//
// model.setReturnRowsClause(returnRowsClause);
// }
//
// while (identifierEquals("REFERENCE")) {
// ReferenceModelClause referenceModelClause = new ReferenceModelClause();
// lexer.nextToken();
//
// SQLExpr name = expr();
// referenceModelClause.setName(name);
//
// accept(Token.ON);
// accept(Token.LPAREN);
// OracleSelect subQuery = this.select();
// accept(Token.RPAREN);
// referenceModelClause.setSubQuery(subQuery);
//
// parseModelColumnClause();
//
// parseCellReferenceOptions(referenceModelClause.getCellReferenceOptions());
//
// model.getReferenceModelClauses().add(referenceModelClause);
// }
//
// parseMainModelClause(model);
//
// queryBlock.setModelClause(model);
// }
// private void parseMainModelClause(ModelClause modelClause) {
// MainModelClause mainModel = new MainModelClause();
//
// if (identifierEquals("MAIN")) {
// lexer.nextToken();
// mainModel.setMainModelName(expr());
// }
//
// ModelColumnClause modelColumnClause = new ModelColumnClause();
// parseQueryPartitionClause(modelColumnClause);
// mainModel.setModelColumnClause(modelColumnClause);
//
// acceptIdentifier("DIMENSION");
// accept(Token.BY);
// accept(Token.LPAREN);
// for (;;) {
// if (lexer.token() == Token.RPAREN) {
// lexer.nextToken();
// break;
// }
//
// ModelColumn column = new ModelColumn();
// column.setExpr(expr());
// column.setAlias(as());
// modelColumnClause.getDimensionByColumns().add(column);
//
// if (lexer.token() == Token.COMMA) {
// lexer.nextToken();
// continue;
// }
// }
//
// acceptIdentifier("MEASURES");
// accept(Token.LPAREN);
// for (;;) {
// if (lexer.token() == Token.RPAREN) {
// lexer.nextToken();
// break;
// }
//
// ModelColumn column = new ModelColumn();
// column.setExpr(expr());
// column.setAlias(as());
// modelColumnClause.getMeasuresColumns().add(column);
//
// if (lexer.token() == Token.COMMA) {
// lexer.nextToken();
// continue;
// }
// }
// mainModel.setModelColumnClause(modelColumnClause);
//
// parseCellReferenceOptions(mainModel.getCellReferenceOptions());
//
// parseModelRulesClause(mainModel);
//
// modelClause.setMainModel(mainModel);
// }
// private void parseModelRulesClause(MainModelClause mainModel) {
// ModelRulesClause modelRulesClause = new ModelRulesClause();
// if (identifierEquals("RULES")) {
// lexer.nextToken();
// if (lexer.token() == Token.UPDATE) {
// modelRulesClause.getOptions().add(ModelRuleOption.UPDATE);
// lexer.nextToken();
// } else if (identifierEquals("UPSERT")) {
// modelRulesClause.getOptions().add(ModelRuleOption.UPSERT);
// lexer.nextToken();
// }
//
// if (identifierEquals("AUTOMATIC")) {
// lexer.nextToken();
// accept(Token.ORDER);
// modelRulesClause.getOptions().add(ModelRuleOption.AUTOMATIC_ORDER);
// } else if (identifierEquals("SEQUENTIAL")) {
// lexer.nextToken();
// accept(Token.ORDER);
// modelRulesClause.getOptions().add(ModelRuleOption.SEQUENTIAL_ORDER);
// }
// }
//
// if (identifierEquals("ITERATE")) {
// lexer.nextToken();
// accept(Token.LPAREN);
// modelRulesClause.setIterate(expr());
// accept(Token.RPAREN);
//
// if (identifierEquals("UNTIL")) {
// lexer.nextToken();
// accept(Token.LPAREN);
// modelRulesClause.setUntil(expr());
// accept(Token.RPAREN);
// }
// }
//
// accept(Token.LPAREN);
// for (;;) {
// if (lexer.token() == Token.RPAREN) {
// lexer.nextToken();
// break;
// }
//
// CellAssignmentItem item = new CellAssignmentItem();
// if (lexer.token() == Token.UPDATE) {
// item.setOption(ModelRuleOption.UPDATE);
// } else if (identifierEquals("UPSERT")) {
// item.setOption(ModelRuleOption.UPSERT);
// }
//
// item.setCellAssignment(parseCellAssignment());
// item.setOrderBy(this.parseOrderBy());
// accept(Token.EQ);
// item.setExpr(expr());
//
// modelRulesClause.getCellAssignmentItems().add(item);
// }
//
// mainModel.setModelRulesClause(modelRulesClause);
// }
// private CellAssignment parseCellAssignment() {
// CellAssignment cellAssignment = new CellAssignment();
//
// cellAssignment.setMeasureColumn(expr());
// accept(Token.LBRACKET);
// this.exprParser.exprList(cellAssignment.getConditions());
// accept(Token.RBRACKET);
//
// return cellAssignment;
// }
// private void parseQueryPartitionClause(ModelColumnClause modelColumnClause) {
// if (identifierEquals("PARTITION")) {
// QueryPartitionClause queryPartitionClause = new QueryPartitionClause();
//
// lexer.nextToken();
// accept(Token.BY);
// if (lexer.token() == Token.LPAREN) {
// lexer.nextToken();
// exprParser.exprList(queryPartitionClause.getExprList());
// accept(Token.RPAREN);
// } else {
// exprParser.exprList(queryPartitionClause.getExprList());
// }
// modelColumnClause.setQueryPartitionClause(queryPartitionClause);
// }
// }
// private void parseModelColumnClause() {
// throw new ParserException();
// }
// private void parseCellReferenceOptions(List<CellReferenceOption> options) {
// if (identifierEquals("IGNORE")) {
// lexer.nextToken();
// acceptIdentifier("NAV");
// options.add(CellReferenceOption.IgnoreNav);
// } else if (identifierEquals("KEEP")) {
// lexer.nextToken();
// acceptIdentifier("NAV");
// options.add(CellReferenceOption.KeepNav);
// }
//
// if (lexer.token() == Token.UNIQUE) {
// lexer.nextToken();
// if (identifierEquals("DIMENSION")) {
// lexer.nextToken();
// options.add(CellReferenceOption.UniqueDimension);
// } else {
// acceptIdentifier("SINGLE");
// acceptIdentifier("REFERENCE");
// options.add(CellReferenceOption.UniqueDimension);
// }
// }
// }
private void parseGroupBy(OracleSelectQueryBlock queryBlock) {
if (lexer.token() == (Token.GROUP)) {
lexer.nextToken();
accept(Token.BY);
SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause();
for (;;) {
if (identifierEquals("GROUPING")) {
GroupingSetExpr groupingSet = new GroupingSetExpr();
lexer.nextToken();
acceptIdentifier("SETS");
accept(Token.LPAREN);
exprParser.exprList(groupingSet.getParameters());
accept(Token.RPAREN);
groupBy.getItems().add(groupingSet);
} else {
groupBy.getItems().add(this.exprParser.expr());
}
if (!(lexer.token() == (Token.COMMA))) {
break;
}
lexer.nextToken();
}
if (lexer.token() == (Token.HAVING)) {
lexer.nextToken();
groupBy.setHaving(this.exprParser.expr());
}
queryBlock.setGroupBy(groupBy);
} else if (lexer.token() == (Token.HAVING)) {
lexer.nextToken();
SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause();
groupBy.setHaving(this.exprParser.expr());
if (lexer.token() == (Token.GROUP)) {
lexer.nextToken();
accept(Token.BY);
for (;;) {
if (identifierEquals("GROUPING")) {
GroupingSetExpr groupingSet = new GroupingSetExpr();
lexer.nextToken();
acceptIdentifier("SETS");
accept(Token.LPAREN);
exprParser.exprList(groupingSet.getParameters());
accept(Token.RPAREN);
groupBy.getItems().add(groupingSet);
} else {
groupBy.getItems().add(this.exprParser.expr());
}
if (!(lexer.token() == (Token.COMMA))) {
break;
}
lexer.nextToken();
}
}
queryBlock.setGroupBy(groupBy);
}
}
@Override
protected String as() throws ParserException {
if (lexer.token() == Token.CONNECT) {
return null;
}
return super.as();
}
private void parseHierachical(OracleSelectQueryBlock queryBlock) {
OracleSelectHierachicalQueryClause hierachical = null;
if (lexer.token() == Token.CONNECT) {
hierachical = new OracleSelectHierachicalQueryClause();
lexer.nextToken();
accept(Token.BY);
if (lexer.token() == Token.PRIOR) {
lexer.nextToken();
hierachical.setPrior(true);
}
if (identifierEquals("NOCYCLE")) {
hierachical.setNoCycle(true);
}
hierachical.setConnectBy(this.exprParser.expr());
}
if (lexer.token() == Token.START) {
lexer.nextToken();
if (hierachical == null) {
hierachical = new OracleSelectHierachicalQueryClause();
}
accept(Token.WITH);
hierachical.setStartWith(this.exprParser.expr());
}
if (lexer.token() == Token.CONNECT) {
if (hierachical == null) {
hierachical = new OracleSelectHierachicalQueryClause();
}
lexer.nextToken();
accept(Token.BY);
if (lexer.token() == Token.PRIOR) {
lexer.nextToken();
hierachical.setPrior(true);
}
if (identifierEquals("NOCYCLE")) {
hierachical.setNoCycle(true);
}
hierachical.setConnectBy(this.exprParser.expr());
}
if (hierachical != null) {
queryBlock.setHierachicalQueryClause(hierachical);
}
}
@Override
public SQLTableSource parseTableSource() {
if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
OracleSelectSubqueryTableSource tableSource;
if (lexer.token() == Token.SELECT) {
tableSource = new OracleSelectSubqueryTableSource(select());
} else if (lexer.token() == (Token.LPAREN)) {
tableSource = new OracleSelectSubqueryTableSource(select());
} else {
throw new ParserException("TODO :" + lexer.token());
}
accept(Token.RPAREN);
parsePivot(tableSource);
return parseTableSourceRest(tableSource);
}
if (lexer.token() == (Token.SELECT)) {
throw new ParserException("TODO");
}
OracleSelectTableReference tableReference = new OracleSelectTableReference();
if (identifierEquals("ONLY")) {
lexer.nextToken();
accept(Token.LPAREN);
parseTableSourceQueryTableExpr(tableReference);
accept(Token.RPAREN);
} else {
parseTableSourceQueryTableExpr(tableReference);
parsePivot(tableReference);
}
return parseTableSourceRest(tableReference);
}
private void parseTableSourceQueryTableExpr(OracleSelectTableReference tableReference) {
tableReference.setExpr(this.exprParser.expr());
{
FlashbackQueryClause clause = flashback();
tableReference.setFlashback(clause);
}
if (identifierEquals("SAMPLE")) {
lexer.nextToken();
SampleClause sample = new SampleClause();
if (identifierEquals("BLOCK")) {
sample.setBlock(true);
lexer.nextToken();
}
accept(Token.LPAREN);
this.exprParser.exprList(sample.getPercent());
accept(Token.RPAREN);
if (identifierEquals("SEED")) {
lexer.nextToken();
accept(Token.LPAREN);
sample.setSeedValue(expr());
accept(Token.RPAREN);
}
tableReference.setSampleClause(sample);
}
if (identifierEquals("PARTITION")) {
lexer.nextToken();
PartitionExtensionClause partition = new PartitionExtensionClause();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
partition.setPartition(exprParser.name());
accept(Token.RPAREN);
} else {
accept(Token.FOR);
accept(Token.LPAREN);
exprParser.names(partition.getFor());
accept(Token.RPAREN);
}
tableReference.setPartition(partition);
}
if (identifierEquals("SUBPARTITION")) {
lexer.nextToken();
PartitionExtensionClause partition = new PartitionExtensionClause();
partition.setSubPartition(true);
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
partition.setPartition(exprParser.name());
accept(Token.RPAREN);
} else {
accept(Token.FOR);
accept(Token.LPAREN);
exprParser.names(partition.getFor());
accept(Token.RPAREN);
}
tableReference.setPartition(partition);
}
if (identifierEquals("VERSIONS")) {
lexer.nextToken();
if (lexer.token() == Token.BETWEEN) {
lexer.nextToken();
VersionsFlashbackQueryClause clause = new VersionsFlashbackQueryClause();
if (identifierEquals("SCN")) {
clause.setType(AsOfFlashbackQueryClause.Type.SCN);
lexer.nextToken();
} else {
acceptIdentifier("TIMESTAMP");
clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP);
}
SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) exprParser.expr();
if (binaryExpr.getOperator() != SQLBinaryOperator.BooleanAnd) {
throw new SQLParserException("syntax error : " + binaryExpr.getOperator());
}
clause.setBegin(binaryExpr.getLeft());
clause.setEnd(binaryExpr.getRight());
tableReference.setFlashback(clause);
} else {
throw new SQLParserException("TODO");
}
}
}
private FlashbackQueryClause flashback() {
if (lexer.token() == Token.AS) {
lexer.nextToken();
}
if (lexer.token() == Token.OF) {
lexer.nextToken();
if (identifierEquals("SCN")) {
AsOfFlashbackQueryClause clause = new AsOfFlashbackQueryClause();
clause.setType(AsOfFlashbackQueryClause.Type.SCN);
lexer.nextToken();
clause.setExpr(exprParser.expr());
return clause;
} else if (identifierEquals("SNAPSHOT")) {
lexer.nextToken();
accept(Token.LPAREN);
AsOfSnapshotClause clause = new AsOfSnapshotClause();
clause.setExpr(this.expr());
accept(Token.RPAREN);
return clause;
} else {
AsOfFlashbackQueryClause clause = new AsOfFlashbackQueryClause();
acceptIdentifier("TIMESTAMP");
clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP);
clause.setExpr(exprParser.expr());
return clause;
}
}
return null;
}
protected SQLTableSource parseTableSourceRest(OracleSelectTableSource tableSource) {
if (lexer.token() == Token.AS) {
lexer.nextToken();
if (lexer.token() == Token.OF) {
tableSource.setFlashback(flashback());
}
tableSource.setAlias(as());
} else if ((tableSource.getAlias() == null) || (tableSource.getAlias().length() == 0)) {
if (lexer.token() != Token.LEFT && lexer.token() != Token.RIGHT
&& lexer.token() != Token.FULL) {
tableSource.setAlias(as());
}
}
if (lexer.token() == Token.HINT) {
this.exprParser.parseHints(tableSource.getHints());
}
OracleSelectJoin.JoinType joinType = null;
if (lexer.token() == Token.LEFT) {
lexer.nextToken();
if (lexer.token() == Token.OUTER) {
lexer.nextToken();
}
accept(Token.JOIN);
joinType = OracleSelectJoin.JoinType.LEFT_OUTER_JOIN;
}
if (lexer.token() == Token.RIGHT) {
lexer.nextToken();
if (lexer.token() == Token.OUTER) {
lexer.nextToken();
}
accept(Token.JOIN);
joinType = OracleSelectJoin.JoinType.RIGHT_OUTER_JOIN;
}
if (lexer.token() == Token.FULL) {
lexer.nextToken();
if (lexer.token() == Token.OUTER) {
lexer.nextToken();
}
accept(Token.JOIN);
joinType = OracleSelectJoin.JoinType.FULL_OUTER_JOIN;
}
if (lexer.token() == Token.INNER) {
lexer.nextToken();
accept(Token.JOIN);
joinType = OracleSelectJoin.JoinType.INNER_JOIN;
}
if (lexer.token() == Token.CROSS) {
lexer.nextToken();
accept(Token.JOIN);
joinType = OracleSelectJoin.JoinType.CROSS_JOIN;
}
if (lexer.token() == Token.JOIN) {
lexer.nextToken();
joinType = OracleSelectJoin.JoinType.JOIN;
}
if (lexer.token() == (Token.COMMA)) {
lexer.nextToken();
joinType = OracleSelectJoin.JoinType.COMMA;
}
if (joinType != null) {
OracleSelectJoin join = new OracleSelectJoin();
join.setLeft(tableSource);
join.setJoinType(joinType);
join.setRight(parseTableSource());
if (lexer.token() == Token.ON) {
lexer.nextToken();
join.setCondition(this.exprParser.expr());
} else if (lexer.token() == Token.USING) {
lexer.nextToken();
accept(Token.LPAREN);
this.exprParser.exprList(join.getUsing());
accept(Token.RPAREN);
}
return parseTableSourceRest(join);
}
return tableSource;
}
private void parsePivot(OracleSelectTableSource tableSource) {
OracleSelectPivot.Item item;
if (identifierEquals("PIVOT")) {
lexer.nextToken();
OracleSelectPivot pivot = new OracleSelectPivot();
if (identifierEquals("XML")) {
lexer.nextToken();
pivot.setXml(true);
}
accept(Token.LPAREN);
while (true) {
item = new OracleSelectPivot.Item();
item.setExpr(this.exprParser.expr());
item.setAlias(as());
pivot.getItems().add(item);
if (!(lexer.token() == (Token.COMMA)))
break;
lexer.nextToken();
}
accept(Token.FOR);
if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
while (true) {
pivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));
lexer.nextToken();
if (!(lexer.token() == (Token.COMMA)))
break;
lexer.nextToken();
}
accept(Token.RPAREN);
} else {
pivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));
lexer.nextToken();
}
accept(Token.IN);
accept(Token.LPAREN);
if (lexer.token() == (Token.LPAREN)) {
throw new ParserException("TODO");
}
if (lexer.token() == (Token.SELECT)) {
throw new ParserException("TODO");
}
for (;;) {
item = new OracleSelectPivot.Item();
item.setExpr(this.exprParser.expr());
item.setAlias(as());
pivot.getPivotIn().add(item);
if (lexer.token() != Token.COMMA) {
break;
}
lexer.nextToken();
}
accept(Token.RPAREN);
accept(Token.RPAREN);
tableSource.setPivot(pivot);
} else if (identifierEquals("UNPIVOT")) {
lexer.nextToken();
OracleSelectUnPivot unPivot = new OracleSelectUnPivot();
if (identifierEquals("INCLUDE")) {
lexer.nextToken();
acceptIdentifier("NULLS");
unPivot.setNullsIncludeType(OracleSelectUnPivot.NullsIncludeType.INCLUDE_NULLS);
} else if (identifierEquals("EXCLUDE")) {
lexer.nextToken();
acceptIdentifier("NULLS");
unPivot.setNullsIncludeType(OracleSelectUnPivot.NullsIncludeType.EXCLUDE_NULLS);
}
accept(Token.LPAREN);
if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
this.exprParser.exprList(unPivot.getItems());
accept(Token.RPAREN);
} else {
unPivot.getItems().add(this.exprParser.expr());
}
accept(Token.FOR);
if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
while (true) {
unPivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));
lexer.nextToken();
if (!(lexer.token() == (Token.COMMA)))
break;
lexer.nextToken();
}
accept(Token.RPAREN);
} else {
unPivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));
lexer.nextToken();
}
accept(Token.IN);
accept(Token.LPAREN);
if (lexer.token() == (Token.LPAREN)) {
throw new ParserException("TODO");
}
if (lexer.token() == (Token.SELECT)) {
throw new ParserException("TODO");
}
for (;;) {
item = new OracleSelectPivot.Item();
item.setExpr(this.exprParser.expr());
item.setAlias(as());
unPivot.getPivotIn().add(item);
if (lexer.token() != Token.COMMA) {
break;
}
lexer.nextToken();
}
accept(Token.RPAREN);
accept(Token.RPAREN);
tableSource.setPivot(unPivot);
}
}
protected void parseInto(OracleSelectQueryBlock x) {
if (lexer.token() == Token.INTO) {
lexer.nextToken();
SQLExpr expr = expr();
if (lexer.token() != Token.COMMA) {
x.setInto(expr);
return;
}
SQLListExpr list = new SQLListExpr();
list.getItems().add(expr);
while (lexer.token() == Token.COMMA) {
lexer.nextToken();
list.getItems().add(expr());
}
x.setInto(list);
}
}
private void parseHints(OracleSelectQueryBlock queryBlock) {
this.exprParser.parseHints(queryBlock.getHints());
}
}