diff --git a/dbms/src/Databases/DatabaseOrdinary.cpp b/dbms/src/Databases/DatabaseOrdinary.cpp index 0021f47c4c7..b0719649094 100644 --- a/dbms/src/Databases/DatabaseOrdinary.cpp +++ b/dbms/src/Databases/DatabaseOrdinary.cpp @@ -45,6 +45,12 @@ namespace detail { return base_path + (endsWith(base_path, "/") ? "" : "/") + escapeForFileName(table_name) + ".sql"; } + + String getDatabaseMetadataPath(const String & base_path) + { + return (endsWith(base_path, "/") ? base_path.substr(0, base_path.size() - 1) : base_path) + ".sql"; + } + } static void loadTable( @@ -332,16 +338,21 @@ void DatabaseOrdinary::removeTable( static ASTPtr getCreateQueryImpl(const String & path, const String & table_name) { - String table_metadata_path = detail::getTableMetadataPath(path, table_name); + String metadata_path; + + if (table_name.empty()) + metadata_path = detail::getDatabaseMetadataPath(path); + else + metadata_path = detail::getTableMetadataPath(path, table_name); String query; { - ReadBufferFromFile in(table_metadata_path, 4096); + ReadBufferFromFile in(metadata_path, 4096); readStringUntilEOF(query, in); } ParserCreateQuery parser; - return parseQuery(parser, query.data(), query.data() + query.size(), "in file " + table_metadata_path); + return parseQuery(parser, query.data(), query.data() + query.size(), "in file " + metadata_path); } diff --git a/dbms/src/Databases/IDatabase.h b/dbms/src/Databases/IDatabase.h index 74cbe0b2202..8d62c0e3d45 100644 --- a/dbms/src/Databases/IDatabase.h +++ b/dbms/src/Databases/IDatabase.h @@ -124,7 +124,8 @@ public: const Context & context, const String & name) = 0; - /// Get the CREATE TABLE query for the table. It can also provide information for detached tables for which there is metadata. + /// Get the CREATE TABLE query for the table or CREATE DATABASE query for database if name is empty. + /// It can also provide information for detached tables for which there is metadata. virtual ASTPtr getCreateQuery( const Context & context, const String & name) const = 0; diff --git a/dbms/src/Interpreters/InterpreterFactory.cpp b/dbms/src/Interpreters/InterpreterFactory.cpp index 9d30c586129..2e43efbb12e 100644 --- a/dbms/src/Interpreters/InterpreterFactory.cpp +++ b/dbms/src/Interpreters/InterpreterFactory.cpp @@ -107,7 +107,11 @@ std::unique_ptr InterpreterFactory::get(ASTPtr & query, Context & { return std::make_unique(query, context); } - else if (typeid_cast(query.get())) + else if (typeid_cast(query.get())) + { + return std::make_unique(query, context); + } + else if (typeid_cast(query.get())) { return std::make_unique(query, context); } diff --git a/dbms/src/Interpreters/InterpreterShowCreateQuery.cpp b/dbms/src/Interpreters/InterpreterShowCreateQuery.cpp index d4bd116bcf7..705b9bb4120 100644 --- a/dbms/src/Interpreters/InterpreterShowCreateQuery.cpp +++ b/dbms/src/Interpreters/InterpreterShowCreateQuery.cpp @@ -39,7 +39,7 @@ Block InterpreterShowCreateQuery::getSampleBlock() BlockInputStreamPtr InterpreterShowCreateQuery::executeImpl() { - const ASTShowCreateQuery & ast = typeid_cast(*query_ptr); + const auto & ast = dynamic_cast(*query_ptr); if (ast.temporary && !ast.database.empty()) throw Exception("Temporary databases are not possible.", ErrorCodes::SYNTAX_ERROR); diff --git a/dbms/src/Parsers/ParserTablePropertiesQuery.cpp b/dbms/src/Parsers/ParserTablePropertiesQuery.cpp index 570597b0fa6..45e92f9e181 100644 --- a/dbms/src/Parsers/ParserTablePropertiesQuery.cpp +++ b/dbms/src/Parsers/ParserTablePropertiesQuery.cpp @@ -19,6 +19,7 @@ bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & ParserKeyword s_desc("DESC"); ParserKeyword s_show("SHOW"); ParserKeyword s_create("CREATE"); + ParserKeyword s_database("DATABASE"); ParserKeyword s_table("TABLE"); ParserToken s_dot(TokenType::Dot); ParserIdentifier name_p; @@ -27,6 +28,8 @@ bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & ASTPtr table; std::shared_ptr query; + bool parse_only_database_name = false; + if (s_exists.ignore(pos, expected)) { query = std::make_shared(); @@ -36,26 +39,40 @@ bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & if (!s_create.ignore(pos, expected)) return false; - query = std::make_shared(); + if (s_database.ignore(pos, expected)) + { + parse_only_database_name = true; + query = std::make_shared(); + } + else + query = std::make_shared(); } else { return false; } - if (s_temporary.ignore(pos, expected)) - query->temporary = true; - - s_table.ignore(pos, expected); - - if (!name_p.parse(pos, table, expected)) - return false; - - if (s_dot.ignore(pos, expected)) + if (parse_only_database_name) { - database = table; + if (!name_p.parse(pos, database, expected)) + return false; + } + else + { + if (s_temporary.ignore(pos, expected)) + query->temporary = true; + + s_table.ignore(pos, expected); + if (!name_p.parse(pos, table, expected)) return false; + + if (s_dot.ignore(pos, expected)) + { + database = table; + if (!name_p.parse(pos, table, expected)) + return false; + } } if (database) diff --git a/dbms/src/Parsers/TablePropertiesQueriesASTs.h b/dbms/src/Parsers/TablePropertiesQueriesASTs.h index 312b112f494..15a1d397fa4 100644 --- a/dbms/src/Parsers/TablePropertiesQueriesASTs.h +++ b/dbms/src/Parsers/TablePropertiesQueriesASTs.h @@ -12,12 +12,18 @@ struct ASTExistsQueryIDAndQueryNames static constexpr auto Query = "EXISTS TABLE"; }; -struct ASTShowCreateQueryIDAndQueryNames +struct ASTShowCreateTableQueryIDAndQueryNames { - static constexpr auto ID = "ShowCreateQuery"; + static constexpr auto ID = "ShowCreateTableQuery"; static constexpr auto Query = "SHOW CREATE TABLE"; }; +struct ASTShowCreateDatabaseQueryIDAndQueryNames +{ + static constexpr auto ID = "ShowCreateDatabaseQuery"; + static constexpr auto Query = "SHOW CREATE DATABASE"; +}; + struct ASTDescribeQueryExistsQueryIDAndQueryNames { static constexpr auto ID = "DescribeQuery"; @@ -25,7 +31,17 @@ struct ASTDescribeQueryExistsQueryIDAndQueryNames }; using ASTExistsQuery = ASTQueryWithTableAndOutputImpl; -using ASTShowCreateQuery = ASTQueryWithTableAndOutputImpl; +using ASTShowCreateTableQuery = ASTQueryWithTableAndOutputImpl; + +class ASTShowCreateDatabaseQuery : public ASTQueryWithTableAndOutputImpl +{ +protected: + void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override + { + settings.ostr << (settings.hilite ? hilite_keyword : "") << ASTShowCreateDatabaseQueryIDAndQueryNames::Query + << " " << (settings.hilite ? hilite_none : "") << backQuoteIfNeed(database); + } +}; class ASTDescribeQuery : public ASTQueryWithOutput {