improved sql parser schema repository.

This commit is contained in:
wenshao
2017-08-08 14:59:18 +08:00
parent 9f50882488
commit bcb692f424
15 changed files with 649 additions and 252 deletions
@@ -21,6 +21,7 @@ import java.util.*;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;
@@ -235,6 +236,9 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
if (column instanceof SQLIdentifierExpr
&& SQLUtils.nameEquals(columnName, ((SQLIdentifierExpr) column).getName())) {
return unique.columns.size() > 1;
} else if (column instanceof SQLMethodInvokeExpr
&& SQLUtils.nameEquals(((SQLMethodInvokeExpr) column).getMethodName(), columnName)) {
return true;
}
} else if (element instanceof MySqlKey) {
MySqlKey unique = (MySqlKey) element;
@@ -243,6 +247,9 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
if (column instanceof SQLIdentifierExpr
&& SQLUtils.nameEquals(columnName, ((SQLIdentifierExpr) column).getName())) {
return true;
} else if (column instanceof SQLMethodInvokeExpr
&& SQLUtils.nameEquals(((SQLMethodInvokeExpr) column).getMethodName(), columnName)) {
return true;
}
}
}
@@ -265,6 +272,9 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
if (column instanceof SQLIdentifierExpr
&& SQLUtils.nameEquals(columnName, ((SQLIdentifierExpr) column).getName())) {
return unique.columns.size() == 1;
} else if (column instanceof SQLMethodInvokeExpr
&& SQLUtils.nameEquals(((SQLMethodInvokeExpr) column).getMethodName(), columnName)) {
return true;
}
}
}
@@ -48,6 +48,9 @@ public class SQLGrantStatement extends SQLStatementImpl {
private boolean adminOption;
private SQLExpr identifiedBy;
private String identifiedByPassword;
private boolean withGrantOption;
@Override
protected void accept0(SQLASTVisitor visitor) {
@@ -135,4 +138,20 @@ public class SQLGrantStatement extends SQLStatementImpl {
public void setIdentifiedBy(SQLExpr identifiedBy) {
this.identifiedBy = identifiedBy;
}
public String getIdentifiedByPassword() {
return identifiedByPassword;
}
public void setIdentifiedByPassword(String identifiedByPassword) {
this.identifiedByPassword = identifiedByPassword;
}
public boolean getWithGrantOption() {
return withGrantOption;
}
public void setWithGrantOption(boolean withGrantOption) {
this.withGrantOption = withGrantOption;
}
}
@@ -22,6 +22,7 @@ import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLUnique extends SQLConstraintImpl implements SQLUniqueConstraint, SQLTableElement {
@@ -122,6 +123,12 @@ public class SQLUnique extends SQLConstraintImpl implements SQLUniqueConstraint,
columns.remove(i);
return true;
}
if (expr instanceof SQLMethodInvokeExpr
&& SQLUtils.nameEquals(((SQLMethodInvokeExpr) expr).getMethodName(), columnName.getSimpleName())) {
columns.remove(i);
return true;
}
}
return false;
}
@@ -215,15 +215,16 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement
}
public boolean apply(SQLAlterTableAddIndex item) {
if (item.isKey()) {
MySqlPrimaryKey x = new MySqlPrimaryKey();
if (item.isUnique()) {
MySqlUnique x = new MySqlUnique();
item.cloneTo(x);
x.setParent(this);
this.tableElementList.add(x);
return true;
}
if (item.isUnique()) {
MySqlUnique x = new MySqlUnique();
if (item.isKey()) {
MySqlKey x = new MySqlKey();
item.cloneTo(x);
x.setParent(this);
this.tableElementList.add(x);
@@ -19,6 +19,7 @@ import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
@@ -46,22 +47,22 @@ public class MySqlRenameTableStatement extends MySqlStatementImpl {
public static class Item extends MySqlObjectImpl {
private SQLExpr name;
private SQLExpr to;
private SQLName name;
private SQLName to;
public SQLExpr getName() {
public SQLName getName() {
return name;
}
public void setName(SQLExpr name) {
public void setName(SQLName name) {
this.name = name;
}
public SQLExpr getTo() {
public SQLName getTo() {
return to;
}
public void setTo(SQLExpr to) {
public void setTo(SQLName to) {
this.to = to;
}
@@ -21,6 +21,7 @@ import java.util.List;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
@@ -29,8 +30,8 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
public class MySqlTableIndex extends MySqlObjectImpl implements SQLTableElement {
private SQLName name;
private String indexType;
private SQLName name;
private String indexType;
private List<SQLSelectOrderByItem> columns = new ArrayList<SQLSelectOrderByItem>();
public MySqlTableIndex(){
@@ -106,6 +107,11 @@ public class MySqlTableIndex extends MySqlObjectImpl implements SQLTableElement
columns.remove(i);
return true;
}
if (expr instanceof SQLMethodInvokeExpr
&& SQLUtils.nameEquals(((SQLMethodInvokeExpr) expr).getMethodName(), columnName.getSimpleName())) {
columns.remove(i);
return true;
}
}
return false;
}
@@ -785,6 +785,11 @@ public class MySqlExprParser extends SQLExprParser {
lexer.nextToken();
}
if (lexer.token() != Token.LPAREN) {
SQLName name = this.name();
primaryKey.setName(name);
}
accept(Token.LPAREN);
for (;;) {
primaryKey.addColumn(this.expr());
@@ -2464,7 +2464,7 @@ public class MySqlStatementParser extends SQLStatementParser {
if (lexer.token() == Token.COLUMN) {
lexer.nextToken();
parseAlterTableAddColumn(stmt);
} else if (lexer.token() == Token.INDEX) {
} else if (lexer.token() == Token.INDEX || identifierEquals("FULLTEXT")) {
SQLAlterTableAddIndex item = parseAlterTableAddIndex();
item.setParent(stmt);
stmt.addItem(item);
@@ -2484,31 +2484,52 @@ public class MySqlStatementParser extends SQLStatementParser {
stmt.addItem(item);
} else if (lexer.token() == Token.CONSTRAINT) {
lexer.nextToken();
SQLName constraintName = this.exprParser.name();
if (lexer.token() == Token.PRIMARY) {
SQLPrimaryKey primaryKey = ((MySqlExprParser) this.exprParser).parsePrimaryKey();
primaryKey.setName(constraintName);
SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(primaryKey);
item.setParent(stmt);
stmt.addItem(item);
} else if (lexer.token() == Token.FOREIGN) {
MysqlForeignKey fk = this.getExprParser().parseForeignKey();
fk.setName(constraintName);
fk.setHasConstraint(true);
SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(fk);
stmt.addItem(item);
} else if (lexer.token() == Token.UNIQUE) {
SQLUnique unique = this.exprParser.parseUnique();
SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(unique);
stmt.addItem(item);
} else {
throw new ParserException("TODO " + lexer.info());
SQLName constraintName = this.exprParser.name();
if (lexer.token() == Token.PRIMARY) {
SQLPrimaryKey primaryKey = ((MySqlExprParser) this.exprParser).parsePrimaryKey();
primaryKey.setName(constraintName);
SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(primaryKey);
item.setParent(stmt);
stmt.addItem(item);
} else if (lexer.token() == Token.FOREIGN) {
MysqlForeignKey fk = this.getExprParser().parseForeignKey();
fk.setName(constraintName);
fk.setHasConstraint(true);
SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(fk);
stmt.addItem(item);
} else if (lexer.token() == Token.UNIQUE) {
SQLUnique unique = this.exprParser.parseUnique();
SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(unique);
stmt.addItem(item);
} else {
throw new ParserException("TODO " + lexer.info());
}
}
} else if (lexer.token() == Token.PARTITION) {
lexer.nextToken();
@@ -2647,7 +2668,7 @@ public class MySqlStatementParser extends SQLStatementParser {
}
MySqlRenameTableStatement renameStmt = new MySqlRenameTableStatement();
MySqlRenameTableStatement.Item item = new MySqlRenameTableStatement.Item();
item.setName(stmt.getTableSource().getExpr());
item.setName((SQLName) stmt.getTableSource().getExpr());
item.setTo(this.exprParser.name());
renameStmt.addItem(item);
@@ -458,15 +458,21 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
@Override
public boolean visit(MySqlTableIndex x) {
String indexType = x.getIndexType();
if ("FULLTEXT".equalsIgnoreCase(indexType)) {
print0(ucase ? "FULLTEXT " : "fulltext ");
}
print0(ucase ? "INDEX" : "index");
if (x.getName() != null) {
print(' ');
x.getName().accept(this);
}
if (x.getIndexType() != null) {
if (indexType != null && !"FULLTEXT".equalsIgnoreCase(indexType)) {
print0(ucase ? " USING " : " using ");
print0(x.getIndexType());
print0(indexType);
}
print('(');
@@ -133,9 +133,9 @@ public class MySqlShowColumnOutpuVisitor extends MySqlOutputVisitor {
print(" | ");
if (column.containsNotNullConstaint()) {
print("YES");
} else {
print("NO ");
} else {
print("YES");
}
print(" | ");
@@ -613,7 +613,24 @@ public class SQLStatementParser extends SQLParser {
if (lexer.token() == Token.IDENTIFIED) {
lexer.nextToken();
accept(Token.BY);
stmt.setIdentifiedBy(this.exprParser.expr());
if (identifierEquals("PASSWORD")) {
lexer.nextToken();
String password = lexer.stringVal();
accept(Token.LITERAL_CHARS);
stmt.setIdentifiedByPassword(password);
} else {
stmt.setIdentifiedBy(this.exprParser.expr());
}
}
if (lexer.token() == Token.WITH) {
lexer.nextToken();
if (lexer.token() == Token.GRANT) {
lexer.nextToken();
acceptIdentifier("OPTION");
stmt.setWithGrantOption(true);
}
}
return stmt;
@@ -626,6 +643,7 @@ public class SQLStatementParser extends SQLParser {
lexer.nextToken();
if (identifierEquals("PRIVILEGES")) {
privilege = "ALL PRIVILEGES";
lexer.nextToken();
} else {
privilege = "ALL";
}
@@ -2403,6 +2421,11 @@ public class SQLStatementParser extends SQLParser {
protected SQLAlterTableAddIndex parseAlterTableAddIndex() {
SQLAlterTableAddIndex item = new SQLAlterTableAddIndex();
if (identifierEquals("FULLTEXT")) {
lexer.nextToken();
item.setType("FULLTEXT");
}
if (lexer.token() == Token.UNIQUE) {
item.setUnique(true);
lexer.nextToken();
@@ -22,10 +22,7 @@ import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowCreateTableStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
@@ -283,8 +280,17 @@ public class SchemaRepository {
MySqlShowCreateTableStatement showCreateTableStmt = (MySqlShowCreateTableStatement) stmt;
SQLName table = showCreateTableStmt.getName();
SchemaObject schemaObject = findTable(table);
MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) schemaObject.getStatement();
createTableStmt.output(buf);
if (schemaObject == null) {
buf.append("ERROR 1146 (42S02): Table '" + table + "' doesn't exist\n");
} else {
MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) schemaObject.getStatement();
createTableStmt.output(buf);
}
} else if (stmt instanceof MySqlRenameTableStatement) {
MySqlRenameTableStatement renameStmt = (MySqlRenameTableStatement) stmt;
for (MySqlRenameTableStatement.Item item : renameStmt.getItems()) {
renameTable(item.getName(), item.getTo());
}
} else if (stmt instanceof SQLShowTablesStatement) {
SQLShowTablesStatement showTables = (SQLShowTablesStatement) stmt;
SQLName database = showTables.getDatabase();
@@ -337,6 +343,36 @@ public class SchemaRepository {
return null;
}
private boolean renameTable(SQLName name, SQLName to) {
Schema schema;
if (name instanceof SQLPropertyExpr) {
String schemaName = ((SQLPropertyExpr) name).getOwnernName();
schema = findSchema(schemaName);
} else {
schema = getDefaultSchema();
}
if (schema == null) {
return false;
}
String tableName = name.getSimpleName();
SchemaObject schemaObject = schema.findTable(tableName);
if (schemaObject != null) {
MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) schemaObject.getStatement();
if (createTableStmt != null) {
createTableStmt.setName(to.clone());
}
String toName = SQLUtils.normalize(to.getSimpleName()).toLowerCase();
schema.objects.put(toName, schemaObject);
String name_lower = SQLUtils.normalize(tableName).toLowerCase();
schema.objects.remove(name_lower);
}
return true;
}
private class MySqlResolveVisitor extends MySqlASTVisitorAdapter implements SchemaResolveVisitor {
private int options;