diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java index c44303f7c0..d967d318fc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java @@ -333,7 +333,7 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { continue; } - if (identifierEquals("TABLESPACE")) { + if (lexer.token() == Token.TABLESPACE) { lexer.nextToken(); TableSpaceOption option = new TableSpaceOption(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 43481bd829..ff1a07f7df 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -2348,7 +2348,7 @@ public class MySqlStatementParser extends SQLStatementParser { } } stmt.getItems().add(item); - } else if (identifierEquals("DISABLE")) { + } else if (lexer.token() == Token.DISABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { @@ -2361,7 +2361,7 @@ public class MySqlStatementParser extends SQLStatementParser { SQLAlterTableDisableKeys item = new SQLAlterTableDisableKeys(); stmt.getItems().add(item); } - } else if (identifierEquals("ENABLE")) { + } else if (lexer.token() == Token.ENABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); @@ -2390,12 +2390,12 @@ public class MySqlStatementParser extends SQLStatementParser { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } else if (identifierEquals("DISCARD")) { lexer.nextToken(); - acceptIdentifier("TABLESPACE"); + accept(Token.TABLESPACE); MySqlAlterTableDiscardTablespace item = new MySqlAlterTableDiscardTablespace(); stmt.getItems().add(item); } else if (identifierEquals("IMPORT")) { lexer.nextToken(); - acceptIdentifier("TABLESPACE"); + accept(Token.TABLESPACE); MySqlAlterTableImportTablespace item = new MySqlAlterTableImportTablespace(); stmt.getItems().add(item); } else if (identifierEquals("FORCE")) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTableStatement.java index 9c397bcf7e..12cf68553e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTableStatement.java @@ -26,36 +26,46 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class OracleCreateTableStatement extends SQLCreateTableStatement implements OracleDDLStatement { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private SQLName tablespace; + private SQLName tablespace; - private SQLSelect select; + private SQLSelect select; - private boolean inMemoryMetadata; + private boolean inMemoryMetadata; - private boolean cursorSpecificSegment; + private boolean cursorSpecificSegment; // NOPARALLEL - private Boolean parallel; + private Boolean parallel; - private OracleStorageClause storage; + private OracleStorageClause storage; - private boolean organizationIndex = false; + private boolean organizationIndex = false; - private SQLExpr ptcfree; - private SQLExpr pctused; - private SQLExpr initrans; - private SQLExpr maxtrans; + private SQLExpr ptcfree; + private SQLExpr pctused; + private SQLExpr initrans; + private SQLExpr maxtrans; - private Boolean logging; - private Boolean compress; - private boolean onCommit; - private boolean preserveRows; + private Boolean logging; + private Boolean compress; + private boolean onCommit; + private boolean preserveRows; - private Boolean cache; + private Boolean cache; - private SQLPartitioningClause partitioning; + private SQLPartitioningClause partitioning; + + private DeferredSegmentCreation deferredSegmentCreation; + + public DeferredSegmentCreation getDeferredSegmentCreation() { + return deferredSegmentCreation; + } + + public void setDeferredSegmentCreation(DeferredSegmentCreation deferredSegmentCreation) { + this.deferredSegmentCreation = deferredSegmentCreation; + } public SQLPartitioningClause getPartitioning() { return partitioning; @@ -209,4 +219,7 @@ public class OracleCreateTableStatement extends SQLCreateTableStatement implemen visitor.endVisit(this); } + public static enum DeferredSegmentCreation { + IMMEDIATE, DEFERRED + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OraclePrimaryKey.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OraclePrimaryKey.java index 80eb6b4b4b..7da076b950 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OraclePrimaryKey.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OraclePrimaryKey.java @@ -27,19 +27,19 @@ import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; public class OraclePrimaryKey extends OracleSQLObjectImpl implements SQLPrimaryKey, SQLTableElement { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private SQLName name; - private List columns = new ArrayList(); + private SQLName name; + private List columns = new ArrayList(); - private SQLExpr usingIndex; + private OracleUsingIndexClause using; @Override public void accept0(OracleASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, name); acceptChild(visitor, columns); - acceptChild(visitor, usingIndex); + acceptChild(visitor, using); } visitor.endVisit(this); } @@ -60,12 +60,12 @@ public class OraclePrimaryKey extends OracleSQLObjectImpl implements SQLPrimaryK this.columns = columns; } - public SQLExpr getUsingIndex() { - return usingIndex; + public OracleUsingIndexClause getUsing() { + return using; } - public void setUsingIndex(SQLExpr usingIndex) { - this.usingIndex = usingIndex; + public void setUsing(OracleUsingIndexClause using) { + this.using = using; } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUsingIndexClause.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUsingIndexClause.java new file mode 100644 index 0000000000..6130f6e34a --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUsingIndexClause.java @@ -0,0 +1,115 @@ +/* + * Copyright 1999-2011 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.ast.stmt; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +@SuppressWarnings("serial") +public class OracleUsingIndexClause extends OracleSQLObjectImpl { + + private SQLName index; + private SQLName tablespace; + + private SQLExpr ptcfree; + private SQLExpr pctused; + private SQLExpr initrans; + private SQLExpr maxtrans; + + private Boolean enable = null; + + private boolean computeStatistics = false; + + public OracleUsingIndexClause(){ + + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, index); + acceptChild(visitor, tablespace); + } + visitor.endVisit(this); + } + + public Boolean getEnable() { + return enable; + } + + public void setEnable(Boolean enable) { + this.enable = enable; + } + + public boolean isComputeStatistics() { + return computeStatistics; + } + + public void setComputeStatistics(boolean computeStatistics) { + this.computeStatistics = computeStatistics; + } + + public SQLName getIndex() { + return index; + } + + public void setIndex(SQLName index) { + this.index = index; + } + + public SQLName getTablespace() { + return tablespace; + } + + public void setTablespace(SQLName tablespace) { + this.tablespace = tablespace; + } + + public SQLExpr getPtcfree() { + return ptcfree; + } + + public void setPtcfree(SQLExpr ptcfree) { + this.ptcfree = ptcfree; + } + + public SQLExpr getPctused() { + return pctused; + } + + public void setPctused(SQLExpr pctused) { + this.pctused = pctused; + } + + public SQLExpr getInitrans() { + return initrans; + } + + public void setInitrans(SQLExpr initrans) { + this.initrans = initrans; + } + + public SQLExpr getMaxtrans() { + return maxtrans; + } + + public void setMaxtrans(SQLExpr maxtrans) { + this.maxtrans = maxtrans; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java index f20f8a4d56..2ba7bb3d9e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java @@ -21,6 +21,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.OraclePartitionByRangeCla import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleRangeValuesClause; 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; @@ -45,7 +46,7 @@ public class OracleCreateTableParser extends SQLCreateTableParser { OracleCreateTableStatement stmt = (OracleCreateTableStatement) super.parseCrateTable(acceptCreate); for (;;) { - if (identifierEquals("TABLESPACE")) { + if (lexer.token() == Token.TABLESPACE) { lexer.nextToken(); stmt.setTablespace(this.exprParser.name()); continue; @@ -126,7 +127,7 @@ public class OracleCreateTableParser extends SQLCreateTableParser { accept(Token.INDEX); stmt.setOrganizationIndex(true); continue; - } else if (identifierEquals("PCTFREE")) { + } else if (lexer.token() == Token.PCTFREE) { lexer.nextToken(); stmt.setPtcfree(this.exprParser.expr()); continue; @@ -134,14 +135,24 @@ public class OracleCreateTableParser extends SQLCreateTableParser { lexer.nextToken(); stmt.setPctused(this.exprParser.expr()); continue; - } else if (identifierEquals("INITRANS")) { + } else if (lexer.token() == Token.INITRANS) { lexer.nextToken(); stmt.setInitrans(this.exprParser.expr()); continue; - } else if (identifierEquals("MAXTRANS")) { + } 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) { + stmt.setDeferredSegmentCreation(DeferredSegmentCreation.IMMEDIATE); + } else { + accept(Token.DEFERRED); + stmt.setDeferredSegmentCreation(DeferredSegmentCreation.DEFERRED); + } + continue; } else if (identifierEquals("PARTITION")) { lexer.nextToken(); accept(Token.BY); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index a6e2c8f6b0..e197de1c77 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -64,6 +64,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleOrderByItem; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePrimaryKey; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUsingIndexClause; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; @@ -73,6 +74,11 @@ public class OracleExprParser extends SQLExprParser { + + + + + public boolean allowStringAdditive = false; /** @@ -417,6 +423,13 @@ public class OracleExprParser extends SQLExprParser { sqlExpr = cursorExpr; return primaryRest(sqlExpr); case MODEL: + case PCTFREE: + case INITRANS: + case MAXTRANS: + case SEGMENT: + case CREATION: + case IMMEDIATE: + case DEFERRED: sqlExpr = new SQLIdentifierExpr(lexer.stringVal()); lexer.nextToken(); return primaryRest(sqlExpr); @@ -948,7 +961,47 @@ public class OracleExprParser extends SQLExprParser { if (lexer.token() == Token.USING) { lexer.nextToken(); accept(Token.INDEX); - primaryKey.setUsingIndex(expr()); + + OracleUsingIndexClause using = new OracleUsingIndexClause(); + + for (;;) { + if (lexer.token() == Token.TABLESPACE) { + lexer.nextToken(); + using.setTablespace(this.name()); + continue; + } else if (lexer.token() == Token.PCTFREE) { + lexer.nextToken(); + using.setPtcfree(this.expr()); + continue; + } else if (lexer.token() == Token.INITRANS) { + lexer.nextToken(); + using.setInitrans(this.expr()); + continue; + } else if (lexer.token() == Token.MAXTRANS) { + lexer.nextToken(); + using.setMaxtrans(this.expr()); + continue; + } else if (lexer.token() == Token.COMPUTE) { + lexer.nextToken(); + acceptIdentifier("STATISTICS"); + using.setComputeStatistics(true); + continue; + } else if (lexer.token() == Token.ENABLE) { + lexer.nextToken(); + using.setEnable(true); + continue; + } else if (lexer.token() == Token.DISABLE) { + lexer.nextToken(); + using.setEnable(false); + continue; + } else if (lexer.token() == Token.IDENTIFIER) { + using.setTablespace(this.name()); + break; + } else { + break; + } + } + primaryKey.setUsing(using); } return primaryKey; } @@ -956,7 +1009,7 @@ public class OracleExprParser extends SQLExprParser { public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) { column = super.parseColumnRest(column); - if (identifierEquals("ENABLE")) { + if (lexer.token() == Token.ENABLE) { lexer.nextToken(); column.setEnable(Boolean.TRUE); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java index 667f261495..a982be7e74 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java @@ -33,7 +33,7 @@ public class OracleLexer extends Lexer { static { Map map = new HashMap(); - + map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords()); map.put("BEGIN", Token.BEGIN); @@ -78,9 +78,17 @@ public class OracleLexer extends Lexer { map.put("WAIT", Token.WAIT); map.put("WITH", Token.WITH); - + map.put("IDENTIFIED", Token.IDENTIFIED); + map.put("PCTFREE", Token.PCTFREE); + map.put("INITRANS", Token.INITRANS); + map.put("MAXTRANS", Token.MAXTRANS); + map.put("SEGMENT", Token.SEGMENT); + map.put("CREATION", Token.CREATION); + map.put("IMMEDIATE", Token.IMMEDIATE); + map.put("DEFERRED", Token.DEFERRED); + DEFAULT_ORACLE_KEYWORDS = new Keywords(map); } @@ -120,7 +128,7 @@ public class OracleLexer extends Lexer { bufPos++; mybatisFlag = true; } - + for (;;) { ch = charAt(++pos); @@ -131,7 +139,7 @@ public class OracleLexer extends Lexer { bufPos++; continue; } - + if (quoteFlag) { if (ch != '"') { throw new ParserException("syntax error"); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index 18a40396c9..d807677401 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -378,7 +378,7 @@ public class OracleStatementParser extends SQLStatementParser { lexer.nextToken(); stmt.setWait(Boolean.FALSE); continue; - } else if (identifierEquals("IMMEDIATE")) { + } else if (lexer.token() == Token.IMMEDIATE) { lexer.nextToken(); stmt.setImmediate(Boolean.TRUE); continue; @@ -711,11 +711,11 @@ public class OracleStatementParser extends SQLStatementParser { stmt.setName(this.exprParser.name()); for (;;) { - if (identifierEquals("ENABLE")) { + if (lexer.token() == Token.ENABLE) { lexer.nextToken(); stmt.setEnable(Boolean.TRUE); continue; - } else if (identifierEquals("DISABLE")) { + } else if (lexer.token() == Token.DISABLE) { lexer.nextToken(); stmt.setEnable(Boolean.FALSE); continue; @@ -734,11 +734,11 @@ public class OracleStatementParser extends SQLStatementParser { stmt.setName(this.exprParser.name()); for (;;) { - if (identifierEquals("ENABLE")) { + if (lexer.token() == Token.ENABLE) { lexer.nextToken(); stmt.setEnable(Boolean.TRUE); continue; - } else if (identifierEquals("DISABLE")) { + } else if (lexer.token() == Token.DISABLE) { lexer.nextToken(); stmt.setEnable(Boolean.FALSE); continue; @@ -757,11 +757,11 @@ public class OracleStatementParser extends SQLStatementParser { stmt.setName(this.exprParser.name()); for (;;) { - if (identifierEquals("ENABLE")) { + if (lexer.token() == Token.ENABLE) { lexer.nextToken(); stmt.setEnable(Boolean.TRUE); continue; - } else if (identifierEquals("DISABLE")) { + } else if (lexer.token() == Token.DISABLE) { lexer.nextToken(); stmt.setEnable(Boolean.FALSE); continue; @@ -774,7 +774,7 @@ public class OracleStatementParser extends SQLStatementParser { } return stmt; - } else if (identifierEquals("TABLESPACE")) { + } else if (lexer.token() == Token.TABLESPACE) { lexer.nextToken(); OracleAlterTablespaceStatement stmt = new OracleAlterTablespaceStatement(); @@ -875,7 +875,7 @@ public class OracleStatementParser extends SQLStatementParser { } else if (identifierEquals("MOVE")) { lexer.nextToken(); - if (identifierEquals("TABLESPACE")) { + if (lexer.token() == Token.TABLESPACE) { lexer.nextToken(); OracleAlterTableMoveTablespace item = new OracleAlterTableMoveTablespace(); @@ -929,7 +929,7 @@ public class OracleStatementParser extends SQLStatementParser { } else if (lexer.token() == Token.DROP) { parseAlterDrop(stmt); continue; - } else if (identifierEquals("DISABLE")) { + } else if (lexer.token() == Token.DISABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); @@ -939,7 +939,7 @@ public class OracleStatementParser extends SQLStatementParser { } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } - } else if (identifierEquals("ENABLE")) { + } else if (lexer.token() == Token.ENABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); @@ -1065,7 +1065,7 @@ public class OracleStatementParser extends SQLStatementParser { spec.setPartition(this.exprParser.name()); for (;;) { - if (identifierEquals("TABLESPACE")) { + if (lexer.token() == Token.TABLESPACE) { lexer.nextToken(); SQLName tablespace = this.exprParser.name(); spec.getSegmentAttributeItems().add(new TableSpaceItem(tablespace)); @@ -1651,7 +1651,7 @@ public class OracleStatementParser extends SQLStatementParser { accept(Token.RPAREN); for (;;) { - if (identifierEquals("TABLESPACE")) { + if (lexer.token() == Token.TABLESPACE) { lexer.nextToken(); stmt.setTablespace(this.exprParser.name()); continue; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java index 961cd5e0ec..6555685ec4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java @@ -118,6 +118,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSetTransactionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleTruncateStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUsingIndexClause; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface OracleASTVisitor extends SQLASTVisitor { @@ -601,4 +602,8 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleDropSequenceStatement x); void endVisit(OracleDropSequenceStatement x); + + boolean visit(OracleUsingIndexClause x); + + void endVisit(OracleUsingIndexClause x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java index 48c450e33b..5f22cc1632 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java @@ -130,6 +130,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSetTransactionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleTruncateStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUsingIndexClause; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements OracleASTVisitor { @@ -1365,4 +1366,14 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora } + @Override + public boolean visit(OracleUsingIndexClause x) { + return true; + } + + @Override + public void endVisit(OracleUsingIndexClause x) { + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 4b081ef519..7a88797688 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -159,6 +159,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSetTransactionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleTruncateStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUsingIndexClause; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleASTVisitor { @@ -2319,9 +2320,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print("PRIMARY KEY ("); printAndAccept(x.getColumns(), ", "); print(")"); - if (x.getUsingIndex() != null) { - print(" USING INDEX "); - x.getUsingIndex().accept(this); + if (x.getUsing() != null) { + print(" "); + x.getUsing().accept(this); } return false; } @@ -2340,12 +2341,22 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.isOrganizationIndex()) { print(" ORGANIZATION INDEX"); } - - if (x.getTablespace() != null) { - print(" TABLESPACE "); - x.getTablespace().accept(this); + + if (x.getPtcfree() != null) { + print(" PCTFREE "); + x.getPtcfree().accept(this); } - + + if (x.getInitrans() != null) { + print(" INITRANS "); + x.getInitrans().accept(this); + } + + if (x.getMaxtrans() != null) { + print(" MAXTRANS "); + x.getMaxtrans().accept(this); + } + if (x.isInMemoryMetadata()) { print(" IN_MEMORY_METADATA"); } @@ -2377,6 +2388,11 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } else if (x.getLogging() == Boolean.FALSE) { print(" NOLOGGING"); } + + if (x.getTablespace() != null) { + print(" TABLESPACE "); + x.getTablespace().accept(this); + } if (x.getStorage() != null) { print(" "); @@ -3097,4 +3113,52 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public void endVisit(OracleDropSequenceStatement x) { } + + @Override + public boolean visit(OracleUsingIndexClause x) { + print("USING INDEX"); + if (x.getIndex() != null) { + print(' '); + x.getIndex().accept(this); + } else { + if (x.getPtcfree() != null) { + print(" PCTFREE "); + x.getPtcfree().accept(this); + } + + if (x.getInitrans() != null) { + print(" INITRANS "); + x.getInitrans().accept(this); + } + + if (x.getMaxtrans() != null) { + print(" MAXTRANS "); + x.getMaxtrans().accept(this); + } + + if (x.isComputeStatistics()) { + print(" COMPUTE STATISTICS"); + } + + if (x.getTablespace() != null) { + print(" TABLESPACE "); + x.getTablespace().accept(this); + } + + if (x.getEnable() != null) { + if (x.getEnable().booleanValue()) { + print(" ENABLE"); + } else { + print(" DISABLE"); + } + } + } + + return false; + } + + @Override + public void endVisit(OracleUsingIndexClause x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index 802f3ac6d5..8dc2bed9df 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -152,6 +152,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSetTransactionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleTruncateStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUsingIndexClause; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Column; @@ -1784,4 +1785,14 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public void endVisit(OracleDropSequenceStatement x) { } + + @Override + public boolean visit(OracleUsingIndexClause x) { + return false; + } + + @Override + public void endVisit(OracleUsingIndexClause x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java index f35111b823..b73a529d5a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java @@ -35,6 +35,9 @@ public class Keywords { map.put("AND", Token.AND); map.put("ANY", Token.ANY); map.put("AS", Token.AS); + + map.put("ENABLE", Token.ENABLE); + map.put("DISABLE", Token. DISABLE); map.put("ASC", Token.ASC); map.put("BETWEEN", Token.BETWEEN); @@ -48,6 +51,7 @@ public class Keywords { map.put("DATABASE", Token.DATABASE); map.put("DEFAULT", Token.DEFAULT); map.put("COLUMN", Token.COLUMN); + map.put("TABLESPACE", Token.TABLESPACE); map.put("DELETE", Token.DELETE); map.put("DESC", Token.DESC); @@ -119,7 +123,8 @@ public class Keywords { map.put("REPLACE", Token.REPLACE); map.put("COMMENT", Token.COMMENT); - + map.put("COMPUTE", Token.COMPUTE); + DEFAULT_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java index 8016300a11..1d367e7620 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java @@ -77,6 +77,8 @@ public class SQLCreateTableParser extends SQLDDLParser { } else if (lexer.token == Token.UNIQUE) { SQLUnique unique = exprParser.parseUnique(); createTable.getTableElementList().add(unique); + } else if (lexer.token() == Token.TABLESPACE) { + throw new ParserException("TODO " + lexer.token()); } else { throw new ParserException("TODO " + lexer.token()); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 2c8b78049c..b03f8edfed 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -233,6 +233,9 @@ public class SQLExprParser extends SQLParser { case IF: case END: case COMMENT: + case COMPUTE: + case ENABLE: + case DISABLE: sqlExpr = new SQLIdentifierExpr(lexer.stringVal()); lexer.nextToken(); break; diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 5a6e2528d9..0248d9f2f5 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -324,7 +324,7 @@ public class SQLStatementParser extends SQLParser { } else { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } - } else if (identifierEquals("DISABLE")) { + } else if (lexer.token() == Token.DISABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { @@ -337,7 +337,7 @@ public class SQLStatementParser extends SQLParser { SQLAlterTableDisableKeys item = new SQLAlterTableDisableKeys(); stmt.getItems().add(item); } - } else if (identifierEquals("ENABLE")) { + } else if (lexer.token() == Token.ENABLE) { lexer.nextToken(); if (lexer.token() == Token.CONSTRAINT) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index d4eca19223..a0ca1c617a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -35,6 +35,7 @@ public enum Token { ALTER("ALTER"), DROP("DROP"), TABLE("TABLE"), + TABLESPACE("TABLESPACE"), UPDATE("UPDATE"), SET("SET"), SELECT("SELECT"), @@ -167,6 +168,18 @@ public enum Token { SAVEPOINT("SAVEPOINT"), CROSS("CROSS"), + PCTFREE("PCTFREE"), + INITRANS("INITRANS"), + MAXTRANS("MAXTRANS"), + ENABLE("ENABLE"), + DISABLE("DISABLE"), + SEGMENT("SEGMENT"), + CREATION("CREATION"), + IMMEDIATE("IMMEDIATE"), + DEFERRED("DEFERRED"), + + COMPUTE("COMPUTE"), + // transact-sql TOP("TOP"), diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableDisableKeys.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableDisableKeys.java index 0874bd9179..f3b9866942 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableDisableKeys.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableDisableKeys.java @@ -15,15 +15,15 @@ */ package com.alibaba.druid.bvt.sql.mysql; -import junit.framework.Assert; import junit.framework.TestCase; +import org.junit.Assert; + import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; import com.alibaba.druid.sql.parser.Token; -import com.alibaba.druid.stat.TableStat.Column; public class MySqlAlterTableDisableKeys extends TestCase { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterTableTest8.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterTableTest8.java index 7395d66c0d..3e87292aca 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterTableTest8.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterTableTest8.java @@ -17,7 +17,7 @@ package com.alibaba.druid.bvt.sql.oracle; import java.util.List; -import junit.framework.Assert; +import org.junit.Assert; import com.alibaba.druid.sql.OracleTest; import com.alibaba.druid.sql.ast.SQLStatement; @@ -29,7 +29,8 @@ public class OracleAlterTableTest8 extends OracleTest { public void test_0() throws Exception { String sql = // - "ALTER TABLE ws_i18n_translate_item ADD CONSTRAINT ws_i18n_translate_item_pk PRIMARY KEY (id) USING INDEX ws_i18n_translate_item_pk"; + "ALTER TABLE ws_i18n_translate_item ADD CONSTRAINT ws_i18n_translate_item_pk "// + + "PRIMARY KEY (id) USING INDEX ws_i18n_translate_item_pk"; OracleStatementParser parser = new OracleStatementParser(sql); List statementList = parser.parseStatementList(); @@ -53,7 +54,7 @@ public class OracleAlterTableTest8 extends OracleTest { Assert.assertEquals(1, visitor.getColumns().size()); - Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("ws_i18n_translate_item", "id"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("ws_i18n_translate_item", "id"))); // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest18.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest18.java new file mode 100644 index 0000000000..1a8b5fb795 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest18.java @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2011 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.bvt.sql.oracle; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +public class OracleCreateTableTest18 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + " CREATE TABLE \"SONAR\".\"AUTHORS\" " // + + " ( \"ID\" NUMBER(38,0) NOT NULL ENABLE, " // + + " \"PERSON_ID\" NUMBER(38,0) NOT NULL ENABLE, " // + + " \"LOGIN\" VARCHAR2(100 BYTE), " // + + " \"CREATED_AT\" TIMESTAMP (6), " // + + " \"UPDATED_AT\" TIMESTAMP (6), " // + + " PRIMARY KEY (\"ID\")" // + + " USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS " // + + " TABLESPACE \"USERS\" ENABLE" // + + " ) SEGMENT CREATION DEFERRED " // + + " PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 " // + + " NOCOMPRESS LOGGING" // + + " TABLESPACE \"USERS\" ;"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statement = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("CREATE TABLE \"SONAR\".\"AUTHORS\" (" // + + "\n\t\"ID\" NUMBER(38, 0) NOT NULL ENABLE," // + + "\n\t\"PERSON_ID\" NUMBER(38, 0) NOT NULL ENABLE," // + + "\n\t\"LOGIN\" VARCHAR2(100 BYTE)," // + + "\n\t\"CREATED_AT\" TIMESTAMP(6)," // + + "\n\t\"UPDATED_AT\" TIMESTAMP(6)," // + + "\n\tPRIMARY KEY (\"ID\") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS TABLESPACE \"USERS\" ENABLE" // + + "\n) PCTFREE 10 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING TABLESPACE \"USERS\"", // + SQLUtils.toSQLString(statement, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statement.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + + Assert.assertEquals(5, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("SONAR.AUTHORS", "ID"))); + } +}