mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved oracle pl/sql parser.
This commit is contained in:
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
|
||||
|
||||
public class OracleConntinueStatement extends OracleStatementImpl {
|
||||
|
||||
private SQLExpr when;
|
||||
private SQLName label;
|
||||
|
||||
public SQLExpr getWhen() {
|
||||
return when;
|
||||
}
|
||||
|
||||
public void setWhen(SQLExpr when) {
|
||||
if (when != null) {
|
||||
when.setParent(this);
|
||||
}
|
||||
this.when = when;
|
||||
}
|
||||
|
||||
public SQLName getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(SQLName label) {
|
||||
if (label != null) {
|
||||
label.setParent(this);
|
||||
}
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept0(OracleASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, label);
|
||||
acceptChild(visitor, when);
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
|
||||
}
|
||||
+9
-6
@@ -42,7 +42,7 @@ public class OracleExceptionStatement extends OracleStatementImpl implements Ora
|
||||
public static class Item extends OracleSQLObjectImpl {
|
||||
|
||||
private SQLExpr when;
|
||||
private List<SQLStatement> statements = new ArrayList<SQLStatement>();
|
||||
private SQLStatement statement;
|
||||
|
||||
public SQLExpr getWhen() {
|
||||
return when;
|
||||
@@ -52,19 +52,22 @@ public class OracleExceptionStatement extends OracleStatementImpl implements Ora
|
||||
this.when = when;
|
||||
}
|
||||
|
||||
public List<SQLStatement> getStatements() {
|
||||
return statements;
|
||||
public SQLStatement getStatement() {
|
||||
return statement;
|
||||
}
|
||||
|
||||
public void setStatements(List<SQLStatement> statements) {
|
||||
this.statements = statements;
|
||||
public void setStatement(SQLStatement statement) {
|
||||
if (statement != null) {
|
||||
statement.setParent(this);
|
||||
}
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept0(OracleASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, when);
|
||||
acceptChild(visitor, statements);
|
||||
acceptChild(visitor, statement);
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ public class OracleExitStatement extends OracleStatementImpl {
|
||||
}
|
||||
|
||||
public void setWhen(SQLExpr when) {
|
||||
if (when != null) {
|
||||
when.setParent(this);
|
||||
}
|
||||
this.when = when;
|
||||
}
|
||||
|
||||
|
||||
+13
-4
@@ -33,6 +33,8 @@ public class OracleForStatement extends OracleStatementImpl {
|
||||
|
||||
private boolean all;
|
||||
|
||||
private SQLName endLabel;
|
||||
|
||||
@Override
|
||||
public void accept0(OracleASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
@@ -63,10 +65,6 @@ public class OracleForStatement extends OracleStatementImpl {
|
||||
return statements;
|
||||
}
|
||||
|
||||
public void setStatements(List<SQLStatement> statements) {
|
||||
this.statements = statements;
|
||||
}
|
||||
|
||||
public boolean isAll() {
|
||||
return all;
|
||||
}
|
||||
@@ -74,4 +72,15 @@ public class OracleForStatement extends OracleStatementImpl {
|
||||
public void setAll(boolean all) {
|
||||
this.all = all;
|
||||
}
|
||||
|
||||
public SQLName getEndLabel() {
|
||||
return endLabel;
|
||||
}
|
||||
|
||||
public void setEndLabel(SQLName endLabel) {
|
||||
if (endLabel != null) {
|
||||
endLabel.setParent(this);
|
||||
}
|
||||
this.endLabel = endLabel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ public class OracleLexer extends Lexer {
|
||||
map.put("COMMENT", Token.COMMENT);
|
||||
map.put("COMMIT", Token.COMMIT);
|
||||
map.put("CONNECT", Token.CONNECT);
|
||||
map.put("CONTINUE", Token.CONTINUE);
|
||||
|
||||
map.put("CROSS", Token.CROSS);
|
||||
map.put("CURSOR", Token.CURSOR);
|
||||
|
||||
+38
-5
@@ -191,6 +191,22 @@ public class OracleStatementParser extends SQLStatementParser {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.CONTINUE) {
|
||||
lexer.nextToken();
|
||||
OracleConntinueStatement stmt = new OracleConntinueStatement();
|
||||
|
||||
if (lexer.token() == Token.IDENTIFIER) {
|
||||
SQLName label = this.exprParser.name();
|
||||
stmt.setLabel(label);
|
||||
}
|
||||
if (lexer.token() == Token.WHEN) {
|
||||
lexer.nextToken();
|
||||
stmt.setWhen(this.exprParser.expr());
|
||||
}
|
||||
statementList.add(stmt);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.FETCH || identifierEquals("FETCH")) {
|
||||
SQLStatement stmt = parseFetch();
|
||||
statementList.add(stmt);
|
||||
@@ -262,7 +278,21 @@ public class OracleStatementParser extends SQLStatementParser {
|
||||
continue;
|
||||
}
|
||||
if (lexer.token() == Token.FOR) {
|
||||
statementList.add(this.parseFor());
|
||||
OracleForStatement forStatement = this.parseFor();
|
||||
if (lexer.token() == Token.IDENTIFIER) {
|
||||
String strVal = lexer.stringVal();
|
||||
int stmtListSize = statementList.size();
|
||||
if (stmtListSize > 0) {
|
||||
SQLStatement lastStmt = statementList.get(stmtListSize - 1);
|
||||
if (lastStmt instanceof OracleLabelStatement) {
|
||||
if (((OracleLabelStatement) lastStmt).getLabel().getSimpleName().equalsIgnoreCase(strVal)) {
|
||||
SQLName endLabbel = this.exprParser.name();
|
||||
forStatement.setEndLabel(endLabbel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
statementList.add(forStatement);
|
||||
continue;
|
||||
}
|
||||
if (lexer.token() == Token.LOOP) {
|
||||
@@ -458,7 +488,9 @@ public class OracleStatementParser extends SQLStatementParser {
|
||||
public SQLStatement parseRaise() {
|
||||
lexer.nextToken();
|
||||
OracleRaiseStatement stmt = new OracleRaiseStatement();
|
||||
stmt.setException(this.exprParser.expr());
|
||||
if (lexer.token() != Token.SEMI) {
|
||||
stmt.setException(this.exprParser.expr());
|
||||
}
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -574,7 +606,7 @@ public class OracleStatementParser extends SQLStatementParser {
|
||||
} else {
|
||||
accept(Token.LOOP);
|
||||
|
||||
this.parseStatementList(stmt.getStatements());
|
||||
this.parseStatementList(stmt.getStatements(), -1, stmt);
|
||||
accept(Token.END);
|
||||
accept(Token.LOOP);
|
||||
}
|
||||
@@ -586,7 +618,7 @@ public class OracleStatementParser extends SQLStatementParser {
|
||||
|
||||
SQLLoopStatement stmt = new SQLLoopStatement();
|
||||
|
||||
this.parseStatementList(stmt.getStatements());
|
||||
this.parseStatementList(stmt.getStatements(), -1, stmt);
|
||||
accept(Token.END);
|
||||
accept(Token.LOOP);
|
||||
return stmt;
|
||||
@@ -1308,7 +1340,8 @@ public class OracleStatementParser extends SQLStatementParser {
|
||||
OracleExceptionStatement.Item item = new OracleExceptionStatement.Item();
|
||||
item.setWhen(this.exprParser.expr());
|
||||
accept(Token.THEN);
|
||||
parseStatementList(item.getStatements());
|
||||
SQLStatement thenStmt = this.parseStatement();
|
||||
item.setStatement(thenStmt);
|
||||
|
||||
stmt.addItem(item);
|
||||
|
||||
|
||||
@@ -393,6 +393,10 @@ public interface OracleASTVisitor extends SQLASTVisitor {
|
||||
|
||||
void endVisit(OracleExitStatement x);
|
||||
|
||||
boolean visit(OracleConntinueStatement x);
|
||||
|
||||
void endVisit(OracleConntinueStatement x);
|
||||
|
||||
boolean visit(OracleRaiseStatement x);
|
||||
|
||||
void endVisit(OracleRaiseStatement x);
|
||||
|
||||
+10
@@ -948,6 +948,16 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OracleConntinueStatement x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(OracleConntinueStatement x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OracleRaiseStatement x) {
|
||||
return true;
|
||||
|
||||
+33
-7
@@ -109,7 +109,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
|
||||
return;
|
||||
}
|
||||
|
||||
if (x instanceof OraclePLSQLCommitStatement) {
|
||||
if (x instanceof OraclePLSQLCommitStatement
|
||||
|| x instanceof OracleLabelStatement
|
||||
|| x instanceof OracleExceptionStatement.Item) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1495,14 +1497,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
|
||||
public boolean visit(com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExceptionStatement.Item x) {
|
||||
print0(ucase ? "WHEN " : "when ");
|
||||
x.getWhen().accept(this);
|
||||
print0(ucase ? " THEN " : " then ");
|
||||
incrementIndent();
|
||||
x.getStatement().accept(this);
|
||||
|
||||
for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
|
||||
println();
|
||||
SQLStatement stmt = x.getStatements().get(i);
|
||||
stmt.setParent(x);
|
||||
stmt.accept(this);
|
||||
}
|
||||
decrementIndent();
|
||||
return false;
|
||||
}
|
||||
@@ -1898,6 +1896,11 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
|
||||
if (!all) {
|
||||
println();
|
||||
print0(ucase ? "END LOOP" : "end loop");
|
||||
SQLName endLabel = x.getEndLabel();
|
||||
if (endLabel != null) {
|
||||
print(' ');
|
||||
endLabel.accept(this);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2496,6 +2499,29 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean visit(OracleConntinueStatement x) {
|
||||
print0(ucase ? "CONTINUE" : "continue");
|
||||
|
||||
SQLName label = x.getLabel();
|
||||
if (label != null) {
|
||||
print(' ');
|
||||
label.accept(this);
|
||||
}
|
||||
|
||||
if (x.getWhen() != null) {
|
||||
print0(ucase ? " WHEN " : " when ");
|
||||
x.getWhen().accept(this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(OracleConntinueStatement x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OracleRaiseStatement x) {
|
||||
print0(ucase ? "RAISE" : "raise");
|
||||
|
||||
+10
@@ -1281,6 +1281,16 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OracleConntinueStatement x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(OracleConntinueStatement x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OracleRaiseStatement x) {
|
||||
return false;
|
||||
|
||||
@@ -322,6 +322,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
x = ParameterizedOutputVisitorUtils.merge(this, x);
|
||||
}
|
||||
|
||||
SQLBinaryOperator operator = x.getOperator();
|
||||
|
||||
if (parameters != null
|
||||
&& parameters.size() > 0
|
||||
&& x.getOperator() == SQLBinaryOperator.Equality
|
||||
@@ -343,8 +345,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
|
||||
SQLObject parent = x.getParent();
|
||||
boolean isRoot = parent instanceof SQLSelectQueryBlock;
|
||||
boolean relational = x.getOperator() == SQLBinaryOperator.BooleanAnd
|
||||
|| x.getOperator() == SQLBinaryOperator.BooleanOr;
|
||||
boolean relational = operator == SQLBinaryOperator.BooleanAnd
|
||||
|| operator == SQLBinaryOperator.BooleanOr;
|
||||
|
||||
if (isRoot && relational) {
|
||||
incrementIndent();
|
||||
@@ -352,8 +354,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
|
||||
List<SQLExpr> groupList = new ArrayList<SQLExpr>();
|
||||
SQLExpr left = x.getLeft();
|
||||
SQLExpr right = x.getRight();
|
||||
for (;;) {
|
||||
if (left instanceof SQLBinaryOpExpr && ((SQLBinaryOpExpr) left).getOperator() == x.getOperator()) {
|
||||
if (left instanceof SQLBinaryOpExpr && ((SQLBinaryOpExpr) left).getOperator() == operator) {
|
||||
SQLBinaryOpExpr binaryLeft = (SQLBinaryOpExpr) left;
|
||||
groupList.add(binaryLeft.getRight());
|
||||
left = binaryLeft.getLeft();
|
||||
@@ -376,7 +379,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
printlnComments(item.getBeforeCommentsDirect());
|
||||
}
|
||||
|
||||
visitBinaryLeft(item, x.getOperator());
|
||||
visitBinaryLeft(item, operator);
|
||||
|
||||
if (isPrettyFormat() && item.hasAfterComment()) {
|
||||
print(' ');
|
||||
@@ -388,13 +391,25 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
printComment(item.getParent().getAfterCommentsDirect(), "\n");
|
||||
}
|
||||
|
||||
boolean printOpSpace = true;
|
||||
if (relational) {
|
||||
println();
|
||||
} else {
|
||||
print0(" ");
|
||||
if (operator == SQLBinaryOperator.Modulus
|
||||
&& JdbcConstants.ORACLE.equals(dbType)
|
||||
&& left instanceof SQLIdentifierExpr
|
||||
&& right instanceof SQLIdentifierExpr
|
||||
&& ((SQLIdentifierExpr) right).getName().equalsIgnoreCase("NOTFOUND")) {
|
||||
printOpSpace = false;
|
||||
}
|
||||
if (printOpSpace) {
|
||||
print(' ');
|
||||
}
|
||||
}
|
||||
printOperator(operator);
|
||||
if (printOpSpace) {
|
||||
print(' ');
|
||||
}
|
||||
printOperator(x.getOperator());
|
||||
print0(" ");
|
||||
}
|
||||
|
||||
visitorBinaryRight(x);
|
||||
|
||||
Reference in New Issue
Block a user