mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
sql parser refactor.
This commit is contained in:
@@ -24,6 +24,7 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName {
|
||||
private String name;
|
||||
|
||||
private transient String lowerName;
|
||||
private transient Boolean parameter;
|
||||
|
||||
public SQLIdentifierExpr(){
|
||||
|
||||
@@ -53,8 +54,12 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName {
|
||||
return lowerName;
|
||||
}
|
||||
|
||||
public void setLowerName(String lowerName) {
|
||||
this.lowerName = lowerName;
|
||||
public Boolean isParameter() {
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public void setParameter(Boolean parameter) {
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
public void output(StringBuffer buf) {
|
||||
|
||||
@@ -39,6 +39,13 @@ public class SQLCreateProcedureStatement extends SQLStatementImpl {
|
||||
|
||||
private SQLName authid;
|
||||
|
||||
// for mysql
|
||||
private boolean deterministic;
|
||||
private boolean containsSql;
|
||||
private boolean noSql;
|
||||
private boolean readSqlData;
|
||||
private boolean modifiesSqlData;
|
||||
|
||||
@Override
|
||||
public void accept0(SQLASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
@@ -119,4 +126,44 @@ public class SQLCreateProcedureStatement extends SQLStatementImpl {
|
||||
public void setJavaCallSpec(String javaCallSpec) {
|
||||
this.javaCallSpec = javaCallSpec;
|
||||
}
|
||||
|
||||
public boolean isDeterministic() {
|
||||
return deterministic;
|
||||
}
|
||||
|
||||
public void setDeterministic(boolean deterministic) {
|
||||
this.deterministic = deterministic;
|
||||
}
|
||||
|
||||
public boolean isContainsSql() {
|
||||
return containsSql;
|
||||
}
|
||||
|
||||
public void setContainsSql(boolean containsSql) {
|
||||
this.containsSql = containsSql;
|
||||
}
|
||||
|
||||
public boolean isNoSql() {
|
||||
return noSql;
|
||||
}
|
||||
|
||||
public void setNoSql(boolean noSql) {
|
||||
this.noSql = noSql;
|
||||
}
|
||||
|
||||
public boolean isReadSqlData() {
|
||||
return readSqlData;
|
||||
}
|
||||
|
||||
public void setReadSqlData(boolean readSqlData) {
|
||||
this.readSqlData = readSqlData;
|
||||
}
|
||||
|
||||
public boolean isModifiesSqlData() {
|
||||
return modifiesSqlData;
|
||||
}
|
||||
|
||||
public void setModifiesSqlData(boolean modifiesSqlData) {
|
||||
this.modifiesSqlData = modifiesSqlData;
|
||||
}
|
||||
}
|
||||
|
||||
+40
-14
@@ -2030,6 +2030,8 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
if (identifierEquals("USING")) {
|
||||
lexer.nextToken();
|
||||
exprParser.exprList(stmt.getParameters(), stmt);
|
||||
} else if (lexer.token() == Token.IDENTIFIER) {
|
||||
exprParser.exprList(stmt.getParameters(), stmt);
|
||||
}
|
||||
|
||||
return stmt;
|
||||
@@ -3252,8 +3254,31 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
parserParameters(stmt.getParameters(), stmt);
|
||||
accept(Token.RPAREN);// match ")"
|
||||
}
|
||||
SQLStatement block;
|
||||
|
||||
for (;;) {
|
||||
if (identifierEquals("DETERMINISTIC")) {
|
||||
lexer.nextToken();
|
||||
stmt.setDeterministic(true);
|
||||
continue;
|
||||
}
|
||||
if (identifierEquals("CONTAINS")) {
|
||||
lexer.nextToken();
|
||||
acceptIdentifier("SQL");
|
||||
stmt.setContainsSql(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (identifierEquals("SQL")) {
|
||||
lexer.nextToken();
|
||||
acceptIdentifier("SECURITY");
|
||||
SQLName authid = this.exprParser.name();
|
||||
stmt.setAuthid(authid);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
SQLStatement block;
|
||||
if (lexer.token() == Token.BEGIN) {
|
||||
block = this.parseBlock();
|
||||
} else {
|
||||
@@ -3565,7 +3590,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
|
||||
accept(Token.THEN);
|
||||
|
||||
this.parseProcedureStatementList(stmt.getStatements());
|
||||
this.parseStatementList(stmt.getStatements(), -1, stmt);
|
||||
|
||||
while (lexer.token() == Token.ELSE) {
|
||||
lexer.nextToken();
|
||||
@@ -3578,12 +3603,13 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
elseIf.setCondition(this.exprParser.expr());
|
||||
|
||||
accept(Token.THEN);
|
||||
this.parseProcedureStatementList(elseIf.getStatements());
|
||||
this.parseStatementList(elseIf.getStatements(), -1, elseIf);
|
||||
|
||||
|
||||
stmt.getElseIfList().add(elseIf);
|
||||
} else {
|
||||
SQLIfStatement.Else elseItem = new SQLIfStatement.Else();
|
||||
this.parseProcedureStatementList(elseItem.getStatements());
|
||||
this.parseStatementList(elseItem.getStatements(), -1, elseItem);
|
||||
stmt.setElseItem(elseItem);
|
||||
break;
|
||||
}
|
||||
@@ -3610,7 +3636,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
|
||||
accept(Token.DO);
|
||||
|
||||
this.parseProcedureStatementList(stmt.getStatements());
|
||||
this.parseStatementList(stmt.getStatements(), -1, stmt);
|
||||
|
||||
accept(Token.END);
|
||||
|
||||
@@ -3638,7 +3664,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
|
||||
accept(Token.DO);
|
||||
|
||||
this.parseProcedureStatementList(stmt.getStatements());
|
||||
this.parseStatementList(stmt.getStatements(), -1, stmt);
|
||||
|
||||
accept(Token.END);
|
||||
|
||||
@@ -3672,14 +3698,14 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
accept(Token.THEN);
|
||||
|
||||
// when block
|
||||
parseProcedureStatementList(when.getStatements());
|
||||
this.parseStatementList(when.getStatements(), -1, when);
|
||||
|
||||
stmt.addWhenStatement(when);
|
||||
}
|
||||
if (lexer.token() == Token.ELSE) {
|
||||
// parse else block
|
||||
SQLIfStatement.Else elseStmt = new SQLIfStatement.Else();
|
||||
parseProcedureStatementList(elseStmt.getStatements());
|
||||
this.parseStatementList(elseStmt.getStatements(), -1, elseStmt);
|
||||
stmt.setElseItem(elseStmt);
|
||||
}
|
||||
} else// grammar 2
|
||||
@@ -3696,7 +3722,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
accept(Token.THEN);
|
||||
|
||||
// when block
|
||||
parseProcedureStatementList(when.getStatements());
|
||||
this.parseStatementList(when.getStatements(), -1, when);
|
||||
|
||||
stmt.addWhenStatement(when);
|
||||
}
|
||||
@@ -3704,7 +3730,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
accept(Token.ELSE);
|
||||
// else block
|
||||
SQLIfStatement.Else elseStmt = new SQLIfStatement.Else();
|
||||
parseProcedureStatementList(elseStmt.getStatements());
|
||||
this.parseStatementList(elseStmt.getStatements(), -1, elseStmt);
|
||||
stmt.setElseItem(elseStmt);
|
||||
}
|
||||
}
|
||||
@@ -3799,7 +3825,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
public SQLLoopStatement parseLoop() {
|
||||
SQLLoopStatement loopStmt = new SQLLoopStatement();
|
||||
accept(Token.LOOP);
|
||||
parseProcedureStatementList(loopStmt.getStatements());
|
||||
this.parseStatementList(loopStmt.getStatements(), -1, loopStmt);
|
||||
accept(Token.END);
|
||||
accept(Token.LOOP);
|
||||
accept(Token.SEMI);
|
||||
@@ -3814,7 +3840,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
SQLLoopStatement loopStmt = new SQLLoopStatement();
|
||||
loopStmt.setLabelName(label);
|
||||
accept(Token.LOOP);
|
||||
parseProcedureStatementList(loopStmt.getStatements());
|
||||
this.parseStatementList(loopStmt.getStatements(), -1, loopStmt);
|
||||
accept(Token.END);
|
||||
accept(Token.LOOP);
|
||||
if (lexer.token() != Token.SEMI) {
|
||||
@@ -3832,7 +3858,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
SQLBlockStatement block = new SQLBlockStatement();
|
||||
block.setLabelName(label);
|
||||
accept(Token.BEGIN);
|
||||
parseProcedureStatementList(block.getStatementList());
|
||||
this.parseStatementList(block.getStatementList(), -1, block);
|
||||
accept(Token.END);
|
||||
acceptIdentifier(label);
|
||||
return block;
|
||||
@@ -3888,7 +3914,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
MySqlRepeatStatement repeatStmt = new MySqlRepeatStatement();
|
||||
repeatStmt.setLabelName(label);
|
||||
accept(Token.REPEAT);
|
||||
parseProcedureStatementList(repeatStmt.getStatements());
|
||||
this.parseStatementList(repeatStmt.getStatements(), -1, repeatStmt);
|
||||
accept(Token.UNTIL);
|
||||
repeatStmt.setCondition(exprParser.expr());
|
||||
accept(Token.END);
|
||||
|
||||
@@ -3141,45 +3141,6 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* visit procedure create node
|
||||
*/
|
||||
@Override
|
||||
public boolean visit(SQLCreateProcedureStatement x) {
|
||||
if (x.isOrReplace()) {
|
||||
print0(ucase ? "CREATE OR REPLACE PROCEDURE " : "create or replace procedure ");
|
||||
} else {
|
||||
print0(ucase ? "CREATE PROCEDURE " : "create procedure ");
|
||||
}
|
||||
x.getName().accept(this);
|
||||
|
||||
int paramSize = x.getParameters().size();
|
||||
|
||||
print0(" (");
|
||||
if (paramSize > 0) {
|
||||
incrementIndent();
|
||||
println();
|
||||
|
||||
for (int i = 0; i < paramSize; ++i) {
|
||||
if (i != 0) {
|
||||
print0(", ");
|
||||
println();
|
||||
}
|
||||
SQLParameter param = x.getParameters().get(i);
|
||||
param.accept(this);
|
||||
}
|
||||
|
||||
decrementIndent();
|
||||
println();
|
||||
}
|
||||
print(')');
|
||||
|
||||
println();
|
||||
x.getBlock().setParent(x);
|
||||
x.getBlock().accept(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLIfStatement x) {
|
||||
print0(ucase ? "IF " : "if ");
|
||||
@@ -3587,6 +3548,72 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* visit procedure create node
|
||||
*/
|
||||
@Override
|
||||
public boolean visit(SQLCreateProcedureStatement x) {
|
||||
if (x.isOrReplace()) {
|
||||
print0(ucase ? "CREATE OR REPLACE PROCEDURE " : "create or replace procedure ");
|
||||
} else {
|
||||
print0(ucase ? "CREATE PROCEDURE " : "create procedure ");
|
||||
}
|
||||
x.getName().accept(this);
|
||||
|
||||
int paramSize = x.getParameters().size();
|
||||
|
||||
print0(" (");
|
||||
if (paramSize > 0) {
|
||||
incrementIndent();
|
||||
println();
|
||||
|
||||
for (int i = 0; i < paramSize; ++i) {
|
||||
if (i != 0) {
|
||||
print0(", ");
|
||||
println();
|
||||
}
|
||||
SQLParameter param = x.getParameters().get(i);
|
||||
param.accept(this);
|
||||
}
|
||||
|
||||
decrementIndent();
|
||||
println();
|
||||
}
|
||||
print(')');
|
||||
|
||||
if (x.isDeterministic()) {
|
||||
println();
|
||||
print(ucase ? "DETERMINISTIC" : "deterministic");
|
||||
}
|
||||
|
||||
if (x.isContainsSql()) {
|
||||
println();
|
||||
print0(ucase ? "CONTAINS SQL" : "contains sql");
|
||||
}
|
||||
|
||||
if (x.isNoSql()) {
|
||||
println();
|
||||
print(ucase ? "NO SQL" : "no sql");
|
||||
}
|
||||
|
||||
if (x.isModifiesSqlData()) {
|
||||
println();
|
||||
print(ucase ? "MODIFIES SQL DATA" : "modifies sql data");
|
||||
}
|
||||
|
||||
SQLName authid = x.getAuthid();
|
||||
if (authid != null) {
|
||||
println();
|
||||
print(ucase ? "SQL SECURITY " : "sql security ");
|
||||
authid.accept(this);
|
||||
}
|
||||
|
||||
println();
|
||||
x.getBlock().setParent(x);
|
||||
x.getBlock().accept(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCreateFunctionStatement x) {
|
||||
print0(ucase ? "CREATE FUNCTION " : "create function ");
|
||||
|
||||
@@ -103,6 +103,8 @@ public class SQLStatementParser extends SQLParser {
|
||||
case EOF:
|
||||
case END:
|
||||
case UNTIL:
|
||||
case ELSE:
|
||||
case WHEN:
|
||||
if (lexer.isKeepComments() && lexer.hasComment() && statementList.size() > 0) {
|
||||
SQLStatement stmt = statementList.get(statementList.size() - 1);
|
||||
stmt.addAfterComment(lexer.readAndResetComments());
|
||||
@@ -289,6 +291,12 @@ public class SQLStatementParser extends SQLParser {
|
||||
statementList.add(stmt);
|
||||
continue;
|
||||
}
|
||||
case LEAVE: {
|
||||
SQLStatement stmt = parseLeave();
|
||||
stmt.setParent(parent);
|
||||
statementList.add(stmt);
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -435,6 +443,10 @@ public class SQLStatementParser extends SQLParser {
|
||||
throw new ParserException("not supported. " + lexer.info());
|
||||
}
|
||||
|
||||
public SQLStatement parseLeave() {
|
||||
throw new ParserException("not supported. " + lexer.info());
|
||||
}
|
||||
|
||||
public SQLStatement parseReturn() {
|
||||
if (lexer.token() == Token.RETURN
|
||||
|| identifierEquals("RETURN")) {
|
||||
|
||||
@@ -574,12 +574,16 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
|
||||
}
|
||||
|
||||
if (expr instanceof SQLIdentifierExpr) {
|
||||
SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;
|
||||
if (isParam(identifierExpr)) {
|
||||
return null;
|
||||
}
|
||||
Column attrColumn = (Column) expr.getAttribute(ATTR_COLUMN);
|
||||
if (attrColumn != null) {
|
||||
return attrColumn;
|
||||
}
|
||||
|
||||
String column = ((SQLIdentifierExpr) expr).getName();
|
||||
String column = identifierExpr.getName();
|
||||
String table = getCurrentTable();
|
||||
if (table != null && aliasMap.containsKey(table)) {
|
||||
table = aliasMap.get(table);
|
||||
@@ -715,12 +719,18 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x.getInto() != null && x.getInto().getExpr() instanceof SQLName) {
|
||||
SQLName into = (SQLName) x.getInto().getExpr();
|
||||
String ident = into.toString();
|
||||
TableStat stat = getTableStat(ident);
|
||||
if (stat != null) {
|
||||
stat.incrementInsertCount();
|
||||
SQLExprTableSource into = x.getInto();
|
||||
if (into != null && into.getExpr() instanceof SQLName) {
|
||||
SQLName intoExpr = (SQLName) into.getExpr();
|
||||
|
||||
boolean isParam = intoExpr instanceof SQLIdentifierExpr && isParam((SQLIdentifierExpr) intoExpr);
|
||||
|
||||
if (!isParam) {
|
||||
String ident = intoExpr.toString();
|
||||
TableStat stat = getTableStat(ident);
|
||||
if (stat != null) {
|
||||
stat.incrementInsertCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,6 +771,36 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isParam(SQLIdentifierExpr x) {
|
||||
if (x.isParameter() != null) {
|
||||
return x.isParameter();
|
||||
}
|
||||
|
||||
for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {
|
||||
if (parent instanceof SQLCreateProcedureStatement) {
|
||||
SQLCreateProcedureStatement stmt = (SQLCreateProcedureStatement) parent;
|
||||
for (SQLParameter parameter : stmt.getParameters()) {
|
||||
if (x.equals(parameter.getName())) {
|
||||
x.setParameter(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (parent instanceof SQLBlockStatement) {
|
||||
SQLBlockStatement stmt = (SQLBlockStatement) parent;
|
||||
for (SQLParameter parameter : stmt.getParameters()) {
|
||||
if (x.equals(parameter.getName())) {
|
||||
x.setParameter(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void endVisit(SQLSelectQueryBlock x) {
|
||||
String originalTable = (String) x.getAttribute("_old_local_");
|
||||
x.putAttribute("table", getCurrentTable());
|
||||
@@ -945,6 +985,10 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
|
||||
}
|
||||
|
||||
public boolean visit(SQLIdentifierExpr x) {
|
||||
if (isParam(x)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String currentTable = getCurrentTable();
|
||||
|
||||
if (containsSubQuery(currentTable)) {
|
||||
@@ -1208,7 +1252,12 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
|
||||
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
if (isSimpleExprTableSource(x)) {
|
||||
String ident = x.getExpr().toString();
|
||||
SQLExpr expr = x.getExpr();
|
||||
if (expr instanceof SQLIdentifierExpr && isParam((SQLIdentifierExpr) expr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String ident = expr.toString();
|
||||
|
||||
if (variants.containsKey(ident)) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user