From 7268c17624b756c084cc4c45154e195b71f459cf Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 21 Sep 2017 22:05:27 +0800 Subject: [PATCH] improved oracle sql parser. --- .../alibaba/druid/sql/SQLTransformUtils.java | 11 ++ .../alibaba/druid/sql/ast/SQLDataType.java | 1 + .../druid/sql/ast/expr/SQLNumberExpr.java | 5 +- .../statement/SQLAlterFunctionStatement.java | 62 ++++++ .../ast/statement/SQLAlterTypeStatement.java | 79 ++++++++ .../statement/SQLCreateFunctionStatement.java | 28 +++ .../statement/SQLCreateTableStatement.java | 3 + .../visitor/OracleToMySqlOutputVisitor.java | 10 + .../ast/stmt/OracleCreateTypeStatement.java | 96 +++++++++ .../oracle/parser/OracleExprParser.java | 6 + .../oracle/parser/OracleFunctionDataType.java | 87 +++++++++ .../dialect/oracle/parser/OracleLexer.java | 2 +- .../oracle/parser/OracleStatementParser.java | 182 +++++++++++++++++- .../oracle/visitor/OracleASTVisitor.java | 4 + .../visitor/OracleASTVisitorAdapter.java | 10 + .../oracle/visitor/OracleOutputVisitor.java | 51 ++++- .../visitor/OracleSchemaStatVisitor.java | 10 + .../druid/sql/parser/SQLStatementParser.java | 17 ++ .../sql/visitor/SQLASTOutputVisitor.java | 70 ++++++- .../druid/sql/visitor/SQLASTVisitor.java | 8 + .../sql/visitor/SQLASTVisitorAdapter.java | 20 ++ .../druid/sql/visitor/SchemaStatVisitor.java | 8 + .../java/com/alibaba/druid/util/FnvHash.java | 5 + .../META-INF/druid/parser/postgresql/keywords | 1 + ...ySqlParameterizedOutputVisitorTest_56.java | 65 +++++++ .../alter/OracleAlterFunctionTest0.java | 66 +++++++ .../oracle/alter/OracleAlterTypeTest0.java | 66 +++++++ .../create/OracleCreateFunctionTest_1.java | 67 +++++++ .../oracle/create/OracleCreateTypeTest0.java | 101 ++++++++++ .../oracle/create/OracleCreateTypeTest1.java | 83 ++++++++ ...acleParameterizedOutputVisitorTest_01.java | 8 +- ...acleParameterizedOutputVisitorTest_02.java | 55 ++++++ .../Oracle2PG_DataTypeTest_datetime.java | 7 + 33 files changed, 1273 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterFunctionStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTypeStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTypeStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleFunctionDataType.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_56.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterFunctionTest0.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterTypeTest0.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateFunctionTest_1.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTypeTest0.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTypeTest1.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_02.java diff --git a/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java b/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java index 566de60a15..bc0aadc22b 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java @@ -588,6 +588,10 @@ public class SQLTransformUtils { dataType = new SQLDataTypeImpl(SQLDataType.Constants.TIMESTAMP, 0); } else if (nameHash == FnvHash.Constants.TIMESTAMP) { x.setName(SQLDataType.Constants.TIMESTAMP); + if (x.isWithLocalTimeZone()) { + x.setWithLocalTimeZone(false); + x.setWithTimeZone(null); + } dataType = x; } else if (nameHash == FnvHash.Constants.DATETIME) { int len = -1; @@ -669,6 +673,13 @@ public class SQLTransformUtils { } } + if (nameHashCode64 == FnvHash.Constants.SYSTIMESTAMP) { + SQLMethodInvokeExpr xx = x.clone(); + xx.setMethodName("CURRENT_TIMESTAMP"); + xx.setParent(x.getParent()); + return xx; + } + return x; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java b/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java index 2efde8f0aa..a18b9d7f6f 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java @@ -31,6 +31,7 @@ public interface SQLDataType extends SQLObject { void setWithTimeZone(Boolean value); boolean isWithLocalTimeZone(); + void setWithLocalTimeZone(boolean value); SQLDataType clone(); diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumberExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumberExpr.java index b1b2643a61..40ef8ffa77 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumberExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumberExpr.java @@ -110,7 +110,10 @@ public class SQLNumberExpr extends SQLNumericLiteralExpr implements SQLValuableE } public SQLNumberExpr clone() { - return new SQLNumberExpr(number); + SQLNumberExpr x = new SQLNumberExpr(); + x.chars = chars; + x.number = number; + return x; } public SQLDataType computeDataType() { diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterFunctionStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterFunctionStatement.java new file mode 100644 index 0000000000..9b088e5898 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterFunctionStatement.java @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.sql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLAlterFunctionStatement extends SQLStatementImpl { + private SQLName name; + + private boolean debug; + private boolean reuseSettings; + + public boolean isDebug() { + return debug; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public SQLName getName() { + return name; + } + + public void setName(SQLName name) { + if (name != null) { + name.setParent(this); + } + this.name = name; + } + + public boolean isReuseSettings() { + return reuseSettings; + } + + public void setReuseSettings(boolean x) { + this.reuseSettings = x; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + } + visitor.endVisit(this); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTypeStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTypeStatement.java new file mode 100644 index 0000000000..c0499fdde9 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTypeStatement.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.sql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLAlterTypeStatement extends SQLStatementImpl { + private SQLName name; + + private boolean compile; + private boolean debug; + private boolean body; + private boolean reuseSettings; + + public SQLName getName() { + return name; + } + + public void setName(SQLName name) { + if (name != null) { + name.setParent(this); + } + this.name = name; + } + + public boolean isCompile() { + return compile; + } + + public void setCompile(boolean compile) { + this.compile = compile; + } + + public boolean isDebug() { + return debug; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public boolean isBody() { + return body; + } + + public void setBody(boolean body) { + this.body = body; + } + + public boolean isReuseSettings() { + return reuseSettings; + } + + public void setReuseSettings(boolean reuseSettings) { + this.reuseSettings = reuseSettings; + } + + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + } + visitor.endVisit(this); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java index a96f0c7113..c7eec2888c 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java @@ -46,6 +46,9 @@ public class SQLCreateFunctionStatement extends SQLStatementImpl implements SQLC private String comment; private boolean deterministic = false; + private boolean parallelEnable; + private boolean aggregate; + private SQLName using; public SQLCreateFunctionStatement clone() { SQLCreateFunctionStatement x = new SQLCreateFunctionStatement(); @@ -210,4 +213,29 @@ public class SQLCreateFunctionStatement extends SQLStatementImpl implements SQLC public void setDataType(SQLDataType dataType) { this.setReturnDataType(dataType); } + + + public boolean isParallelEnable() { + return parallelEnable; + } + + public void setParallelEnable(boolean parallel_enable) { + this.parallelEnable = parallel_enable; + } + + public boolean isAggregate() { + return aggregate; + } + + public void setAggregate(boolean aggregate) { + this.aggregate = aggregate; + } + + public SQLName getUsing() { + return using; + } + + public void setUsing(SQLName using) { + this.using = using; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java index c34a2d4249..872af6995e 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java @@ -47,6 +47,8 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS protected SQLExprTableSource like; + + public SQLCreateTableStatement(){ } @@ -928,4 +930,5 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS public String toString() { return SQLUtils.toSQLString(this, dbType); } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/OracleToMySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/OracleToMySqlOutputVisitor.java index 0f50643b8c..7615ce1b4d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/OracleToMySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/OracleToMySqlOutputVisitor.java @@ -1005,4 +1005,14 @@ public class OracleToMySqlOutputVisitor extends MySqlOutputVisitor implements Or public void endVisit(OracleCreateSynonymStatement x) { } + + @Override + public boolean visit(OracleCreateTypeStatement x) { + return false; + } + + @Override + public void endVisit(OracleCreateTypeStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTypeStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTypeStatement.java new file mode 100644 index 0000000000..82f9d2ff4a --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTypeStatement.java @@ -0,0 +1,96 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLParameter; +import com.alibaba.druid.sql.ast.statement.SQLCreateStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +import java.util.ArrayList; +import java.util.List; + +public class OracleCreateTypeStatement extends OracleStatementImpl implements SQLCreateStatement { + private boolean orReplace; + private SQLName name; + private boolean force; + private SQLName oid; + private boolean body; + + private List parameters = new ArrayList(); + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + acceptChild(visitor, oid); + acceptChild(visitor, parameters); + } + visitor.endVisit(this); + } + + public SQLName getName() { + return name; + } + + public void setName(SQLName name) { + if (name != null) { + name.setParent(this); + } + this.name = name; + } + + public boolean isOrReplace() { + return orReplace; + } + + public void setOrReplace(boolean orReplace) { + this.orReplace = orReplace; + } + + public boolean isForce() { + return force; + } + + public void setForce(boolean force) { + this.force = force; + } + + public SQLName getOid() { + return oid; + } + + public void setOid(SQLName oid) { + if (oid != null) { + oid.setParent(this); + } + this.oid = oid; + } + + public List getParameters() { + return parameters; + } + + public boolean isBody() { + return body; + } + + public void setBody(boolean body) { + this.body = body; + } +} 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 393999dd5d..b9285b7d9d 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 @@ -994,6 +994,12 @@ public class OracleExprParser extends SQLExprParser { dbLink.setDbLink(link); return dbLink; } +// +// if (name.nameHashCode64() == FnvHash.Constants.UNSUPPORTED +// && lexer.identifierEquals(FnvHash.Constants.TYPE)) { +// name = new SQLIdentifierExpr(name.getSimpleName() + " " + lexer.stringVal()); +// lexer.nextToken(); +// } return name; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleFunctionDataType.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleFunctionDataType.java new file mode 100644 index 0000000000..1125297d29 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleFunctionDataType.java @@ -0,0 +1,87 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.sql.dialect.oracle.parser; + +import com.alibaba.druid.sql.ast.SQLDataType; +import com.alibaba.druid.sql.ast.SQLDataTypeImpl; +import com.alibaba.druid.sql.ast.SQLParameter; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +import java.util.ArrayList; +import java.util.List; + +public class OracleFunctionDataType extends SQLDataTypeImpl { + private boolean isStatic = false; + private final List parameters = new ArrayList(); + + private SQLDataType returnDataType; + + private SQLStatement block; + + public boolean isStatic() { + return isStatic; + } + + public void setStatic(boolean aStatic) { + isStatic = aStatic; + } + + public List getParameters() { + return parameters; + } + + public SQLDataType getReturnDataType() { + return returnDataType; + } + + public void setReturnDataType(SQLDataType x) { + if (x != null) { + x.setParent(this); + } + this.returnDataType = x; + } + + public OracleFunctionDataType clone() { + OracleFunctionDataType x = new OracleFunctionDataType(); + cloneTo(x); + + x.isStatic = isStatic; + if (returnDataType != null) { + x.setReturnDataType(returnDataType.clone()); + } + for (SQLParameter parameter : parameters) { + SQLParameter p2 = parameter.clone(); + p2.setParent(x); + x.parameters.add(p2); + } + + return x; + } + + public SQLStatement getBlock() { + return block; + } + + public void setBlock(SQLStatement block) { + if (block != null) { + block.setParent(this); + } + this.block = block; + } +} 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 78ee204ccf..713c5fc8a2 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 @@ -249,7 +249,7 @@ public class OracleLexer extends Lexer { stringVal = subString(mark + startHintSp, (bufPos - startHintSp) - 1); token = Token.HINT; } else { - stringVal = subString(mark, bufPos); + stringVal = subString(mark, bufPos + 1); token = Token.MULTI_LINE_COMMENT; commentCount++; if (keepComments) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index 340503e96a..d664892cfe 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -29,6 +29,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartit import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.UpdateIndexesClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement.LockMode; import com.alibaba.druid.sql.parser.*; +import com.alibaba.druid.util.FnvHash; import com.alibaba.druid.util.JdbcConstants; public class OracleStatementParser extends SQLStatementParser { @@ -752,7 +753,6 @@ public class OracleStatementParser extends SQLStatementParser { } public SQLCreateFunctionStatement parseCreateFunction() { - accept(Token.CREATE); SQLCreateFunctionStatement stmt = (SQLCreateFunctionStatement) parseFunction(); stmt.setCreate(true); return stmt; @@ -770,6 +770,9 @@ public class OracleStatementParser extends SQLStatementParser { stmt.setOrReplace(true); } } else { + if (lexer.token() == Token.DECLARE) { + lexer.nextToken(); + } stmt.setCreate(false); } @@ -805,10 +808,8 @@ public class OracleStatementParser extends SQLStatementParser { return stmt; } - if (lexer.token() == Token.IS) { + if (lexer.token() == Token.IS || lexer.token() == Token.AS) { lexer.nextToken(); - } else { - accept(Token.AS); } if (lexer.identifierEquals("LANGUAGE")) { @@ -825,7 +826,30 @@ public class OracleStatementParser extends SQLStatementParser { return stmt; } - SQLStatement block = this.parseBlock(); + if (lexer.identifierEquals("PARALLEL_ENABLE")) { + lexer.nextToken(); + stmt.setParallelEnable(true); + } + + if (lexer.identifierEquals("AGGREGATE")) { + lexer.nextToken(); + stmt.setAggregate(true); + } + + if (lexer.token() == Token.USING) { + lexer.nextToken(); + SQLName using = this.exprParser.name(); + stmt.setUsing(using); + } + + SQLStatement block; + if (lexer.token() == Token.SEMI) { + stmt.setAfterSemi(true); + lexer.nextToken(); + block = null; + } else { + block = this.parseBlock(); + } stmt.setBlock(block); @@ -1031,6 +1055,7 @@ public class OracleStatementParser extends SQLStatementParser { } public SQLStatement parserAlter() { + Lexer.SavePoint savePoint = lexer.mark(); accept(Token.ALTER); if (lexer.token() == Token.SESSION) { lexer.nextToken(); @@ -1227,11 +1252,76 @@ public class OracleStatementParser extends SQLStatementParser { } return stmt; + } else if (lexer.token() == Token.FUNCTION) { + lexer.reset(savePoint); + return parseAlterFunction(); + } else if (lexer.identifierEquals(FnvHash.Constants.TYPE)) { + lexer.reset(savePoint); + return parseAlterType(); } throw new ParserException("TODO : " + lexer.info()); } + protected SQLStatement parseAlterType() { + accept(Token.ALTER); + acceptIdentifier("TYPE"); + + SQLAlterTypeStatement stmt = new SQLAlterTypeStatement(); + stmt.setDbType(dbType); + + SQLName name = this.exprParser.name(); + stmt.setName(name); + + if (lexer.identifierEquals("COMPILE")) { + stmt.setCompile(true); + lexer.nextToken(); + } + + if (lexer.identifierEquals("DEBUG")) { + stmt.setDebug(true); + lexer.nextToken(); + } + + if (lexer.identifierEquals("BODY")) { + stmt.setBody(true); + lexer.nextToken(); + } + + if (lexer.identifierEquals("REUSE")) { + stmt.setReuseSettings(true); + lexer.nextToken(); + acceptIdentifier("SETTINGS"); + } + + return stmt; + } + + protected SQLStatement parseAlterFunction() { + accept(Token.ALTER); + accept(Token.FUNCTION); + + SQLAlterFunctionStatement stmt = new SQLAlterFunctionStatement(); + stmt.setDbType(dbType); + + SQLName name = this.exprParser.name(); + stmt.setName(name); + + acceptIdentifier("COMPILE"); + + if (lexer.identifierEquals("DEBUG")) { + stmt.setDebug(true); + lexer.nextToken(); + } + + if (lexer.identifierEquals("REUSE")) { + stmt.setReuseSettings(true); + lexer.nextToken(); + acceptIdentifier("SETTINGS"); + } + return stmt; + } + private SQLStatement parseAlterTable() { lexer.nextToken(); SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType()); @@ -1528,6 +1618,8 @@ public class OracleStatementParser extends SQLStatementParser { SQLBlockStatement block = new SQLBlockStatement(); block.setDbType(JdbcConstants.ORACLE); + Lexer.SavePoint savePoint = lexer.mark(); + if (lexer.token() == Token.DECLARE) { lexer.nextToken(); } @@ -1548,6 +1640,11 @@ public class OracleStatementParser extends SQLStatementParser { return stmt; } + if (lexer.token() == Token.FUNCTION) { + lexer.reset(savePoint); + return this.parseCreateFunction(); + } + accept(Token.BEGIN); parseStatementList(block.getStatementList(), -1, block); @@ -1573,6 +1670,7 @@ public class OracleStatementParser extends SQLStatementParser { private void parserParameters(List parameters, SQLObject parent) { for (;;) { SQLParameter parameter = new SQLParameter(); + parameter.setParent(parent); SQLName name; SQLDataType dataType = null; @@ -1666,9 +1764,31 @@ public class OracleStatementParser extends SQLStatementParser { parameter.setConstant(true); } - dataType = this.exprParser.parseDataType(false); + if ((name.nameHashCode64() == FnvHash.Constants.MEMBER + || name.nameHashCode64() == FnvHash.Constants.STATIC) + && lexer.token() == Token.FUNCTION) { + OracleFunctionDataType functionDataType = new OracleFunctionDataType(); + functionDataType.setStatic(name.nameHashCode64() == FnvHash.Constants.STATIC); + lexer.nextToken(); + functionDataType.setName(lexer.stringVal()); + accept(Token.IDENTIFIER); + accept(Token.LPAREN); + this.parserParameters(functionDataType.getParameters(), functionDataType); + accept(Token.RPAREN); + accept(Token.RETURN); + functionDataType.setReturnDataType(this.exprParser.parseDataType()); + dataType = functionDataType; + name = null; - if (lexer.token() == Token.COLONEQ) { + if (lexer.token() == Token.IS) { + lexer.nextToken(); + SQLStatement block = this.parseBlock(); + functionDataType.setBlock(block); + } + } else { + dataType = this.exprParser.parseDataType(false); + } + if (lexer.token() == Token.COLONEQ || lexer.token() == Token.DEFAULT) { lexer.nextToken(); parameter.setDefaultValue(this.exprParser.expr()); } @@ -1679,11 +1799,12 @@ public class OracleStatementParser extends SQLStatementParser { parameters.add(parameter); Token token = lexer.token(); - if (token == Token.COMMA || token == Token.SEMI) { + if (token == Token.COMMA || token == Token.SEMI || token == Token.IS) { lexer.nextToken(); } - if (lexer.token() != Token.BEGIN && lexer.token() != Token.RPAREN) { + token = lexer.token(); + if (token != Token.BEGIN && token != Token.RPAREN && token != Token.EOF) { continue; } @@ -2397,4 +2518,47 @@ public class OracleStatementParser extends SQLStatementParser { stmt.setObject(this.exprParser.name()); return stmt; } + + public SQLStatement parseCreateType() { + OracleCreateTypeStatement stmt = new OracleCreateTypeStatement(); + accept(Token.CREATE); + + if (lexer.token() == Token.OR) { + lexer.nextToken(); + accept(Token.REPLACE); + stmt.setOrReplace(true); + } + + acceptIdentifier("TYPE"); + + if (lexer.identifierEquals("BODY")) { + lexer.nextToken(); + stmt.setBody(true); + } + + SQLName name = this.exprParser.name(); + stmt.setName(name); + + if (lexer.token() == Token.AS || lexer.token() == Token.IS) { + lexer.nextToken(); + } + + if (lexer.identifierEquals("OBJECT")) { + lexer.nextToken(); + } + + if (lexer.identifierEquals(FnvHash.Constants.STATIC)) { + this.parserParameters(stmt.getParameters(), stmt); + } else { + accept(Token.LPAREN); + this.parserParameters(stmt.getParameters(), stmt); + accept(Token.RPAREN); + } + + if (lexer.token() == Token.SEMI) { + lexer.nextToken(); + stmt.setAfterSemi(true); + } + return stmt; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java index a78756018e..40b5afb356 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java @@ -429,4 +429,8 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleCreateSynonymStatement x); void endVisit(OracleCreateSynonymStatement x); + + boolean visit(OracleCreateTypeStatement x); + + void endVisit(OracleCreateTypeStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java index 4d7134c336..6b9b396b2f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java @@ -1063,4 +1063,14 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora public void endVisit(OracleCreateSynonymStatement x) { } + + @Override + public boolean visit(OracleCreateTypeStatement x) { + return true; + } + + @Override + public void endVisit(OracleCreateTypeStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 92b70d0d4b..bbd5fa2d41 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -2683,7 +2683,25 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS return false; } - block.accept(this); + if (x.isParallelEnable()) { + print0(ucase ? "PARALLEL_ENABLE" : "parallel_enable"); + println(); + } + + if (x.isAggregate()) { + print0(ucase ? "AGGREGATE" : "aggregate"); + println(); + } + + SQLName using = x.getUsing(); + if (using != null) { + print0(ucase ? "USING " : "using "); + using.accept(this); + } + + if (block != null) { + block.accept(this); + } return false; } @@ -3259,7 +3277,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(OracleCreateSynonymStatement x) { - if (x.isOrReplace()) { print0(ucase ? "CREATE OR REPLACE " : "create or replace "); } else { @@ -3284,4 +3301,34 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public void endVisit(OracleCreateSynonymStatement x) { } + + @Override + public boolean visit(OracleCreateTypeStatement x) { + if (x.isOrReplace()) { + print0(ucase ? "CREATE OR REPLACE TYPE " : "create or replace type "); + } else { + print0(ucase ? "CREATE TYPE " : "create type "); + } + + x.getName().accept(this); + + if (x.isForce()) { + print0(ucase ? "FORCE " : "force "); + } + + print0(" AS OBJECT ("); + indentCount++; + println(); + printlnAndAccept(x.getParameters(), ", "); + + indentCount--; + println(); + print0(")"); + return false; + } + + @Override + public void endVisit(OracleCreateTypeStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index e0547c9e7e..f4e6e712e7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -1355,4 +1355,14 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public void endVisit(OracleCreateSynonymStatement x) { } + + @Override + public boolean visit(OracleCreateTypeStatement x) { + return false; + } + + @Override + public void endVisit(OracleCreateTypeStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 73b75658f6..47d74dff5f 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -1874,11 +1874,21 @@ public class SQLStatementParser extends SQLParser { return parseCreateTrigger(); } + if (lexer.token == Token.FUNCTION) { + lexer.reset(markBp, markChar, Token.CREATE); + return parseCreateFunction(); + } + if (lexer.identifierEquals(FnvHash.Constants.PACKAGE)) { lexer.reset(markBp, markChar, Token.CREATE); return parseCreatePackage(); } + if (lexer.identifierEquals(FnvHash.Constants.TYPE)) { + lexer.reset(markBp, markChar, Token.CREATE); + return parseCreateType(); + } + // lexer.reset(mark_bp, mark_ch, Token.CREATE); throw new ParserException("TODO " + lexer.info()); } else if (token == Token.DATABASE) { @@ -1927,11 +1937,18 @@ public class SQLStatementParser extends SQLParser { } else if (lexer.identifierEquals(FnvHash.Constants.MATERIALIZED)) { lexer.reset(markBp, markChar, Token.CREATE); return parseCreateMaterializedView(); + } else if (lexer.identifierEquals(FnvHash.Constants.TYPE)) { + lexer.reset(markBp, markChar, Token.CREATE); + return parseCreateType(); } throw new ParserException("TODO " + lexer.token); } + public SQLStatement parseCreateType() { + throw new ParserException("TODO " + lexer.token); + } + public SQLStatement parseCreateUser() { accept(Token.CREATE); accept(Token.USER); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index ec58dfce5c..765cb51fb9 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -39,6 +39,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes; import com.alibaba.druid.sql.ast.statement.SQLDeclareStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreatePackageStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleForStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleFunctionDataType; import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.util.JdbcUtils; import oracle.sql.SQLUtil; @@ -4239,8 +4240,32 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet return false; } + public boolean visit(OracleFunctionDataType x) { + if (x.isStatic()) { + print0(ucase ? "STATIC " : "static "); + } + + print0(ucase ? "FUNCTION " : "function "); + + print0(x.getName()); + + print(" ("); + printAndAccept(x.getParameters(), ", "); + print(")"); + print0(ucase ? " RETURN " : " return "); + x.getReturnDataType().accept(this); + + SQLStatement block = x.getBlock(); + if (block != null) { + block.accept(this); + } + + return false; + } + @Override public boolean visit(SQLParameter x) { + SQLName name = x.getName(); if (x.getDataType().getName().equalsIgnoreCase("CURSOR")) { print0(ucase ? "CURSOR " : "cursor "); x.getName().accept(this); @@ -4255,6 +4280,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet SQLDataType dataType = x.getDataType(); if (JdbcConstants.ORACLE.equals(dbType)) { + if (dataType instanceof OracleFunctionDataType) { + OracleFunctionDataType functionDataType = (OracleFunctionDataType) dataType; + visit(functionDataType); + return false; + } String dataTypeName = dataType.getName(); boolean printType = (dataTypeName.startsWith("TABLE OF") && x.getDefaultValue() == null) || dataTypeName.equalsIgnoreCase("REF CURSOR") @@ -4263,7 +4293,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? "TYPE " : "type "); } - x.getName().accept(this); + name.accept(this); if (x.getParamType() == SQLParameter.ParameterType.IN) { print0(ucase ? " IN " : " in "); } else if (x.getParamType() == SQLParameter.ParameterType.OUT) { @@ -5277,6 +5307,44 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet return false; } + public boolean visit(SQLAlterFunctionStatement x) { + print0(ucase ? "ALTER FUNCTION " : "alter function "); + x.getName().accept(this); + + if (x.isDebug()) { + print0(ucase ? " DEBUG" : " debug"); + } + + if (x.isReuseSettings()) { + print0(ucase ? " REUSE SETTINGS" : " reuse settings"); + } + + return false; + } + + public boolean visit(SQLAlterTypeStatement x) { + print0(ucase ? "ALTER TYPE " : "alter type "); + x.getName().accept(this); + + if (x.isCompile()) { + print0(ucase ? " COMPILE" : " compile"); + } + + if (x.isBody()) { + print0(ucase ? " BODY" : " body"); + } + + if (x.isDebug()) { + print0(ucase ? " DEBUG" : " debug"); + } + + if (x.isReuseSettings()) { + print0(ucase ? " REUSE SETTINGS" : " reuse settings"); + } + + return false; + } + public Boolean getPrintStatementAfterSemi() { return printStatementAfterSemi; } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 8aaab00cb7..c6790bc3e3 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -750,4 +750,12 @@ public interface SQLASTVisitor { boolean visit(SQLCreateUserStatement x); void endVisit(SQLCreateUserStatement x); + + boolean visit(SQLAlterFunctionStatement x); + + void endVisit(SQLAlterFunctionStatement x); + + boolean visit(SQLAlterTypeStatement x); + + void endVisit(SQLAlterTypeStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index 050d81902e..2f22226ea1 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -1719,6 +1719,26 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { } + @Override + public boolean visit(SQLAlterFunctionStatement x) { + return true; + } + + @Override + public void endVisit(SQLAlterFunctionStatement x) { + + } + + @Override + public boolean visit(SQLAlterTypeStatement x) { + return true; + } + + @Override + public void endVisit(SQLAlterTypeStatement x) { + + } + public final boolean isEnabled(VisitorFeature feature) { return VisitorFeature.isEnabled(this.features, feature); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index f187cbd31f..4063799307 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -2365,4 +2365,12 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { x.accept(this); } } + + public boolean visit(SQLAlterFunctionStatement x) { + return false; + } + + public boolean visit(SQLAlterTypeStatement x) { + return false; + } } diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index 570d42655f..44a6336668 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -501,5 +501,10 @@ public final class FnvHash { long BITMAP = fnv1a_64_lower("BITMAP"); long PACKAGE = fnv1a_64_lower("PACKAGE"); long TRUNC = fnv1a_64_lower("TRUNC"); + long SYSTIMESTAMP = fnv1a_64_lower("SYSTIMESTAMP"); + long TYPE = fnv1a_64_lower("TYPE"); + long MEMBER = fnv1a_64_lower("MEMBER"); + long STATIC = fnv1a_64_lower("STATIC"); + long UNSUPPORTED = fnv1a_64_lower("UNSUPPORTED"); } } diff --git a/src/main/resources/META-INF/druid/parser/postgresql/keywords b/src/main/resources/META-INF/druid/parser/postgresql/keywords index 8aba3279f8..270c836e62 100644 --- a/src/main/resources/META-INF/druid/parser/postgresql/keywords +++ b/src/main/resources/META-INF/druid/parser/postgresql/keywords @@ -149,6 +149,7 @@ ntile null occurrences_regex octet_length +oid offset on only diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_56.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_56.java new file mode 100644 index 0000000000..079ac31932 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_56.java @@ -0,0 +1,65 @@ +package com.alibaba.druid.bvt.sql.mysql.param; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.util.JdbcConstants; +import com.alibaba.druid.util.JdbcUtils; +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by wenshao on 16/8/23. + */ +public class MySqlParameterizedOutputVisitorTest_56 extends TestCase { + public void test_for_parameterize() throws Exception { + final String dbType = JdbcConstants.MYSQL; + String sql = "/* 0b802ab415058233338893940e1882/0.1.2.23//abd5b625/ */select `ktv_resource`.`RESOURCE_ID`,`ktv_resource`.`RESOURCE_PROVIDER`,`ktv_resource`.`KTV_ID`,`ktv_resource`.`RESOURCE_TYPE`,`ktv_resource`.`SUB_RESOURCE_TYPE`,`ktv_resource`.`STATUS`,`ktv_resource`.`START_TIME`,`ktv_resource`.`END_TIME`,`ktv_resource`.`FEATURE`,`ktv_resource`.`GMT_CREATED`,`ktv_resource`.`GMT_MODIFIED`,`ktv_resource`.`source`,`ktv_resource`.`seller_id`,`ktv_resource`.`original_Resource_Id`,`ktv_resource`.`business_unit`,`ktv_resource`.`resource_code`,`ktv_resource`.`OPTIONS`,`ktv_resource`.`AVAILABLE_COUNT`,`ktv_resource`.`TOTAL_COUNT`,`ktv_resource`.`OUT_INSTANCE_ID`,`ktv_resource`.`CONSUME_ID`,`ktv_resource`.`GROUP_ID`,`ktv_resource`.`BUSINESS_ID`,`ktv_resource`.`rule`,`ktv_resource`.`market_place`,`ktv_resource`.`VERSION` from `ktv_resource_0062` `ktv_resource` where ((`ktv_resource`.`KTV_ID` = 880693310) AND (`ktv_resource`.`STATUS` = 1) AND (`ktv_resource`.`START_TIME` <= '2017-09-19 20:15:34.199') AND (`ktv_resource`.`END_TIME` >= '2017-09-19 20:15:34.199') AND (`ktv_resource`.`seller_id` IN (2680068332)) AND (`ktv_resource`.`AVAILABLE_COUNT` IS NULL OR (`ktv_resource`.`AVAILABLE_COUNT` > 0) OR (`ktv_resource`.`AVAILABLE_COUNT` = -1))) limit 0,30"; + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + List stmtList = parser.parseStatementList(); + SQLStatement statement = stmtList.get(0); + + StringBuilder out = new StringBuilder(); + SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, JdbcConstants.MYSQL); + List parameters = new ArrayList(); + visitor.setParameterized(true); + visitor.setParameterizedMergeInList(true); + visitor.setParameters(parameters); + /*visitor.setPrettyFormat(false);*/ + statement.accept(visitor); + /* JSONArray array = new JSONArray(); + for(String table : visitor.getTables()){ + array.add(table.replaceAll("`","")); + }*/ + + String psql = out.toString(); + + System.out.println(psql); + + + assertEquals("SELECT `ktv_resource`.`RESOURCE_ID`, `ktv_resource`.`RESOURCE_PROVIDER`, `ktv_resource`.`KTV_ID`, `ktv_resource`.`RESOURCE_TYPE`, `ktv_resource`.`SUB_RESOURCE_TYPE`\n" + + "\t, `ktv_resource`.`STATUS`, `ktv_resource`.`START_TIME`, `ktv_resource`.`END_TIME`, `ktv_resource`.`FEATURE`, `ktv_resource`.`GMT_CREATED`\n" + + "\t, `ktv_resource`.`GMT_MODIFIED`, `ktv_resource`.`source`, `ktv_resource`.`seller_id`, `ktv_resource`.`original_Resource_Id`, `ktv_resource`.`business_unit`\n" + + "\t, `ktv_resource`.`resource_code`, `ktv_resource`.`OPTIONS`, `ktv_resource`.`AVAILABLE_COUNT`, `ktv_resource`.`TOTAL_COUNT`, `ktv_resource`.`OUT_INSTANCE_ID`\n" + + "\t, `ktv_resource`.`CONSUME_ID`, `ktv_resource`.`GROUP_ID`, `ktv_resource`.`BUSINESS_ID`, `ktv_resource`.`rule`, `ktv_resource`.`market_place`\n" + + "\t, `ktv_resource`.`VERSION`\n" + + "FROM ktv_resource `ktv_resource`\n" + + "WHERE `ktv_resource`.`KTV_ID` = ?\n" + + "\tAND `ktv_resource`.`STATUS` = ?\n" + + "\tAND `ktv_resource`.`START_TIME` <= ?\n" + + "\tAND `ktv_resource`.`END_TIME` >= ?\n" + + "\tAND `ktv_resource`.`seller_id` IN (?)\n" + + "\tAND (`ktv_resource`.`AVAILABLE_COUNT` IS NULL\n" + + "\t\tOR `ktv_resource`.`AVAILABLE_COUNT` > ?\n" + + "\t\tOR `ktv_resource`.`AVAILABLE_COUNT` = ?)\n" + + "LIMIT ?, ?", psql); + + String rsql = SQLUtils.format(psql, JdbcConstants.MYSQL, parameters); + System.out.println(rsql); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterFunctionTest0.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterFunctionTest0.java new file mode 100644 index 0000000000..4bd7cf0a77 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterFunctionTest0.java @@ -0,0 +1,66 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.alter; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class OracleAlterFunctionTest0 extends OracleTest { + + public void test_0() throws Exception { + String sql = // + "ALTER FUNCTION \"ZEUS\".\"STRCAT\" COMPILE REUSE SETTINGS;"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("cdc.en_complaint_ipr_stat_fdt0"))); + + Assert.assertEquals(0, visitor.getColumns().size()); + + assertEquals("ALTER FUNCTION \"ZEUS\".\"STRCAT\" REUSE SETTINGS;",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + assertEquals("alter function \"ZEUS\".\"STRCAT\" reuse settings;",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterTypeTest0.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterTypeTest0.java new file mode 100644 index 0000000000..cecd26ab17 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterTypeTest0.java @@ -0,0 +1,66 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.alter; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class OracleAlterTypeTest0 extends OracleTest { + + public void test_0() throws Exception { + String sql = // + "ALTER TYPE \"ZEUS\".\"STRCAT_TYPE\" COMPILE BODY REUSE SETTINGS;"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("cdc.en_complaint_ipr_stat_fdt0"))); + + Assert.assertEquals(0, visitor.getColumns().size()); + + assertEquals("ALTER TYPE \"ZEUS\".\"STRCAT_TYPE\" COMPILE BODY REUSE SETTINGS;",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + assertEquals("alter type \"ZEUS\".\"STRCAT_TYPE\" compile body reuse settings;",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateFunctionTest_1.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateFunctionTest_1.java new file mode 100644 index 0000000000..fbc55c8ee1 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateFunctionTest_1.java @@ -0,0 +1,67 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleCreateFunctionTest_1 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "CREATE OR REPLACE FUNCTION STRCAT(input varchar2 )\n" + + "RETURN varchar2\n" + + "PARALLEL_ENABLE AGGREGATE USING strcat_type;"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); + + assertEquals("CREATE OR REPLACE FUNCTION STRCAT (\n" + + "\tinput varchar2\n" + + ")\n" + + "RETURN varchar2\n" + + "PARALLEL_ENABLE\n" + + "AGGREGATE\n" + + "USING strcat_type;",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(0, visitor.getTables().size()); + + assertEquals(0, visitor.getColumns().size()); + +// assertTrue(visitor.getColumns().contains(new TableStat.Column("orders", "order_total"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTypeTest0.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTypeTest0.java new file mode 100644 index 0000000000..3a9b70b0b1 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTypeTest0.java @@ -0,0 +1,101 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import org.junit.Assert; + +import java.util.List; + +public class OracleCreateTypeTest0 extends OracleTest { + + public void test_0() throws Exception { + String sql = // + "CREATE TYPE customer_typ_demo AS OBJECT\n" + + " ( customer_id NUMBER(6)\n" + + " , cust_first_name VARCHAR2(20)\n" + + " , cust_last_name VARCHAR2(20)\n" + + " , cust_address CUST_ADDRESS_TYP\n" + + " , phone_numbers PHONE_LIST_TYP\n" + + " , nls_language VARCHAR2(3)\n" + + " , nls_territory VARCHAR2(30)\n" + + " , credit_limit NUMBER(9,2)\n" + + " , cust_email VARCHAR2(30)\n" + + " , cust_orders ORDER_LIST_TYP\n" + + " ) ;"; // + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("relationships : " + visitor.getRelationships()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(0, visitor.getTables().size()); + + assertEquals(0, visitor.getColumns().size()); + + { + String text = SQLUtils.toOracleString(stmt); + + assertEquals("CREATE TYPE customer_typ_demo AS OBJECT (\n" + + "\tcustomer_id NUMBER(6), \n" + + "\tcust_first_name VARCHAR2(20), \n" + + "\tcust_last_name VARCHAR2(20), \n" + + "\tcust_address CUST_ADDRESS_TYP, \n" + + "\tphone_numbers PHONE_LIST_TYP, \n" + + "\tnls_language VARCHAR2(3), \n" + + "\tnls_territory VARCHAR2(30), \n" + + "\tcredit_limit NUMBER(9, 2), \n" + + "\tcust_email VARCHAR2(30), \n" + + "\tcust_orders ORDER_LIST_TYP\n" + + ");", text); + } + + { + String text = SQLUtils.toOracleString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + + assertEquals("create type customer_typ_demo AS OBJECT (\n" + + "\tcustomer_id NUMBER(6), \n" + + "\tcust_first_name VARCHAR2(20), \n" + + "\tcust_last_name VARCHAR2(20), \n" + + "\tcust_address CUST_ADDRESS_TYP, \n" + + "\tphone_numbers PHONE_LIST_TYP, \n" + + "\tnls_language VARCHAR2(3), \n" + + "\tnls_territory VARCHAR2(30), \n" + + "\tcredit_limit NUMBER(9, 2), \n" + + "\tcust_email VARCHAR2(30), \n" + + "\tcust_orders ORDER_LIST_TYP\n" + + ");", text); + } + // assertTrue(visitor.getColumns().contains(new TableStat.Column("acduser.vw_acd_info", "xzqh"))); + + // assertTrue(visitor.getOrderByColumns().contains(new TableStat.Column("employees", "last_name"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTypeTest1.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTypeTest1.java new file mode 100644 index 0000000000..a4f9acd001 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTypeTest1.java @@ -0,0 +1,83 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; + +import java.util.List; + +public class OracleCreateTypeTest1 extends OracleTest { + + public void test_0() throws Exception { + String sql = // + "CREATE OR REPLACE TYPE BODY \"STRCAT_TYPE\" is\n" + + " static function ODCIAggregateInitialize(cs_ctx IN OUT strcat_type) return number\n" + + " is\n" + + " begin\n" + + " cs_ctx := strcat_type( null );\n" + + " return ODCIConst.Success;\n" + + " end;"; // + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("relationships : " + visitor.getRelationships()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(0, visitor.getTables().size()); + + assertEquals(0, visitor.getColumns().size()); + + { + String text = SQLUtils.toOracleString(stmt); + + assertEquals("CREATE OR REPLACE TYPE \"STRCAT_TYPE\" AS OBJECT (\n" + + "\tSTATIC FUNCTION ODCIAggregateInitialize (cs_ctx IN OUT strcat_type) RETURN numberBEGIN\n" + + "\t\tcs_ctx := strcat_type(NULL);\n" + + "\t\tRETURN ODCIConst.Success;\n" + + "\tEND;\n" + + ")", text); + } + + { + String text = SQLUtils.toOracleString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + + assertEquals("create or replace type \"STRCAT_TYPE\" AS OBJECT (\n" + + "\tstatic function ODCIAggregateInitialize (cs_ctx in out strcat_type) return numberbegin\n" + + "\t\tcs_ctx := strcat_type(null);\n" + + "\t\treturn ODCIConst.Success;\n" + + "\tend;\n" + + ")", text); + } + // assertTrue(visitor.getColumns().contains(new TableStat.Column("acduser.vw_acd_info", "xzqh"))); + + // assertTrue(visitor.getOrderByColumns().contains(new TableStat.Column("employees", "last_name"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_01.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_01.java index 48e598cd51..a826f2879e 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_01.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_01.java @@ -1,5 +1,5 @@ -package com.alibaba.druid.bvt.sql.oracle.visitor; +package com.alibaba.druid.bvt.sql.oracle.visitor; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.util.JdbcConstants; @@ -46,10 +46,4 @@ public class OracleParameterizedOutputVisitorTest_01 extends TestCase { "\tAND dd.owner = 'EAIREP'", tempResult); } - static void f() { - String ip = ""; - String port = ""; - String[] ins = new String[]{ip, "_", port}; - - } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_02.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_02.java new file mode 100644 index 0000000000..96060a2add --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_02.java @@ -0,0 +1,55 @@ +package com.alibaba.druid.bvt.sql.oracle.visitor; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by wenshao on 16/8/23. + */ +public class OracleParameterizedOutputVisitorTest_02 extends TestCase { + public void test_for_parameterize() throws Exception { + String sql = "/*\n" + + " The name + type results of these queries will be used by the Code Assistant\n" + + " if the \"Describe Context\" option is enabled. After typing 3 or more characters\n" + + " the Code Assistant will show a list of matching names.\n" + + " Separate multiple queries with semi-colons and use the :schema bind variable\n" + + " to restrict names to the currently connected user.\n" + + " In case of an error the query results will be omitted. No error message will\n" + + " be displayed.\n" + + " Place this file in the PL/SQL Developer installation directory for all users,\n" + + " or in the \"%APPDATA%\\PLSQL Developer\" directory for a specific user.\n" + + "*/\n" + + "SELECT object_name, object_type\n" + + "FROM sys.all_objects o\n" + + "WHERE o.owner = :schema\n" + + " AND o.object_type IN (?)"; + + List parameters = new ArrayList(); + parameters.add(3); + parameters.add(4); + String rsql = SQLUtils.format(sql, JdbcConstants.ORACLE, parameters); + assertEquals("/*\n" + + " The name + type results of these queries will be used by the Code Assistant\n" + + " if the \"Describe Context\" option is enabled. After typing 3 or more characters\n" + + " the Code Assistant will show a list of matching names.\n" + + " Separate multiple queries with semi-colons and use the :schema bind variable\n" + + " to restrict names to the currently connected user.\n" + + " In case of an error the query results will be omitted. No error message will\n" + + " be displayed.\n" + + " Place this file in the PL/SQL Developer installation directory for all users,\n" + + " or in the \"%APPDATA%\\PLSQL Developer\" directory for a specific user.\n" + + "*/\n" + + "SELECT object_name, object_type\n" + + "FROM sys.all_objects o\n" + + "WHERE o.owner = 3\n" + + "\tAND o.object_type IN (4)", rsql); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_datetime.java b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_datetime.java index e78d016363..c283bfe254 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_datetime.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_datetime.java @@ -34,4 +34,11 @@ public class Oracle2PG_DataTypeTest_datetime extends TestCase { SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); assertEquals("TIMESTAMP", pgDataType.toString()); } + + public void test_oracle2pg_timestamp2() throws Exception { + String sql = "TIMESTAMP WITH TIME ZONE"; + SQLDataType dataType = SQLParserUtils.createExprParser(sql, JdbcConstants.ORACLE).parseDataType(); + SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); + assertEquals("TIMESTAMP WITH TIME ZONE", pgDataType.toString()); + } }