Fix CTE in view.

This commit is contained in:
Amos Bird 2021-04-05 14:36:33 +08:00
parent cf2931384b
commit 46c9affa83
No known key found for this signature in database
GPG Key ID: 80D430DCBECFEDB4
4 changed files with 44 additions and 22 deletions

View File

@ -13,28 +13,7 @@ namespace DB
void ApplyWithSubqueryVisitor::visit(ASTPtr & ast, const Data & data) void ApplyWithSubqueryVisitor::visit(ASTPtr & ast, const Data & data)
{ {
if (auto * node_select = ast->as<ASTSelectQuery>()) if (auto * node_select = ast->as<ASTSelectQuery>())
{ visit(*node_select, data);
std::optional<Data> new_data;
if (auto with = node_select->with())
{
for (auto & child : with->children)
{
visit(child, new_data ? *new_data : data);
if (auto * ast_with_elem = child->as<ASTWithElement>())
{
if (!new_data)
new_data = data;
new_data->subqueries[ast_with_elem->name] = ast_with_elem->subquery;
}
}
}
for (auto & child : node_select->children)
{
if (child != node_select->with())
visit(child, new_data ? *new_data : data);
}
}
else else
{ {
for (auto & child : ast->children) for (auto & child : ast->children)
@ -46,6 +25,36 @@ void ApplyWithSubqueryVisitor::visit(ASTPtr & ast, const Data & data)
} }
} }
void ApplyWithSubqueryVisitor::visit(ASTSelectQuery & ast, const Data & data)
{
std::optional<Data> new_data;
if (auto with = ast.with())
{
for (auto & child : with->children)
{
visit(child, new_data ? *new_data : data);
if (auto * ast_with_elem = child->as<ASTWithElement>())
{
if (!new_data)
new_data = data;
new_data->subqueries[ast_with_elem->name] = ast_with_elem->subquery;
}
}
}
for (auto & child : ast.children)
{
if (child != ast.with())
visit(child, new_data ? *new_data : data);
}
}
void ApplyWithSubqueryVisitor::visit(ASTSelectWithUnionQuery & ast, const Data & data)
{
for (auto & child : ast.children)
visit(child, data);
}
void ApplyWithSubqueryVisitor::visit(ASTTableExpression & table, const Data & data) void ApplyWithSubqueryVisitor::visit(ASTTableExpression & table, const Data & data)
{ {
if (table.database_and_table_name) if (table.database_and_table_name)

View File

@ -7,6 +7,8 @@
namespace DB namespace DB
{ {
class ASTFunction; class ASTFunction;
class ASTSelectQuery;
class ASTSelectWithUnionQuery;
struct ASTTableExpression; struct ASTTableExpression;
class ApplyWithSubqueryVisitor class ApplyWithSubqueryVisitor
@ -18,9 +20,13 @@ public:
}; };
static void visit(ASTPtr & ast) { visit(ast, {}); } static void visit(ASTPtr & ast) { visit(ast, {}); }
static void visit(ASTSelectQuery & select) { visit(select, {}); }
static void visit(ASTSelectWithUnionQuery & select) { visit(select, {}); }
private: private:
static void visit(ASTPtr & ast, const Data & data); static void visit(ASTPtr & ast, const Data & data);
static void visit(ASTSelectQuery & ast, const Data & data);
static void visit(ASTSelectWithUnionQuery & ast, const Data & data);
static void visit(ASTTableExpression & table, const Data & data); static void visit(ASTTableExpression & table, const Data & data);
static void visit(ASTFunction & func, const Data & data); static void visit(ASTFunction & func, const Data & data);
}; };

View File

@ -59,6 +59,7 @@
#include <Interpreters/QueryLog.h> #include <Interpreters/QueryLog.h>
#include <Interpreters/addTypeConversionToAST.h> #include <Interpreters/addTypeConversionToAST.h>
#include <Interpreters/FunctionNameNormalizer.h> #include <Interpreters/FunctionNameNormalizer.h>
#include <Interpreters/ApplyWithSubqueryVisitor.h>
#include <TableFunctions/TableFunctionFactory.h> #include <TableFunctions/TableFunctionFactory.h>
#include <common/logger_useful.h> #include <common/logger_useful.h>
@ -887,6 +888,8 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
if (create.select && create.isView()) if (create.select && create.isView())
{ {
// Expand CTE before filling default database
ApplyWithSubqueryVisitor().visit(*create.select);
AddDefaultDatabaseVisitor visitor(current_database); AddDefaultDatabaseVisitor visitor(current_database);
visitor.visit(*create.select); visitor.visit(*create.select);
} }

View File

@ -1,3 +1,7 @@
drop table if exists t; drop table if exists t;
create table t engine = Memory as with cte as (select * from numbers(10)) select * from cte; create table t engine = Memory as with cte as (select * from numbers(10)) select * from cte;
drop table t; drop table t;
drop table if exists view1;
create view view1 as with t as (select number n from numbers(3)) select n from t;
drop table view1;