1 | //===----------------------------------------------------------------------===// |
2 | // DuckDB |
3 | // |
4 | // duckdb/catalog/catalog.hpp |
5 | // |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #pragma once |
10 | |
11 | #include "duckdb/catalog/catalog_entry.hpp" |
12 | #include "duckdb/common/mutex.hpp" |
13 | #include "duckdb/parser/query_error_context.hpp" |
14 | #include "duckdb/catalog/catalog_transaction.hpp" |
15 | #include "duckdb/common/reference_map.hpp" |
16 | #include "duckdb/common/atomic.hpp" |
17 | #include "duckdb/common/optional_ptr.hpp" |
18 | #include "duckdb/common/enums/on_entry_not_found.hpp" |
19 | #include <functional> |
20 | |
21 | namespace duckdb { |
22 | struct CreateSchemaInfo; |
23 | struct DropInfo; |
24 | struct BoundCreateTableInfo; |
25 | struct AlterTableInfo; |
26 | struct CreateTableFunctionInfo; |
27 | struct CreateCopyFunctionInfo; |
28 | struct CreatePragmaFunctionInfo; |
29 | struct CreateFunctionInfo; |
30 | struct CreateViewInfo; |
31 | struct CreateSequenceInfo; |
32 | struct CreateCollationInfo; |
33 | struct CreateIndexInfo; |
34 | struct CreateTypeInfo; |
35 | struct CreateTableInfo; |
36 | struct DatabaseSize; |
37 | |
38 | class AttachedDatabase; |
39 | class ClientContext; |
40 | class Transaction; |
41 | |
42 | class AggregateFunctionCatalogEntry; |
43 | class CollateCatalogEntry; |
44 | class SchemaCatalogEntry; |
45 | class TableCatalogEntry; |
46 | class ViewCatalogEntry; |
47 | class SequenceCatalogEntry; |
48 | class TableFunctionCatalogEntry; |
49 | class CopyFunctionCatalogEntry; |
50 | class PragmaFunctionCatalogEntry; |
51 | class CatalogSet; |
52 | class DatabaseInstance; |
53 | class DependencyManager; |
54 | |
55 | struct CatalogLookup; |
56 | struct CatalogEntryLookup; |
57 | struct SimilarCatalogEntry; |
58 | |
59 | class Binder; |
60 | class LogicalOperator; |
61 | class PhysicalOperator; |
62 | class LogicalCreateIndex; |
63 | class LogicalCreateTable; |
64 | class LogicalInsert; |
65 | class LogicalDelete; |
66 | class LogicalUpdate; |
67 | class CreateStatement; |
68 | |
69 | //! The Catalog object represents the catalog of the database. |
70 | class Catalog { |
71 | public: |
72 | explicit Catalog(AttachedDatabase &db); |
73 | virtual ~Catalog(); |
74 | |
75 | public: |
76 | //! Get the SystemCatalog from the ClientContext |
77 | DUCKDB_API static Catalog &GetSystemCatalog(ClientContext &context); |
78 | //! Get the SystemCatalog from the DatabaseInstance |
79 | DUCKDB_API static Catalog &GetSystemCatalog(DatabaseInstance &db); |
80 | //! Get the specified Catalog from the ClientContext |
81 | DUCKDB_API static Catalog &GetCatalog(ClientContext &context, const string &catalog_name); |
82 | //! Get the specified Catalog from the DatabaseInstance |
83 | DUCKDB_API static Catalog &GetCatalog(DatabaseInstance &db, const string &catalog_name); |
84 | //! Gets the specified Catalog from the database if it exists |
85 | DUCKDB_API static optional_ptr<Catalog> GetCatalogEntry(ClientContext &context, const string &catalog_name); |
86 | //! Get the specific Catalog from the AttachedDatabase |
87 | DUCKDB_API static Catalog &GetCatalog(AttachedDatabase &db); |
88 | |
89 | DUCKDB_API AttachedDatabase &GetAttached(); |
90 | DUCKDB_API DatabaseInstance &GetDatabase(); |
91 | |
92 | virtual bool IsDuckCatalog() { |
93 | return false; |
94 | } |
95 | virtual void Initialize(bool load_builtin) = 0; |
96 | |
97 | bool IsSystemCatalog() const; |
98 | bool IsTemporaryCatalog() const; |
99 | |
100 | //! Returns the current version of the catalog (incremented whenever anything changes, not stored between restarts) |
101 | DUCKDB_API idx_t GetCatalogVersion(); |
102 | //! Trigger a modification in the catalog, increasing the catalog version and returning the previous version |
103 | DUCKDB_API idx_t ModifyCatalog(); |
104 | |
105 | //! Returns the catalog name - based on how the catalog was attached |
106 | DUCKDB_API const string &GetName(); |
107 | DUCKDB_API idx_t GetOid(); |
108 | DUCKDB_API virtual string GetCatalogType() = 0; |
109 | |
110 | DUCKDB_API CatalogTransaction GetCatalogTransaction(ClientContext &context); |
111 | |
112 | //! Creates a schema in the catalog. |
113 | DUCKDB_API virtual optional_ptr<CatalogEntry> CreateSchema(CatalogTransaction transaction, |
114 | CreateSchemaInfo &info) = 0; |
115 | DUCKDB_API optional_ptr<CatalogEntry> CreateSchema(ClientContext &context, CreateSchemaInfo &info); |
116 | //! Creates a table in the catalog. |
117 | DUCKDB_API optional_ptr<CatalogEntry> CreateTable(CatalogTransaction transaction, BoundCreateTableInfo &info); |
118 | DUCKDB_API optional_ptr<CatalogEntry> CreateTable(ClientContext &context, BoundCreateTableInfo &info); |
119 | //! Creates a table in the catalog. |
120 | DUCKDB_API optional_ptr<CatalogEntry> CreateTable(ClientContext &context, unique_ptr<CreateTableInfo> info); |
121 | //! Create a table function in the catalog |
122 | DUCKDB_API optional_ptr<CatalogEntry> CreateTableFunction(CatalogTransaction transaction, |
123 | CreateTableFunctionInfo &info); |
124 | DUCKDB_API optional_ptr<CatalogEntry> CreateTableFunction(ClientContext &context, CreateTableFunctionInfo &info); |
125 | // Kept for backwards compatibility |
126 | DUCKDB_API optional_ptr<CatalogEntry> CreateTableFunction(ClientContext &context, |
127 | optional_ptr<CreateTableFunctionInfo> info); |
128 | //! Create a copy function in the catalog |
129 | DUCKDB_API optional_ptr<CatalogEntry> CreateCopyFunction(CatalogTransaction transaction, |
130 | CreateCopyFunctionInfo &info); |
131 | DUCKDB_API optional_ptr<CatalogEntry> CreateCopyFunction(ClientContext &context, CreateCopyFunctionInfo &info); |
132 | //! Create a pragma function in the catalog |
133 | DUCKDB_API optional_ptr<CatalogEntry> CreatePragmaFunction(CatalogTransaction transaction, |
134 | CreatePragmaFunctionInfo &info); |
135 | DUCKDB_API optional_ptr<CatalogEntry> CreatePragmaFunction(ClientContext &context, CreatePragmaFunctionInfo &info); |
136 | //! Create a scalar or aggregate function in the catalog |
137 | DUCKDB_API optional_ptr<CatalogEntry> CreateFunction(CatalogTransaction transaction, CreateFunctionInfo &info); |
138 | DUCKDB_API optional_ptr<CatalogEntry> CreateFunction(ClientContext &context, CreateFunctionInfo &info); |
139 | //! Creates a table in the catalog. |
140 | DUCKDB_API optional_ptr<CatalogEntry> CreateView(CatalogTransaction transaction, CreateViewInfo &info); |
141 | DUCKDB_API optional_ptr<CatalogEntry> CreateView(ClientContext &context, CreateViewInfo &info); |
142 | //! Creates a sequence in the catalog. |
143 | DUCKDB_API optional_ptr<CatalogEntry> CreateSequence(CatalogTransaction transaction, CreateSequenceInfo &info); |
144 | DUCKDB_API optional_ptr<CatalogEntry> CreateSequence(ClientContext &context, CreateSequenceInfo &info); |
145 | //! Creates a Enum in the catalog. |
146 | DUCKDB_API optional_ptr<CatalogEntry> CreateType(CatalogTransaction transaction, CreateTypeInfo &info); |
147 | DUCKDB_API optional_ptr<CatalogEntry> CreateType(ClientContext &context, CreateTypeInfo &info); |
148 | //! Creates a collation in the catalog |
149 | DUCKDB_API optional_ptr<CatalogEntry> CreateCollation(CatalogTransaction transaction, CreateCollationInfo &info); |
150 | DUCKDB_API optional_ptr<CatalogEntry> CreateCollation(ClientContext &context, CreateCollationInfo &info); |
151 | //! Creates an index in the catalog |
152 | DUCKDB_API optional_ptr<CatalogEntry> CreateIndex(CatalogTransaction transaction, CreateIndexInfo &info); |
153 | DUCKDB_API optional_ptr<CatalogEntry> CreateIndex(ClientContext &context, CreateIndexInfo &info); |
154 | |
155 | //! Creates a table in the catalog. |
156 | DUCKDB_API optional_ptr<CatalogEntry> CreateTable(CatalogTransaction transaction, SchemaCatalogEntry &schema, |
157 | BoundCreateTableInfo &info); |
158 | //! Create a table function in the catalog |
159 | DUCKDB_API optional_ptr<CatalogEntry> |
160 | CreateTableFunction(CatalogTransaction transaction, SchemaCatalogEntry &schema, CreateTableFunctionInfo &info); |
161 | //! Create a copy function in the catalog |
162 | DUCKDB_API optional_ptr<CatalogEntry> CreateCopyFunction(CatalogTransaction transaction, SchemaCatalogEntry &schema, |
163 | CreateCopyFunctionInfo &info); |
164 | //! Create a pragma function in the catalog |
165 | DUCKDB_API optional_ptr<CatalogEntry> |
166 | CreatePragmaFunction(CatalogTransaction transaction, SchemaCatalogEntry &schema, CreatePragmaFunctionInfo &info); |
167 | //! Create a scalar or aggregate function in the catalog |
168 | DUCKDB_API optional_ptr<CatalogEntry> CreateFunction(CatalogTransaction transaction, SchemaCatalogEntry &schema, |
169 | CreateFunctionInfo &info); |
170 | //! Creates a view in the catalog |
171 | DUCKDB_API optional_ptr<CatalogEntry> CreateView(CatalogTransaction transaction, SchemaCatalogEntry &schema, |
172 | CreateViewInfo &info); |
173 | //! Creates a table in the catalog. |
174 | DUCKDB_API optional_ptr<CatalogEntry> CreateSequence(CatalogTransaction transaction, SchemaCatalogEntry &schema, |
175 | CreateSequenceInfo &info); |
176 | //! Creates a enum in the catalog. |
177 | DUCKDB_API optional_ptr<CatalogEntry> CreateType(CatalogTransaction transaction, SchemaCatalogEntry &schema, |
178 | CreateTypeInfo &info); |
179 | //! Creates a collation in the catalog |
180 | DUCKDB_API optional_ptr<CatalogEntry> CreateCollation(CatalogTransaction transaction, SchemaCatalogEntry &schema, |
181 | CreateCollationInfo &info); |
182 | |
183 | //! Drops an entry from the catalog |
184 | DUCKDB_API void DropEntry(ClientContext &context, DropInfo &info); |
185 | |
186 | //! Returns the schema object with the specified name, or throws an exception if it does not exist |
187 | DUCKDB_API SchemaCatalogEntry &GetSchema(ClientContext &context, const string &name, |
188 | QueryErrorContext error_context = QueryErrorContext()); |
189 | DUCKDB_API optional_ptr<SchemaCatalogEntry> GetSchema(ClientContext &context, const string &name, |
190 | OnEntryNotFound if_not_found, |
191 | QueryErrorContext error_context = QueryErrorContext()); |
192 | DUCKDB_API SchemaCatalogEntry &GetSchema(CatalogTransaction transaction, const string &name, |
193 | QueryErrorContext error_context = QueryErrorContext()); |
194 | DUCKDB_API virtual optional_ptr<SchemaCatalogEntry> |
195 | GetSchema(CatalogTransaction transaction, const string &schema_name, OnEntryNotFound if_not_found, |
196 | QueryErrorContext error_context = QueryErrorContext()) = 0; |
197 | DUCKDB_API static SchemaCatalogEntry &GetSchema(ClientContext &context, const string &catalog_name, |
198 | const string &schema_name, |
199 | QueryErrorContext error_context = QueryErrorContext()); |
200 | DUCKDB_API static optional_ptr<SchemaCatalogEntry> GetSchema(ClientContext &context, const string &catalog_name, |
201 | const string &schema_name, |
202 | OnEntryNotFound if_not_found, |
203 | QueryErrorContext error_context = QueryErrorContext()); |
204 | //! Scans all the schemas in the system one-by-one, invoking the callback for each entry |
205 | DUCKDB_API virtual void ScanSchemas(ClientContext &context, std::function<void(SchemaCatalogEntry &)> callback) = 0; |
206 | //! Gets the "schema.name" entry of the specified type, if entry does not exist behavior depends on OnEntryNotFound |
207 | DUCKDB_API optional_ptr<CatalogEntry> GetEntry(ClientContext &context, CatalogType type, const string &schema, |
208 | const string &name, OnEntryNotFound if_not_found, |
209 | QueryErrorContext error_context = QueryErrorContext()); |
210 | DUCKDB_API CatalogEntry &GetEntry(ClientContext &context, CatalogType type, const string &schema, |
211 | const string &name, QueryErrorContext error_context = QueryErrorContext()); |
212 | //! Gets the "catalog.schema.name" entry of the specified type, if entry does not exist behavior depends on |
213 | //! OnEntryNotFound |
214 | DUCKDB_API static optional_ptr<CatalogEntry> GetEntry(ClientContext &context, CatalogType type, |
215 | const string &catalog, const string &schema, |
216 | const string &name, OnEntryNotFound if_not_found, |
217 | QueryErrorContext error_context = QueryErrorContext()); |
218 | DUCKDB_API static CatalogEntry &GetEntry(ClientContext &context, CatalogType type, const string &catalog, |
219 | const string &schema, const string &name, |
220 | QueryErrorContext error_context = QueryErrorContext()); |
221 | |
222 | //! Gets the "schema.name" entry without a specified type, if entry does not exist an exception is thrown |
223 | DUCKDB_API CatalogEntry &GetEntry(ClientContext &context, const string &schema, const string &name); |
224 | |
225 | //! Fetches a logical type from the catalog |
226 | DUCKDB_API LogicalType GetType(ClientContext &context, const string &schema, const string &names, |
227 | OnEntryNotFound if_not_found); |
228 | |
229 | DUCKDB_API static LogicalType GetType(ClientContext &context, const string &catalog_name, const string &schema, |
230 | const string &name); |
231 | |
232 | template <class T> |
233 | optional_ptr<T> GetEntry(ClientContext &context, const string &schema_name, const string &name, |
234 | OnEntryNotFound if_not_found, QueryErrorContext error_context = QueryErrorContext()) { |
235 | auto entry = GetEntry(context, T::Type, schema_name, name, if_not_found, error_context); |
236 | if (!entry) { |
237 | return nullptr; |
238 | } |
239 | if (entry->type != T::Type) { |
240 | throw CatalogException(error_context.FormatError("%s is not an %s" , name, T::Name)); |
241 | } |
242 | return &entry->template Cast<T>(); |
243 | } |
244 | template <class T> |
245 | T &GetEntry(ClientContext &context, const string &schema_name, const string &name, |
246 | QueryErrorContext error_context = QueryErrorContext()) { |
247 | auto entry = GetEntry<T>(context, schema_name, name, OnEntryNotFound::THROW_EXCEPTION, error_context); |
248 | return *entry; |
249 | } |
250 | |
251 | //! Append a scalar or aggregate function to the catalog |
252 | DUCKDB_API optional_ptr<CatalogEntry> AddFunction(ClientContext &context, CreateFunctionInfo &info); |
253 | |
254 | //! Alter an existing entry in the catalog. |
255 | DUCKDB_API void Alter(ClientContext &context, AlterInfo &info); |
256 | |
257 | virtual unique_ptr<PhysicalOperator> PlanCreateTableAs(ClientContext &context, LogicalCreateTable &op, |
258 | unique_ptr<PhysicalOperator> plan) = 0; |
259 | virtual unique_ptr<PhysicalOperator> PlanInsert(ClientContext &context, LogicalInsert &op, |
260 | unique_ptr<PhysicalOperator> plan) = 0; |
261 | virtual unique_ptr<PhysicalOperator> PlanDelete(ClientContext &context, LogicalDelete &op, |
262 | unique_ptr<PhysicalOperator> plan) = 0; |
263 | virtual unique_ptr<PhysicalOperator> PlanUpdate(ClientContext &context, LogicalUpdate &op, |
264 | unique_ptr<PhysicalOperator> plan) = 0; |
265 | virtual unique_ptr<LogicalOperator> BindCreateIndex(Binder &binder, CreateStatement &stmt, TableCatalogEntry &table, |
266 | unique_ptr<LogicalOperator> plan) = 0; |
267 | |
268 | virtual DatabaseSize GetDatabaseSize(ClientContext &context) = 0; |
269 | |
270 | virtual bool InMemory() = 0; |
271 | virtual string GetDBPath() = 0; |
272 | |
273 | public: |
274 | template <class T> |
275 | static optional_ptr<T> GetEntry(ClientContext &context, const string &catalog_name, const string &schema_name, |
276 | const string &name, OnEntryNotFound if_not_found, |
277 | QueryErrorContext error_context = QueryErrorContext()) { |
278 | auto entry = GetEntry(context, T::Type, catalog_name, schema_name, name, if_not_found, error_context); |
279 | if (!entry) { |
280 | return nullptr; |
281 | } |
282 | if (entry->type != T::Type) { |
283 | throw CatalogException(error_context.FormatError("%s is not an %s" , name, T::Name)); |
284 | } |
285 | return &entry->template Cast<T>(); |
286 | } |
287 | template <class T> |
288 | static T &GetEntry(ClientContext &context, const string &catalog_name, const string &schema_name, |
289 | const string &name, QueryErrorContext error_context = QueryErrorContext()) { |
290 | auto entry = |
291 | GetEntry<T>(context, catalog_name, schema_name, name, OnEntryNotFound::THROW_EXCEPTION, error_context); |
292 | return *entry; |
293 | } |
294 | |
295 | DUCKDB_API vector<reference<SchemaCatalogEntry>> GetSchemas(ClientContext &context); |
296 | DUCKDB_API static vector<reference<SchemaCatalogEntry>> GetSchemas(ClientContext &context, |
297 | const string &catalog_name); |
298 | DUCKDB_API static vector<reference<SchemaCatalogEntry>> GetAllSchemas(ClientContext &context); |
299 | |
300 | virtual void Verify(); |
301 | |
302 | static CatalogException UnrecognizedConfigurationError(ClientContext &context, const string &name); |
303 | |
304 | protected: |
305 | //! Reference to the database |
306 | AttachedDatabase &db; |
307 | |
308 | private: |
309 | CatalogEntryLookup LookupEntryInternal(CatalogTransaction transaction, CatalogType type, const string &schema, |
310 | const string &name); |
311 | CatalogEntryLookup LookupEntry(ClientContext &context, CatalogType type, const string &schema, const string &name, |
312 | OnEntryNotFound if_not_found, QueryErrorContext error_context = QueryErrorContext()); |
313 | static CatalogEntryLookup LookupEntry(ClientContext &context, vector<CatalogLookup> &lookups, CatalogType type, |
314 | const string &name, OnEntryNotFound if_not_found, |
315 | QueryErrorContext error_context = QueryErrorContext()); |
316 | |
317 | //! Return an exception with did-you-mean suggestion. |
318 | static CatalogException CreateMissingEntryException(ClientContext &context, const string &entry_name, |
319 | CatalogType type, |
320 | const reference_set_t<SchemaCatalogEntry> &schemas, |
321 | QueryErrorContext error_context); |
322 | |
323 | //! Return the close entry name, the distance and the belonging schema. |
324 | static SimilarCatalogEntry SimilarEntryInSchemas(ClientContext &context, const string &entry_name, CatalogType type, |
325 | const reference_set_t<SchemaCatalogEntry> &schemas); |
326 | |
327 | virtual void DropSchema(ClientContext &context, DropInfo &info) = 0; |
328 | |
329 | public: |
330 | template <class TARGET> |
331 | TARGET &Cast() { |
332 | D_ASSERT(dynamic_cast<TARGET *>(this)); |
333 | return reinterpret_cast<TARGET &>(*this); |
334 | } |
335 | |
336 | template <class TARGET> |
337 | const TARGET &Cast() const { |
338 | D_ASSERT(dynamic_cast<const TARGET *>(this)); |
339 | return reinterpret_cast<const TARGET &>(*this); |
340 | } |
341 | }; |
342 | |
343 | } // namespace duckdb |
344 | |