完全支持Oracle Interval表达式

git-svn-id: http://code.alibabatech.com/svn/druid/trunk@949 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
wenshao
2011-10-13 02:42:20 +00:00
parent 34fee37f94
commit 0a4e4dafb9
7 changed files with 283 additions and 20 deletions
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.expr;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -22,7 +23,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleIntervalExpr extends SQLLiteralExpr {
private static final long serialVersionUID = 1L;
private String value;
private SQLExpr value;
private OracleIntervalType type;
private Integer precision;
private Integer factionalSecondsPrecision;
@@ -33,11 +34,11 @@ public class OracleIntervalExpr extends SQLLiteralExpr {
}
public String getValue() {
public SQLExpr getValue() {
return this.value;
}
public void setValue(String value) {
public void setValue(SQLExpr value) {
this.value = value;
}
@@ -19,6 +19,7 @@ import java.math.BigInteger;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
@@ -57,6 +58,35 @@ public class OracleExprParser extends SQLExprParser {
public boolean allowStringAdditive = false;
/**
@@ -240,6 +270,44 @@ public class OracleExprParser extends SQLExprParser {
expr = dblink;
}
if (lexer.token() == Token.DAY || lexer.token() == Token.YEAR) {
OracleIntervalExpr interval = new OracleIntervalExpr();
interval.setValue(expr);
OracleIntervalType type = OracleIntervalType.valueOf(lexer.token().name);
interval.setType(type);
lexer.nextToken();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
if (lexer.token() != Token.LITERAL_INT) {
throw new ParserException("syntax error");
}
interval.setPrecision(lexer.integerValue().intValue());
lexer.nextToken();
accept(Token.RPAREN);
}
accept(Token.TO);
if (lexer.token() == Token.SECOND) {
lexer.nextToken();
interval.setToType(OracleIntervalType.SECOND);
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
if (lexer.token() != Token.LITERAL_INT) {
throw new ParserException("syntax error");
}
interval.setFactionalSecondsPrecision(lexer.integerValue().intValue());
lexer.nextToken();
accept(Token.RPAREN);
}
} else {
interval.setToType(OracleIntervalType.MONTH);
lexer.nextToken();
}
expr = interval;
}
return super.primaryRest(expr);
}
@@ -458,16 +526,53 @@ public class OracleExprParser extends SQLExprParser {
if (lexer.token() != Token.LITERAL_CHARS) {
throw new ParserException("syntax error : " + lexer.token());
}
interval.setValue(lexer.stringVal());
interval.setValue(new SQLCharExpr(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;
OracleIntervalType type = OracleIntervalType.valueOf(lexer.token().name);
interval.setType(type);
lexer.nextToken();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
if (lexer.token() != Token.LITERAL_INT) {
throw new ParserException("syntax error");
}
interval.setPrecision(lexer.integerValue().intValue());
lexer.nextToken();
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
if (lexer.token() != Token.LITERAL_INT) {
throw new ParserException("syntax error");
}
interval.setFactionalSecondsPrecision(lexer.integerValue().intValue());
lexer.nextToken();
}
accept(Token.RPAREN);
}
if (lexer.token() == Token.TO) {
accept(Token.TO);
if (lexer.token() == Token.SECOND) {
lexer.nextToken();
interval.setToType(OracleIntervalType.SECOND);
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
if (lexer.token() != Token.LITERAL_INT) {
throw new ParserException("syntax error");
}
interval.setToFactionalSecondsPrecision(lexer.integerValue().intValue());
lexer.nextToken();
accept(Token.RPAREN);
}
} else {
interval.setToType(OracleIntervalType.MONTH);
lexer.nextToken();
}
}
return interval;
}
}
@@ -95,6 +95,12 @@ public class OracleLexer extends Lexer {
map.put("TIMESTAMP", Token.TIMESTAMP);
map.put("CURSOR", Token.CURSOR);
map.put("DAY", Token.DAY);
map.put("YEAR", Token.YEAR);
map.put("MONTH", Token.MONTH);
map.put("SECOND", Token.SECOND);
map.put("TO", Token.TO);
DEFAULT_ORACLE_KEYWORDS = new Keywords(map);
}
@@ -24,6 +24,7 @@ import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr;
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType;
@@ -241,12 +242,19 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
}
public boolean visit(OracleIntervalExpr x) {
print("INTERVAL '");
print(x.getValue());
print("' ");
if (x.getValue() instanceof SQLLiteralExpr) {
print("INTERVAL ");
x.getValue().accept(this);
print(" ");
} else {
print('(');
x.getValue().accept(this);
print(") ");
}
print(x.getType().name());
if ((x.getPrecision() != null) || (x.getFactionalSecondsPrecision() != null)) {
if (x.getPrecision() != null) {
print("(");
print(x.getPrecision().intValue());
if (x.getFactionalSecondsPrecision() != null) {
@@ -258,10 +266,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
if (x.getToType() != null) {
print(" TO ");
print(x.getType().name());
print(x.getToType().name());
if (x.getToFactionalSecondsPrecision() != null) {
print("(");
print(x.getFactionalSecondsPrecision().intValue());
print(x.getToFactionalSecondsPrecision().intValue());
print(")");
}
}
@@ -1152,6 +1160,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
@Override
public void endVisit(OracleCursorExpr x) {
}
}
@@ -106,7 +106,12 @@ public enum Token {
EXTRACT("EXTRACT"),
TIMESTAMP("TIMESTAMP"),
DATE("DATE"),
CURSOR("CURSOR"),
CURSOR("SECOND"),
DAY("DAY"),
YEAR("YEAR"),
MONTH("MONTH"),
SECOND("SECOND"),
TO("TO"),
EOF,
ERROR,
@@ -0,0 +1,102 @@
package com.alibaba.druid.bvt.sql.oracle;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import junit.framework.Assert;
import junit.framework.TestCase;
public class OracleIntervalTest extends TestCase {
public void test_interval_literal() throws Exception {
String sql = "SELECT INTERVAL '123-2' YEAR(3) TO MONTH FROM DUAL";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
String text = TestUtils.output(stmt);
Assert.assertEquals("SELECT INTERVAL '123-2' YEAR(3) TO MONTH\nFROM DUAL;\n", text);
System.out.println(text);
}
public void test_interval_literal_1() throws Exception {
String sql = "SELECT INTERVAL '123' YEAR(3) FROM DUAL";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
String text = TestUtils.output(stmt);
Assert.assertEquals("SELECT INTERVAL '123' YEAR(3)\nFROM DUAL;\n", text);
System.out.println(text);
}
public void test_interval_literal_2() throws Exception {
String sql = "SELECT INTERVAL '5-3' YEAR TO MONTH + INTERVAL'20' MONTH FROM DUAL";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
String text = TestUtils.output(stmt);
Assert.assertEquals("SELECT INTERVAL '5-3' YEAR TO MONTH + INTERVAL '20' MONTH\nFROM DUAL;\n", text);
System.out.println(text);
}
public void test_interval_literal_3() throws Exception {
String sql = "SELECT INTERVAL '6-11' YEAR TO MONTH FROM DUAL";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
String text = TestUtils.output(stmt);
Assert.assertEquals("SELECT INTERVAL '6-11' YEAR TO MONTH\nFROM DUAL;\n", text);
System.out.println(text);
}
public void test_interval_literal_4() throws Exception {
String sql = "SELECT INTERVAL '4 5:12:10.222' DAY TO SECOND(3) FROM DUAL";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
String text = TestUtils.output(stmt);
Assert.assertEquals("SELECT INTERVAL '4 5:12:10.222' DAY TO SECOND(3)\nFROM DUAL;\n", text);
System.out.println(text);
}
public void test_interval_literal_5() throws Exception {
String sql = "SELECT INTERVAL '30.12345' SECOND(2,4) FROM DUAL";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
String text = TestUtils.output(stmt);
Assert.assertEquals("SELECT INTERVAL '30.12345' SECOND(2, 4)\nFROM DUAL;\n", text);
System.out.println(text);
}
public void test_interval() throws Exception {
String sql = "SELECT (SYSTIMESTAMP - order_date) DAY(9) TO SECOND from orders WHERE order_id = 2458;";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
String text = TestUtils.output(stmt);
Assert.assertEquals("SELECT (SYSTIMESTAMP - order_date) DAY(9) TO SECOND\n" + "FROM orders\n"
+ "WHERE order_id = 2458;\n", text);
System.out.println(text);
}
}
@@ -0,0 +1,36 @@
package com.alibaba.druid.bvt.sql.oracle;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import junit.framework.Assert;
import junit.framework.TestCase;
public class OracleNumberLiteralTest extends TestCase {
public void test_number_literal() throws Exception {
String sql = "SELECT 7, +255, 0.5, +6.34,25e-03, +6.34F, 0.5d, -1D FROM DUAL";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
String text = TestUtils.output(stmt);
Assert.assertEquals("SELECT 7, 255, 0.5, 6.34, 0.025\n\t, 6.34F, 0.5D, -1.0D\nFROM DUAL;\n", text);
System.out.println(text);
}
public void test_number_literal_2() throws Exception {
String sql = "SELECT BINARY_FLOAT_INFINITY FROM DUAL";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
String text = TestUtils.output(stmt);
Assert.assertEquals("SELECT BINARY_FLOAT_INFINITY\nFROM DUAL;\n", text);
System.out.println(text);
}
}