diff --git a/dbms/src/Parsers/ASTCreateQuery.h b/dbms/src/Parsers/ASTCreateQuery.h index c052b3c9c60..4f5e3faca50 100644 --- a/dbms/src/Parsers/ASTCreateQuery.h +++ b/dbms/src/Parsers/ASTCreateQuery.h @@ -90,6 +90,44 @@ public: }; +class ASTColumns : public IAST +{ +public: + ASTExpressionList * columns = nullptr; + ASTExpressionList * indices = nullptr; + + String getID(char) const override { return "Columns definition"; } + + ASTPtr clone() const override + { + auto res = std::make_shared(); + + if (columns) + res->set(res->columns, columns->clone()); + if (indices) + res->set(res->indices, indices->clone()); + + return res; + } + + void formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const override + { + ASTExpressionList list; + + if (columns) + for (const auto & column : columns->children) + list.children.push_back(column); + + if (indices) + for (const auto & index : indices->children) + list.children.push_back(index); + + if (!list.children.empty()) + list.formatImpl(s, state, frame; + } +}; + + /// CREATE TABLE or ATTACH TABLE query class ASTCreateQuery : public ASTQueryWithTableAndOutput, public ASTQueryWithOnCluster { @@ -100,6 +138,7 @@ public: bool is_materialized_view{false}; bool is_populate{false}; ASTExpressionList * columns = nullptr; + ASTColumns * columns_list = nullptr; String to_database; /// For CREATE MATERIALIZED VIEW mv TO table. String to_table; ASTStorage * storage = nullptr; @@ -115,6 +154,8 @@ public: auto res = std::make_shared(*this); res->children.clear(); + if (columns_list) + res->set(res->columns_list, columns_list->clone()); if (columns) res->set(res->columns, columns->clone()); if (storage) @@ -184,6 +225,15 @@ protected: << (!as_database.empty() ? backQuoteIfNeed(as_database) + "." : "") << backQuoteIfNeed(as_table); } + if (columns_list) + { + settings.ostr << (settings.one_line ? " (" : "\n("); + FormatStateStacked frame_nested = frame; + ++frame_nested.indent; + columns_list->formatImpl(settings, state, frame_nested); + settings.ostr << (settings.one_line ? ")" : "\n)"); + } + if (columns) { settings.ostr << (settings.one_line ? " (" : "\n("); diff --git a/dbms/src/Parsers/ParserCreateQuery.cpp b/dbms/src/Parsers/ParserCreateQuery.cpp index 891bccaa45a..cdbba778471 100644 --- a/dbms/src/Parsers/ParserCreateQuery.cpp +++ b/dbms/src/Parsers/ParserCreateQuery.cpp @@ -139,6 +139,35 @@ bool ParserIndexDeclaration::parseImpl(Pos & pos, ASTPtr & node, Expected & expe return true; } + +bool ParserColumnAndIndexDeclaraion::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) +{ + ParserKeyword s_index("INDEX"); + + ParserIndexDeclaration index_p; + ParserColumnDeclaration column_p; + + ASTPtr column = nullptr; + ASTPtr index = nullptr; + + if (s_index.ignore(pos, expected)) + { + if (!index_p.parse(pos, index, expected)) + return false; + } + else + { + if (!column_p.parse(pos, column, expected)) + return false; + } + + if (column) + node = column; + else + node = index; + return true; +} + bool ParserIndexDeclarationList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserList(std::make_unique(), std::make_unique(TokenType::Comma), false) @@ -146,6 +175,39 @@ bool ParserIndexDeclarationList::parseImpl(Pos & pos, ASTPtr & node, Expected & } +bool ParserColumnsOrIndicesDeclaration::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) +{ + ASTPtr list; + if (!ParserList(std::make_unique(), std::make_unique(TokenType::Comma), false) + .parse(pos, list, expected)) + return false; + + ASTPtr columns = std::make_shared(); + ASTPtr indices = std::make_shared(); + + for (const auto & elem : list->children) + { + if (dynamic_cast(elem.get())) + columns->children.push_back(elem); + else if (dynamic_cast(elem.get())) + indices->children.push_back(elem); + else + return false; + } + + auto res = std::make_shared(); + + if (!columns->children.empty()) + res->set(res->columns, columns); + if (!indices->children.empty()) + res->set(res->indices, indices); + + node = res; + + return true; +} + + bool ParserStorage::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_engine("ENGINE"); diff --git a/dbms/src/Parsers/ParserCreateQuery.h b/dbms/src/Parsers/ParserCreateQuery.h index 90b5c99c851..e77b80a3b98 100644 --- a/dbms/src/Parsers/ParserCreateQuery.h +++ b/dbms/src/Parsers/ParserCreateQuery.h @@ -231,6 +231,15 @@ protected: bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; }; + +class ParserColumnAndIndexDeclaraion : public IParserBase +{ +protected: + const char * getName() const override { return "column or index declaration"; } + bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; +}; + + class ParserIndexDeclarationList : public IParserBase { protected: @@ -239,6 +248,14 @@ protected: }; +class ParserColumnsOrIndicesDeclaration : public IParserBase +{ + protected: + const char * getName() const override { return "columns or indices declaration"; } + bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; +}; + + /** * ENGINE = name [PARTITION BY expr] [ORDER BY expr] [PRIMARY KEY expr] [SAMPLE BY expr] * [INDEXES name BY expr TYPE type(args) GRANULARITY value, ...] [SETTINGS name = value, ...]