mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
完全支持Oracle Interval表达式
git-svn-id: http://code.alibabatech.com/svn/druid/trunk@949 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
Regular → Executable
+4
-3
@@ -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);
|
||||
}
|
||||
|
||||
+15
-7
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user