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
14namespace duckdb {
15
16DuckCatalog::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
21DuckCatalog::~DuckCatalog() {
22}
23
24void 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
49bool DuckCatalog::IsDuckCatalog() {
50 return true;
51}
52
53//===--------------------------------------------------------------------===//
54// Schema
55//===--------------------------------------------------------------------===//
56optional_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
66optional_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
95void 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
105void DuckCatalog::DropSchema(ClientContext &context, DropInfo &info) {
106 DropSchema(transaction: GetCatalogTransaction(context), info);
107}
108
109void 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
114void DuckCatalog::ScanSchemas(std::function<void(SchemaCatalogEntry &)> callback) {
115 schemas->Scan(callback: [&](CatalogEntry &entry) { callback(entry.Cast<SchemaCatalogEntry>()); });
116}
117
118optional_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
131DatabaseSize DuckCatalog::GetDatabaseSize(ClientContext &context) {
132 return db.GetStorageManager().GetDatabaseSize();
133}
134
135bool DuckCatalog::InMemory() {
136 return db.GetStorageManager().InMemory();
137}
138
139string DuckCatalog::GetDBPath() {
140 return db.GetStorageManager().GetDBPath();
141}
142
143void DuckCatalog::Verify() {
144#ifdef DEBUG
145 Catalog::Verify();
146 schemas->Verify(*this);
147#endif
148}
149
150} // namespace duckdb
151