Skip to content

Commit

Permalink
增加解析MySQL CREATE TABLE AS WITH SELECT 语法的能力 #5421
Browse files Browse the repository at this point in the history
增加解析MySQL CREATE TABLE AS WITH SELECT 语法的能力 #5421
但是t1表名没在stat信息里,看了应该是在SchemaResolveVisitorFactory的1902行加上MySqlCreateTableStatement的适配,但是试了还是不行,得进一步分析
  • Loading branch information
lizongbo authored and wenshao committed Sep 29, 2023
1 parent 1c99aae commit d991a88
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.ads.visitor.AdsOutputVisitor;
Expand Down Expand Up @@ -61,6 +62,7 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement
// for ads
protected Map<String, SQLName> with = new HashMap<String, SQLName>(3);

protected SQLStatement withSelect;
// adb
protected SQLName archiveBy;
protected Boolean withData;
Expand All @@ -77,6 +79,14 @@ public void setHints(List<SQLCommentHint> hints) {
this.hints = hints;
}

public SQLStatement getWithSelect() {
return withSelect;
}

public void setWithSelect(SQLStatement withSelect) {
this.withSelect = withSelect;
}

@Deprecated
public SQLSelect getQuery() {
return select;
Expand Down Expand Up @@ -156,6 +166,9 @@ public void accept0(MySqlASTVisitor visitor) {
if (select != null) {
select.accept(visitor);
}
if (withSelect != null) {
withSelect.accept(visitor);
}
}
visitor.endVisit(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,9 @@ public MySqlCreateTableStatement parseCreateTable(boolean acceptCreate) {
stmt.setSelect(query);
accept(Token.RPAREN);
}
if (lexer.token() == Token.WITH) {
stmt.setWithSelect(this.parseWith());
}
}

SQLCommentHint hint = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,9 @@ public boolean visit(MySqlCreateTableStatement x) {
}
}
}
if (x.getWithSelect() instanceof SQLSelectStatement) {
visit((SQLSelectStatement) x.getWithSelect());
}

return val;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9914,6 +9914,12 @@ public boolean visit(MySqlCreateTableStatement x) {
println();
x.getSelect().accept(this);
}
if (x.getWithSelect() != null) {
println();
print0(ucase ? "AS" : "as");
println();
x.getWithSelect().accept(this);
}

if (x.getStoredBy() != null) {
println();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.alibaba.druid.bvt.sql.mysql.issues;

import java.util.Map;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.parser.SQLParserUtils;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;

import org.apache.commons.lang3.StringUtils;
import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
* 验证 create table as with语句的解析
* @author lizongbo
* @see <a href="https://github.com/alibaba/druid/issues/5421">Issue来源</a>
*/
public class Issue5421 {

@Test
public void test_create_table_with() throws Exception {
for (DbType dbType : new DbType[]{DbType.mysql}) {
for (String sql : new String[]{
"create table if not exists t2 as\n"
+ "with X as ( select * from t1)\n"
+ "select * from X;",
}) {
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);
SQLStatement statement = parser.parseStatement();
System.out.println("原始的sql===" + sql);
sql=normalizeSql(sql);
System.out.println("归一化的sql===" + sql);
String newSql=normalizeSql(statement.toString())+";";
System.out.println("生成的sql===" + newSql);
assertTrue(newSql.equalsIgnoreCase(sql));
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);
statement.accept(visitor);
//@todo 为什么这里的表名只有t2,而没有t1,还需要进一步分析
System.out.println("getTables==" + visitor.getTables());
Map<TableStat.Name, TableStat> tableMap = visitor.getTables();
assertFalse(tableMap.isEmpty());
assertTrue(tableMap.containsKey(new TableStat.Name("t2")));

}
}
}

static String normalizeSql(String sql) {
sql = StringUtils.replace(sql, " ( ", "(");
sql = StringUtils.replace(sql, "( ", "(");
sql = StringUtils.replace(sql, " )", ")");
sql = StringUtils.replace(sql, "\t", " ");
sql = StringUtils.replace(sql, "\n", " ");
sql = StringUtils.replace(sql, "\'", "\"");
sql = StringUtils.replace(sql, " ( ", "(");
sql = StringUtils.replace(sql, " (", "(");
sql = StringUtils.replace(sql, "( ", "(");
sql = StringUtils.replace(sql, " )", ")");
sql = StringUtils.replace(sql, " )", ")");
sql = StringUtils.replace(sql, "( ", "(");
sql = StringUtils.replace(sql, " ", " ");
sql = StringUtils.replace(sql, " ", " ");
sql = StringUtils.replace(sql, " ", " ");
sql = StringUtils.replace(sql, " ", " ");
sql = StringUtils.replace(sql, "( ", "(");
sql = StringUtils.replace(sql, ", ", ",");
sql = StringUtils.replace(sql, " ,", ",");
return sql;
}
}

0 comments on commit d991a88

Please sign in to comment.