-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Expand file tree
/
Copy pathIDatabase.h
More file actions
480 lines (371 loc) · 18.4 KB
/
IDatabase.h
File metadata and controls
480 lines (371 loc) · 18.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
#pragma once
#include <Core/UUID.h>
#include <Databases/LoadingStrictnessLevel.h>
#include <Disks/IDisk.h>
#include <Interpreters/Context_fwd.h>
#include <Interpreters/DDLGuard.h>
#include <Interpreters/QueryFlags.h>
#include <Parsers/IAST_fwd.h>
#include <QueryPipeline/BlockIO.h>
#include <Storages/IStorage_fwd.h>
#include <base/types.h>
#include <Common/AsyncLoader_fwd.h>
#include <ctime>
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <vector>
namespace DB
{
struct Settings;
struct ConstraintsDescription;
struct IndicesDescription;
struct StorageInMemoryMetadata;
struct StorageID;
class ASTCreateQuery;
struct AlterCommand;
class AlterCommands;
class SettingsChanges;
using DictionariesWithID = std::vector<std::pair<String, UUID>>;
struct ParsedTablesMetadata;
struct QualifiedTableName;
class IRestoreCoordination;
/// This structure is returned when getLightweightTablesIterator is called
/// It contains basic details of the table, currently only the table name
struct LightWeightTableDetails
{
String name;
};
class IDatabaseTablesIterator
{
public:
virtual void next() = 0;
virtual bool isValid() const = 0;
virtual const String & name() const = 0;
/// This method can return nullptr if table metadata could not be loaded
/// (e.g. DataLake database where individual table metadata fetch fails).
virtual const StoragePtr & table() const = 0;
explicit IDatabaseTablesIterator(const String & database_name_) : database_name(database_name_) { }
explicit IDatabaseTablesIterator(String && database_name_) : database_name(std::move(database_name_)) { }
virtual ~IDatabaseTablesIterator() = default;
virtual UUID uuid() const { return UUIDHelpers::Nil; }
const String & databaseName() const { assert(!database_name.empty()); return database_name; }
protected:
String database_name;
};
/// Copies list of tables and iterates through such snapshot.
class DatabaseTablesSnapshotIterator : public IDatabaseTablesIterator
{
private:
Tables tables;
Tables::iterator it;
protected:
DatabaseTablesSnapshotIterator(DatabaseTablesSnapshotIterator && other) noexcept
: IDatabaseTablesIterator(std::move(other.database_name))
{
size_t idx = std::distance(other.tables.begin(), other.it);
std::swap(tables, other.tables);
other.it = other.tables.end();
it = tables.begin();
std::advance(it, idx);
}
public:
DatabaseTablesSnapshotIterator(const Tables & tables_, const String & database_name_)
: IDatabaseTablesIterator(database_name_), tables(tables_), it(tables.begin())
{
}
DatabaseTablesSnapshotIterator(Tables && tables_, String && database_name_)
: IDatabaseTablesIterator(std::move(database_name_)), tables(std::move(tables_)), it(tables.begin())
{
}
void next() override { ++it; }
bool isValid() const override { return it != tables.end(); }
const String & name() const override { return it->first; }
const StoragePtr & table() const override { return it->second; }
};
using DatabaseTablesIteratorPtr = std::unique_ptr<IDatabaseTablesIterator>;
struct SnapshotDetachedTable final
{
String database;
String table;
UUID uuid = UUIDHelpers::Nil;
String metadata_path;
bool is_permanently{};
};
class DatabaseDetachedTablesSnapshotIterator
{
private:
SnapshotDetachedTables snapshot;
SnapshotDetachedTables::iterator it;
protected:
DatabaseDetachedTablesSnapshotIterator(DatabaseDetachedTablesSnapshotIterator && other) noexcept
{
size_t idx = std::distance(other.snapshot.begin(), other.it);
std::swap(snapshot, other.snapshot);
other.it = other.snapshot.end();
it = snapshot.begin();
std::advance(it, idx);
}
public:
explicit DatabaseDetachedTablesSnapshotIterator(const SnapshotDetachedTables & tables_) : snapshot(tables_), it(snapshot.begin())
{
}
explicit DatabaseDetachedTablesSnapshotIterator(SnapshotDetachedTables && tables_) : snapshot(std::move(tables_)), it(snapshot.begin())
{
}
void next() { ++it; }
bool isValid() const { return it != snapshot.end(); }
String database() const { return it->second.database; }
String table() const { return it->second.table; }
UUID uuid() const { return it->second.uuid; }
String metadataPath() const { return it->second.metadata_path; }
bool isPermanently() const { return it->second.is_permanently; }
};
using DatabaseDetachedTablesSnapshotIteratorPtr = std::unique_ptr<DatabaseDetachedTablesSnapshotIterator>;
/** Database engine.
* It is responsible for:
* - initialization of set of known tables and dictionaries;
* - checking existence of a table and getting a table object;
* - retrieving a list of all tables;
* - creating and dropping tables;
* - renaming tables and moving between databases with same engine.
*/
class IDatabase : public std::enable_shared_from_this<IDatabase>
{
public:
IDatabase() = delete;
explicit IDatabase(String database_name_);
/// Get name of database engine.
virtual String getEngineName() const = 0;
/// External database (i.e. PostgreSQL/Datalake/...) does not support any of ClickHouse internal tables:
/// - *MergeTree
/// - Distributed
/// - RocksDB
/// - ...
virtual bool isExternal() const { return true; }
virtual bool isDatalakeCatalog() const { return false; }
/// Load a set of existing tables.
/// You can call only once, right after the object is created.
virtual void loadStoredObjects( /// NOLINT
ContextMutablePtr /*context*/,
LoadingStrictnessLevel /*mode*/)
{
}
virtual bool supportsLoadingInTopologicalOrder() const { return false; }
virtual void beforeLoadingMetadata(
ContextMutablePtr /*context*/, LoadingStrictnessLevel /*mode*/)
{
}
virtual void loadTablesMetadata(ContextPtr /*local_context*/, ParsedTablesMetadata & /*metadata*/, bool /*is_startup*/);
virtual void loadTableFromMetadata(
ContextMutablePtr /*local_context*/,
const String & /*file_path*/,
const QualifiedTableName & /*name*/,
const ASTPtr & /*ast*/,
LoadingStrictnessLevel /*mode*/);
/// Create a task to load table `name` after specified dependencies `startup_after` using `async_loader`.
/// `load_after` must contain the tasks returned by `loadTableFromMetadataAsync()` for dependent tables (see TablesLoader).
/// The returned task is also stored inside the database for cancellation on destruction.
virtual LoadTaskPtr loadTableFromMetadataAsync(
AsyncLoader & /*async_loader*/,
LoadJobSet /*load_after*/,
ContextMutablePtr /*local_context*/,
const String & /*file_path*/,
const QualifiedTableName & /*name*/,
const ASTPtr & /*ast*/,
LoadingStrictnessLevel /*mode*/);
/// Create a task to startup table `name` after specified dependencies `startup_after` using `async_loader`.
/// The returned task is also stored inside the database for cancellation on destruction.
[[nodiscard]] virtual LoadTaskPtr startupTableAsync(
AsyncLoader & /*async_loader*/,
LoadJobSet /*startup_after*/,
const QualifiedTableName & /*name*/,
LoadingStrictnessLevel /*mode*/);
/// Create a task to startup database after specified dependencies `startup_after` using `async_loader`.
/// `startup_after` must contain all the tasks returned by `startupTableAsync()` for every table (see TablesLoader).
/// The returned task is also stored inside the database for cancellation on destruction.
[[nodiscard]] virtual LoadTaskPtr startupDatabaseAsync(
AsyncLoader & /*async_loader*/,
LoadJobSet /*startup_after*/,
LoadingStrictnessLevel /*mode*/);
/// Waits for specific table to be started up, i.e. task returned by `startupTableAsync()` is done
virtual void waitTableStarted(const String & /*name*/) const {}
/// Waits for the database to be started up, i.e. task returned by `startupDatabaseAsync()` is done
virtual void waitDatabaseStarted() const {}
/// Cancels all load and startup tasks and waits for currently running tasks to finish.
/// Should be used during shutdown to (1) prevent race with startup, (2) stop any not yet started task and (3) avoid exceptions if startup failed
virtual void stopLoading() {}
/// Check the existence of the table in memory (attached).
virtual bool isTableExist(const String & name, ContextPtr context) const = 0;
/// Check the existence of the table in any state (in active / detached / detached permanently state).
/// Throws exception when table exists.
virtual void checkMetadataFilenameAvailability(const String & /*table_name*/) const {}
/// Check if the table name exceeds the max allowed length
virtual void checkTableNameLength(const String & /*table_name*/) const {}
/// Get the table for work. Return nullptr if there is no table.
virtual StoragePtr tryGetTable(const String & name, ContextPtr context) const = 0;
virtual StoragePtr getTable(const String & name, ContextPtr context) const;
virtual UUID tryGetTableUUID(const String & /*table_name*/) const { return UUIDHelpers::Nil; }
using FilterByNameFunction = std::function<bool(const String &)>;
/// Get an iterator that allows you to pass through all the tables.
/// 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.
/// Wait for all tables to be loaded and started up. If `skip_not_loaded` is true, then not yet loaded or not yet started up (at the moment of iterator creation) tables are excluded.
virtual DatabaseTablesIteratorPtr getTablesIterator(ContextPtr context, const FilterByNameFunction & filter_by_table_name = {}, bool skip_not_loaded = false) const = 0; /// NOLINT
/// Same as above, but may return non-fully initialized StoragePtr objects which are not suitable for reading.
/// Useful for queries like "SHOW TABLES"
virtual std::vector<LightWeightTableDetails> getLightweightTablesIterator(ContextPtr context, const FilterByNameFunction & filter_by_table_name = {}, bool skip_not_loaded = false) const /// NOLINT
{
std::vector<LightWeightTableDetails> result;
for (auto iterator = getTablesIterator(context, filter_by_table_name, skip_not_loaded); iterator->isValid(); iterator->next())
{
if (const auto & table = iterator->table())
result.emplace_back(iterator->name());
}
return result;
}
virtual DatabaseDetachedTablesSnapshotIteratorPtr getDetachedTablesIterator(
ContextPtr /*context*/, const FilterByNameFunction & /*filter_by_table_name = {}*/, bool /*skip_not_loaded = false*/) const;
/// Returns list of table names.
virtual Strings getAllTableNames(ContextPtr context) const
{
// NOTE: This default implementation wait for all tables to be loaded and started up. It should be reimplemented for databases that support async loading.
Strings result;
for (auto table_it = getTablesIterator(context); table_it->isValid(); table_it->next())
result.emplace_back(table_it->name());
return result;
}
/// Is the database empty.
virtual bool empty() const = 0;
virtual bool isReadOnly() const { return false; }
/// Add the table to the database. Record its presence in the metadata.
virtual void createTable(
ContextPtr /*context*/,
const String & /*name*/,
const StoragePtr & /*table*/,
const ASTPtr & /*query*/);
/// Delete the table from the database, drop table and delete the metadata.
virtual void dropTable( /// NOLINT
ContextPtr /*context*/,
const String & /*name*/,
[[maybe_unused]] bool sync = false);
/// Add a table to the database, but do not add it to the metadata. The database may not support this method.
///
/// Note: ATTACH TABLE statement actually uses createTable method.
virtual void attachTable(ContextPtr /* context */, const String & /*name*/, const StoragePtr & /*table*/, [[maybe_unused]] const String & relative_table_path);
/// Forget about the table without deleting it, and return it. The database may not support this method.
virtual StoragePtr detachTable(ContextPtr /* context */, const String & /*name*/);
/// Forget about the table without deleting it's data, but rename metadata file to prevent reloading it
/// with next restart. The database may not support this method.
virtual void detachTablePermanently(ContextPtr /*context*/, const String & /*name*/);
/// Returns list of table names that were permanently detached.
/// This list may not be updated in runtime and may be filled only on server startup
virtual Strings getNamesOfPermanentlyDetachedTables() const;
/// Rename the table and possibly move the table to another database.
virtual void renameTable(
ContextPtr /*context*/,
const String & /*name*/,
IDatabase & /*to_database*/,
const String & /*to_name*/,
bool /*exchange*/,
bool /*dictionary*/);
using ASTModifier = std::function<void(IAST &)>;
/// Change the table structure in metadata.
/// You must call under the alter_lock of the corresponding table . If engine_modifier is empty, then engine does not change.
virtual void alterTable(
ContextPtr /*context*/,
const StorageID & /*table_id*/,
const StorageInMemoryMetadata & /*metadata*/,
bool validate_new_create_query);
/// Special method for ReplicatedMergeTree and DatabaseReplicated
virtual bool canExecuteReplicatedMetadataAlter() const { return true; }
/// Returns time of table's metadata change, 0 if there is no corresponding metadata file.
virtual time_t getObjectMetadataModificationTime(const String & /*name*/) const
{
return static_cast<time_t>(0);
}
/// Get the CREATE TABLE query for the table.
/// It can also provide information for detached tables for which there is metadata.
///
/// Does not throw if the table does not exist, but can throw on other errors.
ASTPtr tryGetCreateTableQuery(const String & name, ContextPtr context) const
{
return getCreateTableQueryImpl(name, context, /*throw_on_error=*/ false);
}
ASTPtr getCreateTableQuery(const String & name, ContextPtr context) const
{
return getCreateTableQueryImpl(name, context, /*throw_on_error=*/ true);
}
/// Get the CREATE DATABASE query for current database.
ASTPtr getCreateDatabaseQuery() const
{
std::lock_guard lock{mutex};
return getCreateDatabaseQueryImpl();
}
String getDatabaseComment() const
{
std::lock_guard lock{mutex};
return comment;
}
void setDatabaseComment(String new_comment)
{
std::lock_guard lock{mutex};
comment = std::move(new_comment);
}
/// Get name of database.
String getDatabaseName() const
{
std::lock_guard lock{mutex};
return database_name;
}
virtual void checkDatabase() const
{
//No-op
}
// Alter comment of database.
virtual void alterDatabaseComment(const AlterCommand &, ContextPtr);
/// Get UUID of database.
virtual UUID getUUID() const { return UUIDHelpers::Nil; }
virtual void renameDatabase(ContextPtr, const String & /*new_name*/);
/// Returns path for persistent data storage if the database supports it, empty string otherwise
virtual String getDataPath() const { return {}; }
/// Returns path for persistent data storage for table if the database supports it, empty string otherwise. Table must exist
virtual String getTableDataPath(const String & /*table_name*/) const { return {}; }
/// Returns path for persistent data storage for CREATE/ATTACH query if the database supports it, empty string otherwise
virtual String getTableDataPath(const ASTCreateQuery & /*query*/) const { return {}; }
/// Returns metadata path if the database supports it, empty string otherwise
virtual String getMetadataPath() const { return {}; }
/// Returns metadata path of a concrete table if the database supports it, empty string otherwise
virtual String getObjectMetadataPath(const String & /*table_name*/) const { return {}; }
/// All tables and dictionaries should be detached before detaching the database.
virtual bool shouldBeEmptyOnDetach() const { return true; }
virtual void assertCanBeDetached(bool /*cleanup*/) {}
virtual void waitDetachedTableNotInUse(const UUID & /*uuid*/) { }
virtual void checkDetachedTableNotInUse(const UUID & /*uuid*/) { }
/// Ask all tables to complete the background threads they are using and delete all table objects.
virtual void shutdown() = 0;
/// Delete data and metadata stored inside the database, if exists.
virtual void drop(ContextPtr /*context*/) {}
virtual void applySettingsChanges(const SettingsChanges &, ContextPtr);
virtual bool hasReplicationThread() const { return false; }
virtual void stopReplication();
virtual bool shouldReplicateQuery(const ContextPtr & /*query_context*/, const ASTPtr & /*query_ptr*/) const { return false; }
virtual BlockIO tryEnqueueReplicatedDDL(const ASTPtr & /*query*/, ContextPtr /*query_context*/, [[maybe_unused]] QueryFlags flags, DDLGuardPtr && /*database_guard*/);
/// Returns CREATE TABLE queries and corresponding tables prepared for writing to a backup.
virtual std::vector<std::pair<ASTPtr, StoragePtr>> getTablesForBackup(const FilterByNameFunction & filter, const ContextPtr & context) const;
/// Creates a table restored from backup.
virtual void createTableRestoredFromBackup(const ASTPtr & create_table_query, ContextMutablePtr context, std::shared_ptr<IRestoreCoordination> restore_coordination, UInt64 timeout_ms);
/// Get the disk storing metedata files of the tables
virtual DiskPtr getDisk() const;
virtual ~IDatabase();
protected:
virtual ASTPtr getCreateDatabaseQueryImpl() const = 0;
virtual ASTPtr getCreateTableQueryImpl(const String & /*name*/, ContextPtr /*context*/, bool throw_on_error) const;
mutable std::mutex mutex;
String database_name TSA_GUARDED_BY(mutex);
String comment TSA_GUARDED_BY(mutex);
};
using DatabasePtr = std::shared_ptr<IDatabase>;
using ConstDatabasePtr = std::shared_ptr<const IDatabase>;
using Databases = std::map<String, DatabasePtr, std::less<>>;
}