| 1 | #include "duckdb/catalog/duck_catalog.hpp" |
| 2 | #include "duckdb/catalog/dependency_manager.hpp" |
| 3 | #include "duckdb/catalog/catalog_entry/duck_schema_entry.hpp" |
| 4 | #include "duckdb/storage/storage_manager.hpp" |
| 5 | #include "duckdb/parser/parsed_data/drop_info.hpp" |
| 6 | #include "duckdb/parser/parsed_data/create_schema_info.hpp" |
| 7 | #include "duckdb/catalog/default/default_schemas.hpp" |
| 8 | #include "duckdb/function/built_in_functions.hpp" |
| 9 | #include "duckdb/main/attached_database.hpp" |
| 10 | #ifndef DISABLE_CORE_FUNCTIONS_EXTENSION |
| 11 | #include "duckdb/core_functions/core_functions.hpp" |
| 12 | #endif |
| 13 | |
| 14 | namespace duckdb { |
| 15 | |
| 16 | DuckCatalog::DuckCatalog(AttachedDatabase &db) |
| 17 | : Catalog(db), dependency_manager(make_uniq<DependencyManager>(args&: *this)), |
| 18 | schemas(make_uniq<CatalogSet>(args&: *this, args: make_uniq<DefaultSchemaGenerator>(args&: *this))) { |
| 19 | } |
| 20 | |
| 21 | DuckCatalog::~DuckCatalog() { |
| 22 | } |
| 23 | |
| 24 | void DuckCatalog::Initialize(bool load_builtin) { |
| 25 | // first initialize the base system catalogs |
| 26 | // these are never written to the WAL |
| 27 | // we start these at 1 because deleted entries default to 0 |
| 28 | auto data = CatalogTransaction::GetSystemTransaction(db&: GetDatabase()); |
| 29 | |
| 30 | // create the default schema |
| 31 | CreateSchemaInfo info; |
| 32 | info.schema = DEFAULT_SCHEMA; |
| 33 | info.internal = true; |
| 34 | CreateSchema(transaction: data, info); |
| 35 | |
| 36 | if (load_builtin) { |
| 37 | // initialize default functions |
| 38 | BuiltinFunctions builtin(data, *this); |
| 39 | builtin.Initialize(); |
| 40 | |
| 41 | #ifndef DISABLE_CORE_FUNCTIONS_EXTENSION |
| 42 | CoreFunctions::RegisterFunctions(catalog&: *this, transaction: data); |
| 43 | #endif |
| 44 | } |
| 45 | |
| 46 | Verify(); |
| 47 | } |
| 48 | |
| 49 | bool DuckCatalog::IsDuckCatalog() { |
| 50 | return true; |
| 51 | } |
| 52 | |
| 53 | //===--------------------------------------------------------------------===// |
| 54 | // Schema |
| 55 | //===--------------------------------------------------------------------===// |
| 56 | optional_ptr<CatalogEntry> DuckCatalog::CreateSchemaInternal(CatalogTransaction transaction, CreateSchemaInfo &info) { |
| 57 | DependencyList dependencies; |
| 58 | auto entry = make_uniq<DuckSchemaEntry>(args&: *this, args&: info.schema, args&: info.internal); |
| 59 | auto result = entry.get(); |
| 60 | if (!schemas->CreateEntry(transaction, name: info.schema, value: std::move(entry), dependencies)) { |
| 61 | return nullptr; |
| 62 | } |
| 63 | return (CatalogEntry *)result; |
| 64 | } |
| 65 | |
| 66 | optional_ptr<CatalogEntry> DuckCatalog::CreateSchema(CatalogTransaction transaction, CreateSchemaInfo &info) { |
| 67 | D_ASSERT(!info.schema.empty()); |
| 68 | auto result = CreateSchemaInternal(transaction, info); |
| 69 | if (!result) { |
| 70 | switch (info.on_conflict) { |
| 71 | case OnCreateConflict::ERROR_ON_CONFLICT: |
| 72 | throw CatalogException("Schema with name %s already exists!" , info.schema); |
| 73 | case OnCreateConflict::REPLACE_ON_CONFLICT: { |
| 74 | DropInfo drop_info; |
| 75 | drop_info.type = CatalogType::SCHEMA_ENTRY; |
| 76 | drop_info.catalog = info.catalog; |
| 77 | drop_info.name = info.schema; |
| 78 | DropSchema(transaction, info&: drop_info); |
| 79 | result = CreateSchemaInternal(transaction, info); |
| 80 | if (!result) { |
| 81 | throw InternalException("Failed to create schema entry in CREATE_OR_REPLACE" ); |
| 82 | } |
| 83 | break; |
| 84 | } |
| 85 | case OnCreateConflict::IGNORE_ON_CONFLICT: |
| 86 | break; |
| 87 | default: |
| 88 | throw InternalException("Unsupported OnCreateConflict for CreateSchema" ); |
| 89 | } |
| 90 | return nullptr; |
| 91 | } |
| 92 | return result; |
| 93 | } |
| 94 | |
| 95 | void DuckCatalog::DropSchema(CatalogTransaction transaction, DropInfo &info) { |
| 96 | D_ASSERT(!info.name.empty()); |
| 97 | ModifyCatalog(); |
| 98 | if (!schemas->DropEntry(transaction, name: info.name, cascade: info.cascade)) { |
| 99 | if (info.if_not_found == OnEntryNotFound::THROW_EXCEPTION) { |
| 100 | throw CatalogException("Schema with name \"%s\" does not exist!" , info.name); |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | void DuckCatalog::DropSchema(ClientContext &context, DropInfo &info) { |
| 106 | DropSchema(transaction: GetCatalogTransaction(context), info); |
| 107 | } |
| 108 | |
| 109 | void DuckCatalog::ScanSchemas(ClientContext &context, std::function<void(SchemaCatalogEntry &)> callback) { |
| 110 | schemas->Scan(transaction: GetCatalogTransaction(context), |
| 111 | callback: [&](CatalogEntry &entry) { callback(entry.Cast<SchemaCatalogEntry>()); }); |
| 112 | } |
| 113 | |
| 114 | void DuckCatalog::ScanSchemas(std::function<void(SchemaCatalogEntry &)> callback) { |
| 115 | schemas->Scan(callback: [&](CatalogEntry &entry) { callback(entry.Cast<SchemaCatalogEntry>()); }); |
| 116 | } |
| 117 | |
| 118 | optional_ptr<SchemaCatalogEntry> DuckCatalog::GetSchema(CatalogTransaction transaction, const string &schema_name, |
| 119 | OnEntryNotFound if_not_found, QueryErrorContext error_context) { |
| 120 | D_ASSERT(!schema_name.empty()); |
| 121 | auto entry = schemas->GetEntry(transaction, name: schema_name); |
| 122 | if (!entry) { |
| 123 | if (if_not_found == OnEntryNotFound::THROW_EXCEPTION) { |
| 124 | throw CatalogException(error_context.FormatError(msg: "Schema with name %s does not exist!" , params: schema_name)); |
| 125 | } |
| 126 | return nullptr; |
| 127 | } |
| 128 | return &entry->Cast<SchemaCatalogEntry>(); |
| 129 | } |
| 130 | |
| 131 | DatabaseSize DuckCatalog::GetDatabaseSize(ClientContext &context) { |
| 132 | return db.GetStorageManager().GetDatabaseSize(); |
| 133 | } |
| 134 | |
| 135 | bool DuckCatalog::InMemory() { |
| 136 | return db.GetStorageManager().InMemory(); |
| 137 | } |
| 138 | |
| 139 | string DuckCatalog::GetDBPath() { |
| 140 | return db.GetStorageManager().GetDBPath(); |
| 141 | } |
| 142 | |
| 143 | void DuckCatalog::Verify() { |
| 144 | #ifdef DEBUG |
| 145 | Catalog::Verify(); |
| 146 | schemas->Verify(*this); |
| 147 | #endif |
| 148 | } |
| 149 | |
| 150 | } // namespace duckdb |
| 151 | |