This commit is contained in:
wenshao
2013-04-28 15:13:54 +08:00
12 changed files with 741 additions and 141 deletions
@@ -21,8 +21,10 @@ import java.util.List;
import java.util.Map;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLPartitioningClause;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -38,11 +40,28 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement
private SQLPartitioningClause partitioning;
private List<SQLCommentHint> hints = new ArrayList<SQLCommentHint>();
private SQLExprTableSource like;
public MySqlCreateTableStatement(){
}
private List<SQLCommentHint> hints = new ArrayList<SQLCommentHint>();
public SQLExprTableSource getLike() {
return like;
}
public void setLike(SQLName like) {
this.setLike(new SQLExprTableSource(like));
}
public void setLike(SQLExprTableSource like) {
if (like != null) {
like.setParent(this);
}
this.like = like;
}
public List<SQLCommentHint> getHints() {
return hints;
@@ -76,35 +95,6 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement
this.query = query;
}
@Override
public void output(StringBuffer buf) {
if (Type.GLOBAL_TEMPORARY.equals(this.type)) {
buf.append("CREATE TEMPORARY TABLE ");
} else {
buf.append("CREATE TABLE ");
}
if (ifNotExiists) {
buf.append("IF NOT EXISTS ");
}
this.tableSource.output(buf);
buf.append(" ");
buf.append("(");
for (int i = 0, size = tableElementList.size(); i < size; ++i) {
if (i != 0) {
buf.append(", ");
}
tableElementList.get(i).output(buf);
}
buf.append(")");
if (query != null) {
buf.append(" ");
query.output(buf);
}
}
public boolean isIfNotExiists() {
return ifNotExiists;
}
@@ -127,6 +117,8 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement
this.acceptChild(visitor, getHints());
this.acceptChild(visitor, getTableSource());
this.acceptChild(visitor, getTableElementList());
this.acceptChild(visitor, getLike());
this.acceptChild(visitor, getQuery());
}
visitor.endVisit(this);
}
@@ -26,6 +26,8 @@ public class MySqlSQLColumnDefinition extends SQLColumnDefinition {
private SQLExpr onUpdate;
private SQLExpr storage;
public MySqlSQLColumnDefinition(){
}
@@ -38,12 +40,21 @@ public class MySqlSQLColumnDefinition extends SQLColumnDefinition {
this.autoIncrement = autoIncrement;
}
public SQLExpr getOnUpdate() {
return onUpdate;
}
public void setOnUpdate(SQLExpr onUpdate) {
this.onUpdate = onUpdate;
}
public SQLExpr getStorage() {
return storage;
}
public void setStorage(SQLExpr storage) {
this.storage = storage;
}
}
@@ -72,67 +72,78 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
stmt.setName(this.exprParser.name());
if (lexer.token() == Token.LIKE) {
lexer.nextToken();
SQLName name = this.exprParser.name();
stmt.setLike(name);
}
if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
for (;;) {
if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.LITERAL_CHARS) {
SQLColumnDefinition column = this.exprParser.parseColumn();
stmt.getTableElementList().add(column);
} else if (lexer.token() == Token.CONSTRAINT //
|| lexer.token() == Token.PRIMARY //
|| lexer.token() == Token.UNIQUE
) {
stmt.getTableElementList().add(parseConstraint());
} else if (lexer.token() == (Token.INDEX)) {
lexer.nextToken();
if (lexer.token() == Token.LIKE) {
lexer.nextToken();
SQLName name = this.exprParser.name();
stmt.setLike(name);
} else {
for (;;) {
if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.LITERAL_CHARS) {
SQLColumnDefinition column = this.exprParser.parseColumn();
stmt.getTableElementList().add(column);
} else if (lexer.token() == Token.CONSTRAINT //
|| lexer.token() == Token.PRIMARY //
|| lexer.token() == Token.UNIQUE) {
stmt.getTableElementList().add(parseConstraint());
} else if (lexer.token() == (Token.INDEX)) {
lexer.nextToken();
MySqlTableIndex idx = new MySqlTableIndex();
MySqlTableIndex idx = new MySqlTableIndex();
if (lexer.token() == Token.IDENTIFIER) {
if (!"USING".equalsIgnoreCase(lexer.stringVal())) {
idx.setName(this.exprParser.name());
if (lexer.token() == Token.IDENTIFIER) {
if (!"USING".equalsIgnoreCase(lexer.stringVal())) {
idx.setName(this.exprParser.name());
}
}
}
if (identifierEquals("USING")) {
lexer.nextToken();
idx.setIndexType(lexer.stringVal());
lexer.nextToken();
}
accept(Token.LPAREN);
for (;;) {
idx.getColumns().add(this.exprParser.expr());
if (!(lexer.token() == (Token.COMMA))) {
break;
} else {
if (identifierEquals("USING")) {
lexer.nextToken();
idx.setIndexType(lexer.stringVal());
lexer.nextToken();
}
accept(Token.LPAREN);
for (;;) {
idx.getColumns().add(this.exprParser.expr());
if (!(lexer.token() == (Token.COMMA))) {
break;
} else {
lexer.nextToken();
}
}
accept(Token.RPAREN);
stmt.getTableElementList().add(idx);
} else if (lexer.token() == (Token.KEY)) {
stmt.getTableElementList().add(parseConstraint());
} else if (lexer.token() == (Token.PRIMARY)) {
stmt.getTableElementList().add(parseConstraint());
} else if (lexer.token() == (Token.FOREIGN)) {
MySqlForeignKey fk = this.getExprParser().parseForeignKey();
stmt.getTableElementList().add(fk);
} else if (lexer.token() == Token.CHECK) {
lexer.nextToken();
SQLCheck check = new SQLCheck();
accept(Token.LPAREN);
check.setExpr(this.exprParser.expr());
accept(Token.RPAREN);
stmt.getTableElementList().add(check);
}
accept(Token.RPAREN);
stmt.getTableElementList().add(idx);
} else if (lexer.token() == (Token.KEY)) {
stmt.getTableElementList().add(parseConstraint());
} else if (lexer.token() == (Token.PRIMARY)) {
stmt.getTableElementList().add(parseConstraint());
} else if (lexer.token() == (Token.FOREIGN)) {
MySqlForeignKey fk = this.getExprParser().parseForeignKey();
stmt.getTableElementList().add(fk);
} else if (lexer.token() == Token.CHECK) {
lexer.nextToken();
SQLCheck check = new SQLCheck();
accept(Token.LPAREN);
check.setExpr(this.exprParser.expr());
accept(Token.RPAREN);
stmt.getTableElementList().add(check);
}
if (!(lexer.token() == (Token.COMMA))) {
break;
} else {
lexer.nextToken();
if (!(lexer.token() == (Token.COMMA))) {
break;
} else {
lexer.nextToken();
}
}
}
@@ -142,20 +153,190 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
for (;;) {
if (identifierEquals("ENGINE")) {
lexer.nextToken();
accept(Token.EQ);
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("ENGINE", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("AUTO_INCREMENT")) {
lexer.nextToken();
accept(Token.EQ);
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("AUTO_INCREMENT", lexer.numberString());
lexer.nextToken();
continue;
}
if (identifierEquals("AVG_ROW_LENGTH")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("AVG_ROW_LENGTH", lexer.numberString());
lexer.nextToken();
continue;
}
if (lexer.token() == Token.DEFAULT) {
lexer.nextToken();
parseTableOptionCharsetOrCollate(stmt);
continue;
}
if (parseTableOptionCharsetOrCollate(stmt)) {
continue;
}
if (identifierEquals("CHECKSUM")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("CHECKSUM", lexer.numberString());
lexer.nextToken();
continue;
}
if (identifierEquals("COMMENT")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("COMMENT", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("CONNECTION")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("CONNECTION", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("DATA")) {
lexer.nextToken();
acceptIdentifier("DIRECTORY");
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("DATA DIRECTORY", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("DELAY_KEY_WRITE")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("DELAY_KEY_WRITE", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("INDEX")) {
lexer.nextToken();
acceptIdentifier("DIRECTORY");
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("INDEX DIRECTORY", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("INSERT_METHOD")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("INSERT_METHOD", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("KEY_BLOCK_SIZE")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("KEY_BLOCK_SIZE", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("MAX_ROWS")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("MAX_ROWS", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("MIN_ROWS")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("MIN_ROWS", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("PACK_KEYS")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("PACK_KEYS", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("PASSWORD")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("PASSWORD", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("ROW_FORMAT")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("ROW_FORMAT", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("TABLESPACE")) {
lexer.nextToken();
String tablespace_name = lexer.stringVal();
accept(Token.IDENTIFIER);
if (identifierEquals("STORAGE")) {
throw new ParserException("TODO STORAGE");
}
stmt.getTableOptions().put("TABLESPACE", tablespace_name);
continue;
}
if (identifierEquals("TYPE")) {
lexer.nextToken();
accept(Token.EQ);
@@ -163,14 +344,6 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
lexer.nextToken();
continue;
}
if (identifierEquals("COMMENT")) {
lexer.nextToken();
accept(Token.EQ);
stmt.getTableOptions().put("COMMENT", lexer.stringVal());
lexer.nextToken();
continue;
}
if (identifierEquals("PARTITION")) {
lexer.nextToken();
@@ -199,28 +372,6 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal());
}
}
if (lexer.token() == Token.DEFAULT) {
lexer.nextToken();
if (identifierEquals("CHARACTER")) {
lexer.nextToken();
accept(Token.SET);
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("CHARACTER SET", lexer.stringVal());
lexer.nextToken();
continue;
} else if (identifierEquals("CHARSET")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("CHARSET", lexer.stringVal());
lexer.nextToken();
continue;
}
}
break;
}
@@ -237,6 +388,41 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
return stmt;
}
private boolean parseTableOptionCharsetOrCollate(MySqlCreateTableStatement stmt) {
if (identifierEquals("CHARACTER")) {
lexer.nextToken();
accept(Token.SET);
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("CHARACTER SET", lexer.stringVal());
lexer.nextToken();
return true;
}
if (identifierEquals("CHARSET")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("CHARSET", lexer.stringVal());
lexer.nextToken();
return true;
}
if (identifierEquals("COLLATE")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().put("COLLATE", lexer.stringVal());
lexer.nextToken();
return true;
}
return false;
}
protected SQLTableConstaint parseConstraint() {
SQLName name = null;
if (lexer.token() == (Token.CONSTRAINT)) {
@@ -276,7 +462,7 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
if (name != null) {
key.setName(name);
}
if (identifierEquals("USING")) {
lexer.nextToken();
key.setIndexType(lexer.stringVal());
@@ -559,6 +559,14 @@ public class MySqlExprParser extends SQLExprParser {
accept(Token.LITERAL_CHARS);
}
if (identifierEquals("STORAGE")) {
lexer.nextToken();
SQLExpr expr = expr();
if (column instanceof MySqlSQLColumnDefinition) {
((MySqlSQLColumnDefinition) column).setStorage(expr);
}
}
super.parseColumnRest(column);
return column;
@@ -710,18 +718,27 @@ public class MySqlExprParser extends SQLExprParser {
public MySqlUnique parseUnique() {
accept(Token.UNIQUE);
if (lexer.token() == Token.KEY) {
lexer.nextToken();
}
MySqlUnique primaryKey = new MySqlUnique();
MySqlUnique unique = new MySqlUnique();
if (identifierEquals("USING")) {
lexer.nextToken();
primaryKey.setIndexType(lexer.stringVal());
unique.setIndexType(lexer.stringVal());
lexer.nextToken();
}
if (lexer.token() != Token.LPAREN) {
SQLName name = name();
unique.setName(name);
}
accept(Token.LPAREN);
for (;;) {
primaryKey.getColumns().add(this.expr());
unique.getColumns().add(this.expr());
if (!(lexer.token() == (Token.COMMA))) {
break;
} else {
@@ -730,7 +747,7 @@ public class MySqlExprParser extends SQLExprParser {
}
accept(Token.RPAREN);
return primaryKey;
return unique;
}
public MySqlForeignKey parseForeignKey() {
@@ -296,12 +296,17 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
}
if (mysqlColumn != null && mysqlColumn.getStorage() != null) {
print(" STORAGE ");
mysqlColumn.getStorage().accept(this);
}
if (mysqlColumn != null && mysqlColumn.getOnUpdate() != null) {
print(" ON UPDATE ");
mysqlColumn.getOnUpdate().accept(this);
}
if (mysqlColumn != null && mysqlColumn.isAutoIncrement()) {
print(" AUTO_INCREMENT");
}
@@ -332,7 +337,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
printAndAccept(x.getArguments(), ", ");
print(")");
}
if (Boolean.TRUE == x.getAttribute("unsigned")) {
print(" unsigned");
}
@@ -426,31 +431,53 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
x.getName().accept(this);
print(" (");
incrementIndent();
println();
for (int i = 0, size = x.getTableElementList().size(); i < size; ++i) {
if (i != 0) {
print(", ");
println();
if (x.getLike() != null) {
print(" LIKE ");
x.getLike().accept(this);
}
int size = x.getTableElementList().size();
if (size > 0) {
print(" (");
incrementIndent();
println();
for (int i = 0; i < size; ++i) {
if (i != 0) {
print(", ");
println();
}
x.getTableElementList().get(i).accept(this);
}
x.getTableElementList().get(i).accept(this);
decrementIndent();
println();
print(")");
}
decrementIndent();
println();
print(")");
for (Map.Entry<String, String> option : x.getTableOptions().entrySet()) {
String key = option.getKey();
print(" ");
print(' ');
print(key);
if ("TABLESPACE".equals(key)) {
print(' ');
print(option.getValue());
continue;
}
print(" = ");
if ("COMMENT".equals(key)) {
print('\'');
print(option.getValue());
print('\'');
new SQLCharExpr(option.getValue()).accept(this);
} else if ("CONNECTION".equals(key)) {
new SQLCharExpr(option.getValue()).accept(this);
} else if ("DATA DIRECTORY".equals(key)) {
new SQLCharExpr(option.getValue()).accept(this);
} else if ("INDEX DIRECTORY".equals(key)) {
new SQLCharExpr(option.getValue()).accept(this);
} else if ("PASSWORD".equals(key)) {
new SQLCharExpr(option.getValue()).accept(this);
} else {
print(option.getValue());
}