1#pragma once
2
3#include <Core/Types.h>
4#include <Parsers/IAST_fwd.h>
5#include <Storages/IStorage_fwd.h>
6#include <Storages/StorageInMemoryMetadata.h>
7#include <Dictionaries/IDictionary.h>
8#include <Common/Exception.h>
9
10#include <ctime>
11#include <functional>
12#include <memory>
13
14
15namespace DB
16{
17
18class Context;
19struct Settings;
20struct ConstraintsDescription;
21class ColumnsDescription;
22struct IndicesDescription;
23struct TableStructureWriteLockHolder;
24class ASTCreateQuery;
25using Dictionaries = std::set<String>;
26
27namespace ErrorCodes
28{
29 extern const int NOT_IMPLEMENTED;
30 extern const int CANNOT_GET_CREATE_TABLE_QUERY;
31 extern const int CANNOT_GET_CREATE_TABLE_QUERY;
32 extern const int CANNOT_GET_CREATE_DICTIONARY_QUERY;
33}
34
35class IDatabaseTablesIterator
36{
37public:
38 virtual void next() = 0;
39 virtual bool isValid() const = 0;
40
41 virtual const String & name() const = 0;
42 virtual const StoragePtr & table() const = 0;
43
44 virtual ~IDatabaseTablesIterator() = default;
45};
46
47/// Copies list of tables and iterates through such snapshot.
48class DatabaseTablesSnapshotIterator : public IDatabaseTablesIterator
49{
50private:
51 Tables tables;
52 Tables::iterator it;
53
54public:
55 DatabaseTablesSnapshotIterator(Tables & tables_) : tables(tables_), it(tables.begin()) {}
56
57 DatabaseTablesSnapshotIterator(Tables && tables_) : tables(tables_), it(tables.begin()) {}
58
59 void next() { ++it; }
60
61 bool isValid() const { return it != tables.end(); }
62
63 const String & name() const { return it->first; }
64
65 const StoragePtr & table() const { return it->second; }
66};
67
68/// Copies list of dictionaries and iterates through such snapshot.
69class DatabaseDictionariesSnapshotIterator
70{
71private:
72 Dictionaries dictionaries;
73 Dictionaries::iterator it;
74
75public:
76 DatabaseDictionariesSnapshotIterator() = default;
77 DatabaseDictionariesSnapshotIterator(Dictionaries & dictionaries_) : dictionaries(dictionaries_), it(dictionaries.begin()) {}
78
79 DatabaseDictionariesSnapshotIterator(Dictionaries && dictionaries_) : dictionaries(dictionaries_), it(dictionaries.begin()) {}
80
81 void next() { ++it; }
82
83 bool isValid() const { return !dictionaries.empty() && it != dictionaries.end(); }
84
85 const String & name() const { return *it; }
86};
87
88using DatabaseTablesIteratorPtr = std::unique_ptr<IDatabaseTablesIterator>;
89using DatabaseDictionariesIteratorPtr = std::unique_ptr<DatabaseDictionariesSnapshotIterator>;
90
91
92/** Database engine.
93 * It is responsible for:
94 * - initialization of set of known tables and dictionaries;
95 * - checking existence of a table and getting a table object;
96 * - retrieving a list of all tables;
97 * - creating and dropping tables;
98 * - renaming tables and moving between databases with same engine.
99 */
100
101class IDatabase : public std::enable_shared_from_this<IDatabase>
102{
103public:
104 IDatabase() = delete;
105 IDatabase(String database_name_) : database_name(std::move(database_name_)) {}
106
107 /// Get name of database engine.
108 virtual String getEngineName() const = 0;
109
110 /// Load a set of existing tables.
111 /// You can call only once, right after the object is created.
112 virtual void loadStoredObjects(Context & /*context*/, bool /*has_force_restore_data_flag*/) {}
113
114 /// Check the existence of the table.
115 virtual bool isTableExist(
116 const Context & context,
117 const String & name) const = 0;
118
119 /// Check the existence of the dictionary
120 virtual bool isDictionaryExist(
121 const Context & /*context*/,
122 const String & /*name*/) const
123 {
124 return false;
125 }
126
127 /// Get the table for work. Return nullptr if there is no table.
128 virtual StoragePtr tryGetTable(
129 const Context & context,
130 const String & name) const = 0;
131
132 using FilterByNameFunction = std::function<bool(const String &)>;
133
134 /// Get an iterator that allows you to pass through all the tables.
135 /// It is possible to have "hidden" tables that are not visible when passing through, but are visible if you get them by name using the functions above.
136 virtual DatabaseTablesIteratorPtr getTablesIterator(const Context & context, const FilterByNameFunction & filter_by_table_name = {}) = 0;
137
138 /// Get an iterator to pass through all the dictionaries.
139 virtual DatabaseDictionariesIteratorPtr getDictionariesIterator(const Context & /*context*/, [[maybe_unused]] const FilterByNameFunction & filter_by_dictionary_name = {})
140 {
141 return std::make_unique<DatabaseDictionariesSnapshotIterator>();
142 }
143
144 /// Get an iterator to pass through all the tables and dictionary tables.
145 virtual DatabaseTablesIteratorPtr getTablesWithDictionaryTablesIterator(const Context & context, const FilterByNameFunction & filter_by_name = {})
146 {
147 return getTablesIterator(context, filter_by_name);
148 }
149
150 /// Is the database empty.
151 virtual bool empty(const Context & context) const = 0;
152
153 /// Add the table to the database. Record its presence in the metadata.
154 virtual void createTable(
155 const Context & /*context*/,
156 const String & /*name*/,
157 const StoragePtr & /*table*/,
158 const ASTPtr & /*query*/)
159 {
160 throw Exception("There is no CREATE TABLE query for Database" + getEngineName(), ErrorCodes::NOT_IMPLEMENTED);
161 }
162
163 /// Add the dictionary to the database. Record its presence in the metadata.
164 virtual void createDictionary(
165 const Context & /*context*/,
166 const String & /*dictionary_name*/,
167 const ASTPtr & /*query*/)
168 {
169 throw Exception("There is no CREATE DICTIONARY query for Database" + getEngineName(), ErrorCodes::NOT_IMPLEMENTED);
170 }
171
172 /// Delete the table from the database. Delete the metadata.
173 virtual void removeTable(
174 const Context & /*context*/,
175 const String & /*name*/)
176 {
177 throw Exception("There is no DROP TABLE query for Database" + getEngineName(), ErrorCodes::NOT_IMPLEMENTED);
178 }
179
180 /// Delete the dictionary from the database. Delete the metadata.
181 virtual void removeDictionary(
182 const Context & /*context*/,
183 const String & /*dictionary_name*/)
184 {
185 throw Exception("There is no DROP DICTIONARY query for Database" + getEngineName(), ErrorCodes::NOT_IMPLEMENTED);
186 }
187
188 /// Add a table to the database, but do not add it to the metadata. The database may not support this method.
189 virtual void attachTable(const String & /*name*/, const StoragePtr & /*table*/)
190 {
191 throw Exception("There is no ATTACH TABLE query for Database" + getEngineName(), ErrorCodes::NOT_IMPLEMENTED);
192 }
193
194 /// Add dictionary to the database, but do not add it to the metadata. The database may not support this method.
195 /// If dictionaries_lazy_load is false it also starts loading the dictionary asynchronously.
196 virtual void attachDictionary(const String & /*name*/, const Context & /*context*/)
197 {
198 throw Exception("There is no ATTACH DICTIONARY query for Database" + getEngineName(), ErrorCodes::NOT_IMPLEMENTED);
199 }
200
201 /// Forget about the table without deleting it, and return it. The database may not support this method.
202 virtual StoragePtr detachTable(const String & /*name*/)
203 {
204 throw Exception("There is no DETACH TABLE query for Database" + getEngineName(), ErrorCodes::NOT_IMPLEMENTED);
205 }
206
207 /// Forget about the dictionary without deleting it. The database may not support this method.
208 virtual void detachDictionary(const String & /*name*/, const Context & /*context*/)
209 {
210 throw Exception("There is no DETACH DICTIONARY query for Database" + getEngineName(), ErrorCodes::NOT_IMPLEMENTED);
211 }
212
213 /// Rename the table and possibly move the table to another database.
214 virtual void renameTable(
215 const Context & /*context*/,
216 const String & /*name*/,
217 IDatabase & /*to_database*/,
218 const String & /*to_name*/,
219 TableStructureWriteLockHolder &)
220 {
221 throw Exception(getEngineName() + ": renameTable() is not supported", ErrorCodes::NOT_IMPLEMENTED);
222 }
223
224 using ASTModifier = std::function<void(IAST &)>;
225
226 /// Change the table structure in metadata.
227 /// You must call under the TableStructureLock of the corresponding table . If engine_modifier is empty, then engine does not change.
228 virtual void alterTable(
229 const Context & /*context*/,
230 const String & /*name*/,
231 const StorageInMemoryMetadata & /*metadata*/)
232 {
233 throw Exception(getEngineName() + ": alterTable() is not supported", ErrorCodes::NOT_IMPLEMENTED);
234 }
235
236 /// Returns time of table's metadata change, 0 if there is no corresponding metadata file.
237 virtual time_t getObjectMetadataModificationTime(const String & /*name*/) const
238 {
239 return static_cast<time_t>(0);
240 }
241
242 /// Get the CREATE TABLE query for the table. It can also provide information for detached tables for which there is metadata.
243 ASTPtr tryGetCreateTableQuery(const Context & context, const String & name) const noexcept
244 {
245 return getCreateTableQueryImpl(context, name, false);
246 }
247
248 ASTPtr getCreateTableQuery(const Context & context, const String & name) const
249 {
250 return getCreateTableQueryImpl(context, name, true);
251 }
252
253 /// Get the CREATE DICTIONARY query for the dictionary. Returns nullptr if dictionary doesn't exists.
254 ASTPtr tryGetCreateDictionaryQuery(const Context & context, const String & name) const noexcept
255 {
256 return getCreateDictionaryQueryImpl(context, name, false);
257 }
258
259 ASTPtr getCreateDictionaryQuery(const Context & context, const String & name) const
260 {
261 return getCreateDictionaryQueryImpl(context, name, true);
262 }
263
264 /// Get the CREATE DATABASE query for current database.
265 virtual ASTPtr getCreateDatabaseQuery() const = 0;
266
267 /// Get name of database.
268 String getDatabaseName() const { return database_name; }
269 /// Returns path for persistent data storage if the database supports it, empty string otherwise
270 virtual String getDataPath() const { return {}; }
271 /// Returns path for persistent data storage for table if the database supports it, empty string otherwise. Table must exist
272 virtual String getTableDataPath(const String & /*table_name*/) const { return {}; }
273 /// Returns path for persistent data storage for CREATE/ATTACH query if the database supports it, empty string otherwise
274 virtual String getTableDataPath(const ASTCreateQuery & /*query*/) const { return {}; }
275 /// Returns metadata path if the database supports it, empty string otherwise
276 virtual String getMetadataPath() const { return {}; }
277 /// Returns metadata path of a concrete table if the database supports it, empty string otherwise
278 virtual String getObjectMetadataPath(const String & /*table_name*/) const { return {}; }
279
280 /// Ask all tables to complete the background threads they are using and delete all table objects.
281 virtual void shutdown() = 0;
282
283 /// Delete data and metadata stored inside the database, if exists.
284 virtual void drop(const Context & /*context*/) {}
285
286 virtual ~IDatabase() {}
287
288protected:
289 virtual ASTPtr getCreateTableQueryImpl(const Context & /*context*/, const String & /*name*/, bool throw_on_error) const
290 {
291 if (throw_on_error)
292 throw Exception("There is no SHOW CREATE TABLE query for Database" + getEngineName(), ErrorCodes::CANNOT_GET_CREATE_TABLE_QUERY);
293 return nullptr;
294 }
295
296 virtual ASTPtr getCreateDictionaryQueryImpl(const Context & /*context*/, const String & /*name*/, bool throw_on_error) const
297 {
298 if (throw_on_error)
299 throw Exception("There is no SHOW CREATE DICTIONARY query for Database" + getEngineName(), ErrorCodes::CANNOT_GET_CREATE_DICTIONARY_QUERY);
300 return nullptr;
301 }
302
303 String database_name;
304};
305
306using DatabasePtr = std::shared_ptr<IDatabase>;
307using Databases = std::map<String, DatabasePtr>;
308
309}
310