Merge pull request #22657 from amosbird/ctefix3

Fix CTE usage in view definition
This commit is contained in:
alexey-milovidov 2021-04-15 02:01:10 +03:00 committed by GitHub
commit 9b546f3b89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 22 deletions

View File

@ -13,9 +13,22 @@ 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);
else
{ {
for (auto & child : ast->children)
visit(child, data);
if (auto * node_func = ast->as<ASTFunction>())
visit(*node_func, data);
else if (auto * node_table = ast->as<ASTTableExpression>())
visit(*node_table, data);
}
}
void ApplyWithSubqueryVisitor::visit(ASTSelectQuery & ast, const Data & data)
{
std::optional<Data> new_data; std::optional<Data> new_data;
if (auto with = node_select->with()) if (auto with = ast.with())
{ {
for (auto & child : with->children) for (auto & child : with->children)
{ {
@ -29,21 +42,17 @@ void ApplyWithSubqueryVisitor::visit(ASTPtr & ast, const Data & data)
} }
} }
for (auto & child : node_select->children) for (auto & child : ast.children)
{ {
if (child != node_select->with()) if (child != ast.with())
visit(child, new_data ? *new_data : data); visit(child, new_data ? *new_data : data);
} }
} }
else
{ void ApplyWithSubqueryVisitor::visit(ASTSelectWithUnionQuery & ast, const Data & data)
for (auto & child : ast->children) {
for (auto & child : ast.children)
visit(child, data); visit(child, data);
if (auto * node_func = ast->as<ASTFunction>())
visit(*node_func, data);
else if (auto * node_table = ast->as<ASTTableExpression>())
visit(*node_table, data);
}
} }
void ApplyWithSubqueryVisitor::visit(ASTTableExpression & table, const Data & data) void ApplyWithSubqueryVisitor::visit(ASTTableExpression & table, const Data & data)

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>
@ -890,6 +891,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;