1#include <Databases/DatabasesCommon.h>
2#include <Interpreters/InterpreterCreateQuery.h>
3#include <Parsers/ParserCreateQuery.h>
4#include <Parsers/formatAST.h>
5#include <Storages/StorageDictionary.h>
6#include <Storages/StorageFactory.h>
7#include <Common/typeid_cast.h>
8#include <TableFunctions/TableFunctionFactory.h>
9
10
11namespace DB
12{
13
14namespace ErrorCodes
15{
16 extern const int EMPTY_LIST_OF_COLUMNS_PASSED;
17 extern const int TABLE_ALREADY_EXISTS;
18 extern const int UNKNOWN_TABLE;
19 extern const int LOGICAL_ERROR;
20 extern const int DICTIONARY_ALREADY_EXISTS;
21}
22
23DatabaseWithOwnTablesBase::DatabaseWithOwnTablesBase(const String & name_, const String & logger)
24 : IDatabase(name_), log(&Logger::get(logger))
25{
26}
27
28bool DatabaseWithOwnTablesBase::isTableExist(
29 const Context & /*context*/,
30 const String & table_name) const
31{
32 std::lock_guard lock(mutex);
33 return tables.find(table_name) != tables.end() || dictionaries.find(table_name) != dictionaries.end();
34}
35
36StoragePtr DatabaseWithOwnTablesBase::tryGetTable(
37 const Context & /*context*/,
38 const String & table_name) const
39{
40 std::lock_guard lock(mutex);
41 auto it = tables.find(table_name);
42 if (it != tables.end())
43 return it->second;
44 return {};
45}
46
47DatabaseTablesIteratorPtr DatabaseWithOwnTablesBase::getTablesIterator(const Context & /*context*/, const FilterByNameFunction & filter_by_table_name)
48{
49 std::lock_guard lock(mutex);
50 if (!filter_by_table_name)
51 return std::make_unique<DatabaseTablesSnapshotIterator>(tables);
52
53 Tables filtered_tables;
54 for (const auto & [table_name, storage] : tables)
55 if (filter_by_table_name(table_name))
56 filtered_tables.emplace(table_name, storage);
57
58 return std::make_unique<DatabaseTablesSnapshotIterator>(std::move(filtered_tables));
59}
60
61bool DatabaseWithOwnTablesBase::empty(const Context & /*context*/) const
62{
63 std::lock_guard lock(mutex);
64 return tables.empty() && dictionaries.empty();
65}
66
67StoragePtr DatabaseWithOwnTablesBase::detachTable(const String & table_name)
68{
69 StoragePtr res;
70 {
71 std::lock_guard lock(mutex);
72 if (dictionaries.count(table_name))
73 throw Exception("Cannot detach dictionary " + database_name + "." + table_name + " as table, use DETACH DICTIONARY query.", ErrorCodes::UNKNOWN_TABLE);
74
75 auto it = tables.find(table_name);
76 if (it == tables.end())
77 throw Exception("Table " + backQuote(database_name) + "." + backQuote(table_name) + " doesn't exist.", ErrorCodes::UNKNOWN_TABLE);
78 res = it->second;
79 tables.erase(it);
80 }
81
82 return res;
83}
84
85void DatabaseWithOwnTablesBase::attachTable(const String & table_name, const StoragePtr & table)
86{
87 std::lock_guard lock(mutex);
88 if (!tables.emplace(table_name, table).second)
89 throw Exception("Table " + database_name + "." + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
90}
91
92void DatabaseWithOwnTablesBase::shutdown()
93{
94 /// You can not hold a lock during shutdown.
95 /// Because inside `shutdown` function tables can work with database, and mutex is not recursive.
96
97 Tables tables_snapshot;
98 {
99 std::lock_guard lock(mutex);
100 tables_snapshot = tables;
101 }
102
103 for (const auto & kv : tables_snapshot)
104 {
105 kv.second->shutdown();
106 }
107
108 std::lock_guard lock(mutex);
109 tables.clear();
110 dictionaries.clear();
111}
112
113DatabaseWithOwnTablesBase::~DatabaseWithOwnTablesBase()
114{
115 try
116 {
117 DatabaseWithOwnTablesBase::shutdown();
118 }
119 catch (...)
120 {
121 tryLogCurrentException(__PRETTY_FUNCTION__);
122 }
123}
124
125}
126