From ec2446adfd6ccf50e5342df6e63df723d7ace674 Mon Sep 17 00:00:00 2001 From: Han Fei Date: Tue, 17 Sep 2024 14:26:25 +0000 Subject: [PATCH 1/3] fix bug about `CREATE ... AS WITH RECURSIVE` --- src/Interpreters/AddDefaultDatabaseVisitor.h | 5 ++++- .../03237_create_table_select_as_with_recursive.reference | 0 .../03237_create_table_select_as_with_recursive.sql | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 tests/queries/0_stateless/03237_create_table_select_as_with_recursive.reference create mode 100644 tests/queries/0_stateless/03237_create_table_select_as_with_recursive.sql diff --git a/src/Interpreters/AddDefaultDatabaseVisitor.h b/src/Interpreters/AddDefaultDatabaseVisitor.h index d59fd35df77..4aebccbc6dd 100644 --- a/src/Interpreters/AddDefaultDatabaseVisitor.h +++ b/src/Interpreters/AddDefaultDatabaseVisitor.h @@ -121,7 +121,10 @@ private: { if (select.recursive_with) for (const auto & child : select.with()->children) - with_aliases.insert(child->as()->name); + { + if (typeid_cast(child.get())) + with_aliases.insert(child->as()->name); + } if (select.tables()) tryVisit(select.refTables()); diff --git a/tests/queries/0_stateless/03237_create_table_select_as_with_recursive.reference b/tests/queries/0_stateless/03237_create_table_select_as_with_recursive.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/03237_create_table_select_as_with_recursive.sql b/tests/queries/0_stateless/03237_create_table_select_as_with_recursive.sql new file mode 100644 index 00000000000..d518e0d9c7c --- /dev/null +++ b/tests/queries/0_stateless/03237_create_table_select_as_with_recursive.sql @@ -0,0 +1,3 @@ +drop table if exists t; +create view t AS (WITH RECURSIVE 42 as ttt SELECT ttt); +drop table t; From dcaa80c90ddfd17bf017fbc00ddb0e27d0741ad6 Mon Sep 17 00:00:00 2001 From: Han Fei Date: Tue, 17 Sep 2024 19:12:58 +0000 Subject: [PATCH 2/3] change parser --- src/Interpreters/AddDefaultDatabaseVisitor.h | 5 +---- src/Parsers/ParserSelectQuery.cpp | 2 +- src/Parsers/ParserWithElement.cpp | 4 ++++ src/Parsers/ParserWithElement.h | 5 +++++ .../03237_create_table_select_as_with_recursive.sql | 3 +-- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Interpreters/AddDefaultDatabaseVisitor.h b/src/Interpreters/AddDefaultDatabaseVisitor.h index 4aebccbc6dd..d59fd35df77 100644 --- a/src/Interpreters/AddDefaultDatabaseVisitor.h +++ b/src/Interpreters/AddDefaultDatabaseVisitor.h @@ -121,10 +121,7 @@ private: { if (select.recursive_with) for (const auto & child : select.with()->children) - { - if (typeid_cast(child.get())) - with_aliases.insert(child->as()->name); - } + with_aliases.insert(child->as()->name); if (select.tables()) tryVisit(select.refTables()); diff --git a/src/Parsers/ParserSelectQuery.cpp b/src/Parsers/ParserSelectQuery.cpp index f72259aad67..9fdf39ef50b 100644 --- a/src/Parsers/ParserSelectQuery.cpp +++ b/src/Parsers/ParserSelectQuery.cpp @@ -106,7 +106,7 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { select_query->recursive_with = s_recursive.ignore(pos, expected); - if (!ParserList(std::make_unique(), std::make_unique(TokenType::Comma)) + if (!ParserList(std::make_unique(select_query->recursive_with), std::make_unique(TokenType::Comma)) .parse(pos, with_expression_list, expected)) return false; if (with_expression_list->children.empty()) diff --git a/src/Parsers/ParserWithElement.cpp b/src/Parsers/ParserWithElement.cpp index 5b31c929685..95eda721ef8 100644 --- a/src/Parsers/ParserWithElement.cpp +++ b/src/Parsers/ParserWithElement.cpp @@ -26,6 +26,10 @@ bool ParserWithElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) with_element->children.push_back(with_element->subquery); node = with_element; } + else if (with_recursive) + { + return false; + } else { pos = old_pos; diff --git a/src/Parsers/ParserWithElement.h b/src/Parsers/ParserWithElement.h index 75ad11f5deb..3b09c00f6a1 100644 --- a/src/Parsers/ParserWithElement.h +++ b/src/Parsers/ParserWithElement.h @@ -10,9 +10,14 @@ namespace DB */ class ParserWithElement : public IParserBase { +public: + ParserWithElement(bool with_recursive_ = false) : with_recursive(with_recursive_) {} protected: const char * getName() const override { return "WITH element"; } bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; + + /// for `WITH RECURSIVE` CTE, we don't allow expression with alias. + bool with_recursive; }; } diff --git a/tests/queries/0_stateless/03237_create_table_select_as_with_recursive.sql b/tests/queries/0_stateless/03237_create_table_select_as_with_recursive.sql index d518e0d9c7c..1d7864f90ac 100644 --- a/tests/queries/0_stateless/03237_create_table_select_as_with_recursive.sql +++ b/tests/queries/0_stateless/03237_create_table_select_as_with_recursive.sql @@ -1,3 +1,2 @@ drop table if exists t; -create view t AS (WITH RECURSIVE 42 as ttt SELECT ttt); -drop table t; +create view t AS (WITH RECURSIVE 42 as ttt SELECT ttt) -- { clientError SYNTAX_ERROR }; From c5e866cd75010a31a38b49c4916d96650e702c7e Mon Sep 17 00:00:00 2001 From: Han Fei Date: Wed, 18 Sep 2024 08:53:49 +0000 Subject: [PATCH 3/3] fix build --- src/Parsers/ParserWithElement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Parsers/ParserWithElement.h b/src/Parsers/ParserWithElement.h index 3b09c00f6a1..fe3628193b9 100644 --- a/src/Parsers/ParserWithElement.h +++ b/src/Parsers/ParserWithElement.h @@ -11,7 +11,7 @@ namespace DB class ParserWithElement : public IParserBase { public: - ParserWithElement(bool with_recursive_ = false) : with_recursive(with_recursive_) {} + explicit ParserWithElement(bool with_recursive_ = false) : with_recursive(with_recursive_) {} protected: const char * getName() const override { return "WITH element"; } bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;