mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved oracle sql parser.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ public interface SQLDataType extends SQLObject {
|
||||
void setWithTimeZone(Boolean value);
|
||||
|
||||
boolean isWithLocalTimeZone();
|
||||
void setWithLocalTimeZone(boolean value);
|
||||
|
||||
SQLDataType clone();
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+96
@@ -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<SQLParameter> parameters = new ArrayList<SQLParameter>();
|
||||
|
||||
@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<SQLParameter> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public boolean isBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(boolean body) {
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<SQLParameter> parameters = new ArrayList<SQLParameter>();
|
||||
|
||||
private SQLDataType returnDataType;
|
||||
|
||||
private SQLStatement block;
|
||||
|
||||
public boolean isStatic() {
|
||||
return isStatic;
|
||||
}
|
||||
|
||||
public void setStatic(boolean aStatic) {
|
||||
isStatic = aStatic;
|
||||
}
|
||||
|
||||
public List<SQLParameter> 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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
+173
-9
@@ -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<SQLParameter> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+10
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+49
-2
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user