Oracle支持BinaryFloat和BinaryDouble

git-svn-id: http://code.alibabatech.com/svn/druid/trunk@171 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
wenshao
2011-05-21 07:10:45 +00:00
parent 8872f603ec
commit 19b51f3eef
17 changed files with 411 additions and 107 deletions
@@ -0,0 +1,45 @@
package com.alibaba.druid.sql.dialect.oracle.ast.expr;
import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleBinaryDoubleExpr extends SQLNumericLiteralExpr {
private static final long serialVersionUID = 1L;
private Double value;
public OracleBinaryDoubleExpr(){
}
public OracleBinaryDoubleExpr(Double value){
super();
this.value = value;
}
@Override
public Number getNumber() {
return value;
}
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
accept0((OracleASTVisitor) visitor);
}
protected void accept0(OracleASTVisitor visitor) {
visitor.visit(this);
visitor.endVisit(this);
}
}
@@ -0,0 +1,45 @@
package com.alibaba.druid.sql.dialect.oracle.ast.expr;
import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleBinaryFloatExpr extends SQLNumericLiteralExpr {
private static final long serialVersionUID = 1L;
private Float value;
public OracleBinaryFloatExpr(){
}
public OracleBinaryFloatExpr(Float value){
super();
this.value = value;
}
@Override
public Number getNumber() {
return value;
}
public Float getValue() {
return value;
}
public void setValue(Float value) {
this.value = value;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
accept0((OracleASTVisitor) visitor);
}
protected void accept0(OracleASTVisitor visitor) {
visitor.visit(this);
visitor.endVisit(this);
}
}
@@ -15,17 +15,28 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.expr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleDateExpr extends OracleDatetimeLiteralExpr {
public class OracleDateExpr extends SQLLiteralExpr {
private static final long serialVersionUID = 1L;
private String literal;
public OracleDateExpr(){
}
public String getLiteral() {
return literal;
}
public void setLiteral(String literal) {
this.literal = literal;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((OracleASTVisitor) visitor);
@@ -36,26 +47,4 @@ public class OracleDateExpr extends OracleDatetimeLiteralExpr {
visitor.endVisit(this);
}
public void output(StringBuffer buf) {
buf.append("DATE '");
buf.append(this.year);
buf.append('-');
buf.append(this.month);
buf.append("-");
buf.append(this.dayOfMonth);
if ((this.hour != 0) || (this.minute != 0) || (this.second != 0)) {
buf.append(' ');
buf.append(this.hour);
buf.append(":");
buf.append(this.minute);
if (this.second != 0) {
buf.append(":");
buf.append(this.second);
}
}
buf.append("'");
}
}
@@ -15,25 +15,26 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.expr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleTimestampExpr extends OracleDatetimeLiteralExpr {
public class OracleTimestampExpr extends SQLLiteralExpr {
private static final long serialVersionUID = 1L;
private int milliSecond;
private String literal;
private String timeZone;
public OracleTimestampExpr(){
}
public int getMilliSecond() {
return this.milliSecond;
public String getLiteral() {
return literal;
}
public void setMilliSecond(int milliSecond) {
this.milliSecond = milliSecond;
public void setLiteral(String literal) {
this.literal = literal;
}
public String getTimeZone() {
@@ -44,40 +45,6 @@ public class OracleTimestampExpr extends OracleDatetimeLiteralExpr {
this.timeZone = timeZone;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("TIMESTAMP '");
buf.append(this.year);
buf.append('-');
buf.append(this.month);
buf.append("-");
buf.append(this.dayOfMonth);
if ((this.hour != 0) || (this.minute != 0) || (this.second != 0) || (this.milliSecond != 0) || (this.timeZone != null)) {
buf.append(' ');
buf.append(this.hour);
buf.append(":");
buf.append(this.minute);
buf.append(":");
buf.append(this.second);
if (this.milliSecond != 0) {
buf.append(".");
buf.append(this.milliSecond);
}
if (this.timeZone != null) {
buf.append(this.timeZone);
}
}
buf.append("'");
return buf.toString();
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((OracleASTVisitor) visitor);
@@ -31,6 +31,8 @@ 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.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.OracleDateExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr;
@@ -357,4 +359,12 @@ public interface OracleASTVisitor extends SQLASTVisitor {
boolean visit(CycleClause x);
void endVisit(CycleClause x);
boolean visit(OracleBinaryFloatExpr x);
void endVisit(OracleBinaryFloatExpr x);
boolean visit(OracleBinaryDoubleExpr x);
void endVisit(OracleBinaryDoubleExpr x);
}
@@ -44,6 +44,8 @@ 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.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.OracleDateExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr;
@@ -265,25 +267,8 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
public boolean visit(OracleDateExpr x) {
print("DATE '");
print(x.getYear());
print("-");
print(x.getMonth());
print("-");
print(x.getDayOfMonth());
if ((x.getHour() != 0) || (x.getMinute() != 0) || (x.getSecond() != 0)) {
print(" ");
print(x.getHour());
print(":");
print(x.getMinute());
if (x.getSecond() != 0) {
print(":");
print(x.getSecond());
}
}
print("'");
print(x.getLiteral());
print('\'');
return false;
}
@@ -905,32 +890,15 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
public boolean visit(OracleTimestampExpr x) {
print("TIMESTAMP '");
print(x.getYear());
print('-');
print(x.getMonth());
print("-");
print(x.getDayOfMonth());
print(x.getLiteral());
print('\'');
if ((x.getHour() != 0) || (x.getMinute() != 0) || (x.getSecond() != 0) || (x.getMilliSecond() != 0) || (x.getTimeZone() != null)) {
print(' ');
print(x.getHour());
print(":");
print(x.getHour());
print(":");
print(x.getSecond());
if (x.getMilliSecond() != 0) {
print(".");
print(x.getMilliSecond());
}
if (x.getTimeZone() != null) {
print(x.getTimeZone());
}
if (x.getTimeZone() != null) {
print(" AT TIME ZONE '");
print(x.getTimeZone());
print('\'');
}
print("'");
return false;
}
@@ -1692,4 +1660,28 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
}
@Override
public boolean visit(OracleBinaryFloatExpr x) {
print(x.getValue().toString());
print('F');
return false;
}
@Override
public void endVisit(OracleBinaryFloatExpr x) {
}
@Override
public boolean visit(OracleBinaryDoubleExpr x) {
print(x.getValue().toString());
print('D');
return false;
}
@Override
public void endVisit(OracleBinaryDoubleExpr x) {
}
}
@@ -15,19 +15,27 @@
*/
package com.alibaba.druid.sql.dialect.oracle.parser;
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.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
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.OracleBinaryDoubleExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr;
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.OracleExtractExpr;
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.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.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
@@ -38,6 +46,9 @@ public class OracleExprParser extends SQLExprParser {
public boolean allowStringAdditive = false;
/**
@@ -75,6 +86,7 @@ public class OracleExprParser extends SQLExprParser {
public SQLExpr primary() throws ParserException {
final Token tok = lexer.token();
SQLExpr sqlExpr = null;
switch (tok) {
case COLON:
lexer.nextToken();
@@ -115,10 +127,124 @@ public class OracleExprParser extends SQLExprParser {
accept(Token.RPAREN);
return primaryRest(extract);
case TIMESTAMP:
return primaryRest(parseTimestamp());
case DATE:
return primaryRest(parseDate());
case BINARY_FLOAT:
OracleBinaryFloatExpr floatExpr = new OracleBinaryFloatExpr();
floatExpr.setValue(Float.parseFloat(lexer.numberString()));
lexer.nextToken();
return primaryRest(floatExpr);
case BINARY_DOUBLE:
OracleBinaryDoubleExpr doubleExpr = new OracleBinaryDoubleExpr();
doubleExpr.setValue(Double.parseDouble(lexer.numberString()));
lexer.nextToken();
return primaryRest(doubleExpr);
case PLUS:
lexer.nextToken();
switch (lexer.token()) {
case LITERAL_INT:
sqlExpr = new SQLIntegerExpr(lexer.integerValue());
lexer.nextToken();
break;
case LITERAL_FLOAT:
sqlExpr = new SQLNumberExpr(lexer.decimalValue());
lexer.nextToken();
break;
case BINARY_FLOAT:
sqlExpr = new OracleBinaryFloatExpr(Float.parseFloat(lexer.numberString()));
lexer.nextToken();
break;
case BINARY_DOUBLE:
sqlExpr = new OracleBinaryDoubleExpr(Double.parseDouble(lexer.numberString()));
lexer.nextToken();
break;
default:
throw new ParserException("TODO");
}
return primaryRest(sqlExpr);
case SUB:
lexer.nextToken();
switch (lexer.token()) {
case LITERAL_INT:
Number integerValue = lexer.integerValue();
if (integerValue instanceof Integer) {
int intVal = ((Integer) integerValue).intValue();
if (intVal == Integer.MIN_VALUE) {
integerValue = Long.valueOf(((long) intVal) * -1);
} else {
integerValue = Integer.valueOf(intVal * -1);
}
} else if (integerValue instanceof Long) {
long longVal = ((Long) integerValue).longValue();
if (longVal == 2147483648L) {
integerValue = Integer.valueOf((int) (((long) longVal) * -1));
} else {
integerValue = Long.valueOf(longVal * -1);
}
} else {
integerValue = ((BigInteger) integerValue).negate();
}
sqlExpr = new SQLIntegerExpr(integerValue);
lexer.nextToken();
break;
case LITERAL_FLOAT:
sqlExpr = new SQLNumberExpr(lexer.decimalValue().negate());
lexer.nextToken();
break;
case BINARY_FLOAT:
sqlExpr = new OracleBinaryFloatExpr(Float.parseFloat(lexer.numberString()) * -1);
lexer.nextToken();
break;
case BINARY_DOUBLE:
sqlExpr = new OracleBinaryDoubleExpr(Double.parseDouble(lexer.numberString()) * -1);
lexer.nextToken();
break;
default:
throw new ParserException("TODO");
}
return primaryRest(sqlExpr);
default:
return super.primary();
}
}
public OracleDateExpr parseDate() {
accept(Token.DATE);
OracleDateExpr timestamp = new OracleDateExpr();
String literal = lexer.stringVal();
timestamp.setLiteral(literal);
accept(Token.LITERAL_CHARS);
return timestamp;
}
public OracleTimestampExpr parseTimestamp() {
accept(Token.TIMESTAMP);
OracleTimestampExpr timestamp = new OracleTimestampExpr();
String literal = lexer.stringVal();
timestamp.setLiteral(literal);
accept(Token.LITERAL_CHARS);
if (identifierEquals("AT")) {
lexer.nextToken();
acceptIdentifier("TIME");
acceptIdentifier("ZONE");
String timezone = lexer.stringVal();
timestamp.setTimeZone(timezone);
accept(Token.LITERAL_CHARS);
}
return timestamp;
}
@Override
public OracleOrderBy parseOrderBy() {
@@ -87,6 +87,8 @@ public class OracleLexer extends Lexer {
map.put("PRIOR", Token.PRIOR);
map.put("WITH", Token.WITH);
map.put("EXTRACT", Token.EXTRACT);
map.put("DATE", Token.DATE);
map.put("TIMESTAMP", Token.TIMESTAMP);
DEFAULT_ORACLE_KEYWORDS = new Keywords(map);
}
@@ -184,4 +186,78 @@ public class OracleLexer extends Lexer {
return;
}
}
public void scanNumber() {
np = bp;
if (ch == '-') {
sp++;
ch = buf[++bp];
}
for (;;) {
if (ch >= '0' && ch <= '9') {
sp++;
} else {
break;
}
ch = buf[++bp];
}
boolean isDouble = false;
if (ch == '.') {
sp++;
ch = buf[++bp];
isDouble = true;
for (;;) {
if (ch >= '0' && ch <= '9') {
sp++;
} else {
break;
}
ch = buf[++bp];
}
}
if (ch == 'e' || ch == 'E') {
sp++;
ch = buf[++bp];
if (ch == '+' || ch == '-') {
sp++;
ch = buf[++bp];
}
for (;;) {
if (ch >= '0' && ch <= '9') {
sp++;
} else {
break;
}
ch = buf[++bp];
}
isDouble = true;
}
if (ch == 'f' || ch == 'F') {
token = Token.BINARY_FLOAT;
scanChar();
return;
}
if (ch == 'd' || ch == 'D') {
token = Token.BINARY_DOUBLE;
scanChar();
return;
}
if (isDouble) {
token = Token.LITERAL_FLOAT;
} else {
token = Token.LITERAL_INT;
}
}
}
@@ -501,7 +501,7 @@ public class OracleSelectParser extends SQLSelectParser {
clause.setType(AsOfFlashbackQueryClause.Type.SCN);
lexer.nextToken();
} else {
acceptIdentifier("TIMESTAMP");
accept(Token.TIMESTAMP);
clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP);
}
clause.setExpr(createExprParser().primary());
@@ -521,7 +521,7 @@ public class OracleSelectParser extends SQLSelectParser {
clause.setType(AsOfFlashbackQueryClause.Type.SCN);
lexer.nextToken();
} else {
acceptIdentifier("TIMESTAMP");
accept(Token.TIMESTAMP);
clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP);
}
@@ -104,6 +104,8 @@ public enum Token {
CONNECT("CONNECT"),
WITH("WITH"),
EXTRACT("EXTRACT"),
TIMESTAMP("TIMESTAMP"),
DATE("DATE"),
EOF,
ERROR,
@@ -119,6 +121,10 @@ public enum Token {
LITERAL_ALIAS,
LINE_COMMENT,
MULTI_LINE_COMMENT,
// Oracle
BINARY_FLOAT,
BINARY_DOUBLE,
LPAREN("("),
RPAREN(")"),
@@ -52,6 +52,12 @@ public class OracleSQLParserResourceTest extends TestCase {
exec_test("bvt/parser/oracle-33.txt");
exec_test("bvt/parser/oracle-34.txt");
exec_test("bvt/parser/oracle-35.txt");
exec_test("bvt/parser/oracle-36.txt");
exec_test("bvt/parser/oracle-37.txt");
exec_test("bvt/parser/oracle-38.txt");
exec_test("bvt/parser/oracle-39.txt");
exec_test("bvt/parser/oracle-40.txt");
exec_test("bvt/parser/oracle-41.txt");
}
@@ -0,0 +1,11 @@
SELECT last_name, employee_id, hire_date
FROM employees
WHERE EXTRACT(YEAR FROM TO_DATE(hire_date, 'DD-MON-RR')) > 2007
ORDER BY hire_date;
---------------------------
SELECT last_name, employee_id, hire_date
FROM employees
WHERE EXTRACT(YEAR FROM TO_DATE(hire_date, 'DD-MON-RR')) > 2007
ORDER BY hire_date;
@@ -0,0 +1,6 @@
SELECT EXTRACT(TIMEZONE_REGION FROM TIMESTAMP '1999-01-01 10:00:00 -08:00')
FROM DUAL;
---------------------------
SELECT EXTRACT(TIMEZONE_REGION FROM TIMESTAMP '1999-01-01 10:00:00 -08:00')
FROM DUAL;
@@ -0,0 +1,5 @@
SELECT TIMESTAMP '2009-10-29 01:30:00' AT TIME ZONE 'US/Pacific'
FROM DUAL;
---------------------------
SELECT TIMESTAMP '2009-10-29 01:30:00' AT TIME ZONE 'US/Pacific'
FROM DUAL;
@@ -0,0 +1,7 @@
SELECT *
FROM my_table
WHERE datecol = DATE '2002-10-03';
---------------------------
SELECT *
FROM my_table
WHERE datecol = DATE '2002-10-03';
@@ -0,0 +1,7 @@
SELECT *
FROM my_table
WHERE TRUNC(SYSDATE) = DATE '2002-10-03';
---------------------------
SELECT *
FROM my_table
WHERE TRUNC(SYSDATE) = DATE '2002-10-03';
@@ -0,0 +1,6 @@
SELECT 25, +6.34, 0.5, 25e-03, -1, 25f, +6.34F, 0.5d, -1D
FROM DUAL
---------------------------
SELECT 25, 6.34, 0.5, 0.025, -1
, 25.0F, 6.34F, 0.5D, -1.0D
FROM DUAL;