diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/PartitionExtensionClause.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/PartitionExtensionClause.java new file mode 100644 index 0000000000..0f7148eb56 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/PartitionExtensionClause.java @@ -0,0 +1,47 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.clause; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject; +import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleASTVisitor; + +public class PartitionExtensionClause extends OracleSQLObject { + + private static final long serialVersionUID = 1L; + + private boolean subPartition; + private SQLName partition; + private final List target = new ArrayList(); + + public boolean isSubPartition() { + return subPartition; + } + + public void setSubPartition(boolean subPartition) { + this.subPartition = subPartition; + } + + public SQLName getPartition() { + return partition; + } + + public void setPartition(SQLName partition) { + this.partition = partition; + } + + public List getFor() { + return target; + } + + @Override + protected void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, partition); + acceptChild(visitor, target); + } + visitor.endVisit(this); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableReference.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableReference.java index b32bd00eeb..154c908dbd 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableReference.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableReference.java @@ -16,23 +16,33 @@ package com.alibaba.druid.sql.dialect.oracle.ast.stmt; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause; import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class OracleSelectTableReference extends SQLExprTableSource implements OracleSelectTableSource { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private boolean only = false; - protected OracleSelectPivotBase pivot; + private boolean only = false; + protected OracleSelectPivotBase pivot; - protected SampleClause sampleClause; + protected PartitionExtensionClause partition; + protected SampleClause sampleClause; public OracleSelectTableReference(){ } + public PartitionExtensionClause getPartition() { + return partition; + } + + public void setPartition(PartitionExtensionClause partition) { + this.partition = partition; + } + public boolean isOnly() { return this.only; } @@ -65,6 +75,7 @@ public class OracleSelectTableReference extends SQLExprTableSource implements Or protected void accept0(OracleASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, this.expr); + acceptChild(visitor, this.partition); acceptChild(visitor, this.sampleClause); acceptChild(visitor, this.pivot); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleASTVisitor.java index 59d7eada7c..0516cbf9d3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleASTVisitor.java @@ -19,6 +19,7 @@ import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeInterval; import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalytic; @@ -313,4 +314,8 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleSelectTableReference x); void endVisit(OracleSelectTableReference x); + + boolean visit(PartitionExtensionClause x); + + void endVisit(PartitionExtensionClause x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleOutputVisitor.java index cc16ffc607..2b440d6d6b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleOutputVisitor.java @@ -31,6 +31,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeInterval; import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalytic; @@ -712,9 +713,20 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.isOnly()) { print("ONLY ("); x.getExpr().accept(this); + + if (x.getPartition() != null) { + print(" "); + x.getPartition().accept(this); + } + print(")"); } else { x.getExpr().accept(this); + + if (x.getPartition() != null) { + print(" "); + x.getPartition().accept(this); + } } if (x.getSampleClause() != null) { @@ -1486,4 +1498,29 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } + @Override + public boolean visit(PartitionExtensionClause x) { + if (x.isSubPartition()) { + print("SUBPARTITION "); + } else { + print("PARTITION "); + } + + if (x.getPartition() != null) { + print("("); + x.getPartition().accept(this); + print(")"); + } else { + print("FOR ("); + printAndAccept(x.getFor(), ","); + print(")"); + } + return false; + } + + @Override + public void endVisit(PartitionExtensionClause x) { + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java index 5cb1b4e20f..378c1a28de 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect; @@ -327,10 +328,39 @@ public class OracleSelectParser extends SQLSelectParser { if (identifierEquals("PARTITION")) { lexer.nextToken(); - throw new ParserException("TODO"); + PartitionExtensionClause partition = new PartitionExtensionClause(); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + partition.setPartition(createExprParser().name()); + accept(Token.RPAREN); + } else { + accept(Token.FOR); + accept(Token.LPAREN); + createExprParser().names(partition.getFor()); + accept(Token.RPAREN); + } + + tableReference.setPartition(partition); } + if (identifierEquals("SUBPARTITION")) { - throw new ParserException("TODO"); + lexer.nextToken(); + PartitionExtensionClause partition = new PartitionExtensionClause(); + partition.setSubPartition(true); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + partition.setPartition(createExprParser().name()); + accept(Token.RPAREN); + } else { + accept(Token.FOR); + accept(Token.LPAREN); + createExprParser().names(partition.getFor()); + accept(Token.RPAREN); + } + + tableReference.setPartition(partition); } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java index fda7834913..806d8afe11 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -47,9 +47,8 @@ public class SQLParser { if (lexer.token() == Token.AS) { lexer.nextToken(); - // QS_TODO remove alias token if (lexer.token() == Token.LITERAL_ALIAS) { - rtnValue = "'" + lexer.stringVal() + "'"; + rtnValue = lexer.stringVal(); lexer.nextToken(); return rtnValue; } @@ -64,10 +63,10 @@ public class SQLParser { } if (lexer.token() == Token.LITERAL_ALIAS) { - rtnValue = "'" + lexer.stringVal() + "'"; + rtnValue = lexer.stringVal(); lexer.nextToken(); } else if (lexer.token() == Token.IDENTIFIER) { - rtnValue = "'" + lexer.stringVal() + "'"; + rtnValue = lexer.stringVal(); lexer.nextToken(); } return rtnValue; diff --git a/src/test/java/com/alibaba/druid/sql/oracle/bvt/OracleSQLParserResourceTest.java b/src/test/java/com/alibaba/druid/sql/oracle/bvt/OracleSQLParserResourceTest.java index 2fb8c2a888..66c0e93444 100644 --- a/src/test/java/com/alibaba/druid/sql/oracle/bvt/OracleSQLParserResourceTest.java +++ b/src/test/java/com/alibaba/druid/sql/oracle/bvt/OracleSQLParserResourceTest.java @@ -22,7 +22,7 @@ public class OracleSQLParserResourceTest extends TestCase { exec_test("bvt/parser/oracle-3.txt"); exec_test("bvt/parser/oracle-4.txt"); exec_test("bvt/parser/oracle-5.txt"); - //exec_test("bvt/parser/oracle-6.txt"); PARTITION + exec_test("bvt/parser/oracle-6.txt"); // PARTITION exec_test("bvt/parser/oracle-7.txt"); exec_test("bvt/parser/oracle-8.txt"); } diff --git a/src/test/resources/bvt/parser/oracle-6.txt b/src/test/resources/bvt/parser/oracle-6.txt index 4f78d70f63..1eeb9d4cb6 100644 --- a/src/test/resources/bvt/parser/oracle-6.txt +++ b/src/test/resources/bvt/parser/oracle-6.txt @@ -2,6 +2,7 @@ SELECT * FROM sales PARTITION (sales_q2_2000) s WHERE s.amount_sold > 1500 ORDER BY cust_id, time_id, channel_id; --------------------------- -SELECT * FROM sales PARTITION (sales_q2_2000) s - WHERE s.amount_sold > 1500 - ORDER BY cust_id, time_id, channel_id; \ No newline at end of file +SELECT * +FROM sales PARTITION (sales_q2_2000) s +WHERE s.amount_sold > 1500 +ORDER BY cust_id, time_id, channel_id; \ No newline at end of file