[Bug] When using view, make toSql method generates the final sql (#6736)

1. Fix the problem that the WITH statement cannot be printed when `UNION` is included in SQL
2. In the `toSql` method, convert the normal VIEW into the final statement
3. Replace `selectStmt.originSql` with `selectStmt.toSql`
This commit is contained in:
Zeno Yang
2021-09-26 11:44:23 +08:00
committed by GitHub
parent ce7f9bef91
commit 11ec38dd6f
4 changed files with 105 additions and 8 deletions

View File

@ -424,14 +424,23 @@ public class InlineViewRef extends TableRef {
String aliasSql = null;
String alias = getExplicitAlias();
if (alias != null) aliasSql = ToSqlUtils.getIdentSql(alias);
StringBuilder sb = new StringBuilder();
if (view != null) {
// TODO(zc):
// return view_.toSql() + (aliasSql == null ? "" : " " + aliasSql);
return name.toSql() + (aliasSql == null ? "" : " " + aliasSql);
// When it is a local view, it does not need to be expanded into a statement,
// because toSql function already contains `with` statement
if (view.isLocalView()) {
return name.toSql() + (aliasSql == null ? "" : " " + aliasSql);
}
sb.append("(")
.append(view.getInlineViewDef())
.append(")")
.append(aliasSql == null ? "" : " " + aliasSql);
return sb.toString();
}
StringBuilder sb = new StringBuilder()
.append("(")
sb.append("(")
.append(queryStmt.toSql())
.append(") ")
.append(aliasSql);

View File

@ -598,6 +598,10 @@ public class SetOperationStmt extends QueryStmt {
return toSqlString;
}
StringBuilder strBuilder = new StringBuilder();
if (withClause_ != null) {
strBuilder.append(withClause_.toSql());
strBuilder.append(" ");
}
Preconditions.checkState(operands.size() > 0);
strBuilder.append(operands.get(0).getQueryStmt().toSql());
for (int i = 1; i < operands.size() - 1; ++i) {

View File

@ -41,7 +41,7 @@ public class SqlCache extends Cache {
public InternalService.PFetchCacheResult getCacheData(Status status) {
InternalService.PFetchCacheRequest request = InternalService.PFetchCacheRequest.newBuilder()
.setSqlKey(CacheProxy.getMd5(selectStmt.getOrigStmt().originStmt))
.setSqlKey(CacheProxy.getMd5(selectStmt.toSql()))
.addParams(InternalService.PCacheParam.newBuilder()
.setPartitionKey(latestTable.latestPartitionId)
.setLastVersion(latestTable.latestVersion)
@ -74,8 +74,8 @@ public class SqlCache extends Cache {
}
InternalService.PUpdateCacheRequest updateRequest =
rowBatchBuilder.buildSqlUpdateRequest(selectStmt.getOrigStmt().originStmt,
latestTable.latestPartitionId, latestTable.latestVersion, latestTable.latestTime);
rowBatchBuilder.buildSqlUpdateRequest(selectStmt.toSql(), latestTable.latestPartitionId,
latestTable.latestVersion, latestTable.latestTime);
if (updateRequest.getValuesCount() > 0) {
CacheBeProxy proxy = new CacheBeProxy();
Status status = new Status();

View File

@ -715,4 +715,88 @@ public class SelectStmtTest {
System.out.println(e.getMessage());
}
}
@Test
public void testWithUnionToSql() throws Exception {
ConnectContext ctx = UtFrameUtils.createDefaultCtx();
String sql1 =
"select \n" +
" t.k1 \n" +
"from (\n" +
" with \n" +
" v1 as (select t1.k1 from db1.tbl1 t1),\n" +
" v2 as (select t2.k1 from db1.tbl1 t2)\n" +
" select v1.k1 as k1 from v1\n" +
" union\n" +
" select v2.k1 as k1 from v2\n" +
") t";
SelectStmt stmt1 = (SelectStmt) UtFrameUtils.parseAndAnalyzeStmt(sql1, ctx);
stmt1.rewriteExprs(new Analyzer(ctx.getCatalog(), ctx).getExprRewriter());
Assert.assertTrue(stmt1.toSql().equals("SELECT `t`.`k1` AS `k1` " +
"FROM (WITH v1 AS (SELECT `t1`.`k1` AS `k1` FROM `default_cluster:db1`.`tbl1` t1)," +
"v2 AS (SELECT `t2`.`k1` AS `k1` FROM `default_cluster:db1`.`tbl1` t2) " +
"SELECT `v1`.`k1` AS `k1` FROM `v1` UNION SELECT `v2`.`k1` AS `k1` FROM `v2`) t"));
String sql2 =
"with\n" +
" v1 as (select t1.k1 from db1.tbl1 t1),\n" +
" v2 as (select t2.k1 from db1.tbl1 t2)\n" +
"select\n" +
" t.k1\n" +
"from (\n" +
" select v1.k1 as k1 from v1\n" +
" union\n" +
" select v2.k1 as k1 from v2\n" +
") t";
SelectStmt stmt2 = (SelectStmt) UtFrameUtils.parseAndAnalyzeStmt(sql2, ctx);
stmt2.rewriteExprs(new Analyzer(ctx.getCatalog(), ctx).getExprRewriter());
Assert.assertTrue(stmt2.toSql().contains("WITH v1 AS (SELECT `t1`.`k1` AS `k1` FROM " +
"`default_cluster:db1`.`tbl1` t1),v2 AS (SELECT `t2`.`k1` AS `k1` FROM `default_cluster:db1`.`tbl1` t2)"));
}
@Test
public void testViewConvertFinalSql() throws Exception {
ConnectContext ctx = UtFrameUtils.createDefaultCtx();
dorisAssert.useDatabase("db1");
String testView1 = "CREATE VIEW `view1` as (select t1.k1, t1.k2 from db1.tbl1 t1)";
dorisAssert.withView(testView1);
String sql1 = "select * from db1.view1;";
SelectStmt stmt1 = (SelectStmt) UtFrameUtils.parseAndAnalyzeStmt(sql1, ctx);
stmt1.rewriteExprs(new Analyzer(ctx.getCatalog(), ctx).getExprRewriter());
Assert.assertTrue(stmt1.toSql().contains("FROM " +
"(SELECT `t1`.`k1` AS `k1`, `t1`.`k2` AS `k2` FROM `default_cluster:db1`.`tbl1` t1)"));
String sql2 =
"select \n" +
" t.k1 \n" +
"from (\n" +
" select v1.k1 from db1.view1 v1\n" +
") t";
SelectStmt stmt2 = (SelectStmt) UtFrameUtils.parseAndAnalyzeStmt(sql2, ctx);
stmt2.rewriteExprs(new Analyzer(ctx.getCatalog(), ctx).getExprRewriter());
Assert.assertTrue(stmt2.toSql().contains("FROM " +
"(SELECT `t1`.`k1` AS `k1`, `t1`.`k2` AS `k2` FROM `default_cluster:db1`.`tbl1` t1) v1"));
// WITH statement contains view, that is, localView contains normal view
String sql3 =
"with\n" +
" v1 as (select t1.k1 from db1.view1 t1),\n" +
" v2 as (select t2.k1 from db1.view1 t2)\n" +
"select\n" +
" t.k1\n" +
"from (\n" +
" select v1.k1 as k1 from v1\n" +
" union\n" +
" select v2.k1 as k1 from v2\n" +
") t";
SelectStmt stmt3 = (SelectStmt) UtFrameUtils.parseAndAnalyzeStmt(sql3, ctx);
stmt3.rewriteExprs(new Analyzer(ctx.getCatalog(), ctx).getExprRewriter());
System.out.println(stmt3.toSql());
Assert.assertTrue(stmt3.toSql().contains("WITH " +
"v1 AS (SELECT `t1`.`k1` AS `k1` FROM (SELECT `t1`.`k1` AS `k1`, `t1`.`k2` AS `k2` FROM `default_cluster:db1`.`tbl1` t1) t1)," +
"v2 AS (SELECT `t2`.`k1` AS `k1` FROM (SELECT `t1`.`k1` AS `k1`, `t1`.`k2` AS `k2` FROM `default_cluster:db1`.`tbl1` t1) t2)"));
dorisAssert.dropView("view1");
}
}