Autonomy Software C++ 24.5.1
Welcome to the Autonomy Software repository of the Mars Rover Design Team (MRDT) at Missouri University of Science and Technology (Missouri S&T)! API reference contains the source code and other resources for the development of the autonomy software for our Mars rover. The Autonomy Software project aims to compete in the University Rover Challenge (URC) by demonstrating advanced autonomous capabilities and robust navigation algorithms.
Loading...
Searching...
No Matches
duckdb::CatalogSet Class Reference

The Catalog Set stores (key, value) map of a set of CatalogEntries. More...

#include <duckdb.hpp>

Collaboration diagram for duckdb::CatalogSet:

Classes

struct  EntryLookup
 

Public Member Functions

DUCKDB_API CatalogSet (Catalog &catalog, unique_ptr< DefaultGenerator > defaults=nullptr)
 
DUCKDB_API bool CreateEntry (CatalogTransaction transaction, const string &name, unique_ptr< CatalogEntry > value, const LogicalDependencyList &dependencies)
 
DUCKDB_API bool CreateEntry (ClientContext &context, const string &name, unique_ptr< CatalogEntry > value, const LogicalDependencyList &dependencies)
 
DUCKDB_API bool AlterEntry (CatalogTransaction transaction, const string &name, AlterInfo &alter_info)
 
DUCKDB_API bool DropEntry (CatalogTransaction transaction, const string &name, bool cascade, bool allow_drop_internal=false)
 
DUCKDB_API bool DropEntry (ClientContext &context, const string &name, bool cascade, bool allow_drop_internal=false)
 
DUCKDB_API void VerifyExistenceOfDependency (transaction_t commit_id, CatalogEntry &entry)
 Verify that the entry referenced by the dependency is still alive.
 
DUCKDB_API void CommitDrop (transaction_t commit_id, transaction_t start_time, CatalogEntry &entry)
 Verify we can still drop the entry while committing.
 
DUCKDB_API DuckCatalogGetCatalog ()
 
bool AlterOwnership (CatalogTransaction transaction, ChangeOwnershipInfo &info)
 
void CleanupEntry (CatalogEntry &catalog_entry)
 
DUCKDB_API EntryLookup GetEntryDetailed (CatalogTransaction transaction, const string &name)
 Returns the entry with the specified name.
 
DUCKDB_API optional_ptr< CatalogEntryGetEntry (CatalogTransaction transaction, const string &name)
 
DUCKDB_API optional_ptr< CatalogEntryGetEntry (ClientContext &context, const string &name)
 
SimilarCatalogEntry SimilarEntry (CatalogTransaction transaction, const string &name)
 
void Undo (CatalogEntry &entry)
 
DUCKDB_API void Scan (const std::function< void(CatalogEntry &)> &callback)
 Scan the catalog set, invoking the callback method for every committed entry.
 
DUCKDB_API void ScanWithPrefix (CatalogTransaction transaction, const std::function< void(CatalogEntry &)> &callback, const string &prefix)
 Scan the catalog set, invoking the callback method for every entry.
 
DUCKDB_API void Scan (CatalogTransaction transaction, const std::function< void(CatalogEntry &)> &callback)
 
DUCKDB_API void ScanWithReturn (CatalogTransaction transaction, const std::function< bool(CatalogEntry &)> &callback)
 
DUCKDB_API void Scan (ClientContext &context, const std::function< void(CatalogEntry &)> &callback)
 
DUCKDB_API void ScanWithReturn (ClientContext &context, const std::function< bool(CatalogEntry &)> &callback)
 
template<class T >
vector< reference< T > > GetEntries (CatalogTransaction transaction)
 
DUCKDB_API bool CreatedByOtherActiveTransaction (CatalogTransaction transaction, transaction_t timestamp)
 
DUCKDB_API bool CommittedAfterStarting (CatalogTransaction transaction, transaction_t timestamp)
 
DUCKDB_API bool HasConflict (CatalogTransaction transaction, transaction_t timestamp)
 
DUCKDB_API bool UseTimestamp (CatalogTransaction transaction, transaction_t timestamp)
 
mutex & GetCatalogLock ()
 
void Verify (Catalog &catalog)
 
void SetDefaultGenerator (unique_ptr< DefaultGenerator > defaults)
 Override the default generator - this should not be used after the catalog set has been used.
 

Static Public Member Functions

static bool IsCommitted (transaction_t timestamp)
 
static void UpdateTimestamp (CatalogEntry &entry, transaction_t timestamp)
 

Private Member Functions

bool DropDependencies (CatalogTransaction transaction, const string &name, bool cascade, bool allow_drop_internal=false)
 
CatalogEntryGetEntryForTransaction (CatalogTransaction transaction, CatalogEntry &current, bool &visible)
 
CatalogEntryGetEntryForTransaction (CatalogTransaction transaction, CatalogEntry &current)
 Given a root entry, gets the entry valid for this transaction.
 
CatalogEntryGetCommittedEntry (CatalogEntry &current)
 
optional_ptr< CatalogEntryGetEntryInternal (CatalogTransaction transaction, const string &name)
 This method is used to retrieve an entry for the purpose of making a new version, through an alter/drop/create.
 
optional_ptr< CatalogEntryCreateCommittedEntry (unique_ptr< CatalogEntry > entry)
 
void CreateDefaultEntries (CatalogTransaction transaction, unique_lock< mutex > &lock)
 Create all default entries.
 
optional_ptr< CatalogEntryCreateDefaultEntry (CatalogTransaction transaction, const string &name, unique_lock< mutex > &lock)
 Attempt to create a default entry with the specified name. Returns the entry if successful, nullptr otherwise.
 
bool DropEntryInternal (CatalogTransaction transaction, const string &name, bool allow_drop_internal=false)
 
bool CreateEntryInternal (CatalogTransaction transaction, const string &name, unique_ptr< CatalogEntry > value, unique_lock< mutex > &read_lock, bool should_be_empty=true)
 
void CheckCatalogEntryInvariants (CatalogEntry &value, const string &name)
 
bool VerifyVacancy (CatalogTransaction transaction, CatalogEntry &entry)
 Verify that the previous entry in the chain is dropped.
 
bool StartChain (CatalogTransaction transaction, const string &name, unique_lock< mutex > &read_lock)
 Start the catalog entry chain with a dummy node.
 
bool RenameEntryInternal (CatalogTransaction transaction, CatalogEntry &old, const string &new_name, AlterInfo &alter_info, unique_lock< mutex > &read_lock)
 

Private Attributes

DuckCatalogcatalog
 
mutex catalog_lock
 The catalog lock is used to make changes to the data.
 
CatalogEntryMap map
 
unique_ptr< DefaultGeneratordefaults
 The generator used to generate default internal entries.
 

Detailed Description

The Catalog Set stores (key, value) map of a set of CatalogEntries.

Constructor & Destructor Documentation

◆ CatalogSet()

duckdb::CatalogSet::CatalogSet ( Catalog catalog,
unique_ptr< DefaultGenerator defaults = nullptr 
)
explicit
22941 : catalog(catalog_p.Cast<DuckCatalog>()), defaults(std::move(defaults)) {
22942 D_ASSERT(catalog_p.IsDuckCatalog());
22943}
unique_ptr< DefaultGenerator > defaults
The generator used to generate default internal entries.
Definition duckdb.hpp:29285

◆ ~CatalogSet()

duckdb::CatalogSet::~CatalogSet ( )
22944 {
22945}

Member Function Documentation

◆ CreateEntry() [1/2]

bool duckdb::CatalogSet::CreateEntry ( CatalogTransaction  transaction,
const string &  name,
unique_ptr< CatalogEntry value,
const LogicalDependencyList dependencies 
)

Create an entry in the catalog set. Returns whether or not it was successful.

23051 {
23052 CheckCatalogEntryInvariants(*value, name);
23053
23054 // Mark this entry as being created by the current active transaction
23055 value->timestamp = transaction.transaction_id;
23056 value->set = this;
23057 catalog.GetDependencyManager()->AddObject(transaction, *value, dependencies);
23058
23059 // lock the catalog for writing
23060 lock_guard<mutex> write_lock(catalog.GetWriteLock());
23061 // lock this catalog set to disallow reading
23062 unique_lock<mutex> read_lock(catalog_lock);
23063
23064 return CreateEntryInternal(transaction, name, std::move(value), read_lock);
23065}
mutex catalog_lock
The catalog lock is used to make changes to the data.
Definition duckdb.hpp:29282
optional_ptr< DependencyManager > GetDependencyManager() override
Returns the dependency manager of this catalog - if the catalog has anye.
Definition duckdb.cpp:26404

◆ CreateEntry() [2/2]

bool duckdb::CatalogSet::CreateEntry ( ClientContext context,
const string &  name,
unique_ptr< CatalogEntry value,
const LogicalDependencyList dependencies 
)
23068 {
23069 return CreateEntry(catalog.GetCatalogTransaction(context), name, std::move(value), dependencies);
23070}
DUCKDB_API bool CreateEntry(CatalogTransaction transaction, const string &name, unique_ptr< CatalogEntry > value, const LogicalDependencyList &dependencies)
Definition duckdb.cpp:23050

◆ AlterEntry()

bool duckdb::CatalogSet::AlterEntry ( CatalogTransaction  transaction,
const string &  name,
AlterInfo alter_info 
)
23161 {
23162 // If the entry does not exist, we error
23163 auto entry = GetEntry(transaction, name);
23164 if (!entry) {
23165 return false;
23166 }
23167 if (!alter_info.allow_internal && entry->internal) {
23168 throw CatalogException("Cannot alter entry \"%s\" because it is an internal system entry", entry->name);
23169 }
23170
23171 unique_ptr<CatalogEntry> value;
23172 if (alter_info.type == AlterType::SET_COMMENT) {
23173 // Copy the existing entry; we are only changing metadata here
23174 if (!transaction.context) {
23175 throw InternalException("Cannot AlterEntry::SET_COMMENT without client context");
23176 }
23177 value = entry->Copy(*transaction.context);
23178 value->comment = alter_info.Cast<SetCommentInfo>().comment_value;
23179 } else {
23180 // Use the existing entry to create the altered entry
23181 value = entry->AlterEntry(transaction, alter_info);
23182 if (!value) {
23183 // alter failed, but did not result in an error
23184 return true;
23185 }
23186 }
23187
23188 // lock the catalog for writing
23189 unique_lock<mutex> write_lock(catalog.GetWriteLock());
23190 // lock this catalog set to disallow reading
23191 unique_lock<mutex> read_lock(catalog_lock);
23192
23193 // fetch the entry again before doing the modification
23194 // this will catch any write-write conflicts between transactions
23195 entry = GetEntryInternal(transaction, name);
23196
23197 // Mark this entry as being created by this transaction
23198 value->timestamp = transaction.transaction_id;
23199 value->set = this;
23200
23201 if (!StringUtil::CIEquals(value->name, entry->name)) {
23202 if (!RenameEntryInternal(transaction, *entry, value->name, alter_info, read_lock)) {
23203 return false;
23204 }
23205 }
23206 auto new_entry = value.get();
23207 map.UpdateEntry(std::move(value));
23208
23209 // push the old entry in the undo buffer for this transaction
23210 unique_ptr<CatalogEntry> entry_to_destroy;
23211 if (transaction.transaction) {
23212 // serialize the AlterInfo into a temporary buffer
23213 MemoryStream stream(Allocator::Get(*transaction.db));
23214 BinarySerializer serializer(stream);
23215 serializer.Begin();
23216 serializer.WriteProperty(100, "column_name", alter_info.GetColumnName());
23217 serializer.WriteProperty(101, "alter_info", &alter_info);
23218 serializer.End();
23219
23220 DuckTransactionManager::Get(GetCatalog().GetAttached())
23221 .PushCatalogEntry(*transaction.transaction, new_entry->Child(), stream.GetData(), stream.GetPosition());
23222 } else {
23223 // if we don't have a transaction this alter is non-transactional
23224 // in that case we are able to just directly destroy the child (if there is any)
23225 entry_to_destroy = new_entry->TakeChild();
23226 }
23227
23228 read_lock.unlock();
23229 write_lock.unlock();
23230
23231 // Check the dependency manager to verify that there are no conflicting dependencies with this alter
23232 catalog.GetDependencyManager()->AlterObject(transaction, *entry, *new_entry, alter_info);
23233 return true;
23234}
optional_ptr< CatalogEntry > GetEntryInternal(CatalogTransaction transaction, const string &name)
This method is used to retrieve an entry for the purpose of making a new version, through an alter/dr...
Definition duckdb.cpp:23073
static DUCKDB_API bool CIEquals(const string &l1, const string &l2)
Case insensitive equals.

◆ DropEntry() [1/2]

bool duckdb::CatalogSet::DropEntry ( CatalogTransaction  transaction,
const string &  name,
bool  cascade,
bool  allow_drop_internal = false 
)
23281 {
23282 if (!DropDependencies(transaction, name, cascade, allow_drop_internal)) {
23283 return false;
23284 }
23285 lock_guard<mutex> write_lock(catalog.GetWriteLock());
23286 lock_guard<mutex> read_lock(catalog_lock);
23287 return DropEntryInternal(transaction, name, allow_drop_internal);
23288}

◆ DropEntry() [2/2]

bool duckdb::CatalogSet::DropEntry ( ClientContext context,
const string &  name,
bool  cascade,
bool  allow_drop_internal = false 
)
23290 {
23291 return DropEntry(catalog.GetCatalogTransaction(context), name, cascade, allow_drop_internal);
23292}

◆ VerifyExistenceOfDependency()

void duckdb::CatalogSet::VerifyExistenceOfDependency ( transaction_t  commit_id,
CatalogEntry entry 
)

Verify that the entry referenced by the dependency is still alive.

Verify that the object referenced by the dependency still exists when we commit the dependency.

23295 {
23296 auto &duck_catalog = GetCatalog();
23297
23298 // Make sure that we don't see any uncommitted changes
23299 auto transaction_id = MAX_TRANSACTION_ID;
23300 // This will allow us to see all committed changes made before this COMMIT happened
23301 auto tx_start_time = commit_id;
23302 CatalogTransaction commit_transaction(duck_catalog.GetDatabase(), transaction_id, tx_start_time);
23303
23304 D_ASSERT(entry.type == CatalogType::DEPENDENCY_ENTRY);
23305 auto &dep = entry.Cast<DependencyEntry>();
23306 duck_catalog.GetDependencyManager()->VerifyExistence(commit_transaction, dep);
23307}

◆ CommitDrop()

void duckdb::CatalogSet::CommitDrop ( transaction_t  commit_id,
transaction_t  start_time,
CatalogEntry entry 
)

Verify we can still drop the entry while committing.

Verify that no dependencies creations were committed since our transaction started, that reference the entry we're dropping

23311 {
23312 auto &duck_catalog = GetCatalog();
23313
23314 entry.OnDrop();
23315 // Make sure that we don't see any uncommitted changes
23316 auto transaction_id = MAX_TRANSACTION_ID;
23317 // This will allow us to see all committed changes made before this COMMIT happened
23318 auto tx_start_time = commit_id;
23319 CatalogTransaction commit_transaction(duck_catalog.GetDatabase(), transaction_id, tx_start_time);
23320
23321 duck_catalog.GetDependencyManager()->VerifyCommitDrop(commit_transaction, start_time, entry);
23322}

◆ GetCatalog()

DuckCatalog & duckdb::CatalogSet::GetCatalog ( )
23324 {
23325 return catalog;
23326}

◆ AlterOwnership()

bool duckdb::CatalogSet::AlterOwnership ( CatalogTransaction  transaction,
ChangeOwnershipInfo info 
)
23095 {
23096 // lock the catalog for writing
23097 unique_lock<mutex> write_lock(catalog.GetWriteLock());
23098
23099 auto entry = GetEntryInternal(transaction, info.name);
23100 if (!entry) {
23101 return false;
23102 }
23103 optional_ptr<CatalogEntry> owner_entry;
23104 auto schema = catalog.GetSchema(transaction, info.owner_schema, OnEntryNotFound::RETURN_NULL);
23105 if (schema) {
23106 vector<CatalogType> entry_types {CatalogType::TABLE_ENTRY, CatalogType::SEQUENCE_ENTRY};
23107 for (auto entry_type : entry_types) {
23108 owner_entry = schema->GetEntry(transaction, entry_type, info.owner_name);
23109 if (owner_entry) {
23110 break;
23111 }
23112 }
23113 }
23114 if (!owner_entry) {
23115 throw CatalogException("CatalogElement \"%s.%s\" does not exist!", info.owner_schema, info.owner_name);
23116 }
23117 write_lock.unlock();
23118 catalog.GetDependencyManager()->AddOwnership(transaction, *owner_entry, *entry);
23119 return true;
23120}
DUCKDB_API SchemaCatalogEntry & GetSchema(ClientContext &context, const EntryLookupInfo &schema_lookup)
Returns the schema object with the specified name, or throws an exception if it does not exist.
Definition duckdb.cpp:7493

◆ CleanupEntry()

void duckdb::CatalogSet::CleanupEntry ( CatalogEntry catalog_entry)
23328 {
23329 // destroy the backed up entry: it is no longer required
23330 lock_guard<mutex> write_lock(catalog.GetWriteLock());
23331 lock_guard<mutex> lock(catalog_lock);
23332 auto &parent = catalog_entry.Parent();
23333 map.DropEntry(catalog_entry);
23334 if (parent.deleted && !parent.HasChild() && !parent.HasParent()) {
23335 // The entry's parent is a tombstone and the entry had no child
23336 // clean up the mapping and the tombstone entry as well
23337 D_ASSERT(map.GetEntry(parent.name).get() == &parent);
23338 map.DropEntry(parent);
23339 }
23340}

◆ GetEntryDetailed()

CatalogSet::EntryLookup duckdb::CatalogSet::GetEntryDetailed ( CatalogTransaction  transaction,
const string &  name 
)

Returns the entry with the specified name.

23455 {
23456 unique_lock<mutex> read_lock(catalog_lock);
23457 auto entry_value = map.GetEntry(name);
23458 if (entry_value) {
23459 // we found an entry for this name
23460 // check the version numbers
23461
23462 auto &catalog_entry = *entry_value;
23463 bool visible;
23464 auto &current = GetEntryForTransaction(transaction, catalog_entry, visible);
23465 if (current.deleted) {
23466 if (!visible) {
23467 return EntryLookup {nullptr, EntryLookup::FailureReason::INVISIBLE};
23468 } else {
23469 return EntryLookup {nullptr, EntryLookup::FailureReason::DELETED};
23470 }
23471 }
23472 D_ASSERT(StringUtil::CIEquals(name, current.name));
23473 return EntryLookup {&current, EntryLookup::FailureReason::SUCCESS};
23474 }
23475 auto default_entry = CreateDefaultEntry(transaction, name, read_lock);
23476 if (!default_entry) {
23477 return EntryLookup {default_entry, EntryLookup::FailureReason::NOT_PRESENT};
23478 }
23479 return EntryLookup {default_entry, EntryLookup::FailureReason::SUCCESS};
23480}
CatalogEntry & GetEntryForTransaction(CatalogTransaction transaction, CatalogEntry &current, bool &visible)
Definition duckdb.cpp:23379
optional_ptr< CatalogEntry > CreateDefaultEntry(CatalogTransaction transaction, const string &name, unique_lock< mutex > &lock)
Attempt to create a default entry with the specified name. Returns the entry if successful,...
Definition duckdb.cpp:23419
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetEntry() [1/2]

optional_ptr< CatalogEntry > duckdb::CatalogSet::GetEntry ( CatalogTransaction  transaction,
const string &  name 
)
23482 {
23483 auto lookup = GetEntryDetailed(transaction, name);
23484 return lookup.result;
23485}
DUCKDB_API EntryLookup GetEntryDetailed(CatalogTransaction transaction, const string &name)
Returns the entry with the specified name.
Definition duckdb.cpp:23455

◆ GetEntry() [2/2]

optional_ptr< CatalogEntry > duckdb::CatalogSet::GetEntry ( ClientContext context,
const string &  name 
)
23487 {
23488 return GetEntry(catalog.GetCatalogTransaction(context), name);
23489}

◆ SimilarEntry()

SimilarCatalogEntry duckdb::CatalogSet::SimilarEntry ( CatalogTransaction  transaction,
const string &  name 
)

Gets the entry that is most similar to the given name (i.e. smallest levenshtein distance), or empty string if none is found. The returned pair consists of the entry name and the distance (smaller means closer).

23404 {
23405 unique_lock<mutex> lock(catalog_lock);
23406 CreateDefaultEntries(transaction, lock);
23407
23408 SimilarCatalogEntry result;
23409 for (auto &kv : map.Entries()) {
23410 auto entry_score = StringUtil::SimilarityRating(kv.first, name);
23411 if (entry_score > result.score) {
23412 result.score = entry_score;
23413 result.name = kv.first;
23414 }
23415 }
23416 return result;
23417}
void CreateDefaultEntries(CatalogTransaction transaction, unique_lock< mutex > &lock)
Create all default entries.
Definition duckdb.cpp:23518
static DUCKDB_API double SimilarityRating(const string &s1, const string &s2)
Returns a normalized similarity rating between 0.0 - 1.0 (higher is more similar)
Here is the call graph for this function:

◆ Undo()

void duckdb::CatalogSet::Undo ( CatalogEntry entry)

Rollback <entry> to be the currently valid entry for a certain catalog entry

23495 {
23496 lock_guard<mutex> write_lock(catalog.GetWriteLock());
23497 lock_guard<mutex> lock(catalog_lock);
23498
23499 // entry has to be restored
23500 // and entry->parent has to be removed ("rolled back")
23501
23502 // i.e. we have to place (entry) as (entry->parent) again
23503 auto &to_be_removed_node = entry.Parent();
23504 to_be_removed_node.Rollback(entry);
23505
23506 D_ASSERT(StringUtil::CIEquals(entry.name, to_be_removed_node.name));
23507 if (!to_be_removed_node.HasParent()) {
23508 to_be_removed_node.Child().SetAsRoot();
23509 }
23510 map.DropEntry(to_be_removed_node);
23511
23512 if (entry.type == CatalogType::INVALID) {
23513 // This was the root of the entry chain
23514 map.DropEntry(entry);
23515 }
23516}
Here is the call graph for this function:

◆ Scan() [1/3]

void duckdb::CatalogSet::Scan ( const std::function< void(CatalogEntry &)> &  callback)

Scan the catalog set, invoking the callback method for every committed entry.

23603 {
23604 // lock the catalog set
23605 lock_guard<mutex> lock(catalog_lock);
23606 for (auto &kv : map.Entries()) {
23607 auto &entry = *kv.second;
23608 auto &commited_entry = GetCommittedEntry(entry);
23609 if (!commited_entry.deleted) {
23610 callback(commited_entry);
23611 }
23612 }
23613}

◆ ScanWithPrefix()

void duckdb::CatalogSet::ScanWithPrefix ( CatalogTransaction  transaction,
const std::function< void(CatalogEntry &)> &  callback,
const string &  prefix 
)

Scan the catalog set, invoking the callback method for every entry.

23586 {
23587 // lock the catalog set
23588 unique_lock<mutex> lock(catalog_lock);
23589 CreateDefaultEntries(transaction, lock);
23590
23591 auto &entries = map.Entries();
23592 auto it = entries.lower_bound(prefix);
23593 auto end = entries.upper_bound(prefix + char(255));
23594 for (; it != end; it++) {
23595 auto &entry = *it->second;
23596 auto &entry_for_transaction = GetEntryForTransaction(transaction, entry);
23597 if (!entry_for_transaction.deleted) {
23598 callback(entry_for_transaction);
23599 }
23600 }
23601}
Here is the call graph for this function:

◆ Scan() [2/3]

void duckdb::CatalogSet::Scan ( CatalogTransaction  transaction,
const std::function< void(CatalogEntry &)> &  callback 
)
23547 {
23548 // Lock the catalog set.
23549 unique_lock<mutex> lock(catalog_lock);
23550 CreateDefaultEntries(transaction, lock);
23551
23552 for (auto &kv : map.Entries()) {
23553 auto &entry = *kv.second;
23554 auto &entry_for_transaction = GetEntryForTransaction(transaction, entry);
23555 if (!entry_for_transaction.deleted) {
23556 callback(entry_for_transaction);
23557 }
23558 }
23559}

◆ ScanWithReturn() [1/2]

void duckdb::CatalogSet::ScanWithReturn ( CatalogTransaction  transaction,
const std::function< bool(CatalogEntry &)> &  callback 
)
23561 {
23562 // Lock the catalog set.
23563 unique_lock<mutex> lock(catalog_lock);
23564 CreateDefaultEntries(transaction, lock);
23565
23566 for (auto &kv : map.Entries()) {
23567 auto &entry = *kv.second;
23568 auto &entry_for_transaction = GetEntryForTransaction(transaction, entry);
23569 if (!entry_for_transaction.deleted) {
23570 if (!callback(entry_for_transaction)) {
23571 return;
23572 }
23573 }
23574 }
23575}

◆ Scan() [3/3]

void duckdb::CatalogSet::Scan ( ClientContext context,
const std::function< void(CatalogEntry &)> &  callback 
)
23577 {
23578 Scan(catalog.GetCatalogTransaction(context), callback);
23579}
DUCKDB_API void Scan(const std::function< void(CatalogEntry &)> &callback)
Scan the catalog set, invoking the callback method for every committed entry.
Definition duckdb.cpp:23603

◆ ScanWithReturn() [2/2]

void duckdb::CatalogSet::ScanWithReturn ( ClientContext context,
const std::function< bool(CatalogEntry &)> &  callback 
)
23581 {
23582 ScanWithReturn(catalog.GetCatalogTransaction(context), callback);
23583}

◆ GetEntries()

template<class T >
vector< reference< T > > duckdb::CatalogSet::GetEntries ( CatalogTransaction  transaction)
inline
29226 {
29227 vector<reference<T>> result;
29228 Scan(transaction, [&](CatalogEntry &entry) { result.push_back(entry.Cast<T>()); });
29229 return result;
29230 }

◆ CreatedByOtherActiveTransaction()

bool duckdb::CatalogSet::CreatedByOtherActiveTransaction ( CatalogTransaction  transaction,
transaction_t  timestamp 
)
23342 {
23343 // True if this transaction is not committed yet and the entry was made by another active (not committed)
23344 // transaction
23345 return (timestamp >= TRANSACTION_ID_START && timestamp != transaction.transaction_id);
23346}

◆ CommittedAfterStarting()

bool duckdb::CatalogSet::CommittedAfterStarting ( CatalogTransaction  transaction,
transaction_t  timestamp 
)
23348 {
23349 // The entry has been committed after this transaction started, this is not our source of truth.
23350 return (timestamp < TRANSACTION_ID_START && timestamp > transaction.start_time);
23351}

◆ HasConflict()

bool duckdb::CatalogSet::HasConflict ( CatalogTransaction  transaction,
transaction_t  timestamp 
)
23353 {
23354 return CreatedByOtherActiveTransaction(transaction, timestamp) || CommittedAfterStarting(transaction, timestamp);
23355}

◆ UseTimestamp()

bool duckdb::CatalogSet::UseTimestamp ( CatalogTransaction  transaction,
transaction_t  timestamp 
)
23362 {
23363 if (timestamp == transaction.transaction_id) {
23364 // we created this version
23365 return true;
23366 }
23367 if (timestamp < transaction.start_time) {
23368 // this version was commited before we started the transaction
23369 return true;
23370 }
23371 return false;
23372}

◆ IsCommitted()

bool duckdb::CatalogSet::IsCommitted ( transaction_t  timestamp)
static

FIXME: transaction_t itself should be a class that has these methods

23357 {
23359 return timestamp < TRANSACTION_ID_START;
23360}
cv::GOpaque< int64_t > timestamp(G g)
Here is the call graph for this function:

◆ UpdateTimestamp()

void duckdb::CatalogSet::UpdateTimestamp ( CatalogEntry entry,
transaction_t  timestamp 
)
static
23491 {
23492 entry.timestamp = timestamp;
23493}

◆ GetCatalogLock()

mutex & duckdb::CatalogSet::GetCatalogLock ( )
inline
29240 {
29241 return catalog_lock;
29242 }

◆ Verify()

void duckdb::CatalogSet::Verify ( Catalog catalog)
23620 {
23621 D_ASSERT(&catalog_p == &catalog);
23622 vector<reference<CatalogEntry>> entries;
23623 Scan([&](CatalogEntry &entry) { entries.push_back(entry); });
23624 for (auto &entry : entries) {
23625 entry.get().Verify(catalog_p);
23626 }
23627}

◆ SetDefaultGenerator()

void duckdb::CatalogSet::SetDefaultGenerator ( unique_ptr< DefaultGenerator defaults)

Override the default generator - this should not be used after the catalog set has been used.

23615 {
23616 lock_guard<mutex> lock(catalog_lock);
23617 defaults = std::move(defaults_p);
23618}

◆ DropDependencies()

bool duckdb::CatalogSet::DropDependencies ( CatalogTransaction  transaction,
const string &  name,
bool  cascade,
bool  allow_drop_internal = false 
)
private
23237 {
23238 auto entry = GetEntry(transaction, name);
23239 if (!entry) {
23240 return false;
23241 }
23242 if (entry->internal && !allow_drop_internal) {
23243 throw CatalogException("Cannot drop entry \"%s\" because it is an internal system entry", entry->name);
23244 }
23245 // check any dependencies of this object
23246 D_ASSERT(entry->ParentCatalog().IsDuckCatalog());
23247 auto &duck_catalog = entry->ParentCatalog().Cast<DuckCatalog>();
23248 duck_catalog.GetDependencyManager()->DropObject(transaction, *entry, cascade);
23249 return true;
23250}

◆ GetEntryForTransaction() [1/2]

CatalogEntry & duckdb::CatalogSet::GetEntryForTransaction ( CatalogTransaction  transaction,
CatalogEntry current,
bool &  visible 
)
private

Given a root entry, gets the entry valid for this transaction, 'visible' is used to indicate whether the entry is actually visible to the transaction

23379 {
23380 reference<CatalogEntry> entry(current);
23381 while (entry.get().HasChild()) {
23382 if (UseTimestamp(transaction, entry.get().timestamp)) {
23383 visible = true;
23384 return entry.get();
23385 }
23386 entry = entry.get().Child();
23387 }
23388 visible = false;
23389 return entry.get();
23390}
Here is the caller graph for this function:

◆ GetEntryForTransaction() [2/2]

CatalogEntry & duckdb::CatalogSet::GetEntryForTransaction ( CatalogTransaction  transaction,
CatalogEntry current 
)
private

Given a root entry, gets the entry valid for this transaction.

23374 {
23375 bool visible;
23376 return GetEntryForTransaction(transaction, current, visible);
23377}
Here is the call graph for this function:

◆ GetCommittedEntry()

CatalogEntry & duckdb::CatalogSet::GetCommittedEntry ( CatalogEntry current)
private
23392 {
23393 reference<CatalogEntry> entry(current);
23394 while (entry.get().HasChild()) {
23395 if (entry.get().timestamp < TRANSACTION_ID_START) {
23396 // this entry is committed: use it
23397 break;
23398 }
23399 entry = entry.get().Child();
23400 }
23401 return entry.get();
23402}

◆ GetEntryInternal()

optional_ptr< CatalogEntry > duckdb::CatalogSet::GetEntryInternal ( CatalogTransaction  transaction,
const string &  name 
)
private

This method is used to retrieve an entry for the purpose of making a new version, through an alter/drop/create.

23073 {
23074 auto entry_value = map.GetEntry(name);
23075 if (!entry_value) {
23076 return nullptr;
23077 }
23078 auto &catalog_entry = *entry_value;
23079
23080 // Check if this entry is visible to our snapshot
23081 if (HasConflict(transaction, catalog_entry.timestamp)) {
23082 // We intend to create a new version of the entry.
23083 // Another transaction has already made an edit to this catalog entry, because of limitations in the Catalog we
23084 // can't create an edit alongside this even if the other transaction might end up getting aborted. So we have to
23085 // abort the transaction.
23086 throw TransactionException("Catalog write-write conflict on alter with \"%s\"", catalog_entry.name);
23087 }
23088 // The entry is visible to our snapshot, check if it's deleted
23089 if (catalog_entry.deleted) {
23090 return nullptr;
23091 }
23092 return &catalog_entry;
23093}

◆ CreateCommittedEntry()

optional_ptr< CatalogEntry > duckdb::CatalogSet::CreateCommittedEntry ( unique_ptr< CatalogEntry entry)
private
23007 {
23008 auto existing_entry = map.GetEntry(entry->name);
23009 if (existing_entry) {
23010 // Return null if an entry by that name already exists
23011 return nullptr;
23012 }
23013
23014 auto catalog_entry = entry.get();
23015
23016 entry->set = this;
23017 // Give the entry commit id 0, so it is visible to all transactions
23018 entry->timestamp = 0;
23019 map.AddEntry(std::move(entry));
23020
23021 return catalog_entry;
23022}

◆ CreateDefaultEntries()

void duckdb::CatalogSet::CreateDefaultEntries ( CatalogTransaction  transaction,
unique_lock< mutex > &  lock 
)
private

Create all default entries.

23518 {
23519 if (!defaults || defaults->created_all_entries) {
23520 return;
23521 }
23522 auto unlock = !defaults->LockDuringCreate();
23523 // this catalog set has a default set defined:
23524 auto default_entries = defaults->GetDefaultEntries();
23525 for (auto &default_entry : default_entries) {
23526 auto entry_value = map.GetEntry(default_entry);
23527 if (!entry_value) {
23528 // we unlock during the CreateEntry, since it might reference other catalog sets...
23529 // specifically for views this can happen since the view will be bound
23530 if (unlock) {
23531 read_lock.unlock();
23532 }
23533 auto entry = defaults->CreateDefaultEntry(transaction, default_entry);
23534 if (!entry) {
23535 throw InternalException("Failed to create default entry for %s", default_entry);
23536 }
23537
23538 if (unlock) {
23539 read_lock.lock();
23540 }
23541 CreateCommittedEntry(std::move(entry));
23542 }
23543 }
23544 defaults->created_all_entries = true;
23545}
Here is the caller graph for this function:

◆ CreateDefaultEntry()

optional_ptr< CatalogEntry > duckdb::CatalogSet::CreateDefaultEntry ( CatalogTransaction  transaction,
const string &  name,
unique_lock< mutex > &  lock 
)
private

Attempt to create a default entry with the specified name. Returns the entry if successful, nullptr otherwise.

23420 {
23421 // no entry found with this name, check for defaults
23422 if (!defaults || defaults->created_all_entries) {
23423 // no defaults either: return null
23424 return nullptr;
23425 }
23426 auto unlock = !defaults->LockDuringCreate();
23427 if (unlock) {
23428 read_lock.unlock();
23429 }
23430 // this catalog set has a default map defined
23431 // check if there is a default entry that we can create with this name
23432 auto entry = defaults->CreateDefaultEntry(transaction, name);
23433
23434 if (unlock) {
23435 read_lock.lock();
23436 }
23437 if (!entry) {
23438 // no default entry
23439 return nullptr;
23440 }
23441 // there is a default entry! create it
23442 auto result = CreateCommittedEntry(std::move(entry));
23443 if (result) {
23444 return result;
23445 }
23446 // we found a default entry, but failed
23447 // this means somebody else created the entry first
23448 // just retry?
23449 if (unlock) {
23450 read_lock.unlock();
23451 }
23452 return GetEntry(transaction, name);
23453}
Here is the caller graph for this function:

◆ DropEntryInternal()

bool duckdb::CatalogSet::DropEntryInternal ( CatalogTransaction  transaction,
const string &  name,
bool  allow_drop_internal = false 
)
private
23252 {
23253 // lock the catalog for writing
23254 // we can only delete an entry that exists
23255 auto entry = GetEntryInternal(transaction, name);
23256 if (!entry) {
23257 return false;
23258 }
23259 if (entry->internal && !allow_drop_internal) {
23260 throw CatalogException("Cannot drop entry \"%s\" because it is an internal system entry", entry->name);
23261 }
23262
23263 // create a new tombstone entry and replace the currently stored one
23264 // set the timestamp to the timestamp of the current transaction
23265 // and point it at the tombstone node
23266 auto value = make_uniq<InCatalogEntry>(CatalogType::DELETED_ENTRY, entry->ParentCatalog(), entry->name);
23267 value->timestamp = transaction.transaction_id;
23268 value->set = this;
23269 value->deleted = true;
23270 auto value_ptr = value.get();
23271 map.UpdateEntry(std::move(value));
23272
23273 // push the old entry in the undo buffer for this transaction
23274 if (transaction.transaction) {
23275 DuckTransactionManager::Get(GetCatalog().GetAttached())
23276 .PushCatalogEntry(*transaction.transaction, value_ptr->Child());
23277 }
23278 return true;
23279}

◆ CreateEntryInternal()

bool duckdb::CatalogSet::CreateEntryInternal ( CatalogTransaction  transaction,
const string &  name,
unique_ptr< CatalogEntry value,
unique_lock< mutex > &  read_lock,
bool  should_be_empty = true 
)
private
23025 {
23026 auto entry_value = map.GetEntry(name);
23027 if (!entry_value) {
23028 // Add a dummy node to start the chain
23029 if (!StartChain(transaction, name, read_lock)) {
23030 return false;
23031 }
23032 } else if (should_be_empty) {
23033 // Verify that the entry is deleted, not altered by another transaction
23034 if (!VerifyVacancy(transaction, *entry_value)) {
23035 return false;
23036 }
23037 }
23038
23039 // Finally add the new entry to the chain
23040 auto value_ptr = value.get();
23041 map.UpdateEntry(std::move(value));
23042 // Push the old entry in the undo buffer for this transaction, so it can be restored in the event of failure
23043 if (transaction.transaction) {
23044 DuckTransactionManager::Get(GetCatalog().GetAttached())
23045 .PushCatalogEntry(*transaction.transaction, value_ptr->Child());
23046 }
23047 return true;
23048}
bool VerifyVacancy(CatalogTransaction transaction, CatalogEntry &entry)
Verify that the previous entry in the chain is dropped.
Definition duckdb.cpp:22967
bool StartChain(CatalogTransaction transaction, const string &name, unique_lock< mutex > &read_lock)
Start the catalog entry chain with a dummy node.
Definition duckdb.cpp:22947

◆ CheckCatalogEntryInvariants()

void duckdb::CatalogSet::CheckCatalogEntryInvariants ( CatalogEntry value,
const string &  name 
)
private
22985 {
22986 if (value.internal && !catalog.IsSystemCatalog() && name != DEFAULT_SCHEMA) {
22987 throw InternalException("Attempting to create internal entry \"%s\" in non-system catalog - internal entries "
22988 "can only be created in the system catalog",
22989 name);
22990 }
22991 if (!value.internal) {
22992 if (!value.temporary && catalog.IsSystemCatalog() && !IsDependencyEntry(value)) {
22993 throw InternalException(
22994 "Attempting to create non-internal entry \"%s\" in system catalog - the system catalog "
22995 "can only contain internal entries",
22996 name);
22997 }
22998 if (value.temporary && !catalog.IsTemporaryCatalog()) {
22999 throw InternalException("Attempting to create temporary entry \"%s\" in non-temporary catalog", name);
23000 }
23001 if (!value.temporary && catalog.IsTemporaryCatalog() && name != DEFAULT_SCHEMA) {
23002 throw InvalidInputException("Cannot create non-temporary entry \"%s\" in temporary catalog", name);
23003 }
23004 }
23005}

◆ VerifyVacancy()

bool duckdb::CatalogSet::VerifyVacancy ( CatalogTransaction  transaction,
CatalogEntry entry 
)
private

Verify that the previous entry in the chain is dropped.

22967 {
22968 if (HasConflict(transaction, entry.timestamp)) {
22969 // A transaction that is not visible to our snapshot has already made a change to this entry.
22970 // Because of Catalog limitations we can't push our change on this, even if the change was made by another
22971 // active transaction that might end up being aborted. So we have to cancel this transaction.
22972 throw TransactionException("Catalog write-write conflict on create with \"%s\"", entry.name);
22973 }
22974 // The entry is visible to our snapshot
22975 if (!entry.deleted) {
22976 return false;
22977 }
22978 return true;
22979}

◆ StartChain()

bool duckdb::CatalogSet::StartChain ( CatalogTransaction  transaction,
const string &  name,
unique_lock< mutex > &  read_lock 
)
private

Start the catalog entry chain with a dummy node.

22947 {
22948 D_ASSERT(!map.GetEntry(name));
22949
22950 // check if there is a default entry
22951 auto entry = CreateDefaultEntry(transaction, name, read_lock);
22952 if (entry) {
22953 return false;
22954 }
22955
22956 // first create a dummy deleted entry
22957 // so other transactions will see that instead of the entry that is to be added.
22958 auto dummy_node = make_uniq<InCatalogEntry>(CatalogType::INVALID, catalog, name);
22959 dummy_node->timestamp = 0;
22960 dummy_node->deleted = true;
22961 dummy_node->set = this;
22962
22963 map.AddEntry(std::move(dummy_node));
22964 return true;
22965}
Here is the call graph for this function:

◆ RenameEntryInternal()

bool duckdb::CatalogSet::RenameEntryInternal ( CatalogTransaction  transaction,
CatalogEntry old,
const string &  new_name,
AlterInfo alter_info,
unique_lock< mutex > &  read_lock 
)
private
23123 {
23124 auto &original_name = old.name;
23125
23126 auto &context = *transaction.context;
23127 auto entry_value = map.GetEntry(new_name);
23128 if (entry_value) {
23129 auto &existing_entry = GetEntryForTransaction(transaction, *entry_value);
23130 if (!existing_entry.deleted) {
23131 // There exists an entry by this name that is not deleted
23132 old.UndoAlter(context, alter_info);
23133 throw CatalogException("Could not rename \"%s\" to \"%s\": another entry with this name already exists!",
23134 original_name, new_name);
23135 }
23136 }
23137
23138 // Add a RENAMED_ENTRY before adding a DELETED_ENTRY, this makes it so that when this is committed
23139 // we know that this was not a DROP statement.
23140 auto renamed_tombstone = make_uniq<InCatalogEntry>(CatalogType::RENAMED_ENTRY, old.ParentCatalog(), original_name);
23141 renamed_tombstone->timestamp = transaction.transaction_id;
23142 renamed_tombstone->deleted = false;
23143 renamed_tombstone->set = this;
23144 if (!CreateEntryInternal(transaction, original_name, std::move(renamed_tombstone), read_lock,
23145 /*should_be_empty = */ false)) {
23146 return false;
23147 }
23148 if (!DropEntryInternal(transaction, original_name, false)) {
23149 return false;
23150 }
23151
23152 // Add the renamed entry
23153 // Start this off with a RENAMED_ENTRY node, for commit/cleanup/rollback purposes
23154 auto renamed_node = make_uniq<InCatalogEntry>(CatalogType::RENAMED_ENTRY, catalog, new_name);
23155 renamed_node->timestamp = transaction.transaction_id;
23156 renamed_node->deleted = false;
23157 renamed_node->set = this;
23158 return CreateEntryInternal(transaction, new_name, std::move(renamed_node), read_lock);
23159}

The documentation for this class was generated from the following files: