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
21namespace duckdb {
22struct CreateSchemaInfo;
23struct DropInfo;
24struct BoundCreateTableInfo;
25struct AlterTableInfo;
26struct CreateTableFunctionInfo;
27struct CreateCopyFunctionInfo;
28struct CreatePragmaFunctionInfo;
29struct CreateFunctionInfo;
30struct CreateViewInfo;
31struct CreateSequenceInfo;
32struct CreateCollationInfo;
33struct CreateIndexInfo;
34struct CreateTypeInfo;
35struct CreateTableInfo;
36struct DatabaseSize;
37
38class AttachedDatabase;
39class ClientContext;
40class Transaction;
41
42class AggregateFunctionCatalogEntry;
43class CollateCatalogEntry;
44class SchemaCatalogEntry;
45class TableCatalogEntry;
46class ViewCatalogEntry;
47class SequenceCatalogEntry;
48class TableFunctionCatalogEntry;
49class CopyFunctionCatalogEntry;
50class PragmaFunctionCatalogEntry;
51class CatalogSet;
52class DatabaseInstance;
53class DependencyManager;
54
55struct CatalogLookup;
56struct CatalogEntryLookup;
57struct SimilarCatalogEntry;
58
59class Binder;
60class LogicalOperator;
61class PhysicalOperator;
62class LogicalCreateIndex;
63class LogicalCreateTable;
64class LogicalInsert;
65class LogicalDelete;
66class LogicalUpdate;
67class CreateStatement;
68
69//! The Catalog object represents the catalog of the database.
70class Catalog {
71public:
72 explicit Catalog(AttachedDatabase &db);
73 virtual ~Catalog();
74
75public:
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
273public:
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
304protected:
305 //! Reference to the database
306 AttachedDatabase &db;
307
308private:
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
329public:
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