improved oracle pl/sql parser.

This commit is contained in:
wenshao
2017-05-13 14:38:32 +08:00
parent 01ab972572
commit a5e4bdd645
16 changed files with 440 additions and 41 deletions
@@ -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);
}
}
@@ -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;
}
@@ -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);
@@ -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);
@@ -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;
@@ -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");
@@ -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);