From 8b2feaeca24b15415a707daba6494b06cb780292 Mon Sep 17 00:00:00 2001 From: spongedc Date: Mon, 14 Dec 2020 22:37:25 +0800 Subject: [PATCH] Support SHOW CREATE VIEW Syntax --- src/Common/ErrorCodes.cpp | 1 + src/Databases/IDatabase.h | 1 + src/Interpreters/InterpreterFactory.cpp | 4 +++ .../InterpreterShowCreateQuery.cpp | 9 ++++++- src/Parsers/ASTCreateQuery.h | 2 ++ src/Parsers/ParserTablePropertiesQuery.cpp | 20 +++++++++----- src/Parsers/ParserTablePropertiesQuery.h | 2 +- src/Parsers/TablePropertiesQueriesASTs.h | 9 +++++++ .../01602_show_create_view.reference | 3 +++ .../0_stateless/01602_show_create_view.sql | 26 +++++++++++++++++++ 10 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 tests/queries/0_stateless/01602_show_create_view.reference create mode 100644 tests/queries/0_stateless/01602_show_create_view.sql diff --git a/src/Common/ErrorCodes.cpp b/src/Common/ErrorCodes.cpp index 1e381808d16..328d0a364ff 100644 --- a/src/Common/ErrorCodes.cpp +++ b/src/Common/ErrorCodes.cpp @@ -529,6 +529,7 @@ M(560, ZSTD_ENCODER_FAILED) \ M(561, ZSTD_DECODER_FAILED) \ M(562, TLD_LIST_NOT_FOUND) \ + M(563, NOT_VIEW) \ \ M(999, KEEPER_EXCEPTION) \ M(1000, POCO_EXCEPTION) \ diff --git a/src/Databases/IDatabase.h b/src/Databases/IDatabase.h index fadec5fe7a9..fb2a9652d4b 100644 --- a/src/Databases/IDatabase.h +++ b/src/Databases/IDatabase.h @@ -30,6 +30,7 @@ namespace ErrorCodes extern const int NOT_IMPLEMENTED; extern const int CANNOT_GET_CREATE_TABLE_QUERY; extern const int CANNOT_GET_CREATE_DICTIONARY_QUERY; + extern const int NOT_VIEW; } class IDatabaseTablesIterator diff --git a/src/Interpreters/InterpreterFactory.cpp b/src/Interpreters/InterpreterFactory.cpp index 30992905f5d..156c3c1ba51 100644 --- a/src/Interpreters/InterpreterFactory.cpp +++ b/src/Interpreters/InterpreterFactory.cpp @@ -160,6 +160,10 @@ std::unique_ptr InterpreterFactory::get(ASTPtr & query, Context & { return std::make_unique(query, context); } + else if (query->as()) + { + return std::make_unique(query, context); + } else if (query->as()) { return std::make_unique(query, context); diff --git a/src/Interpreters/InterpreterShowCreateQuery.cpp b/src/Interpreters/InterpreterShowCreateQuery.cpp index 907523ce94b..bcf6cc09473 100644 --- a/src/Interpreters/InterpreterShowCreateQuery.cpp +++ b/src/Interpreters/InterpreterShowCreateQuery.cpp @@ -43,12 +43,19 @@ BlockInputStreamPtr InterpreterShowCreateQuery::executeImpl() { ASTPtr create_query; ASTQueryWithTableAndOutput * show_query; - if ((show_query = query_ptr->as())) + if ((show_query = query_ptr->as()) || + (show_query = query_ptr->as())) { auto resolve_table_type = show_query->temporary ? Context::ResolveExternal : Context::ResolveOrdinary; auto table_id = context.resolveStorageID(*show_query, resolve_table_type); context.checkAccess(AccessType::SHOW_COLUMNS, table_id); create_query = DatabaseCatalog::instance().getDatabase(table_id.database_name)->getCreateTableQuery(table_id.table_name, context); + if (query_ptr->as()) + { + auto & ast_create_query = create_query->as(); + if (!ast_create_query.isView()) + throw Exception("'" + ast_create_query.database + "." + ast_create_query.table +"' is not VIEW", ErrorCodes::NOT_VIEW); + } } else if ((show_query = query_ptr->as())) { diff --git a/src/Parsers/ASTCreateQuery.h b/src/Parsers/ASTCreateQuery.h index 7b2deb99698..67ad9a89392 100644 --- a/src/Parsers/ASTCreateQuery.h +++ b/src/Parsers/ASTCreateQuery.h @@ -91,6 +91,8 @@ public: return removeOnCluster(clone(), new_database); } + bool isView() { return is_view || is_materialized_view || is_live_view; } + protected: void formatQueryImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override; }; diff --git a/src/Parsers/ParserTablePropertiesQuery.cpp b/src/Parsers/ParserTablePropertiesQuery.cpp index 2ee85a3330d..fcb7c8ef7a4 100644 --- a/src/Parsers/ParserTablePropertiesQuery.cpp +++ b/src/Parsers/ParserTablePropertiesQuery.cpp @@ -21,6 +21,7 @@ bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & ParserKeyword s_create("CREATE"); ParserKeyword s_database("DATABASE"); ParserKeyword s_table("TABLE"); + ParserKeyword s_view("VIEW"); ParserKeyword s_dictionary("DICTIONARY"); ParserToken s_dot(TokenType::Dot); ParserIdentifier name_p; @@ -30,6 +31,7 @@ bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & std::shared_ptr query; bool parse_only_database_name = false; + bool parse_show_create_view = false; bool temporary = false; if (s_exists.ignore(pos, expected)) @@ -56,6 +58,11 @@ bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & } else if (s_dictionary.checkWithoutMoving(pos, expected)) query = std::make_shared(); + else if (s_view.ignore(pos, expected)) + { + query = std::make_shared(); + parse_show_create_view = true; + } else query = std::make_shared(); } @@ -71,15 +78,16 @@ bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & } else { - if (temporary || s_temporary.ignore(pos, expected)) - query->temporary = true; - - if (!s_table.ignore(pos, expected)) - s_dictionary.ignore(pos, expected); + if (!parse_show_create_view) + { + if (temporary || s_temporary.ignore(pos, expected)) + query->temporary = true; + if (!s_table.ignore(pos, expected)) + s_dictionary.ignore(pos, expected); + } if (!name_p.parse(pos, table, expected)) return false; - if (s_dot.ignore(pos, expected)) { database = table; diff --git a/src/Parsers/ParserTablePropertiesQuery.h b/src/Parsers/ParserTablePropertiesQuery.h index 5de4c45db88..8d2c26d34ab 100644 --- a/src/Parsers/ParserTablePropertiesQuery.h +++ b/src/Parsers/ParserTablePropertiesQuery.h @@ -7,7 +7,7 @@ namespace DB { -/** Query (EXISTS | SHOW CREATE) [TABLE|DICTIONARY] [db.]name [FORMAT format] +/** Query (EXISTS | SHOW CREATE) [DATABASE|TABLE|DICTIONARY] [db.]name [FORMAT format] */ class ParserTablePropertiesQuery : public IParserBase { diff --git a/src/Parsers/TablePropertiesQueriesASTs.h b/src/Parsers/TablePropertiesQueriesASTs.h index 6a8e3b2ce83..cbb9b2a382c 100644 --- a/src/Parsers/TablePropertiesQueriesASTs.h +++ b/src/Parsers/TablePropertiesQueriesASTs.h @@ -29,6 +29,14 @@ struct ASTShowCreateTableQueryIDAndQueryNames static constexpr auto QueryTemporary = "SHOW CREATE TEMPORARY TABLE"; }; +struct ASTShowCreateViewQueryIDAndQueryNames +{ + static constexpr auto ID = "ShowCreateViewQuery"; + static constexpr auto Query = "SHOW CREATE VIEW"; + /// No temporary view are supported, just for parsing + static constexpr auto QueryTemporary = ""; +}; + struct ASTShowCreateDatabaseQueryIDAndQueryNames { static constexpr auto ID = "ShowCreateDatabaseQuery"; @@ -54,6 +62,7 @@ struct ASTDescribeQueryExistsQueryIDAndQueryNames using ASTExistsTableQuery = ASTQueryWithTableAndOutputImpl; using ASTExistsDictionaryQuery = ASTQueryWithTableAndOutputImpl; using ASTShowCreateTableQuery = ASTQueryWithTableAndOutputImpl; +using ASTShowCreateViewQuery = ASTQueryWithTableAndOutputImpl; using ASTShowCreateDictionaryQuery = ASTQueryWithTableAndOutputImpl; class ASTShowCreateDatabaseQuery : public ASTQueryWithTableAndOutputImpl diff --git a/tests/queries/0_stateless/01602_show_create_view.reference b/tests/queries/0_stateless/01602_show_create_view.reference new file mode 100644 index 00000000000..2c2ba13bef3 --- /dev/null +++ b/tests/queries/0_stateless/01602_show_create_view.reference @@ -0,0 +1,3 @@ +CREATE VIEW test_1602.v\n(\n `EventDate` DateTime,\n `CounterID` UInt32,\n `UserID` UInt32\n) AS\nSELECT *\nFROM test_1602.tbl +CREATE MATERIALIZED VIEW test_1602.vv\n(\n `EventDate` DateTime,\n `CounterID` UInt32,\n `UserID` UInt32\n)\nENGINE = MergeTree\nPARTITION BY toYYYYMM(EventDate)\nORDER BY (CounterID, EventDate, intHash32(UserID))\nSETTINGS index_granularity = 8192 AS\nSELECT *\nFROM test_1602.tbl +CREATE LIVE VIEW test_1602.vvv\n(\n `EventDate` DateTime,\n `CounterID` UInt32,\n `UserID` UInt32\n) AS\nSELECT *\nFROM test_1602.tbl diff --git a/tests/queries/0_stateless/01602_show_create_view.sql b/tests/queries/0_stateless/01602_show_create_view.sql new file mode 100644 index 00000000000..0a4ecd4ceec --- /dev/null +++ b/tests/queries/0_stateless/01602_show_create_view.sql @@ -0,0 +1,26 @@ +DROP DATABASE IF EXISTS test_1602; + +CREATE DATABASE test_1602; + +CREATE TABLE test_1602.tbl (`EventDate` DateTime, `CounterID` UInt32, `UserID` UInt32) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SETTINGS index_granularity = 8192; + +CREATE VIEW test_1602.v AS SELECT * FROM test_1602.tbl; + +CREATE MATERIALIZED VIEW test_1602.vv (`EventDate` DateTime, `CounterID` UInt32, `UserID` UInt32) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SETTINGS index_granularity = 8192 AS SELECT * FROM test_1602.tbl; + + +SET allow_experimental_live_view=1; + +CREATE LIVE VIEW test_1602.vvv AS SELECT * FROM test_1602.tbl; + +SHOW CREATE VIEW test_1602.v; + +SHOW CREATE VIEW test_1602.vv; + +SHOW CREATE VIEW test_1602.vvv; + +SHOW CREATE VIEW test_1602.not_exist_view; -- { serverError 390 } + +SHOW CREATE VIEW test_1602.tbl; -- { serverError 563 } + +DROP DATABASE IF EXISTS test_1602;