improved sql parser.

This commit is contained in:
wenshao
2017-06-07 13:54:41 +08:00
parent 3165a86e3c
commit 2b75d0f853
26 changed files with 746 additions and 152 deletions
@@ -25,7 +25,15 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
public class MySqlLeaveStatement extends MySqlStatementImpl {
private String labelName;
public MySqlLeaveStatement() {
}
public MySqlLeaveStatement(String labelName) {
this.labelName = labelName;
}
@Override
public void accept0(MySqlASTVisitor visitor) {
visitor.visit(this);
@@ -15,16 +15,8 @@
*/
package com.alibaba.druid.sql.dialect.mysql.parser;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.ast.SQLDeclareItem;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLParameter;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.SQLParameter.ParameterType;
import com.alibaba.druid.sql.ast.SQLPartition;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
@@ -355,6 +347,13 @@ public class MySqlStatementParser extends SQLStatementParser {
return parseCreateProcedure();
}
if (lexer.token() == Token.FUNCTION) {
if (replace) {
lexer.reset(markBp, markChar, Token.CREATE);
}
return parseCreateFunction();
}
throw new ParserException("TODO " + lexer.info());
}
@@ -1750,6 +1749,7 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
values.setParent(stmt);
stmt.getValuesList().add(values);
for (; ; ) {
stmt.addColumn(this.exprParser.name());
@@ -2100,7 +2100,7 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
insertStatement.getValuesList().add(values);
insertStatement.addValueCause(values);
for (; ; ) {
SQLName name = this.exprParser.name();
@@ -3141,6 +3141,61 @@ public class MySqlStatementParser extends SQLStatementParser {
}
public SQLCreateFunctionStatement parseCreateFunction() {
SQLCreateFunctionStatement stmt = new SQLCreateFunctionStatement();
stmt.setDbType(dbType);
if (lexer.token() != Token.FUNCTION) {
if (identifierEquals("DEFINER")) {
lexer.nextToken();
accept(Token.EQ);
SQLName definer = this.exprParser.name();
stmt.setDefiner(definer);
} else {
accept(Token.CREATE);
if (lexer.token() == Token.OR) {
lexer.nextToken();
accept(Token.REPLACE);
stmt.setOrReplace(true);
}
}
}
accept(Token.FUNCTION);
stmt.setName(this.exprParser.name());
if (lexer.token() == Token.LPAREN) {// match "("
lexer.nextToken();
parserParameters(stmt.getParameters(), stmt);
accept(Token.RPAREN);// match ")"
}
acceptIdentifier("RETURNS");
SQLDataType dataType = this.exprParser.parseDataType();
stmt.setReturnDataType(dataType);
for (;;) {
if (identifierEquals("DETERMINISTIC")) {
lexer.nextToken();
stmt.setDeterministic(true);
continue;
}
break;
}
SQLStatement block;
if (lexer.token() == Token.BEGIN) {
block = this.parseBlock();
} else {
block = this.parseStatement();
}
stmt.setBlock(block);
return stmt;
}
/**
* parse create procedure statement
*/
@@ -3173,7 +3228,7 @@ public class MySqlStatementParser extends SQLStatementParser {
if (lexer.token() == Token.LPAREN) {// match "("
lexer.nextToken();
parserParameters(stmt.getParameters());
parserParameters(stmt.getParameters(), stmt);
accept(Token.RPAREN);// match ")"
}
SQLStatement block;
@@ -3194,7 +3249,7 @@ public class MySqlStatementParser extends SQLStatementParser {
*
* @param parameters
*/
private void parserParameters(List<SQLParameter> parameters) {
private void parserParameters(List<SQLParameter> parameters, SQLObject parent) {
if (lexer.token() == Token.RPAREN) {
return;
}
@@ -3587,4 +3587,46 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
return false;
}
@Override
public boolean visit(SQLCreateFunctionStatement x) {
print0(ucase ? "CREATE FUNCTION " : "create function ");
x.getName().accept(this);
int paramSize = x.getParameters().size();
if (paramSize > 0) {
print0(" (");
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();
print(ucase ? "RETURNS " : "returns ");
x.getReturnDataType().accept(this);
if (x.isDeterministic()) {
print(ucase ? " DETERMINISTIC" : " deterministic");
}
SQLStatement block = x.getBlock();
println();
block.accept(this);
return false;
}
} //
@@ -17,12 +17,14 @@ 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.ast.SQLObject;
import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import com.alibaba.druid.util.JdbcConstants;
public class OracleCreateIndexStatement extends SQLCreateIndexStatement implements OracleDDLStatement {
public class OracleCreateIndexStatement extends SQLCreateIndexStatement implements OracleDDLStatement, OracleSegmentAttributes {
private boolean online = false;
@@ -32,12 +34,22 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen
private SQLExpr parallel;
private SQLName tablespace;
private Integer pctfree;
private Integer pctused;
private Integer initrans;
private SQLExpr ptcfree;
private SQLExpr pctused;
private SQLExpr initrans;
private SQLExpr maxtrans;
private Integer maxtrans;
private Integer pctincrease;
private Integer freeLists;
private Boolean compress;
private Integer compressLevel;
private boolean compressForOltp;
private Integer pctthreshold;
private Boolean logging;
protected SQLName tablespace;
protected SQLObject storage;
private Boolean enable = null;
@@ -47,14 +59,6 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen
super (JdbcConstants.ORACLE);
}
public SQLName getTablespace() {
return tablespace;
}
public void setTablespace(SQLName tablespace) {
this.tablespace = tablespace;
}
public SQLExpr getParallel() {
return parallel;
}
@@ -95,37 +99,6 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen
visitor.endVisit(this);
}
public SQLExpr getPtcfree() {
return ptcfree;
}
public void setPtcfree(SQLExpr ptcfree) {
this.ptcfree = ptcfree;
}
public SQLExpr getPctused() {
return pctused;
}
public void setPctused(SQLExpr pctused) {
this.pctused = pctused;
}
public SQLExpr getInitrans() {
return initrans;
}
public void setInitrans(SQLExpr initrans) {
this.initrans = initrans;
}
public SQLExpr getMaxtrans() {
return maxtrans;
}
public void setMaxtrans(SQLExpr maxtrans) {
this.maxtrans = maxtrans;
}
public Boolean getEnable() {
return enable;
@@ -151,4 +124,113 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen
this.online = online;
}
//////////////
public SQLName getTablespace() {
return tablespace;
}
public void setTablespace(SQLName tablespace) {
if (tablespace != null) {
tablespace.setParent(this);
}
this.tablespace = tablespace;
}
public Boolean getCompress() {
return compress;
}
public void setCompress(Boolean compress) {
this.compress = compress;
}
public Integer getCompressLevel() {
return compressLevel;
}
public void setCompressLevel(Integer compressLevel) {
this.compressLevel = compressLevel;
}
public Integer getPctthreshold() {
return pctthreshold;
}
public void setPctthreshold(Integer pctthreshold) {
this.pctthreshold = pctthreshold;
}
public Integer getPctfree() {
return pctfree;
}
public void setPctfree(Integer ptcfree) {
this.pctfree = ptcfree;
}
public Integer getPctused() {
return pctused;
}
public void setPctused(Integer ptcused) {
this.pctused = ptcused;
}
public Integer getInitrans() {
return initrans;
}
public void setInitrans(Integer initrans) {
this.initrans = initrans;
}
public Integer getMaxtrans() {
return maxtrans;
}
public void setMaxtrans(Integer maxtrans) {
this.maxtrans = maxtrans;
}
public Integer getPctincrease() {
return pctincrease;
}
public void setPctincrease(Integer pctincrease) {
this.pctincrease = pctincrease;
}
public Integer getFreeLists() {
return freeLists;
}
public void setFreeLists(Integer freeLists) {
this.freeLists = freeLists;
}
public Boolean getLogging() {
return logging;
}
public void setLogging(Boolean logging) {
this.logging = logging;
}
public SQLObject getStorage() {
return storage;
}
public void setStorage(SQLObject storage) {
this.storage = storage;
}
public boolean isCompressForOltp() {
return compressForOltp;
}
public void setCompressForOltp(boolean compressForOltp) {
this.compressForOltp = compressForOltp;
}
}
@@ -77,6 +77,27 @@ public class OracleLockTableStatement extends OracleStatementImpl {
}
public static enum LockMode {
EXCLUSIVE, SHARE
ROW_SHARE,
ROW_EXCLUSIVE,
SHARE_UPDATE,
SHARE,
SHARE_ROW_EXCLUSIVE,
EXCLUSIVE,
;
public String toString() {
switch (this) {
case ROW_SHARE:
return "ROW SHARE";
case ROW_EXCLUSIVE:
return "ROW EXCLUSIVE";
case SHARE_UPDATE:
return "SHARE UPDATE";
case SHARE_ROW_EXCLUSIVE:
return "SHARE ROW EXCLUSIVE";
default:
return this.name();
}
}
}
}
@@ -1442,12 +1442,38 @@ public class OracleStatementParser extends SQLStatementParser {
stmt.setTable(this.exprParser.name());
accept(Token.IN);
if (lexer.token() == Token.SHARE) {
stmt.setLockMode(LockMode.SHARE);
Token token = lexer.token();
if (token == Token.SHARE) {
lexer.nextToken();
} else if (lexer.token() == Token.EXCLUSIVE) {
if (lexer.token() == Token.ROW) {
lexer.nextToken();
accept(Token.EXCLUSIVE);
stmt.setLockMode(LockMode.SHARE_ROW_EXCLUSIVE);
} else if (lexer.token() == Token.UPDATE) {
lexer.nextToken();
stmt.setLockMode(LockMode.SHARE_UPDATE);
} else {
stmt.setLockMode(LockMode.SHARE);
}
} else if (token == Token.EXCLUSIVE) {
stmt.setLockMode(LockMode.EXCLUSIVE);
lexer.nextToken();
} else if(token == Token.ROW) {
lexer.nextToken();
token = lexer.token();
if (token == Token.SHARE) {
stmt.setLockMode(LockMode.ROW_SHARE);
lexer.nextToken();
} else if (token == Token.EXCLUSIVE) {
stmt.setLockMode(LockMode.ROW_EXCLUSIVE);
lexer.nextToken();
} else {
throw new ParserException(lexer.info());
}
} else {
throw new ParserException(lexer.info());
}
accept(Token.MODE);
@@ -1944,23 +1970,9 @@ public class OracleStatementParser extends SQLStatementParser {
accept(Token.RPAREN);
for (;;) {
if (lexer.token() == Token.TABLESPACE) {
lexer.nextToken();
stmt.setTablespace(this.exprParser.name());
continue;
} else if (lexer.token() == Token.PCTFREE) {
lexer.nextToken();
stmt.setPtcfree(this.exprParser.expr());
continue;
} else if (lexer.token() == Token.INITRANS) {
lexer.nextToken();
stmt.setInitrans(this.exprParser.expr());
continue;
} else if (lexer.token() == Token.MAXTRANS) {
lexer.nextToken();
stmt.setMaxtrans(this.exprParser.expr());
continue;
} else if (lexer.token() == Token.COMPUTE) {
this.getExprParser().parseSegmentAttributes(stmt);
if (lexer.token() == Token.COMPUTE) {
lexer.nextToken();
acceptIdentifier("STATISTICS");
stmt.setComputeStatistics(true);
@@ -1363,7 +1363,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
print0(ucase ? "LOCK TABLE " : "lock table ");
x.getTable().accept(this);
print0(ucase ? " IN " : " in ");
print0(x.getLockMode().name());
print0(x.getLockMode().toString());
print0(ucase ? " MODE " : " mode ");
if (x.isNoWait()) {
print0(ucase ? "NOWAIT" : "nowait");
@@ -1752,24 +1752,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
print0(ucase ? "INDEX ONLY TOPLEVEL" : "index only toplevel");
}
if (x.getPtcfree() != null) {
println();
print0(ucase ? "PCTFREE " : "pctfree ");
x.getPtcfree().accept(this);
}
if (x.getInitrans() != null) {
println();
print0(ucase ? "INITRANS " : "initrans ");
x.getInitrans().accept(this);
}
if (x.getMaxtrans() != null) {
println();
print0(ucase ? "MAXTRANS " : "maxtrans ");
x.getMaxtrans().accept(this);
}
if (x.isComputeStatistics()) {
println();
print0(ucase ? "COMPUTE STATISTICS" : "compute statistics");
@@ -1791,6 +1773,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
print0(ucase ? " PARALLEL " : " parallel ");
x.getParallel().accept(this);
}
this.printOracleSegmentAttributes(x);
return false;
}
@@ -27,33 +27,12 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLServerInsertStatement extends SQLInsertStatement implements SQLServerObject {
private List<ValuesClause> valuesList = new ArrayList<ValuesClause>();
private boolean defaultValues;
private SQLServerTop top;
private SQLServerOutput output;
public ValuesClause getValues() {
if (valuesList.size() == 0) {
return null;
}
return valuesList.get(0);
}
public void setValues(ValuesClause values) {
if (valuesList.size() == 0) {
valuesList.add(values);
} else {
valuesList.set(0, values);
}
}
public List<ValuesClause> getValuesList() {
return valuesList;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((SQLServerASTVisitor) visitor);
@@ -283,7 +283,7 @@ public class SQLServerStatementParser extends SQLStatementParser {
accept(Token.LPAREN);
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
this.exprParser.exprList(values.getValues(), values);
insertStatement.getValuesList().add(values);
insertStatement.addValueCause(values);
accept(Token.RPAREN);
if (!parseCompleteValues && insertStatement.getValuesList().size() >= parseValuesSize) {