/*
* 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 com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLPartition;
import com.alibaba.druid.sql.ast.SQLPartitionBy;
import com.alibaba.druid.sql.ast.SQLPartitionByHash;
import com.alibaba.druid.sql.ast.SQLPartitionByList;
import com.alibaba.druid.sql.ast.SQLPartitionByRange;
import com.alibaba.druid.sql.ast.SQLPartitionValue;
import com.alibaba.druid.sql.ast.SQLSubPartition;
import com.alibaba.druid.sql.ast.SQLSubPartitionBy;
import com.alibaba.druid.sql.ast.SQLSubPartitionByHash;
import com.alibaba.druid.sql.ast.SQLSubPartitionByList;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement.DeferredSegmentCreation;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLCreateTableParser;
import com.alibaba.druid.sql.parser.Token;
public class OracleCreateTableParser extends SQLCreateTableParser {
public OracleCreateTableParser(Lexer lexer){
super(new OracleExprParser(lexer));
}
public OracleCreateTableParser(String sql){
super(new OracleExprParser(sql));
}
protected OracleCreateTableStatement newCreateStatement() {
return new OracleCreateTableStatement();
}
public OracleCreateTableStatement parseCrateTable(boolean acceptCreate) {
OracleCreateTableStatement stmt = (OracleCreateTableStatement) super.parseCrateTable(acceptCreate);
for (;;) {
if (lexer.token() == Token.TABLESPACE) {
lexer.nextToken();
stmt.setTablespace(this.exprParser.name());
continue;
} else if (identifierEquals("IN_MEMORY_METADATA")) {
lexer.nextToken();
stmt.setInMemoryMetadata(true);
continue;
} else if (identifierEquals("CURSOR_SPECIFIC_SEGMENT")) {
lexer.nextToken();
stmt.setCursorSpecificSegment(true);
continue;
} else if (identifierEquals("NOPARALLEL")) {
lexer.nextToken();
stmt.setParallel(false);
continue;
} else if (lexer.token() == Token.LOGGING) {
lexer.nextToken();
stmt.setLogging(Boolean.TRUE);
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 (lexer.token() == Token.NOCOMPRESS) {
lexer.nextToken();
stmt.setCompress(Boolean.FALSE);
continue;
} else if (lexer.token() == Token.ON) {
lexer.nextToken();
accept(Token.COMMIT);
stmt.setOnCommit(true);
continue;
} else if (identifierEquals("PRESERVE")) {
lexer.nextToken();
acceptIdentifier("ROWS");
stmt.setPreserveRows(true);
continue;
} else if (identifierEquals("STORAGE")) {
OracleStorageClause storage = ((OracleExprParser) this.exprParser).parseStorage();
stmt.setStorage(storage);
continue;
} else if (identifierEquals("organization")) {
lexer.nextToken();
accept(Token.INDEX);
stmt.setOrganizationIndex(true);
continue;
} else if (lexer.token() == Token.PCTFREE) {
lexer.nextToken();
stmt.setPtcfree(this.exprParser.expr());
continue;
} else if (identifierEquals("PCTUSED")) {
lexer.nextToken();
stmt.setPctused(this.exprParser.expr());
continue;
} else if (lexer.token() == Token.STORAGE) {
OracleStorageClause storage = ((OracleExprParser) this.exprParser).parseStorage();
stmt.setStorage(storage);
continue;
} else if (lexer.token() == Token.LOB) {
OracleLobStorageClause lobStorage = ((OracleExprParser) this.exprParser).parseLobStorage();
stmt.setLobStorage(lobStorage);
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.SEGMENT) {
lexer.nextToken();
accept(Token.CREATION);
if (lexer.token() == Token.IMMEDIATE) {
lexer.nextToken();
stmt.setDeferredSegmentCreation(DeferredSegmentCreation.IMMEDIATE);
} else {
accept(Token.DEFERRED);
stmt.setDeferredSegmentCreation(DeferredSegmentCreation.DEFERRED);
}
continue;
} else if (identifierEquals("PARTITION")) {
lexer.nextToken();
accept(Token.BY);
if (identifierEquals("RANGE")) {
SQLPartitionByRange partitionByRange = partitionByRange();
partitionClauseRest(partitionByRange);
stmt.setPartitioning(partitionByRange);
continue;
} else if (identifierEquals("HASH")) {
SQLPartitionByHash partitionByHash = partitionByHash();
partitionClauseRest(partitionByHash);
stmt.setPartitioning(partitionByHash);
continue;
} else if (identifierEquals("LIST")) {
SQLPartitionByList partitionByList = partitionByList();
partitionClauseRest(partitionByList);
stmt.setPartitioning(partitionByList);
continue;
} else {
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
break;
}
if (lexer.token() == Token.AS) {
lexer.nextToken();
OracleSelect select = new OracleSelectParser(exprParser).select();
stmt.setSelect(select);
}
return stmt;
}
protected SQLPartitionByList partitionByList() {
acceptIdentifier("LIST");
SQLPartitionByList partitionByList = new SQLPartitionByList();
accept(Token.LPAREN);
partitionByList.setExpr(this.exprParser.expr());
accept(Token.RPAREN);
parsePartitionByRest(partitionByList);
return partitionByList;
}
protected SQLPartitionByHash partitionByHash() {
acceptIdentifier("HASH");
SQLPartitionByHash partitionByHash = new SQLPartitionByHash();
if (lexer.token() == Token.KEY) {
lexer.nextToken();
partitionByHash.setKey(true);
}
accept(Token.LPAREN);
partitionByHash.setExpr(this.exprParser.expr());
accept(Token.RPAREN);
return partitionByHash;
}
protected SQLPartitionByRange partitionByRange() {
acceptIdentifier("RANGE");
accept(Token.LPAREN);
SQLPartitionByRange clause = new SQLPartitionByRange();
for (;;) {
SQLName column = this.exprParser.name();
clause.addColumn(column);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
if (lexer.token() == Token.INTERVAL) {
lexer.nextToken();
accept(Token.LPAREN);
clause.setInterval(this.exprParser.expr());
accept(Token.RPAREN);
}
parsePartitionByRest(clause);
return clause;
}
protected void parsePartitionByRest(SQLPartitionBy clause) {
if (lexer.token() == Token.STORE) {
lexer.nextToken();
accept(Token.IN);
accept(Token.LPAREN);
for (;;) {
SQLName tablespace = this.exprParser.name();
clause.getStoreIn().add(tablespace);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
}
if (identifierEquals("SUBPARTITION")) {
SQLSubPartitionBy subPartitionBy = subPartitionBy();
clause.setSubPartitionBy(subPartitionBy);
}
accept(Token.LPAREN);
for (;;) {
SQLPartition partition = parsePartition();
clause.addPartition(partition);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
}
protected SQLPartition parsePartition() {
acceptIdentifier("PARTITION");
SQLPartition partition = new SQLPartition();
partition.setName(this.exprParser.name());
SQLPartitionValue values = this.exprParser.parsePartitionValues();
if (values != null) {
partition.setValues(values);
}
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
for (;;) {
SQLSubPartition subPartition = parseSubPartition();
partition.addSubPartition(subPartition);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
} else if (identifierEquals("SUBPARTITIONS")) {
lexer.nextToken();
SQLExpr subPartitionsCount = this.exprParser.primary();
partition.setSubPartitionsCount(subPartitionsCount);
}
return partition;
}
protected SQLSubPartition parseSubPartition() {
acceptIdentifier("SUBPARTITION");
SQLSubPartition subPartition = new SQLSubPartition();
SQLName name = this.exprParser.name();
subPartition.setName(name);
SQLPartitionValue values = this.exprParser.parsePartitionValues();
if (values != null) {
subPartition.setValues(values);
}
return subPartition;
}
protected void partitionClauseRest(SQLPartitionBy clause) {
if (identifierEquals("PARTITIONS")) {
lexer.nextToken();
SQLIntegerExpr countExpr = this.exprParser.integerExpr();
clause.setPartitionsCount(countExpr);
}
if (lexer.token() == Token.STORE) {
lexer.nextToken();
accept(Token.IN);
accept(Token.LPAREN);
this.exprParser.names(clause.getStoreIn(), clause);
accept(Token.RPAREN);
}
}
protected SQLSubPartitionBy subPartitionBy() {
lexer.nextToken();
accept(Token.BY);
if (identifierEquals("HASH")) {
lexer.nextToken();
accept(Token.LPAREN);
SQLSubPartitionByHash byHash = new SQLSubPartitionByHash();
SQLExpr expr = this.exprParser.expr();
byHash.setExpr(expr);
accept(Token.RPAREN);
return byHash;
} else if (identifierEquals("LIST")) {
lexer.nextToken();
accept(Token.LPAREN);
SQLSubPartitionByList byList = new SQLSubPartitionByList();
SQLName column = this.exprParser.name();
byList.setColumn(column);
accept(Token.RPAREN);
if (identifierEquals("SUBPARTITION")) {
lexer.nextToken();
acceptIdentifier("TEMPLATE");
accept(Token.LPAREN);
for (;;) {
SQLSubPartition subPartition = parseSubPartition();
subPartition.setParent(byList);
byList.getSubPartitionTemplate().add(subPartition);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
}
return byList;
}
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}