mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-17 21:24:28 +00:00
refactor databases: add DatabaseWithDictionaries
This commit is contained in:
parent
d0af0c8703
commit
b686738056
@ -65,13 +65,6 @@ bool DatabaseDictionary::isTableExist(
|
||||
return context.getExternalDictionariesLoader().getCurrentStatus(table_name) != ExternalLoader::Status::NOT_EXIST;
|
||||
}
|
||||
|
||||
DatabaseDictionariesIteratorPtr DatabaseDictionary::getDictionariesIterator(
|
||||
const Context & /*context*/,
|
||||
const FilterByNameFunction & /*filter_by_dictionary_name*/)
|
||||
{
|
||||
return std::make_unique<DatabaseDictionariesSnapshotIterator>();
|
||||
}
|
||||
|
||||
StoragePtr DatabaseDictionary::tryGetTable(
|
||||
const Context & context,
|
||||
const String & table_name) const
|
||||
|
@ -39,8 +39,6 @@ public:
|
||||
|
||||
DatabaseTablesIteratorPtr getTablesIterator(const Context & context, const FilterByNameFunction & filter_by_table_name = {}) override;
|
||||
|
||||
DatabaseDictionariesIteratorPtr getDictionariesIterator(const Context & context, const FilterByNameFunction & filter_by_dictionary_name = {}) override;
|
||||
|
||||
bool empty(const Context & context) const override;
|
||||
|
||||
ASTPtr getCreateDatabaseQuery(const Context & context) const override;
|
||||
|
@ -78,13 +78,6 @@ void DatabaseLazy::removeTable(
|
||||
DatabaseOnDisk::removeTable(*this, context, table_name, log);
|
||||
}
|
||||
|
||||
DatabaseDictionariesIteratorPtr DatabaseLazy::getDictionariesIterator(
|
||||
const Context & /*context*/,
|
||||
const FilterByNameFunction & /*filter_by_dictionary_name*/)
|
||||
{
|
||||
return std::make_unique<DatabaseDictionariesSnapshotIterator>();
|
||||
}
|
||||
|
||||
void DatabaseLazy::renameTable(
|
||||
const Context & context,
|
||||
const String & table_name,
|
||||
|
@ -75,8 +75,6 @@ public:
|
||||
|
||||
DatabaseTablesIteratorPtr getTablesIterator(const Context & context, const FilterByNameFunction & filter_by_table_name = {}) override;
|
||||
|
||||
DatabaseDictionariesIteratorPtr getDictionariesIterator(const Context & context, const FilterByNameFunction & filter_by_dictionary_name = {}) override;
|
||||
|
||||
void attachTable(const String & table_name, const StoragePtr & table) override;
|
||||
|
||||
StoragePtr detachTable(const String & table_name) override;
|
||||
|
@ -33,8 +33,6 @@ public:
|
||||
|
||||
ASTPtr getCreateDatabaseQuery(const Context & context) const override;
|
||||
|
||||
//FIXME isDictionaryExist(...)
|
||||
|
||||
private:
|
||||
Poco::Logger * log;
|
||||
};
|
||||
|
@ -30,11 +30,6 @@ public:
|
||||
|
||||
DatabaseTablesIteratorPtr getTablesIterator(const Context & context, const FilterByNameFunction & filter_by_table_name = {}) override;
|
||||
|
||||
DatabaseDictionariesIteratorPtr getDictionariesIterator(const Context &, const FilterByNameFunction & = {}) override
|
||||
{
|
||||
return std::make_unique<DatabaseDictionariesSnapshotIterator>();
|
||||
}
|
||||
|
||||
ASTPtr getCreateDatabaseQuery(const Context & context) const override;
|
||||
|
||||
bool isTableExist(const Context & context, const String & name) const override;
|
||||
|
@ -93,7 +93,7 @@ void logAboutProgress(Poco::Logger * log, size_t processed, size_t total, Atomic
|
||||
|
||||
|
||||
DatabaseOrdinary::DatabaseOrdinary(String name_, const String & metadata_path_, const Context & context_)
|
||||
: DatabaseWithOwnTablesBase(std::move(name_))
|
||||
: DatabaseWithDictionaries(std::move(name_))
|
||||
, metadata_path(metadata_path_)
|
||||
, data_path("data/" + escapeForFileName(database_name) + "/")
|
||||
, log(&Logger::get("DatabaseOrdinary (" + database_name + ")"))
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Databases/DatabasesCommon.h>
|
||||
#include <Databases/DatabaseWithDictionaries.h>
|
||||
#include <Common/ThreadPool.h>
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ namespace DB
|
||||
* It stores tables list in filesystem using list of .sql files,
|
||||
* that contain declaration of table represented by SQL ATTACH TABLE query.
|
||||
*/
|
||||
class DatabaseOrdinary : public DatabaseWithOwnTablesBase
|
||||
class DatabaseOrdinary : public DatabaseWithDictionaries //DatabaseWithOwnTablesBase
|
||||
{
|
||||
public:
|
||||
DatabaseOrdinary(String name_, const String & metadata_path_, const Context & context);
|
||||
|
124
dbms/src/Databases/DatabaseWithDictionaries.cpp
Normal file
124
dbms/src/Databases/DatabaseWithDictionaries.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#include <Databases/DatabaseWithDictionaries.h>
|
||||
#include <Interpreters/ExternalDictionariesLoader.h>
|
||||
#include <Interpreters/Context.h>
|
||||
#include <Storages/StorageDictionary.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int EMPTY_LIST_OF_COLUMNS_PASSED;
|
||||
extern const int TABLE_ALREADY_EXISTS;
|
||||
extern const int UNKNOWN_TABLE;
|
||||
extern const int LOGICAL_ERROR;
|
||||
extern const int DICTIONARY_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
|
||||
void DatabaseWithDictionaries::attachDictionary(const String & dictionary_name, const Context & context, bool load)
|
||||
{
|
||||
const auto & external_loader = context.getExternalDictionariesLoader();
|
||||
|
||||
String full_name = getDatabaseName() + "." + dictionary_name;
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
auto status = external_loader.getCurrentStatus(full_name);
|
||||
if (status != ExternalLoader::Status::NOT_EXIST || !dictionaries.emplace(dictionary_name).second)
|
||||
throw Exception(
|
||||
"Dictionary " + full_name + " already exists.",
|
||||
ErrorCodes::DICTIONARY_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
if (load)
|
||||
external_loader.reload(full_name, true);
|
||||
}
|
||||
|
||||
void DatabaseWithDictionaries::detachDictionary(const String & dictionary_name, const Context & context, bool reload)
|
||||
{
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
auto it = dictionaries.find(dictionary_name);
|
||||
if (it == dictionaries.end())
|
||||
throw Exception("Dictionary " + database_name + "." + dictionary_name + " doesn't exist.", ErrorCodes::UNKNOWN_TABLE);
|
||||
dictionaries.erase(it);
|
||||
}
|
||||
|
||||
if (reload)
|
||||
context.getExternalDictionariesLoader().reload(getDatabaseName() + "." + dictionary_name);
|
||||
|
||||
}
|
||||
|
||||
StoragePtr DatabaseWithDictionaries::tryGetTable(const Context & context, const String & table_name) const
|
||||
{
|
||||
if (auto table_ptr = DatabaseWithOwnTablesBase::tryGetTable(context, table_name))
|
||||
return table_ptr;
|
||||
|
||||
if (isDictionaryExist(context, table_name))
|
||||
/// We don't need lock database here, because database doesn't store dictionary itself
|
||||
/// just metadata
|
||||
return getDictionaryStorage(context, table_name);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
DatabaseTablesIteratorPtr DatabaseWithDictionaries::getTablesWithDictionaryTablesIterator(const Context & context, const FilterByNameFunction & filter_by_name)
|
||||
{
|
||||
/// NOTE: it's not atomic
|
||||
auto tables_it = getTablesIterator(context, filter_by_name);
|
||||
auto dictionaries_it = getDictionariesIterator(context, filter_by_name);
|
||||
|
||||
Tables result;
|
||||
while (tables_it && tables_it->isValid())
|
||||
{
|
||||
result.emplace(tables_it->name(), tables_it->table());
|
||||
tables_it->next();
|
||||
}
|
||||
|
||||
while (dictionaries_it && dictionaries_it->isValid())
|
||||
{
|
||||
auto table_name = dictionaries_it->name();
|
||||
auto table_ptr = getDictionaryStorage(context, table_name);
|
||||
if (table_ptr)
|
||||
result.emplace(table_name, table_ptr);
|
||||
dictionaries_it->next();
|
||||
}
|
||||
|
||||
return std::make_unique<DatabaseTablesSnapshotIterator>(result);
|
||||
}
|
||||
|
||||
DatabaseDictionariesIteratorPtr DatabaseWithDictionaries::getDictionariesIterator(const Context & /*context*/, const FilterByNameFunction & filter_by_dictionary_name)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
if (!filter_by_dictionary_name)
|
||||
return std::make_unique<DatabaseDictionariesSnapshotIterator>(dictionaries);
|
||||
|
||||
Dictionaries filtered_dictionaries;
|
||||
for (const auto & dictionary_name : dictionaries)
|
||||
if (filter_by_dictionary_name(dictionary_name))
|
||||
filtered_dictionaries.emplace(dictionary_name);
|
||||
return std::make_unique<DatabaseDictionariesSnapshotIterator>(std::move(filtered_dictionaries));
|
||||
}
|
||||
|
||||
bool DatabaseWithDictionaries::isDictionaryExist(const Context & /*context*/, const String & dictionary_name) const
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
return dictionaries.find(dictionary_name) != dictionaries.end();
|
||||
}
|
||||
|
||||
StoragePtr DatabaseWithDictionaries::getDictionaryStorage(const Context & context, const String & table_name) const
|
||||
{
|
||||
auto dict_name = database_name + "." + table_name;
|
||||
const auto & external_loader = context.getExternalDictionariesLoader();
|
||||
auto dict_ptr = external_loader.tryGetDictionary(dict_name);
|
||||
if (dict_ptr)
|
||||
{
|
||||
const DictionaryStructure & dictionary_structure = dict_ptr->getStructure();
|
||||
auto columns = StorageDictionary::getNamesAndTypes(dictionary_structure);
|
||||
return StorageDictionary::create(database_name, table_name, ColumnsDescription{columns}, context, true, dict_name);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
29
dbms/src/Databases/DatabaseWithDictionaries.h
Normal file
29
dbms/src/Databases/DatabaseWithDictionaries.h
Normal file
@ -0,0 +1,29 @@
|
||||
#include <Databases/DatabasesCommon.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
class DatabaseWithDictionaries : public DatabaseWithOwnTablesBase
|
||||
{
|
||||
public:
|
||||
void attachDictionary(const String & name, const Context & context, bool reload) override;
|
||||
|
||||
void detachDictionary(const String & name, const Context & context, bool reload) override;
|
||||
|
||||
StoragePtr tryGetTable(const Context & context, const String & table_name) const override;
|
||||
|
||||
DatabaseTablesIteratorPtr getTablesWithDictionaryTablesIterator(const Context & context, const FilterByNameFunction & filter_by_dictionary_name = {}) override;
|
||||
|
||||
DatabaseDictionariesIteratorPtr getDictionariesIterator(const Context & context, const FilterByNameFunction & filter_by_dictionary_name = {}) override;
|
||||
|
||||
bool isDictionaryExist(const Context & context, const String & dictionary_name) const override;
|
||||
|
||||
protected:
|
||||
DatabaseWithDictionaries(String name) : DatabaseWithOwnTablesBase(std::move(name)) {}
|
||||
|
||||
StoragePtr getDictionaryStorage(const Context & context, const String & table_name) const;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,7 +1,4 @@
|
||||
#include <Databases/DatabasesCommon.h>
|
||||
|
||||
#include <Interpreters/ExternalDictionariesLoader.h>
|
||||
#include <Interpreters/Context.h>
|
||||
#include <Interpreters/InterpreterCreateQuery.h>
|
||||
#include <Parsers/formatAST.h>
|
||||
#include <Storages/StorageDictionary.h>
|
||||
@ -24,25 +21,6 @@ namespace ErrorCodes
|
||||
extern const int DICTIONARY_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
StoragePtr getDictionaryStorage(const Context & context, const String & table_name, const String & db_name)
|
||||
{
|
||||
auto dict_name = db_name + "." + table_name;
|
||||
const auto & external_loader = context.getExternalDictionariesLoader();
|
||||
auto dict_ptr = external_loader.tryGetDictionary(dict_name);
|
||||
if (dict_ptr)
|
||||
{
|
||||
const DictionaryStructure & dictionary_structure = dict_ptr->getStructure();
|
||||
auto columns = StorageDictionary::getNamesAndTypes(dictionary_structure);
|
||||
return StorageDictionary::create(db_name, table_name, ColumnsDescription{columns}, context, true, dict_name);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool DatabaseWithOwnTablesBase::isTableExist(
|
||||
const Context & /*context*/,
|
||||
const String & table_name) const
|
||||
@ -51,57 +29,17 @@ bool DatabaseWithOwnTablesBase::isTableExist(
|
||||
return tables.find(table_name) != tables.end() || dictionaries.find(table_name) != dictionaries.end();
|
||||
}
|
||||
|
||||
bool DatabaseWithOwnTablesBase::isDictionaryExist(
|
||||
const Context & /*context*/,
|
||||
const String & dictionary_name) const
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
return dictionaries.find(dictionary_name) != dictionaries.end();
|
||||
}
|
||||
|
||||
StoragePtr DatabaseWithOwnTablesBase::tryGetTable(
|
||||
const Context & context,
|
||||
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;
|
||||
}
|
||||
|
||||
if (isDictionaryExist(context, table_name))
|
||||
/// We don't need lock database here, because database doesn't store dictionary itself
|
||||
/// just metadata
|
||||
return getDictionaryStorage(context, table_name, getDatabaseName());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
DatabaseTablesIteratorPtr DatabaseWithOwnTablesBase::getTablesWithDictionaryTablesIterator(const Context & context, const FilterByNameFunction & filter_by_name)
|
||||
{
|
||||
auto tables_it = getTablesIterator(context, filter_by_name);
|
||||
auto dictionaries_it = getDictionariesIterator(context, filter_by_name);
|
||||
|
||||
Tables result;
|
||||
while (tables_it && tables_it->isValid())
|
||||
{
|
||||
result.emplace(tables_it->name(), tables_it->table());
|
||||
tables_it->next();
|
||||
}
|
||||
|
||||
while (dictionaries_it && dictionaries_it->isValid())
|
||||
{
|
||||
auto table_name = dictionaries_it->name();
|
||||
auto table_ptr = getDictionaryStorage(context, table_name, getDatabaseName());
|
||||
if (table_ptr)
|
||||
result.emplace(table_name, table_ptr);
|
||||
dictionaries_it->next();
|
||||
}
|
||||
|
||||
return std::make_unique<DatabaseTablesSnapshotIterator>(result);
|
||||
}
|
||||
|
||||
DatabaseTablesIteratorPtr DatabaseWithOwnTablesBase::getTablesIterator(const Context & /*context*/, const FilterByNameFunction & filter_by_table_name)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
@ -116,20 +54,6 @@ DatabaseTablesIteratorPtr DatabaseWithOwnTablesBase::getTablesIterator(const Con
|
||||
return std::make_unique<DatabaseTablesSnapshotIterator>(std::move(filtered_tables));
|
||||
}
|
||||
|
||||
|
||||
DatabaseDictionariesIteratorPtr DatabaseWithOwnTablesBase::getDictionariesIterator(const Context & /*context*/, const FilterByNameFunction & filter_by_dictionary_name)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
if (!filter_by_dictionary_name)
|
||||
return std::make_unique<DatabaseDictionariesSnapshotIterator>(dictionaries);
|
||||
|
||||
Dictionaries filtered_dictionaries;
|
||||
for (const auto & dictionary_name : dictionaries)
|
||||
if (filter_by_dictionary_name(dictionary_name))
|
||||
filtered_dictionaries.emplace(dictionary_name);
|
||||
return std::make_unique<DatabaseDictionariesSnapshotIterator>(std::move(filtered_dictionaries));
|
||||
}
|
||||
|
||||
bool DatabaseWithOwnTablesBase::empty(const Context & /*context*/) const
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
@ -154,21 +78,6 @@ StoragePtr DatabaseWithOwnTablesBase::detachTable(const String & table_name)
|
||||
return res;
|
||||
}
|
||||
|
||||
void DatabaseWithOwnTablesBase::detachDictionary(const String & dictionary_name, const Context & context, bool reload)
|
||||
{
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
auto it = dictionaries.find(dictionary_name);
|
||||
if (it == dictionaries.end())
|
||||
throw Exception("Dictionary " + database_name + "." + dictionary_name + " doesn't exist.", ErrorCodes::UNKNOWN_TABLE);
|
||||
dictionaries.erase(it);
|
||||
}
|
||||
|
||||
if (reload)
|
||||
context.getExternalDictionariesLoader().reload(getDatabaseName() + "." + dictionary_name);
|
||||
|
||||
}
|
||||
|
||||
void DatabaseWithOwnTablesBase::attachTable(const String & table_name, const StoragePtr & table)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
@ -176,25 +85,6 @@ void DatabaseWithOwnTablesBase::attachTable(const String & table_name, const Sto
|
||||
throw Exception("Table " + database_name + "." + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
|
||||
void DatabaseWithOwnTablesBase::attachDictionary(const String & dictionary_name, const Context & context, bool load)
|
||||
{
|
||||
const auto & external_loader = context.getExternalDictionariesLoader();
|
||||
|
||||
String full_name = getDatabaseName() + "." + dictionary_name;
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
auto status = external_loader.getCurrentStatus(full_name);
|
||||
if (status != ExternalLoader::Status::NOT_EXIST || !dictionaries.emplace(dictionary_name).second)
|
||||
throw Exception(
|
||||
"Dictionary " + full_name + " already exists.",
|
||||
ErrorCodes::DICTIONARY_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
if (load)
|
||||
external_loader.reload(full_name, true);
|
||||
}
|
||||
|
||||
void DatabaseWithOwnTablesBase::shutdown()
|
||||
{
|
||||
/// You can not hold a lock during shutdown.
|
||||
|
@ -24,8 +24,6 @@ public:
|
||||
const Context & context,
|
||||
const String & table_name) const override;
|
||||
|
||||
bool isDictionaryExist(const Context & context, const String & dictionary_name) const override;
|
||||
|
||||
StoragePtr tryGetTable(
|
||||
const Context & context,
|
||||
const String & table_name) const override;
|
||||
@ -34,18 +32,10 @@ public:
|
||||
|
||||
void attachTable(const String & table_name, const StoragePtr & table) override;
|
||||
|
||||
void attachDictionary(const String & name, const Context & context, bool reload) override;
|
||||
|
||||
StoragePtr detachTable(const String & table_name) override;
|
||||
|
||||
void detachDictionary(const String & name, const Context & context, bool reload) override;
|
||||
|
||||
DatabaseTablesIteratorPtr getTablesIterator(const Context & context, const FilterByNameFunction & filter_by_table_name = {}) override;
|
||||
|
||||
DatabaseDictionariesIteratorPtr getDictionariesIterator(const Context & context, const FilterByNameFunction & filter_by_dictionary_name = {}) override;
|
||||
|
||||
DatabaseTablesIteratorPtr getTablesWithDictionaryTablesIterator(const Context & context, const FilterByNameFunction & filter_by_dictionary_name = {}) override;
|
||||
|
||||
void shutdown() override;
|
||||
|
||||
virtual ~DatabaseWithOwnTablesBase() override;
|
||||
|
@ -134,7 +134,10 @@ public:
|
||||
virtual DatabaseTablesIteratorPtr getTablesIterator(const Context & context, const FilterByNameFunction & filter_by_table_name = {}) = 0;
|
||||
|
||||
/// Get an iterator to pass through all the dictionaries.
|
||||
virtual DatabaseDictionariesIteratorPtr getDictionariesIterator(const Context & context, const FilterByNameFunction & filter_by_dictionary_name = {}) = 0;
|
||||
virtual DatabaseDictionariesIteratorPtr getDictionariesIterator(const Context & /*context*/, [[maybe_unused]] const FilterByNameFunction & filter_by_dictionary_name = {})
|
||||
{
|
||||
return std::make_unique<DatabaseDictionariesSnapshotIterator>();
|
||||
}
|
||||
|
||||
/// Get an iterator to pass through all the tables and dictionary tables.
|
||||
virtual DatabaseTablesIteratorPtr getTablesWithDictionaryTablesIterator(const Context & context, const FilterByNameFunction & filter_by_name = {})
|
||||
|
Loading…
Reference in New Issue
Block a user