improved sql parser for OracleCreateIndex. issue #1923

This commit is contained in:
wenshao
2017-08-20 03:44:36 +08:00
parent 95e36c990c
commit 888cdc34f4
10 changed files with 589 additions and 172 deletions
@@ -15,10 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLPartition;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
@@ -97,8 +94,12 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen
this.sort = sort;
}
private boolean local;
private List<SQLName> localStoreIn = new ArrayList<SQLName>();
private List<SQLPartition> localPartitions = new ArrayList<SQLPartition>();
private List<SQLPartition> globalPartitions = new ArrayList<SQLPartition>();
private boolean global;
private List<SQLPartitionBy> globalPartitions = new ArrayList<SQLPartitionBy>();
protected void accept0(SQLASTVisitor visitor) {
accept0((OracleASTVisitor) visitor);
@@ -262,7 +263,27 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen
return localPartitions;
}
public List<SQLPartition> getGlobalPartitions() {
public boolean isLocal() {
return local;
}
public void setLocal(boolean local) {
this.local = local;
}
public List<SQLName> getLocalStoreIn() {
return localStoreIn;
}
public List<SQLPartitionBy> getGlobalPartitions() {
return globalPartitions;
}
public boolean isGlobal() {
return global;
}
public void setGlobal(boolean global) {
this.global = global;
}
}
@@ -183,13 +183,13 @@ public class OracleCreateTableParser extends SQLCreateTableParser {
accept(Token.BY);
if (identifierEquals("RANGE")) {
SQLPartitionByRange partitionByRange = partitionByRange();
partitionClauseRest(partitionByRange);
SQLPartitionByRange partitionByRange = this.getExprParser().partitionByRange();
this.getExprParser().partitionClauseRest(partitionByRange);
stmt.setPartitioning(partitionByRange);
continue;
} else if (identifierEquals("HASH")) {
SQLPartitionByHash partitionByHash = partitionByHash();
partitionClauseRest(partitionByHash);
SQLPartitionByHash partitionByHash = this.getExprParser().partitionByHash();
this.getExprParser().partitionClauseRest(partitionByHash);
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
@@ -210,7 +210,7 @@ public class OracleCreateTableParser extends SQLCreateTableParser {
continue;
} else if (identifierEquals("LIST")) {
SQLPartitionByList partitionByList = partitionByList();
partitionClauseRest(partitionByList);
this.getExprParser().partitionClauseRest(partitionByList);
stmt.setPartitioning(partitionByList);
continue;
} else {
@@ -343,163 +343,11 @@ public class OracleCreateTableParser extends SQLCreateTableParser {
partitionByList.setExpr(this.exprParser.expr());
accept(Token.RPAREN);
parsePartitionByRest(partitionByList);
this.getExprParser().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 = this.getExprParser().parsePartition();
clause.addPartition(partition);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
}
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 = this.getExprParser().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.info());
}
protected void parseCreateTableSupplementalLogingProps(SQLCreateTableStatement stmt) {
acceptIdentifier("SUPPLEMENTAL");
acceptIdentifier("LOG");
@@ -1599,4 +1599,156 @@ public class OracleExprParser extends SQLExprParser {
}
}
}
protected SQLPartitionByRange partitionByRange() {
acceptIdentifier("RANGE");
accept(Token.LPAREN);
SQLPartitionByRange clause = new SQLPartitionByRange();
for (;;) {
SQLName column = this.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.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.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 = this.parsePartition();
clause.addPartition(partition);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
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.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.name();
byList.setColumn(column);
accept(Token.RPAREN);
if (identifierEquals("SUBPARTITION")) {
lexer.nextToken();
acceptIdentifier("TEMPLATE");
accept(Token.LPAREN);
for (;;) {
SQLSubPartition subPartition = this.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.info());
}
protected void partitionClauseRest(SQLPartitionBy clause) {
if (identifierEquals("PARTITIONS")) {
lexer.nextToken();
SQLIntegerExpr countExpr = this.integerExpr();
clause.setPartitionsCount(countExpr);
}
if (lexer.token() == Token.STORE) {
lexer.nextToken();
accept(Token.IN);
accept(Token.LPAREN);
this.names(clause.getStoreIn(), clause);
accept(Token.RPAREN);
}
}
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.expr());
accept(Token.RPAREN);
return partitionByHash;
}
}
@@ -2056,19 +2056,74 @@ public class OracleStatementParser extends SQLStatementParser {
continue;
} else if (identifierEquals("LOCAL")) {
lexer.nextToken();
accept(Token.LPAREN);
stmt.setLocal(true);
for (;;) {
SQLPartition partition = this.getExprParser().parsePartition();
partition.setParent(stmt);
stmt.getLocalPartitions().add(partition);
if (lexer.token() == Token.COMMA) {
if (lexer.token() == Token.STORE) {
lexer.nextToken();
continue;
} else if (lexer.token() == Token.RPAREN) {
accept(Token.IN);
accept(Token.LPAREN);
this.exprParser.names(stmt.getLocalStoreIn(), stmt);
accept(Token.RPAREN);
} else if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
for (; ; ) {
SQLPartition partition = this.getExprParser().parsePartition();
partition.setParent(stmt);
stmt.getLocalPartitions().add(partition);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
} else if (lexer.token() == Token.RPAREN) {
lexer.nextToken();
break;
}
throw new ParserException("TODO : " + lexer.info());
}
} else {
break;
}
throw new ParserException("TODO : " + lexer.info());
}
break;
} else if (identifierEquals("GLOBAL")) {
lexer.nextToken();
stmt.setGlobal(true);
if (lexer.token() == Token.PARTITION) {
lexer.nextToken();
accept(Token.BY);
if (identifierEquals("RANGE")) {
SQLPartitionByRange partitionByRange = this.getExprParser().partitionByRange();
this.getExprParser().partitionClauseRest(partitionByRange);
partitionByRange.setParent(stmt);
stmt.getGlobalPartitions().add(partitionByRange);
continue;
} else if (identifierEquals("HASH")) {
SQLPartitionByHash partitionByHash = this.getExprParser().partitionByHash();
this.getExprParser().partitionClauseRest(partitionByHash);
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
for (; ; ) {
SQLPartition partition = this.getExprParser().parsePartition();
partitionByHash.addPartition(partition);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
} else if (lexer.token() == Token.RPAREN) {
lexer.nextToken();
break;
}
throw new ParserException("TODO : " + lexer.info());
}
}
partitionByHash.setParent(stmt);
stmt.getGlobalPartitions().add(partitionByHash);
continue;
}
}
break;
@@ -1802,6 +1802,29 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
decrementIndent();
println();
print(')');
} else if (x.isLocal()) {
print0(ucase ? " LOCAL" : " local");
}
List<SQLName> localStoreIn = x.getLocalStoreIn();
if (localStoreIn.size() > 0) {
print0(ucase ? " STORE IN (" : " store in (");
printAndAccept(localStoreIn, ", ");
print(')');
}
List<SQLPartitionBy> globalPartitions = x.getGlobalPartitions();
if (globalPartitions.size() > 0) {
for (SQLPartitionBy globalPartition : globalPartitions) {
println();
print0(ucase ? "GLOBAL " : "global ");
globalPartition.accept(this);
}
} else {
if (x.isGlobal()) {
print0(ucase ? " GLOBAL" : " global");
}
}
return false;