ClickHouse/dbms/src/Databases/DatabasesCommon.cpp

159 lines
4.9 KiB
C++
Raw Normal View History

#include <Databases/DatabasesCommon.h>
#include <Interpreters/InterpreterCreateQuery.h>
#include <Parsers/ParserCreateQuery.h>
#include <Parsers/formatAST.h>
2019-10-17 13:05:12 +00:00
#include <Storages/StorageDictionary.h>
#include <Storages/StorageFactory.h>
#include <Common/typeid_cast.h>
2019-10-25 19:07:47 +00:00
#include <Common/escapeForFileName.h>
2019-07-18 18:29:49 +00:00
#include <TableFunctions/TableFunctionFactory.h>
namespace DB
{
namespace ErrorCodes
{
extern const int TABLE_ALREADY_EXISTS;
extern const int UNKNOWN_TABLE;
}
DatabaseWithOwnTablesBase::DatabaseWithOwnTablesBase(const String & name_, const String & logger)
: IDatabase(name_), log(&Logger::get(logger))
{
}
bool DatabaseWithOwnTablesBase::isTableExist(
const Context & /*context*/,
const String & table_name) const
{
2019-01-02 06:44:36 +00:00
std::lock_guard lock(mutex);
2019-10-17 13:05:12 +00:00
return tables.find(table_name) != tables.end() || dictionaries.find(table_name) != dictionaries.end();
}
StoragePtr DatabaseWithOwnTablesBase::tryGetTable(
const Context & /*context*/,
const String & table_name) const
{
std::lock_guard lock(mutex);
auto it = tables.find(table_name);
if (it != tables.end())
return it->second;
2019-10-17 17:18:54 +00:00
return {};
}
2019-10-10 17:33:01 +00:00
DatabaseTablesIteratorPtr DatabaseWithOwnTablesBase::getTablesIterator(const Context & /*context*/, const FilterByNameFunction & filter_by_table_name)
{
2019-01-02 06:44:36 +00:00
std::lock_guard lock(mutex);
if (!filter_by_table_name)
2019-10-10 17:33:01 +00:00
return std::make_unique<DatabaseTablesSnapshotIterator>(tables);
2019-10-17 13:05:12 +00:00
Tables filtered_tables;
for (const auto & [table_name, storage] : tables)
if (filter_by_table_name(table_name))
filtered_tables.emplace(table_name, storage);
2019-10-17 13:05:12 +00:00
2019-10-10 17:33:01 +00:00
return std::make_unique<DatabaseTablesSnapshotIterator>(std::move(filtered_tables));
}
bool DatabaseWithOwnTablesBase::empty(const Context & /*context*/) const
{
2019-01-02 06:44:36 +00:00
std::lock_guard lock(mutex);
2019-10-10 17:33:01 +00:00
return tables.empty() && dictionaries.empty();
}
StoragePtr DatabaseWithOwnTablesBase::detachTable(const String & table_name)
2020-01-30 12:51:47 +00:00
{
std::lock_guard lock(mutex);
return detachTableUnlocked(table_name);
}
StoragePtr DatabaseWithOwnTablesBase::detachTableUnlocked(const String & table_name)
{
StoragePtr res;
2020-01-30 12:51:47 +00:00
if (dictionaries.count(table_name))
throw Exception("Cannot detach dictionary " + database_name + "." + table_name + " as table, use DETACH DICTIONARY query.", ErrorCodes::UNKNOWN_TABLE);
auto it = tables.find(table_name);
if (it == tables.end())
throw Exception("Table " + backQuote(database_name) + "." + backQuote(table_name) + " doesn't exist.", ErrorCodes::UNKNOWN_TABLE);
res = it->second;
tables.erase(it);
2020-03-12 18:04:29 +00:00
auto table_id = res->getStorageID();
if (table_id.hasUUID())
{
2020-03-17 23:51:35 +00:00
assert(getDatabaseName() == DatabaseCatalog::TEMPORARY_DATABASE || getEngineName() == "Atomic");
2020-03-12 18:04:29 +00:00
DatabaseCatalog::instance().removeUUIDMapping(table_id.uuid);
}
return res;
}
2020-01-30 12:51:47 +00:00
void DatabaseWithOwnTablesBase::attachTable(const String & table_name, const StoragePtr & table, const String & relative_table_path)
{
2019-01-02 06:44:36 +00:00
std::lock_guard lock(mutex);
2020-01-30 12:51:47 +00:00
attachTableUnlocked(table_name, table, relative_table_path);
}
void DatabaseWithOwnTablesBase::attachTableUnlocked(const String & table_name, const StoragePtr & table, const String &)
{
if (!tables.emplace(table_name, table).second)
2019-11-01 12:47:55 +00:00
throw Exception("Table " + database_name + "." + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
2020-03-12 18:04:29 +00:00
auto table_id = table->getStorageID();
if (table_id.hasUUID())
{
2020-03-17 23:51:35 +00:00
assert(getDatabaseName() == DatabaseCatalog::TEMPORARY_DATABASE || getEngineName() == "Atomic");
2020-03-12 18:04:29 +00:00
DatabaseCatalog::instance().addUUIDMapping(table_id.uuid, shared_from_this(), table);
}
}
void DatabaseWithOwnTablesBase::shutdown()
{
/// You can not hold a lock during shutdown.
/// Because inside `shutdown` function tables can work with database, and mutex is not recursive.
Tables tables_snapshot;
{
2019-01-02 06:44:36 +00:00
std::lock_guard lock(mutex);
tables_snapshot = tables;
}
2018-06-09 15:48:22 +00:00
for (const auto & kv : tables_snapshot)
{
2020-03-17 23:51:35 +00:00
auto table_id = kv.second->getStorageID();
kv.second->shutdown();
2020-03-17 23:51:35 +00:00
if (table_id.hasUUID())
{
assert(getDatabaseName() == DatabaseCatalog::TEMPORARY_DATABASE || getEngineName() == "Atomic");
DatabaseCatalog::instance().removeUUIDMapping(table_id.uuid);
}
}
2019-01-02 06:44:36 +00:00
std::lock_guard lock(mutex);
tables.clear();
2019-10-14 09:52:43 +00:00
dictionaries.clear();
}
DatabaseWithOwnTablesBase::~DatabaseWithOwnTablesBase()
{
try
{
DatabaseWithOwnTablesBase::shutdown();
}
catch (...)
{
tryLogCurrentException(__PRETTY_FUNCTION__);
}
}
2020-03-20 12:45:06 +00:00
StoragePtr DatabaseWithOwnTablesBase::getTableUnlocked(const String & table_name) const
{
auto it = tables.find(table_name);
if (it != tables.end())
return it->second;
throw Exception("Table " + backQuote(database_name) + "." + backQuote(table_name) + " doesn't exist.", ErrorCodes::UNKNOWN_TABLE);
}
}