mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 17:12:03 +00:00
getCreateTableQuery and getCreateDatabaseQuery [#CLICKHOUSE-3590]
This commit is contained in:
parent
cda51eb920
commit
d6e9d08d5e
@ -3,6 +3,11 @@
|
|||||||
#include <Interpreters/ExternalDictionaries.h>
|
#include <Interpreters/ExternalDictionaries.h>
|
||||||
#include <Storages/StorageDictionary.h>
|
#include <Storages/StorageDictionary.h>
|
||||||
#include <common/logger_useful.h>
|
#include <common/logger_useful.h>
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <IO/WriteBufferFromString.h>
|
||||||
|
#include <IO/Operators.h>
|
||||||
|
#include <Parsers/ParserCreateQuery.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
@ -158,11 +163,34 @@ time_t DatabaseDictionary::getTableMetadataModificationTime(
|
|||||||
return static_cast<time_t>(0);
|
return static_cast<time_t>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPtr DatabaseDictionary::getCreateQuery(
|
ASTPtr DatabaseDictionary::getCreateTableQuery(
|
||||||
const Context &,
|
const Context & context,
|
||||||
const String &) const
|
const String & table_name) const
|
||||||
{
|
{
|
||||||
throw Exception("There is no CREATE TABLE query for DatabaseDictionary tables", ErrorCodes::CANNOT_GET_CREATE_TABLE_QUERY);
|
String query;
|
||||||
|
{
|
||||||
|
WriteBufferFromString buffer(query);
|
||||||
|
|
||||||
|
auto dictionary = context.getExternalDictionaries().getDictionary(table_name);
|
||||||
|
auto names_and_types = StorageDictionary::getNamesAndTypes(dictionary->getStructure());
|
||||||
|
buffer << "CREATE TABLE " << backQuoteIfNeed(name) << '.' << backQuoteIfNeed(table_name) << " (";
|
||||||
|
buffer << StorageDictionary::generateNamesAndTypesDescription(names_and_types.begin(), names_and_types.end());
|
||||||
|
buffer << ") Engine = Dictionary(" << backQuoteIfNeed(table_name) << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
ParserCreateQuery parser;
|
||||||
|
return parseQuery(parser, query.data(), query.data() + query.size(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTPtr DatabaseDictionary::getCreateDatabaseQuery(const Context & /*context*/) const
|
||||||
|
{
|
||||||
|
String query;
|
||||||
|
{
|
||||||
|
WriteBufferFromString buffer(query);
|
||||||
|
buffer << "CREATE DATABASE " << backQuoteIfNeed(name) << " ENGINE = Dictionary";
|
||||||
|
}
|
||||||
|
ParserCreateQuery parser;
|
||||||
|
return parseQuery(parser, query.data(), query.data() + query.size(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseDictionary::shutdown()
|
void DatabaseDictionary::shutdown()
|
||||||
|
@ -89,10 +89,12 @@ public:
|
|||||||
const Context & context,
|
const Context & context,
|
||||||
const String & table_name) override;
|
const String & table_name) override;
|
||||||
|
|
||||||
ASTPtr getCreateQuery(
|
ASTPtr getCreateTableQuery(
|
||||||
const Context & context,
|
const Context & context,
|
||||||
const String & table_name) const override;
|
const String & table_name) const override;
|
||||||
|
|
||||||
|
ASTPtr getCreateDatabaseQuery(const Context & context) const override;
|
||||||
|
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
void drop() override;
|
void drop() override;
|
||||||
};
|
};
|
||||||
|
@ -121,13 +121,18 @@ time_t DatabaseMemory::getTableMetadataModificationTime(
|
|||||||
return static_cast<time_t>(0);
|
return static_cast<time_t>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPtr DatabaseMemory::getCreateQuery(
|
ASTPtr DatabaseMemory::getCreateTableQuery(
|
||||||
const Context &,
|
const Context &,
|
||||||
const String &) const
|
const String &) const
|
||||||
{
|
{
|
||||||
throw Exception("There is no CREATE TABLE query for DatabaseMemory tables", ErrorCodes::CANNOT_GET_CREATE_TABLE_QUERY);
|
throw Exception("There is no CREATE TABLE query for DatabaseMemory tables", ErrorCodes::CANNOT_GET_CREATE_TABLE_QUERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTPtr DatabaseMemory::getCreateDatabaseQuery(const Context &) const
|
||||||
|
{
|
||||||
|
throw Exception("There is no CREATE DATABASE query for DatabaseMemory", ErrorCodes::CANNOT_GET_CREATE_TABLE_QUERY);
|
||||||
|
}
|
||||||
|
|
||||||
void DatabaseMemory::shutdown()
|
void DatabaseMemory::shutdown()
|
||||||
{
|
{
|
||||||
/// You can not hold a lock during shutdown.
|
/// You can not hold a lock during shutdown.
|
||||||
|
@ -80,9 +80,11 @@ public:
|
|||||||
const Context & context,
|
const Context & context,
|
||||||
const String & table_name) override;
|
const String & table_name) override;
|
||||||
|
|
||||||
ASTPtr getCreateQuery(
|
ASTPtr getCreateTableQuery(
|
||||||
const Context & context,
|
const Context & context,
|
||||||
const String & table_name) const override;
|
const String & table_name) const override;
|
||||||
|
|
||||||
|
ASTPtr getCreateDatabaseQuery(const Context & context) const override;
|
||||||
|
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
void drop() override;
|
void drop() override;
|
||||||
|
@ -335,22 +335,13 @@ void DatabaseOrdinary::removeTable(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ASTPtr getQueryFromMetadata(const String & metadata_path)
|
||||||
ASTPtr DatabaseOrdinary::getCreateQueryImpl(const String & path, const String & table_name) const
|
|
||||||
{
|
{
|
||||||
String metadata_path;
|
if (!Poco::File(metadata_path).exists())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
String query;
|
String query;
|
||||||
|
|
||||||
if (table_name.empty())
|
|
||||||
{
|
|
||||||
metadata_path = detail::getDatabaseMetadataPath(path);
|
|
||||||
if (!Poco::File(metadata_path).exists())
|
|
||||||
query = "CREATE DATABASE " + backQuoteIfNeed(name) + " ENGINE = Ordinary";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
metadata_path = detail::getTableMetadataPath(path, table_name);
|
|
||||||
|
|
||||||
if (query.empty())
|
|
||||||
{
|
{
|
||||||
ReadBufferFromFile in(metadata_path, 4096);
|
ReadBufferFromFile in(metadata_path, 4096);
|
||||||
readStringUntilEOF(query, in);
|
readStringUntilEOF(query, in);
|
||||||
@ -360,6 +351,20 @@ ASTPtr DatabaseOrdinary::getCreateQueryImpl(const String & path, const String &
|
|||||||
return parseQuery(parser, query.data(), query.data() + query.size(), "in file " + metadata_path);
|
return parseQuery(parser, query.data(), query.data() + query.size(), "in file " + metadata_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ASTPtr getCreateQueryFromMetadata(const String & metadata_path, const String & database)
|
||||||
|
{
|
||||||
|
ASTPtr ast = getQueryFromMetadata(metadata_path);
|
||||||
|
|
||||||
|
if (ast)
|
||||||
|
{
|
||||||
|
ASTCreateQuery & ast_create_query = typeid_cast<ASTCreateQuery &>(*ast);
|
||||||
|
ast_create_query.attach = false;
|
||||||
|
ast_create_query.database = database;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DatabaseOrdinary::renameTable(
|
void DatabaseOrdinary::renameTable(
|
||||||
const Context & context,
|
const Context & context,
|
||||||
@ -394,7 +399,9 @@ void DatabaseOrdinary::renameTable(
|
|||||||
throw Exception{e};
|
throw Exception{e};
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPtr ast = getCreateQueryImpl(metadata_path, table_name);
|
ASTPtr ast = getQueryFromMetadata(detail::getTableMetadataPath(metadata_path, table_name));
|
||||||
|
if (!ast)
|
||||||
|
throw Exception("There is no metadata file for table " + table_name, ErrorCodes::FILE_DOESNT_EXIST);
|
||||||
ASTCreateQuery & ast_create_query = typeid_cast<ASTCreateQuery &>(*ast);
|
ASTCreateQuery & ast_create_query = typeid_cast<ASTCreateQuery &>(*ast);
|
||||||
ast_create_query.table = to_table_name;
|
ast_create_query.table = to_table_name;
|
||||||
|
|
||||||
@ -422,27 +429,40 @@ time_t DatabaseOrdinary::getTableMetadataModificationTime(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ASTPtr DatabaseOrdinary::getCreateQuery(
|
ASTPtr DatabaseOrdinary::getCreateTableQuery(
|
||||||
const Context & context,
|
const Context & context,
|
||||||
const String & table_name) const
|
const String & table_name) const
|
||||||
{
|
{
|
||||||
ASTPtr ast;
|
ASTPtr ast;
|
||||||
try
|
|
||||||
{
|
|
||||||
ast = getCreateQueryImpl(metadata_path, table_name);
|
|
||||||
}
|
|
||||||
catch (const Exception & e)
|
|
||||||
{
|
|
||||||
/// Handle system.* tables for which there are no table.sql files
|
|
||||||
if (e.code() == ErrorCodes::FILE_DOESNT_EXIST && tryGetTable(context, table_name) != nullptr)
|
|
||||||
throw Exception("There is no CREATE TABLE query for table " + table_name, ErrorCodes::CANNOT_GET_CREATE_TABLE_QUERY);
|
|
||||||
|
|
||||||
throw;
|
auto table_metadata_path = detail::getTableMetadataPath(metadata_path, table_name);
|
||||||
|
ast = getCreateQueryFromMetadata(table_metadata_path, name);
|
||||||
|
if (!ast)
|
||||||
|
{
|
||||||
|
/// Handle system.* tables for which there are no table.sql files.
|
||||||
|
auto msg = tryGetTable(context, table_name)
|
||||||
|
? "There is no CREATE TABLE query for table "
|
||||||
|
: "There is no metadata file for table ";
|
||||||
|
|
||||||
|
throw Exception(msg + table_name, ErrorCodes::CANNOT_GET_CREATE_TABLE_QUERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTCreateQuery & ast_create_query = typeid_cast<ASTCreateQuery &>(*ast);
|
return ast;
|
||||||
ast_create_query.attach = false;
|
}
|
||||||
ast_create_query.database = name;
|
|
||||||
|
ASTPtr DatabaseOrdinary::getCreateDatabaseQuery(const Context & /*context*/) const
|
||||||
|
{
|
||||||
|
ASTPtr ast;
|
||||||
|
|
||||||
|
auto database_metadata_path = detail::getDatabaseMetadataPath(metadata_path);
|
||||||
|
ast = getCreateQueryFromMetadata(database_metadata_path, name);
|
||||||
|
if (!ast)
|
||||||
|
{
|
||||||
|
/// Handle databases (such as default) for which there are no database.sql files.
|
||||||
|
String query = "CREATE DATABASE " + backQuoteIfNeed(name) + " ENGINE = Ordinary";
|
||||||
|
ParserCreateQuery parser;
|
||||||
|
ast = parseQuery(parser, query.data(), query.data() + query.size(), "");
|
||||||
|
}
|
||||||
|
|
||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
@ -55,10 +55,12 @@ public:
|
|||||||
const Context & context,
|
const Context & context,
|
||||||
const String & table_name) override;
|
const String & table_name) override;
|
||||||
|
|
||||||
ASTPtr getCreateQuery(
|
ASTPtr getCreateTableQuery(
|
||||||
const Context & context,
|
const Context & context,
|
||||||
const String & table_name) const override;
|
const String & table_name) const override;
|
||||||
|
|
||||||
|
ASTPtr getCreateDatabaseQuery(const Context & context) const override;
|
||||||
|
|
||||||
String getDataPath() const override;
|
String getDataPath() const override;
|
||||||
String getMetadataPath() const override;
|
String getMetadataPath() const override;
|
||||||
String getTableMetadataPath(const String & table_name) const override;
|
String getTableMetadataPath(const String & table_name) const override;
|
||||||
@ -68,7 +70,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void startupTables(ThreadPool * thread_pool);
|
void startupTables(ThreadPool * thread_pool);
|
||||||
ASTPtr getCreateQueryImpl(const String & path, const String & table_name) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -124,12 +124,14 @@ public:
|
|||||||
const Context & context,
|
const Context & context,
|
||||||
const String & name) = 0;
|
const String & name) = 0;
|
||||||
|
|
||||||
/// Get the CREATE TABLE query for the table or CREATE DATABASE query for database if name is empty.
|
/// Get the CREATE TABLE query for the table. It can also provide information for detached tables for which there is metadata.
|
||||||
/// It can also provide information for detached tables for which there is metadata.
|
virtual ASTPtr getCreateTableQuery(
|
||||||
virtual ASTPtr getCreateQuery(
|
|
||||||
const Context & context,
|
const Context & context,
|
||||||
const String & name) const = 0;
|
const String & name) const = 0;
|
||||||
|
|
||||||
|
/// Get the CREATE DATABASE query for current database.
|
||||||
|
virtual ASTPtr getCreateDatabaseQuery(const Context & context) const = 0;
|
||||||
|
|
||||||
/// Returns path for persistent data storage if the database supports it, empty string otherwise
|
/// Returns path for persistent data storage if the database supports it, empty string otherwise
|
||||||
virtual String getDataPath() const { return {}; }
|
virtual String getDataPath() const { return {}; }
|
||||||
/// Returns metadata path if the database supports it, empty string otherwise
|
/// Returns metadata path if the database supports it, empty string otherwise
|
||||||
|
@ -910,17 +910,17 @@ DatabasePtr Context::detachDatabase(const String & database_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ASTPtr Context::getCreateQuery(const String & database_name, const String & table_name) const
|
ASTPtr Context::getCreateTableQuery(const String & database_name, const String & table_name) const
|
||||||
{
|
{
|
||||||
auto lock = getLock();
|
auto lock = getLock();
|
||||||
|
|
||||||
String db = resolveDatabase(database_name, current_database);
|
String db = resolveDatabase(database_name, current_database);
|
||||||
assertDatabaseExists(db);
|
assertDatabaseExists(db);
|
||||||
|
|
||||||
return shared->databases[db]->getCreateQuery(*this, table_name);
|
return shared->databases[db]->getCreateTableQuery(*this, table_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPtr Context::getCreateExternalQuery(const String & table_name) const
|
ASTPtr Context::getCreateExternalTableQuery(const String & table_name) const
|
||||||
{
|
{
|
||||||
TableAndCreateASTs::const_iterator jt = external_tables.find(table_name);
|
TableAndCreateASTs::const_iterator jt = external_tables.find(table_name);
|
||||||
if (external_tables.end() == jt)
|
if (external_tables.end() == jt)
|
||||||
@ -929,6 +929,15 @@ ASTPtr Context::getCreateExternalQuery(const String & table_name) const
|
|||||||
return jt->second.second;
|
return jt->second.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTPtr Context::getCreateDatabaseQuery(const String & database_name) const
|
||||||
|
{
|
||||||
|
auto lock = getLock();
|
||||||
|
|
||||||
|
String db = resolveDatabase(database_name, current_database);
|
||||||
|
assertDatabaseExists(db);
|
||||||
|
|
||||||
|
return shared->databases[db]->getCreateDatabaseQuery(*this);
|
||||||
|
}
|
||||||
|
|
||||||
Settings Context::getSettings() const
|
Settings Context::getSettings() const
|
||||||
{
|
{
|
||||||
|
@ -241,8 +241,9 @@ public:
|
|||||||
UInt16 getTCPPort() const;
|
UInt16 getTCPPort() const;
|
||||||
|
|
||||||
/// Get query for the CREATE table.
|
/// Get query for the CREATE table.
|
||||||
ASTPtr getCreateQuery(const String & database_name, const String & table_name) const;
|
ASTPtr getCreateTableQuery(const String & database_name, const String & table_name) const;
|
||||||
ASTPtr getCreateExternalQuery(const String & table_name) const;
|
ASTPtr getCreateExternalTableQuery(const String & table_name) const;
|
||||||
|
ASTPtr getCreateDatabaseQuery(const String & database_name) const;
|
||||||
|
|
||||||
const DatabasePtr getDatabase(const String & database_name) const;
|
const DatabasePtr getDatabase(const String & database_name) const;
|
||||||
DatabasePtr getDatabase(const String & database_name);
|
DatabasePtr getDatabase(const String & database_name);
|
||||||
|
@ -432,7 +432,7 @@ void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const
|
|||||||
String as_database_name = create.as_database.empty() ? context.getCurrentDatabase() : create.as_database;
|
String as_database_name = create.as_database.empty() ? context.getCurrentDatabase() : create.as_database;
|
||||||
String as_table_name = create.as_table;
|
String as_table_name = create.as_table;
|
||||||
|
|
||||||
ASTPtr as_create_ptr = context.getCreateQuery(as_database_name, as_table_name);
|
ASTPtr as_create_ptr = context.getCreateTableQuery(as_database_name, as_table_name);
|
||||||
const auto & as_create = typeid_cast<const ASTCreateQuery &>(*as_create_ptr);
|
const auto & as_create = typeid_cast<const ASTCreateQuery &>(*as_create_ptr);
|
||||||
|
|
||||||
if (as_create.is_view)
|
if (as_create.is_view)
|
||||||
@ -461,7 +461,7 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
|
|||||||
if (create.attach && !create.storage && !create.columns)
|
if (create.attach && !create.storage && !create.columns)
|
||||||
{
|
{
|
||||||
// Table SQL definition is available even if the table is detached
|
// Table SQL definition is available even if the table is detached
|
||||||
auto query = context.getCreateQuery(database_name, table_name);
|
auto query = context.getCreateTableQuery(database_name, table_name);
|
||||||
auto & as_create = typeid_cast<const ASTCreateQuery &>(*query);
|
auto & as_create = typeid_cast<const ASTCreateQuery &>(*query);
|
||||||
create = as_create; // Copy the saved create query, but use ATTACH instead of CREATE
|
create = as_create; // Copy the saved create query, but use ATTACH instead of CREATE
|
||||||
create.attach = true;
|
create.attach = true;
|
||||||
|
@ -44,8 +44,13 @@ BlockInputStreamPtr InterpreterShowCreateQuery::executeImpl()
|
|||||||
if (ast.temporary && !ast.database.empty())
|
if (ast.temporary && !ast.database.empty())
|
||||||
throw Exception("Temporary databases are not possible.", ErrorCodes::SYNTAX_ERROR);
|
throw Exception("Temporary databases are not possible.", ErrorCodes::SYNTAX_ERROR);
|
||||||
|
|
||||||
ASTPtr create_query = (ast.temporary ? context.getCreateExternalQuery(ast.table) :
|
ASTPtr create_query;
|
||||||
context.getCreateQuery(ast.database, ast.table));
|
if (ast.temporary)
|
||||||
|
create_query = context.getCreateExternalTableQuery(ast.table);
|
||||||
|
else if (ast.table.empty())
|
||||||
|
create_query = context.getCreateDatabaseQuery(ast.database);
|
||||||
|
else
|
||||||
|
create_query = context.getCreateTableQuery(ast.database, ast.table);
|
||||||
|
|
||||||
if (!create_query && ast.temporary)
|
if (!create_query && ast.temporary)
|
||||||
throw Exception("Unable to show the create query of " + ast.table + ". Maybe it was created by the system.", ErrorCodes::THERE_IS_NO_QUERY);
|
throw Exception("Unable to show the create query of " + ast.table + ". Maybe it was created by the system.", ErrorCodes::THERE_IS_NO_QUERY);
|
||||||
|
@ -89,7 +89,6 @@ void StorageDictionary::checkNamesAndTypesCompatibleWithDictionary(const Diction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void registerStorageDictionary(StorageFactory & factory)
|
void registerStorageDictionary(StorageFactory & factory)
|
||||||
{
|
{
|
||||||
factory.registerStorage("Dictionary", [](const StorageFactory::Arguments & args)
|
factory.registerStorage("Dictionary", [](const StorageFactory::Arguments & args)
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <Core/Defines.h>
|
#include <Core/Defines.h>
|
||||||
#include <common/MultiVersion.h>
|
#include <common/MultiVersion.h>
|
||||||
#include <ext/shared_ptr_helper.h>
|
#include <ext/shared_ptr_helper.h>
|
||||||
|
#include <IO/WriteBufferFromString.h>
|
||||||
|
#include <IO/Operators.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco
|
namespace Poco
|
||||||
@ -33,6 +35,26 @@ public:
|
|||||||
void drop() override {}
|
void drop() override {}
|
||||||
static NamesAndTypesList getNamesAndTypes(const DictionaryStructure & dictionary_structure);
|
static NamesAndTypesList getNamesAndTypes(const DictionaryStructure & dictionary_structure);
|
||||||
|
|
||||||
|
template <typename ForwardIterator>
|
||||||
|
static std::string generateNamesAndTypesDescription(ForwardIterator begin, ForwardIterator end)
|
||||||
|
{
|
||||||
|
std::string description;
|
||||||
|
{
|
||||||
|
WriteBufferFromString buffer(description);
|
||||||
|
bool first = true;
|
||||||
|
for (; begin != end; ++begin)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
buffer << ", ";
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
buffer << begin->name << ' ' << begin->type->getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Ptr = MultiVersion<IDictionaryBase>::Version;
|
using Ptr = MultiVersion<IDictionaryBase>::Version;
|
||||||
|
|
||||||
@ -42,24 +64,6 @@ private:
|
|||||||
|
|
||||||
void checkNamesAndTypesCompatibleWithDictionary(const DictionaryStructure & dictionary_structure) const;
|
void checkNamesAndTypesCompatibleWithDictionary(const DictionaryStructure & dictionary_structure) const;
|
||||||
|
|
||||||
template <typename ForwardIterator>
|
|
||||||
std::string generateNamesAndTypesDescription(ForwardIterator begin, ForwardIterator end) const
|
|
||||||
{
|
|
||||||
if (begin == end)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
std::string description;
|
|
||||||
for (; begin != end; ++begin)
|
|
||||||
{
|
|
||||||
description += ", ";
|
|
||||||
description += begin->name;
|
|
||||||
description += ' ';
|
|
||||||
description += begin->type->getName();
|
|
||||||
}
|
|
||||||
return description.substr(2, description.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StorageDictionary(const String & table_name_,
|
StorageDictionary(const String & table_name_,
|
||||||
const NamesAndTypesList & columns_,
|
const NamesAndTypesList & columns_,
|
||||||
|
@ -204,7 +204,7 @@ BlockInputStreams StorageSystemTables::read(
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ast = database->getCreateQuery(context, table_name);
|
ast = database->getCreateTableQuery(context, table_name);
|
||||||
}
|
}
|
||||||
catch (const Exception & e)
|
catch (const Exception & e)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user