From 34fee37f94978af02cbdbc273152886390c87fd6 Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 12 Oct 2011 15:33:31 +0000 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81Oracle=20CURSOR=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://code.alibabatech.com/svn/druid/trunk@948 b9813039-fb51-4c41-a8b9-e21c2acb5095 --- .../oracle/ast/expr/OracleCursorExpr.java | 42 +++++++++++++++++++ .../oracle/parser/OracleExprParser.java | 24 ++++++++++- .../dialect/oracle/parser/OracleLexer.java | 2 + .../visitor/OracleASTVIsitorAdapter.java | 11 +++++ .../oracle/visitor/OracleASTVisitor.java | 5 +++ .../oracle/visitor/OracleOutputVisitor.java | 13 ++++++ .../com/alibaba/druid/sql/parser/Token.java | 1 + .../druid/bvt/sql/oracle/CursorTest.java | 26 ++++++++++++ .../oracle/OracleSQLParserResourceTest.java | 14 +------ .../druid/bvt/sql/oracle/TestUtils.java | 26 ++++++++++++ 10 files changed, 150 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleCursorExpr.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/CursorTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/TestUtils.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleCursorExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleCursorExpr.java new file mode 100644 index 0000000000..18e97b5adc --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleCursorExpr.java @@ -0,0 +1,42 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.expr; + +import com.alibaba.druid.sql.ast.SQLExprImpl; +import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class OracleCursorExpr extends SQLExprImpl { + + private static final long serialVersionUID = 1L; + + private SQLSelect query; + + public OracleCursorExpr(){ + + } + + public OracleCursorExpr(SQLSelect query){ + super(); + this.query = query; + } + + public SQLSelect getQuery() { + return query; + } + + public void setQuery(SQLSelect query) { + this.query = query; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((OracleASTVisitor) visitor); + } + + protected void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, query); + } + } + +} 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 1e3ebce00d..209321804e 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 @@ -30,6 +30,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalytic; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalyticWindowing; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateTimeUnit; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; @@ -39,6 +40,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalType; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OraclePriorExpr; 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.OracleSelect; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; @@ -47,6 +49,14 @@ import com.alibaba.druid.sql.parser.Token; public class OracleExprParser extends SQLExprParser { + + + + + + + + public boolean allowStringAdditive = false; /** @@ -199,6 +209,18 @@ public class OracleExprParser extends SQLExprParser { throw new ParserException("TODO"); } return primaryRest(sqlExpr); + + case CURSOR: + lexer.nextToken(); + accept(Token.LPAREN); + + OracleSelect select = createSelectParser().select(); + OracleCursorExpr cursorExpr = new OracleCursorExpr(select); + + accept(Token.RPAREN); + + sqlExpr = cursorExpr; + return primaryRest(sqlExpr); default: return super.primary(); } @@ -217,7 +239,7 @@ public class OracleExprParser extends SQLExprParser { expr = dblink; } - + return super.primaryRest(expr); } 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 1a8090aa17..1b88ef3156 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 @@ -93,6 +93,8 @@ public class OracleLexer extends Lexer { map.put("EXTRACT", Token.EXTRACT); map.put("DATE", Token.DATE); map.put("TIMESTAMP", Token.TIMESTAMP); + + map.put("CURSOR", Token.CURSOR); DEFAULT_ORACLE_KEYWORDS = new Keywords(map); } 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 e4147378d0..83ec0477eb 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 @@ -18,6 +18,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalyticWindowing; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArrayAccessExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr; @@ -588,4 +589,14 @@ public class OracleASTVIsitorAdapter extends SQLASTVisitorAdapter implements Ora } + @Override + public boolean visit(OracleCursorExpr x) { + return true; + } + + @Override + public void endVisit(OracleCursorExpr x) { + + } + } 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 151dd28981..1215ac9120 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 @@ -32,6 +32,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalyticWindowing; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArrayAccessExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr; @@ -260,4 +261,8 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleSelect x); void endVisit(OracleSelect x); + + boolean visit(OracleCursorExpr x); + + void endVisit(OracleCursorExpr 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 96d6d52a31..48a2d47e72 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 @@ -45,6 +45,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalyticWindowing; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArrayAccessExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr; @@ -1141,4 +1142,16 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS return false; } + @Override + public boolean visit(OracleCursorExpr x) { + print("CURSOR("); + x.getQuery().accept(this); + print(")"); + return false; + } + + @Override + public void endVisit(OracleCursorExpr x) { + + } } 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 2e1bbd23ee..5008a82f4e 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -106,6 +106,7 @@ public enum Token { EXTRACT("EXTRACT"), TIMESTAMP("TIMESTAMP"), DATE("DATE"), + CURSOR("CURSOR"), EOF, ERROR, diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/CursorTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/CursorTest.java new file mode 100644 index 0000000000..840cbdc837 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/CursorTest.java @@ -0,0 +1,26 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; + +public class CursorTest extends TestCase { + + public void test_cursor() throws Exception { + String sql = "SELECT department_name, CURSOR(SELECT salary, commission_pct FROM employees e WHERE e.department_id = d.department_id) " + + "FROM departments d;"; + + OracleStatementParser parser = new OracleStatementParser(sql); + SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0); + + String text = TestUtils.output(stmt); + + Assert.assertEquals("SELECT department_name, CURSOR(SELECT salary, commission_pct\n" + + "\tFROM employees e\n" + "\tWHERE e.department_id = d.department_id)\n" + + "FROM departments d;\n", text); + + System.out.println(text); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSQLParserResourceTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSQLParserResourceTest.java index ce4610b733..afc1f844fe 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSQLParserResourceTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSQLParserResourceTest.java @@ -10,7 +10,6 @@ import junit.framework.TestCase; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; -import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; import com.alibaba.druid.util.JdbcUtils; public class OracleSQLParserResourceTest extends TestCase { @@ -40,20 +39,9 @@ public class OracleSQLParserResourceTest extends TestCase { Assert.assertEquals(1, statementList.size()); - String text = output(statementList); + String text = TestUtils.output(statementList); System.out.println(text); Assert.assertEquals(expect, text.trim()); } - - private String output(List stmtList) { - StringBuilder out = new StringBuilder(); - OracleOutputVisitor visitor = new OracleOutputVisitor(out); - - for (SQLStatement stmt : stmtList) { - stmt.accept(visitor); - } - - return out.toString(); - } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/TestUtils.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/TestUtils.java new file mode 100644 index 0000000000..153a313176 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/TestUtils.java @@ -0,0 +1,26 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.Arrays; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; + + +public class TestUtils { + + public static String output(List stmtList) { + StringBuilder out = new StringBuilder(); + OracleOutputVisitor visitor = new OracleOutputVisitor(out); + + for (SQLStatement stmt : stmtList) { + stmt.accept(visitor); + } + + return out.toString(); + } + + public static String output(SQLStatement... stmtList) { + return output(Arrays.asList(stmtList)); + } +}