Oracle支持Flashback Clause

git-svn-id: http://code.alibabatech.com/svn/druid/trunk@152 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
wenshao
2011-05-20 01:47:36 +00:00
parent e8b6eef5c5
commit c679069eaa
8 changed files with 95 additions and 20 deletions
@@ -6,7 +6,9 @@ import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleASTVisitor;
public abstract class FlashbackQueryClause extends OracleSQLObject {
private Type type;
private static final long serialVersionUID = 1L;
private Type type;
public Type getType() {
return type;
@@ -21,7 +23,8 @@ public abstract class FlashbackQueryClause extends OracleSQLObject {
}
public static class VersionsFlashbackQueryClause extends FlashbackQueryClause {
private static final long serialVersionUID = 1L;
private SQLExpr begin;
private SQLExpr end;
@@ -52,7 +55,8 @@ public abstract class FlashbackQueryClause extends OracleSQLObject {
}
public static class AsOfFlashbackQueryClause extends FlashbackQueryClause {
private static final long serialVersionUID = 1L;
private SQLExpr expr;
public SQLExpr getExpr() {
@@ -744,6 +744,11 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
decrementIndent();
}
if (x.getFlashback() != null) {
println();
x.getFlashback().accept(this);
}
printAlias(x.getAlias());
@@ -1545,8 +1550,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
public boolean visit(AsOfFlashbackQueryClause x) {
print("AS OF ");
print(x.getType().name());
print(" ");
print(" (");
x.getExpr().accept(this);
print(")");
return false;
}
@@ -23,6 +23,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr;
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.OracleIntervalExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalType;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectOrderByItem;
import com.alibaba.druid.sql.parser.Lexer;
@@ -252,4 +253,24 @@ public class OracleExprParser extends SQLExprParser {
return item;
}
protected SQLExpr parseInterval() {
accept(Token.INTERVAL);
OracleIntervalExpr interval = new OracleIntervalExpr();
if (lexer.token() != Token.LITERAL_CHARS) {
throw new ParserException("syntax error : " + lexer.token());
}
interval.setValue(lexer.stringVal());
lexer.nextToken();
if (lexer.token() != Token.IDENTIFIER) {
throw new ParserException("syntax error : " + lexer.token());
}
OracleIntervalType type = OracleIntervalType.valueOf(lexer.stringVal());
interval.setType(type);
lexer.nextToken();
return interval;
}
}
@@ -16,6 +16,8 @@
package com.alibaba.druid.sql.dialect.oracle.parser;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
@@ -23,6 +25,7 @@ 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.FlashbackQueryClause.AsOfFlashbackQueryClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause;
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;
@@ -380,6 +383,34 @@ public class OracleSelectParser extends SQLSelectParser {
clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP);
}
clause.setExpr(createExprParser().primary());
tableReference.setFlashback(clause);
} else {
throw new SQLParseException("TODO");
}
} else if (identifierEquals("VERSIONS")) {
lexer.nextToken();
if (lexer.token() == Token.BETWEEN) {
lexer.nextToken();
VersionsFlashbackQueryClause clause = new VersionsFlashbackQueryClause();
if (identifierEquals("SCN")) {
clause.setType(AsOfFlashbackQueryClause.Type.SCN);
lexer.nextToken();
} else {
acceptIdentifier("TIMESTAMP");
clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP);
}
SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) createExprParser().expr();
if (binaryExpr.getOperator() != SQLBinaryOperator.BooleanAnd) {
throw new SQLParseException("syntax error : " + binaryExpr.getOperator());
}
clause.setBegin(binaryExpr.getLeft());
clause.setEnd(binaryExpr.getRight());
tableReference.setFlashback(clause);
} else {
throw new SQLParseException("TODO");
@@ -16,20 +16,22 @@ import com.alibaba.druid.util.JdbcUtils;
public class OracleSQLParserResourceTest extends TestCase {
public void test_0() throws Exception {
// exec_test("bvt/parser/oracle-0.txt");
// exec_test("bvt/parser/oracle-1.txt");
// exec_test("bvt/parser/oracle-2.txt");
// 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-7.txt");
// exec_test("bvt/parser/oracle-8.txt");
exec_test("bvt/parser/oracle-0.txt");
exec_test("bvt/parser/oracle-1.txt");
exec_test("bvt/parser/oracle-2.txt");
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-7.txt");
exec_test("bvt/parser/oracle-8.txt");
exec_test("bvt/parser/oracle-9.txt");
exec_test("bvt/parser/oracle-10.txt");
}
public void exec_test(String resource) throws Exception {
System.out.println(resource);
InputStream is = null;
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
@@ -0,0 +1,10 @@
SELECT salary FROM employees
VERSIONS BETWEEN TIMESTAMP
SYSTIMESTAMP - INTERVAL '10' MINUTE AND
SYSTIMESTAMP - INTERVAL '1' MINUTE
WHERE last_name = 'Chung';
---------------------------
SELECT salary
FROM employees
VERSIONS BETWEEN TIMESTAMP SYSTIMESTAMP - INTERVAL '10' MINUTE AND SYSTIMESTAMP - INTERVAL '1' MINUTE
WHERE last_name = 'Chung';
+4 -4
View File
@@ -9,9 +9,9 @@ FROM
FROM employees) b
ORDER BY a.department_id;
---------------------------
SELECT a.department_id AS 'department_id', a.num_emp / b.total_count AS 'total_count', a.sal_sum / b.total_sal AS 'total_sal'
FROM (SELECT department_id, COUNT(*) AS 'num_emp', SUM(salary) AS 'sal_sum'
SELECT a.department_id AS department_id, a.num_emp / b.total_count AS total_count, a.sal_sum / b.total_sal AS total_sal
FROM (SELECT department_id, COUNT(*) AS num_emp, SUM(salary) AS sal_sum
FROM employees
GROUP BY department_id) 'a' , (SELECT COUNT(*) AS 'total_count', SUM(salary) AS 'total_sal'
FROM employees) 'b'
GROUP BY department_id) a , (SELECT COUNT(*) AS total_count, SUM(salary) AS total_sal
FROM employees) b
ORDER BY a.department_id;
+4 -3
View File
@@ -2,6 +2,7 @@ SELECT salary FROM employees
AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '1' MINUTE)
WHERE last_name = 'Chung';
---------------------------
SELECT salary FROM employees
AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '1' MINUTE)
WHERE last_name = 'Chung';
SELECT salary
FROM employees
AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '1' MINUTE)
WHERE last_name = 'Chung';