From 19b51f3eef1fc04d02b9ec3b4c7b09bb6e6eff60 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 21 May 2011 07:10:45 +0000 Subject: [PATCH] =?UTF-8?q?Oracle=E6=94=AF=E6=8C=81BinaryFloat=E5=92=8CBin?= =?UTF-8?q?aryDouble?= 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@171 b9813039-fb51-4c41-a8b9-e21c2acb5095 --- .../ast/expr/OracleBinaryDoubleExpr.java | 45 +++++++ .../ast/expr/OracleBinaryFloatExpr.java | 45 +++++++ .../oracle/ast/expr/OracleDateExpr.java | 35 ++--- .../oracle/ast/expr/OracleTimestampExpr.java | 47 +------ .../oracle/ast/visitor/OracleASTVisitor.java | 10 ++ .../ast/visitor/OracleOutputVisitor.java | 76 +++++------ .../oracle/parser/OracleExprParser.java | 126 ++++++++++++++++++ .../dialect/oracle/parser/OracleLexer.java | 76 +++++++++++ .../oracle/parser/OracleSelectParser.java | 4 +- .../com/alibaba/druid/sql/parser/Token.java | 6 + .../bvt/OracleSQLParserResourceTest.java | 6 + src/test/resources/bvt/parser/oracle-36.txt | 11 ++ src/test/resources/bvt/parser/oracle-37.txt | 6 + src/test/resources/bvt/parser/oracle-38.txt | 5 + src/test/resources/bvt/parser/oracle-39.txt | 7 + src/test/resources/bvt/parser/oracle-40.txt | 7 + src/test/resources/bvt/parser/oracle-41.txt | 6 + 17 files changed, 411 insertions(+), 107 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java create mode 100644 src/test/resources/bvt/parser/oracle-36.txt create mode 100644 src/test/resources/bvt/parser/oracle-37.txt create mode 100644 src/test/resources/bvt/parser/oracle-38.txt create mode 100644 src/test/resources/bvt/parser/oracle-39.txt create mode 100644 src/test/resources/bvt/parser/oracle-40.txt create mode 100644 src/test/resources/bvt/parser/oracle-41.txt diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java new file mode 100644 index 0000000000..3f94f23c0c --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java @@ -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); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java new file mode 100644 index 0000000000..46b8097b5f --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java @@ -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); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDateExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDateExpr.java index c2a321335a..cad3f90beb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDateExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDateExpr.java @@ -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("'"); - } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleTimestampExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleTimestampExpr.java index 762cc5f41f..ce82385aeb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleTimestampExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleTimestampExpr.java @@ -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); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleASTVisitor.java index ce274ae150..cfd3832448 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleASTVisitor.java @@ -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); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleOutputVisitor.java index fb7ee1fe15..8b5006cc1c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/visitor/OracleOutputVisitor.java @@ -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) { + + } + } 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 c53ca71d56..80f838b8f3 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 @@ -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() { 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 71f064939f..734da8432d 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 @@ -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; + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java index e1fadc13d9..aa1d1b844f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java @@ -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); } 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 4828768f96..2e1bbd23ee 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -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(")"), diff --git a/src/test/java/com/alibaba/druid/sql/oracle/bvt/OracleSQLParserResourceTest.java b/src/test/java/com/alibaba/druid/sql/oracle/bvt/OracleSQLParserResourceTest.java index 6e02001049..a2d18be129 100644 --- a/src/test/java/com/alibaba/druid/sql/oracle/bvt/OracleSQLParserResourceTest.java +++ b/src/test/java/com/alibaba/druid/sql/oracle/bvt/OracleSQLParserResourceTest.java @@ -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"); } diff --git a/src/test/resources/bvt/parser/oracle-36.txt b/src/test/resources/bvt/parser/oracle-36.txt new file mode 100644 index 0000000000..3dbdb05e72 --- /dev/null +++ b/src/test/resources/bvt/parser/oracle-36.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; diff --git a/src/test/resources/bvt/parser/oracle-37.txt b/src/test/resources/bvt/parser/oracle-37.txt new file mode 100644 index 0000000000..f3b3d0d789 --- /dev/null +++ b/src/test/resources/bvt/parser/oracle-37.txt @@ -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; \ No newline at end of file diff --git a/src/test/resources/bvt/parser/oracle-38.txt b/src/test/resources/bvt/parser/oracle-38.txt new file mode 100644 index 0000000000..83671d47a4 --- /dev/null +++ b/src/test/resources/bvt/parser/oracle-38.txt @@ -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; \ No newline at end of file diff --git a/src/test/resources/bvt/parser/oracle-39.txt b/src/test/resources/bvt/parser/oracle-39.txt new file mode 100644 index 0000000000..68106c0c3e --- /dev/null +++ b/src/test/resources/bvt/parser/oracle-39.txt @@ -0,0 +1,7 @@ +SELECT * + FROM my_table + WHERE datecol = DATE '2002-10-03'; +--------------------------- +SELECT * +FROM my_table +WHERE datecol = DATE '2002-10-03'; \ No newline at end of file diff --git a/src/test/resources/bvt/parser/oracle-40.txt b/src/test/resources/bvt/parser/oracle-40.txt new file mode 100644 index 0000000000..9357254213 --- /dev/null +++ b/src/test/resources/bvt/parser/oracle-40.txt @@ -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'; \ No newline at end of file diff --git a/src/test/resources/bvt/parser/oracle-41.txt b/src/test/resources/bvt/parser/oracle-41.txt new file mode 100644 index 0000000000..d3f90d3649 --- /dev/null +++ b/src/test/resources/bvt/parser/oracle-41.txt @@ -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; \ No newline at end of file