| 1 | //===----------------------------------------------------------------------===// |
| 2 | // DuckDB |
| 3 | // |
| 4 | // duckdb/catalog/catalog_set.hpp |
| 5 | // |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #pragma once |
| 10 | |
| 11 | #include "duckdb/catalog/catalog_entry.hpp" |
| 12 | #include "duckdb/catalog/default/default_generator.hpp" |
| 13 | #include "duckdb/common/common.hpp" |
| 14 | #include "duckdb/common/case_insensitive_map.hpp" |
| 15 | #include "duckdb/common/pair.hpp" |
| 16 | #include "duckdb/common/unordered_set.hpp" |
| 17 | #include "duckdb/common/mutex.hpp" |
| 18 | #include "duckdb/parser/column_definition.hpp" |
| 19 | #include "duckdb/transaction/transaction.hpp" |
| 20 | #include "duckdb/catalog/catalog_transaction.hpp" |
| 21 | #include "duckdb/catalog/similar_catalog_entry.hpp" |
| 22 | #include <functional> |
| 23 | #include <memory> |
| 24 | |
| 25 | namespace duckdb { |
| 26 | struct AlterInfo; |
| 27 | |
| 28 | class ClientContext; |
| 29 | class DependencyList; |
| 30 | struct MappingValue; |
| 31 | struct EntryIndex; |
| 32 | |
| 33 | class DuckCatalog; |
| 34 | class TableCatalogEntry; |
| 35 | class SequenceCatalogEntry; |
| 36 | |
| 37 | typedef unordered_map<CatalogSet *, unique_lock<mutex>> set_lock_map_t; |
| 38 | |
| 39 | struct EntryValue { |
| 40 | EntryValue() { |
| 41 | throw InternalException("EntryValue called without a catalog entry" ); |
| 42 | } |
| 43 | |
| 44 | explicit EntryValue(unique_ptr<CatalogEntry> entry_p) : entry(std::move(entry_p)), reference_count(0) { |
| 45 | } |
| 46 | //! enable move constructors |
| 47 | EntryValue(EntryValue &&other) noexcept { |
| 48 | Swap(other); |
| 49 | } |
| 50 | EntryValue &operator=(EntryValue &&other) noexcept { |
| 51 | Swap(other); |
| 52 | return *this; |
| 53 | } |
| 54 | void Swap(EntryValue &other) { |
| 55 | std::swap(a&: entry, b&: other.entry); |
| 56 | idx_t count = reference_count; |
| 57 | reference_count = other.reference_count.load(); |
| 58 | other.reference_count = count; |
| 59 | } |
| 60 | |
| 61 | unique_ptr<CatalogEntry> entry; |
| 62 | atomic<idx_t> reference_count; |
| 63 | }; |
| 64 | |
| 65 | //! The Catalog Set stores (key, value) map of a set of CatalogEntries |
| 66 | class CatalogSet { |
| 67 | friend class DependencyManager; |
| 68 | friend class EntryDropper; |
| 69 | friend struct EntryIndex; |
| 70 | |
| 71 | public: |
| 72 | DUCKDB_API explicit CatalogSet(Catalog &catalog, unique_ptr<DefaultGenerator> defaults = nullptr); |
| 73 | ~CatalogSet(); |
| 74 | |
| 75 | //! Create an entry in the catalog set. Returns whether or not it was |
| 76 | //! successful. |
| 77 | DUCKDB_API bool CreateEntry(CatalogTransaction transaction, const string &name, unique_ptr<CatalogEntry> value, |
| 78 | DependencyList &dependencies); |
| 79 | DUCKDB_API bool CreateEntry(ClientContext &context, const string &name, unique_ptr<CatalogEntry> value, |
| 80 | DependencyList &dependencies); |
| 81 | |
| 82 | DUCKDB_API bool AlterEntry(CatalogTransaction transaction, const string &name, AlterInfo &alter_info); |
| 83 | |
| 84 | DUCKDB_API bool DropEntry(CatalogTransaction transaction, const string &name, bool cascade, |
| 85 | bool allow_drop_internal = false); |
| 86 | DUCKDB_API bool DropEntry(ClientContext &context, const string &name, bool cascade, |
| 87 | bool allow_drop_internal = false); |
| 88 | |
| 89 | DUCKDB_API DuckCatalog &GetCatalog(); |
| 90 | |
| 91 | bool AlterOwnership(CatalogTransaction transaction, ChangeOwnershipInfo &info); |
| 92 | |
| 93 | void CleanupEntry(CatalogEntry &catalog_entry); |
| 94 | |
| 95 | //! Returns the entry with the specified name |
| 96 | DUCKDB_API optional_ptr<CatalogEntry> GetEntry(CatalogTransaction transaction, const string &name); |
| 97 | DUCKDB_API optional_ptr<CatalogEntry> GetEntry(ClientContext &context, const string &name); |
| 98 | |
| 99 | //! Gets the entry that is most similar to the given name (i.e. smallest levenshtein distance), or empty string if |
| 100 | //! none is found. The returned pair consists of the entry name and the distance (smaller means closer). |
| 101 | SimilarCatalogEntry SimilarEntry(CatalogTransaction transaction, const string &name); |
| 102 | |
| 103 | //! Rollback <entry> to be the currently valid entry for a certain catalog |
| 104 | //! entry |
| 105 | void Undo(CatalogEntry &entry); |
| 106 | |
| 107 | //! Scan the catalog set, invoking the callback method for every committed entry |
| 108 | DUCKDB_API void Scan(const std::function<void(CatalogEntry &)> &callback); |
| 109 | //! Scan the catalog set, invoking the callback method for every entry |
| 110 | DUCKDB_API void Scan(CatalogTransaction transaction, const std::function<void(CatalogEntry &)> &callback); |
| 111 | DUCKDB_API void Scan(ClientContext &context, const std::function<void(CatalogEntry &)> &callback); |
| 112 | |
| 113 | template <class T> |
| 114 | vector<reference<T>> GetEntries(CatalogTransaction transaction) { |
| 115 | vector<reference<T>> result; |
| 116 | Scan(transaction, [&](CatalogEntry &entry) { result.push_back(entry.Cast<T>()); }); |
| 117 | return result; |
| 118 | } |
| 119 | |
| 120 | DUCKDB_API bool HasConflict(CatalogTransaction transaction, transaction_t timestamp); |
| 121 | DUCKDB_API bool UseTimestamp(CatalogTransaction transaction, transaction_t timestamp); |
| 122 | |
| 123 | void UpdateTimestamp(CatalogEntry &entry, transaction_t timestamp); |
| 124 | |
| 125 | void Verify(Catalog &catalog); |
| 126 | |
| 127 | private: |
| 128 | //! Adjusts table dependencies on the event of an UNDO |
| 129 | void AdjustTableDependencies(CatalogEntry &entry); |
| 130 | //! Adjust one dependency |
| 131 | void AdjustDependency(CatalogEntry &entry, TableCatalogEntry &table, ColumnDefinition &column, bool remove); |
| 132 | //! Adjust User dependency |
| 133 | void AdjustUserDependency(CatalogEntry &entry, ColumnDefinition &column, bool remove); |
| 134 | //! Given a root entry, gets the entry valid for this transaction |
| 135 | CatalogEntry &GetEntryForTransaction(CatalogTransaction transaction, CatalogEntry ¤t); |
| 136 | CatalogEntry &GetCommittedEntry(CatalogEntry ¤t); |
| 137 | optional_ptr<CatalogEntry> GetEntryInternal(CatalogTransaction transaction, const string &name, |
| 138 | EntryIndex *entry_index); |
| 139 | optional_ptr<CatalogEntry> GetEntryInternal(CatalogTransaction transaction, EntryIndex &entry_index); |
| 140 | //! Drops an entry from the catalog set; must hold the catalog_lock to safely call this |
| 141 | void DropEntryInternal(CatalogTransaction transaction, EntryIndex entry_index, CatalogEntry &entry, bool cascade); |
| 142 | optional_ptr<CatalogEntry> CreateEntryInternal(CatalogTransaction transaction, unique_ptr<CatalogEntry> entry); |
| 143 | optional_ptr<MappingValue> GetMapping(CatalogTransaction transaction, const string &name, bool get_latest = false); |
| 144 | void PutMapping(CatalogTransaction transaction, const string &name, EntryIndex entry_index); |
| 145 | void DeleteMapping(CatalogTransaction transaction, const string &name); |
| 146 | void DropEntryDependencies(CatalogTransaction transaction, EntryIndex &entry_index, CatalogEntry &entry, |
| 147 | bool cascade); |
| 148 | |
| 149 | //! Create all default entries |
| 150 | void CreateDefaultEntries(CatalogTransaction transaction, unique_lock<mutex> &lock); |
| 151 | //! Attempt to create a default entry with the specified name. Returns the entry if successful, nullptr otherwise. |
| 152 | optional_ptr<CatalogEntry> CreateDefaultEntry(CatalogTransaction transaction, const string &name, |
| 153 | unique_lock<mutex> &lock); |
| 154 | |
| 155 | EntryIndex PutEntry(idx_t entry_index, unique_ptr<CatalogEntry> entry); |
| 156 | void PutEntry(EntryIndex index, unique_ptr<CatalogEntry> entry); |
| 157 | |
| 158 | private: |
| 159 | DuckCatalog &catalog; |
| 160 | //! The catalog lock is used to make changes to the data |
| 161 | mutex catalog_lock; |
| 162 | //! The set of catalog entries |
| 163 | unordered_map<idx_t, EntryValue> entries; |
| 164 | //! Mapping of string to catalog entry |
| 165 | case_insensitive_map_t<unique_ptr<MappingValue>> mapping; |
| 166 | //! The current catalog entry index |
| 167 | idx_t current_entry = 0; |
| 168 | //! The generator used to generate default internal entries |
| 169 | unique_ptr<DefaultGenerator> defaults; |
| 170 | }; |
| 171 | } // namespace duckdb |
| 172 | |