sql parser support drds ddl, for issue #2433

This commit is contained in:
wenshao
2018-04-01 19:55:24 +08:00
parent 3df15cbaed
commit 8f63d50301
13 changed files with 285 additions and 141 deletions
@@ -21,6 +21,7 @@ public class SQLPartitionByHash extends SQLPartitionBy {
// for aliyun ads
protected boolean key;
protected boolean unique;
public boolean isKey() {
return key;
@@ -30,6 +31,14 @@ public class SQLPartitionByHash extends SQLPartitionBy {
this.key = key;
}
public boolean isUnique() {
return unique;
}
public void setUnique(boolean unique) {
this.unique = unique;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
if (visitor.visit(this)) {
@@ -43,7 +52,10 @@ public class SQLPartitionByHash extends SQLPartitionBy {
public SQLPartitionByHash clone() {
SQLPartitionByHash x = new SQLPartitionByHash();
cloneTo(x);
x.key = key;
x.unique = unique;
for (SQLExpr column : columns) {
SQLExpr c2 = column.clone();
@@ -53,4 +65,8 @@ public class SQLPartitionByHash extends SQLPartitionBy {
return x;
}
public void cloneTo(SQLPartitionByHash x) {
super.cloneTo(x);
}
}
@@ -1106,4 +1106,5 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
}
this.rowFormat = x;
}
}
@@ -125,6 +125,7 @@ public class DB2OutputVisitor extends SQLASTOutputVisitor implements DB2ASTVisit
SQLPartitionBy partitionBy = x.getPartitioning();
if (partitionBy != null) {
println();
print0(ucase ? "PARTITION BY " : "partition by ");
partitionBy.accept(this);
}
@@ -22,10 +22,7 @@ import java.util.List;
import java.util.Map;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLCommentHint;
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.*;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
@@ -39,15 +36,14 @@ import com.alibaba.druid.util.JdbcConstants;
public class MySqlCreateTableStatement extends SQLCreateTableStatement implements MySqlStatement {
private Map<String, SQLObject> tableOptions = new LinkedHashMap<String, SQLObject>();
private List<SQLCommentHint> hints = new ArrayList<SQLCommentHint>();
private List<SQLCommentHint> optionHints = new ArrayList<SQLCommentHint>();
private SQLName tableGroup;
protected SQLPartitionBy dbPartitionBy;
protected SQLPartitionBy tablePartitionBy;
protected SQLExpr tbpartitions;
public MySqlCreateTableStatement(){
super (JdbcConstants.MYSQL);
}
@@ -392,4 +388,37 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement
cloneTo(x);
return x;
}
public SQLPartitionBy getDbPartitionBy() {
return dbPartitionBy;
}
public void setDbPartitionBy(SQLPartitionBy x) {
if (x != null) {
x.setParent(this);
}
this.dbPartitionBy = x;
}
public SQLPartitionBy getTablePartitionBy() {
return tablePartitionBy;
}
public void setTablePartitionBy(SQLPartitionBy x) {
if (x != null) {
x.setParent(this);
}
this.tablePartitionBy = x;
}
public SQLExpr getTbpartitions() {
return tbpartitions;
}
public void setTbpartitions(SQLExpr x) {
if (x != null) {
x.setParent(this);
}
this.tbpartitions = x;
}
}
@@ -529,124 +529,31 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
}
if (lexer.token() == Token.PARTITION) {
lexer.nextToken();
accept(Token.BY);
SQLPartitionBy partitionClause;
boolean linera = false;
if (lexer.identifierEquals("LINEAR")) {
lexer.nextToken();
linera = true;
}
if (lexer.token() == Token.KEY) {
MySqlPartitionByKey clause = new MySqlPartitionByKey();
lexer.nextToken();
if (linera) {
clause.setLinear(true);
}
if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) {
lexer.nextToken();
accept(Token.EQ);
clause.setAlgorithm(lexer.integerValue().shortValue());
lexer.nextToken();
}
accept(Token.LPAREN);
if (lexer.token() != Token.RPAREN) {
for (;;) {
clause.addColumn(this.exprParser.name());
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
}
accept(Token.RPAREN);
partitionClause = clause;
partitionClauseRest(clause);
} else if (lexer.identifierEquals("HASH")) {
lexer.nextToken();
SQLPartitionByHash clause = new SQLPartitionByHash();
if (linera) {
clause.setLinear(true);
}
if (lexer.token() == Token.KEY) {
lexer.nextToken();
clause.setKey(true);
}
accept(Token.LPAREN);
this.exprParser.exprList(clause.getColumns(), clause);
accept(Token.RPAREN);
partitionClause = clause;
partitionClauseRest(clause);
} else if (lexer.identifierEquals("RANGE")) {
SQLPartitionByRange clause = partitionByRange();
partitionClause = clause;
partitionClauseRest(clause);
} else if (lexer.identifierEquals("LIST")) {
lexer.nextToken();
SQLPartitionByList clause = new SQLPartitionByList();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
clause.addColumn(this.exprParser.expr());
accept(Token.RPAREN);
} else {
acceptIdentifier("COLUMNS");
accept(Token.LPAREN);
for (;;) {
clause.addColumn(this.exprParser.name());
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
}
partitionClause = clause;
partitionClauseRest(clause);
} else {
throw new ParserException("TODO. " + lexer.info());
}
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
for (;;) {
SQLPartition partitionDef = this.getExprParser().parsePartition();
partitionClause.addPartition(partitionDef);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
} else {
break;
}
}
accept(Token.RPAREN);
}
SQLPartitionBy partitionClause = parsePartitionBy();
stmt.setPartitioning(partitionClause);
continue;
}
if (lexer.identifierEquals(FnvHash.Constants.DBPARTITION)) {
SQLPartitionBy partitionClause = parsePartitionBy();
stmt.setDbPartitionBy(partitionClause);
continue;
}
if (lexer.identifierEquals(FnvHash.Constants.TBPARTITION)) {
SQLPartitionBy partitionClause = parsePartitionBy();
stmt.setTablePartitionBy(partitionClause);
continue;
}
if (lexer.identifierEquals(FnvHash.Constants.TBPARTITIONS)) {
lexer.nextToken();
SQLExpr tbpartitions = this.exprParser.expr();
stmt.setTbpartitions(tbpartitions);
continue;
}
break;
}
@@ -669,7 +576,127 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
return stmt;
}
private SQLPartitionBy parsePartitionBy() {
lexer.nextToken();
accept(Token.BY);
SQLPartitionBy partitionClause;
boolean linera = false;
if (lexer.identifierEquals("LINEAR")) {
lexer.nextToken();
linera = true;
}
if (lexer.token() == Token.KEY) {
MySqlPartitionByKey clause = new MySqlPartitionByKey();
lexer.nextToken();
if (linera) {
clause.setLinear(true);
}
if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) {
lexer.nextToken();
accept(Token.EQ);
clause.setAlgorithm(lexer.integerValue().shortValue());
lexer.nextToken();
}
accept(Token.LPAREN);
if (lexer.token() != Token.RPAREN) {
for (;;) {
clause.addColumn(this.exprParser.name());
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
}
accept(Token.RPAREN);
partitionClause = clause;
partitionClauseRest(clause);
} else if (lexer.identifierEquals("HASH") || lexer.identifierEquals("UNI_HASH")) {
SQLPartitionByHash clause = new SQLPartitionByHash();
if (lexer.identifierEquals("UNI_HASH")) {
clause.setUnique(true);
}
lexer.nextToken();
if (linera) {
clause.setLinear(true);
}
if (lexer.token() == Token.KEY) {
lexer.nextToken();
clause.setKey(true);
}
accept(Token.LPAREN);
this.exprParser.exprList(clause.getColumns(), clause);
accept(Token.RPAREN);
partitionClause = clause;
partitionClauseRest(clause);
} else if (lexer.identifierEquals("RANGE")) {
SQLPartitionByRange clause = partitionByRange();
partitionClause = clause;
partitionClauseRest(clause);
} else if (lexer.identifierEquals("LIST")) {
lexer.nextToken();
SQLPartitionByList clause = new SQLPartitionByList();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
clause.addColumn(this.exprParser.expr());
accept(Token.RPAREN);
} else {
acceptIdentifier("COLUMNS");
accept(Token.LPAREN);
for (;;) {
clause.addColumn(this.exprParser.name());
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
}
partitionClause = clause;
partitionClauseRest(clause);
} else {
throw new ParserException("TODO. " + lexer.info());
}
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
for (;;) {
SQLPartition partitionDef = this.getExprParser().parsePartition();
partitionClause.addPartition(partitionDef);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
} else {
break;
}
}
accept(Token.RPAREN);
}
return partitionClause;
}
protected SQLPartitionByRange partitionByRange() {
acceptIdentifier("RANGE");
@@ -489,9 +489,31 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
comment.accept(this);
}
if (x.getPartitioning() != null) {
SQLPartitionBy partitionBy = x.getPartitioning();
if (partitionBy != null) {
println();
x.getPartitioning().accept(this);
print0(ucase ? "PARTITION BY " : "partition by ");
partitionBy.accept(this);
}
SQLPartitionBy dbPartitionBy = x.getDbPartitionBy();
if (dbPartitionBy != null) {
println();
print0(ucase ? "DBPARTITION BY " : "dbpartition by ");
dbPartitionBy.accept(this);
}
SQLPartitionBy tbPartitionsBy = x.getTablePartitionBy();
if (tbPartitionsBy != null) {
println();
print0(ucase ? "TBPARTITION BY " : "tbpartition by ");
tbPartitionsBy.accept(this);
}
if (x.getTbpartitions() != null) {
println();
print0(ucase ? "TBPARTITIONS " : "tbpartitions ");
x.getTbpartitions().accept(this);
}
if (x.getTableGroup() != null) {
@@ -1462,9 +1484,9 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
@Override
public boolean visit(MySqlPartitionByKey x) {
if (x.isLinear()) {
print0(ucase ? "PARTITION BY LINEAR KEY (" : "partition by linear key (");
print0(ucase ? "LINEAR KEY (" : "linear key (");
} else {
print0(ucase ? "PARTITION BY KEY (" : "partition by key (");
print0(ucase ? "KEY (" : "key (");
}
printAndAccept(x.getColumns(), ", ");
print(')');
@@ -1747,6 +1747,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
for (SQLPartitionBy globalPartition : globalPartitions) {
println();
print0(ucase ? "GLOBAL " : "global ");
print0(ucase ? "PARTITION BY " : "partition by ");
globalPartition.accept(this);
}
@@ -2097,9 +2098,11 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
print0(ucase ? "MONITORING" : "monitoring");
}
if (x.getPartitioning() != null) {
SQLPartitionBy partitionBy = x.getPartitioning();
if (partitionBy != null) {
println();
x.getPartitioning().accept(this);
print0(ucase ? "PARTITION BY " : "partition by ");
partitionBy.accept(this);
}
if (x.getCluster() != null) {
@@ -2245,9 +2245,11 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
print0(ucase ? "MONITORING" : "monitoring");
}
if (x.getPartitioning() != null) {
SQLPartitionBy partitionBy = x.getPartitioning();
if (partitionBy != null) {
println();
x.getPartitioning().accept(this);
print0(ucase ? "PARTITION BY " : "partition by ");
partitionBy.accept(this);
}
if (x.getCluster() != null) {
@@ -73,7 +73,7 @@ public class SQLParserUtils {
return new OracleStatementParser(sql);
}
if (JdbcUtils.MYSQL.equals(dbType)) {
if (JdbcUtils.MYSQL.equals(dbType) || JdbcUtils.ALIYUN_DRDS.equals(dbType)) {
return new MySqlStatementParser(sql, features);
}
@@ -5083,7 +5083,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
@Override
public boolean visit(SQLPartitionByRange x) {
print0(ucase ? "PARTITION BY RANGE" : "partition by range");
print0(ucase ? "RANGE" : "range");
if (x.getColumns().size() == 1) {
print0(" (");
x.getColumns().get(0).accept(this);
@@ -5125,7 +5125,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
@Override
public boolean visit(SQLPartitionByList x) {
print0(ucase ? "PARTITION BY LIST " : "partition by list ");
print0(ucase ? "LIST " : "list ");
if (x.getColumns().size() == 1) {
print('(');
x.getColumns().get(0).accept(this);
@@ -5145,9 +5145,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
@Override
public boolean visit(SQLPartitionByHash x) {
if (x.isLinear()) {
print0(ucase ? "PARTITION BY LINEAR HASH " : "partition by linear hash ");
print0(ucase ? "LINEAR HASH " : "linear hash ");
} else {
print0(ucase ? "PARTITION BY HASH " : "partition by hash ");
print0(ucase ? "HASH " : "hash ");
}
if (x.isKey()) {
@@ -5939,6 +5939,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
SQLPartitionBy partitionBy = x.getPartitionBy();
if (partitionBy != null) {
println();
print0(ucase ? "PARTITION BY " : "partition by ");
partitionBy.accept(this);
}
@@ -1158,11 +1158,10 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
}
}
} else if (tableSource instanceof SQLWithSubqueryClause.Entry
|| tableSource instanceof SQLSubqueryTableSource) {
return false;
} else if (tableSource instanceof SQLUnionQueryTableSource) {
return false;
} else if (tableSource instanceof SQLLateralViewTableSource) {
|| tableSource instanceof SQLSubqueryTableSource
|| tableSource instanceof SQLUnionQueryTableSource
|| tableSource instanceof SQLLateralViewTableSource
|| tableSource instanceof SQLValuesTableSource) {
return false;
} else {
if (x.getResolvedProcudure() != null) {
@@ -641,5 +641,8 @@ public final class FnvHash {
long CHECKSUM = fnv1a_64_lower("CHECKSUM");
long ROUTINE = fnv1a_64_lower("ROUTINE");
long DATE_FORMAT = fnv1a_64_lower("DATE_FORMAT");
long DBPARTITION = fnv1a_64_lower("DBPARTITION");
long TBPARTITION = fnv1a_64_lower("TBPARTITION");
long TBPARTITIONS = fnv1a_64_lower("TBPARTITIONS");
}
}
@@ -0,0 +1,40 @@
package com.alibaba.druid.bvt.sql.mysql.createTable;
import com.alibaba.druid.sql.MysqlTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.util.JdbcConstants;
import java.util.List;
public class MySqlCreateTableTest108_drds extends MysqlTest {
public void test_0() throws Exception {
String sql = "create table ARCHIVE_ERR_RECORD\n" +
"(\n" +
"SUBS_ORDER_ID numeric(18,0) not null comment '订单编号',\n" +
"ERR_MSG text comment '失败的消息结构',\n" +
"ERR_REASON varchar(255) comment '失败原因',\n" +
"PART_ID integer not null comment '分区标识(取订单编号中的月份)'\n" +
")\n" +
"DBPARTITION BY HASH(SUBS_ORDER_ID)\n" +
"TBPARTITION BY UNI_HASH(PART_ID) TBPARTITIONS 12;";
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ALIYUN_DRDS);
SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);
assertEquals(1, statementList.size());
assertEquals(4, stmt.getTableElementList().size());
assertEquals("CREATE TABLE ARCHIVE_ERR_RECORD (\n" +
"\tSUBS_ORDER_ID numeric(18, 0) NOT NULL COMMENT '订单编号',\n" +
"\tERR_MSG text COMMENT '失败的消息结构',\n" +
"\tERR_REASON varchar(255) COMMENT '失败原因',\n" +
"\tPART_ID integer NOT NULL COMMENT '分区标识(取订单编号中的月份)'\n" +
")\n" +
"DBPARTITION BY HASH (SUBS_ORDER_ID)\n" +
"TBPARTITION BY HASH (PART_ID)\n" +
"TBPARTITIONS 12;", stmt.toString());
}
}