| 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 | |