improve Oracle SQL Parser, support Timestamp & Interval

This commit is contained in:
wenshao
2012-12-29 17:29:23 +08:00
parent a60fe40542
commit 25b4f4582a
10 changed files with 502 additions and 0 deletions
@@ -0,0 +1,48 @@
package com.alibaba.druid.sql.dialect.oracle.ast;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleDataTypeIntervalDay extends SQLDataTypeImpl implements OracleSQLObject {
private static final long serialVersionUID = 1L;
private boolean toSecond = false;
protected final List<SQLExpr> fractionalSeconds = new ArrayList<SQLExpr>();
public OracleDataTypeIntervalDay(){
this.setName("INTERVAL DAY");
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((OracleASTVisitor) visitor);
}
@Override
public void accept0(OracleASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, getArguments());
}
visitor.endVisit(this);
}
public boolean isToSecond() {
return toSecond;
}
public void setToSecond(boolean toSecond) {
this.toSecond = toSecond;
}
public List<SQLExpr> getFractionalSeconds() {
return fractionalSeconds;
}
}
@@ -0,0 +1,28 @@
package com.alibaba.druid.sql.dialect.oracle.ast;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleDataTypeIntervalYear extends SQLDataTypeImpl implements OracleSQLObject {
private static final long serialVersionUID = 1L;
public OracleDataTypeIntervalYear(){
this.setName("INTERVAL YEAR");
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((OracleASTVisitor) visitor);
}
@Override
public void accept0(OracleASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, getArguments());
}
visitor.endVisit(this);
}
}
@@ -0,0 +1,47 @@
package com.alibaba.druid.sql.dialect.oracle.ast;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleDataTypeTimestamp extends SQLDataTypeImpl implements OracleSQLObject {
private static final long serialVersionUID = 1L;
private boolean withTimeZone = false;
private boolean withLocalTimeZone = false;
public OracleDataTypeTimestamp() {
this.setName("TIMESTAMP");
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((OracleASTVisitor) visitor);
}
@Override
public void accept0(OracleASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, getArguments());
}
visitor.endVisit(this);
}
public boolean isWithTimeZone() {
return withTimeZone;
}
public void setWithTimeZone(boolean withTimeZone) {
this.withTimeZone = withTimeZone;
}
public boolean isWithLocalTimeZone() {
return withLocalTimeZone;
}
public void setWithLocalTimeZone(boolean withLocalTimeZone) {
this.withLocalTimeZone = withLocalTimeZone;
}
}
@@ -37,6 +37,9 @@ import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.SQLCharactorDataType;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp;
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;
@@ -75,6 +78,7 @@ public class OracleExprParser extends SQLExprParser {
public boolean allowStringAdditive = false;
/**
@@ -117,9 +121,73 @@ public class OracleExprParser extends SQLExprParser {
return null;
}
if (lexer.token() == Token.INTERVAL) {
lexer.nextToken();
if (identifierEquals("YEAR")) {
lexer.nextToken();
OracleDataTypeIntervalYear interval = new OracleDataTypeIntervalYear();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
interval.getArguments().add(this.expr());
accept(Token.RPAREN);
}
accept(Token.TO);
acceptIdentifier("MONTH");
return interval;
} else {
acceptIdentifier("DAY");
OracleDataTypeIntervalDay interval = new OracleDataTypeIntervalDay();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
interval.getArguments().add(this.expr());
accept(Token.RPAREN);
}
accept(Token.TO);
acceptIdentifier("SECOND");
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
interval.getFractionalSeconds().add(this.expr());
accept(Token.RPAREN);
}
return interval;
}
}
SQLName typeExpr = name();
String typeName = typeExpr.toString();
if ("TIMESTAMP".equalsIgnoreCase(typeName)) {
OracleDataTypeTimestamp timestamp = new OracleDataTypeTimestamp();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
timestamp.getArguments().add(this.expr());
accept(Token.RPAREN);
}
if (lexer.token() == Token.WITH) {
lexer.nextToken();
if (identifierEquals("LOCAL")) {
lexer.nextToken();
timestamp.setWithLocalTimeZone(true);
} else {
timestamp.setWithTimeZone(true);
}
acceptIdentifier("TIME");
acceptIdentifier("ZONE");
}
return timestamp;
}
if (isCharType(typeName)) {
SQLCharactorDataType charType = new SQLCharactorDataType(typeName);
@@ -16,6 +16,9 @@
package com.alibaba.druid.sql.dialect.oracle.visitor;
import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause;
@@ -611,4 +614,17 @@ public interface OracleASTVisitor extends SQLASTVisitor {
boolean visit(OracleDropDatabaseLinkStatement x);
void endVisit(OracleDropDatabaseLinkStatement x);
boolean visit(OracleDataTypeTimestamp x);
void endVisit(OracleDataTypeTimestamp x);
boolean visit(OracleDataTypeIntervalYear x);
void endVisit(OracleDataTypeIntervalYear x);
boolean visit(OracleDataTypeIntervalDay x);
void endVisit(OracleDataTypeIntervalDay x);
}
@@ -16,6 +16,9 @@
package com.alibaba.druid.sql.dialect.oracle.visitor;
import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause;
@@ -1393,4 +1396,34 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora
}
@Override
public boolean visit(OracleDataTypeTimestamp x) {
return true;
}
@Override
public void endVisit(OracleDataTypeTimestamp x) {
}
@Override
public boolean visit(OracleDataTypeIntervalYear x) {
return true;
}
@Override
public void endVisit(OracleDataTypeIntervalYear x) {
}
@Override
public boolean visit(OracleDataTypeIntervalDay x) {
return true;
}
@Override
public void endVisit(OracleDataTypeIntervalDay x) {
}
}
@@ -38,6 +38,9 @@ import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType;
import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause;
@@ -3107,4 +3110,72 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
}
return false;
}
@Override
public boolean visit(OracleDataTypeTimestamp x) {
print(x.getName());
if (x.getArguments().size() > 0) {
print("(");
x.getArguments().get(0).accept(this);
print(")");
}
if (x.isWithTimeZone()) {
print(" WITH TIME ZONE");
} else if (x.isWithLocalTimeZone()) {
print(" WITH LOCAL TIME ZONE");
}
return false;
}
@Override
public void endVisit(OracleDataTypeTimestamp x) {
}
@Override
public boolean visit(OracleDataTypeIntervalYear x) {
print(x.getName());
if (x.getArguments().size() > 0) {
print("(");
x.getArguments().get(0).accept(this);
print(")");
}
print(" TO MONTH");
return false;
}
@Override
public void endVisit(OracleDataTypeIntervalYear x) {
}
@Override
public boolean visit(OracleDataTypeIntervalDay x) {
print(x.getName());
if (x.getArguments().size() > 0) {
print("(");
x.getArguments().get(0).accept(this);
print(")");
}
print(" TO SECOND");
if (x.getFractionalSeconds().size() > 0) {
print("(");
x.getFractionalSeconds().get(0).accept(this);
print(")");
}
return false;
}
@Override
public void endVisit(OracleDataTypeIntervalDay x) {
// TODO Auto-generated method stub
}
}
@@ -37,6 +37,9 @@ import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause;
@@ -1822,4 +1825,34 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle
public void endVisit(OracleDropDatabaseLinkStatement x) {
}
@Override
public boolean visit(OracleDataTypeTimestamp x) {
return false;
}
@Override
public void endVisit(OracleDataTypeTimestamp x) {
}
@Override
public boolean visit(OracleDataTypeIntervalYear x) {
return false;
}
@Override
public void endVisit(OracleDataTypeIntervalYear x) {
}
@Override
public boolean visit(OracleDataTypeIntervalDay x) {
return false;
}
@Override
public void endVisit(OracleDataTypeIntervalDay x) {
}
}