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::DependencyManager Class Reference

The DependencyManager is in charge of managing dependencies between catalog entries. More...

Collaboration diagram for duckdb::DependencyManager:

Public Member Functions

 DependencyManager (DuckCatalog &catalog)
 
void Scan (ClientContext &context, const std::function< void(CatalogEntry &, CatalogEntry &, const DependencyDependentFlags &)> &callback)
 Scans all dependencies, returning pairs of (object, dependent)
 
void AddOwnership (CatalogTransaction transaction, CatalogEntry &owner, CatalogEntry &entry)
 
void ReorderEntries (catalog_entry_vector_t &entries)
 Get the order of entries needed by EXPORT, the objects with no dependencies are exported first.
 
void ReorderEntries (catalog_entry_vector_t &entries, ClientContext &context)
 

Static Public Member Functions

static string GetSchema (const CatalogEntry &entry)
 
static MangledEntryName MangleName (const CatalogEntryInfo &info)
 
static MangledEntryName MangleName (const CatalogEntry &entry)
 
static CatalogEntryInfo GetLookupProperties (const CatalogEntry &entry)
 

Private Types

using dependency_entry_func_t = const std::function< unique_ptr< DependencyEntry >(Catalog &catalog, const DependencyDependent &dependent, const DependencySubject &dependency)>
 
using dependency_callback_t = const std::function< void(DependencyEntry &)>
 

Private Member Functions

bool IsSystemEntry (CatalogEntry &entry) const
 
optional_ptr< CatalogEntryLookupEntry (CatalogTransaction transaction, const LogicalDependency &dependency)
 
optional_ptr< CatalogEntryLookupEntry (CatalogTransaction transaction, CatalogEntry &dependency)
 
string CollectDependents (CatalogTransaction transaction, catalog_entry_set_t &entries, CatalogEntryInfo &info)
 
void CleanupDependencies (CatalogTransaction transaction, CatalogEntry &entry)
 
void ReorderEntry (CatalogTransaction transaction, CatalogEntry &entry, catalog_entry_set_t &visited, catalog_entry_vector_t &order)
 
void ReorderEntries (catalog_entry_vector_t &entries, CatalogTransaction transaction)
 
void AddObject (CatalogTransaction transaction, CatalogEntry &object, const LogicalDependencyList &dependencies)
 
void VerifyExistence (CatalogTransaction transaction, DependencyEntry &object)
 
void VerifyCommitDrop (CatalogTransaction transaction, transaction_t start_time, CatalogEntry &object)
 
catalog_entry_set_t CheckDropDependencies (CatalogTransaction transaction, CatalogEntry &object, bool cascade)
 Returns the objects that should be dropped alongside the object.
 
void DropObject (CatalogTransaction transaction, CatalogEntry &object, bool cascade)
 
void AlterObject (CatalogTransaction transaction, CatalogEntry &old_obj, CatalogEntry &new_obj, AlterInfo &info)
 
void RemoveDependency (CatalogTransaction transaction, const DependencyInfo &info)
 
void CreateDependency (CatalogTransaction transaction, DependencyInfo &info)
 
void CreateDependencies (CatalogTransaction transaction, const CatalogEntry &object, const LogicalDependencyList &dependencies)
 
void CreateSubject (CatalogTransaction transaction, const DependencyInfo &info)
 
void CreateDependent (CatalogTransaction transaction, const DependencyInfo &info)
 
void ScanDependents (CatalogTransaction transaction, const CatalogEntryInfo &info, dependency_callback_t &callback)
 
void ScanSubjects (CatalogTransaction transaction, const CatalogEntryInfo &info, dependency_callback_t &callback)
 
void ScanSetInternal (CatalogTransaction transaction, const CatalogEntryInfo &info, bool subjects, dependency_callback_t &callback)
 
void PrintSubjects (CatalogTransaction transaction, const CatalogEntryInfo &info)
 
void PrintDependents (CatalogTransaction transaction, const CatalogEntryInfo &info)
 
CatalogSetDependents ()
 
CatalogSetSubjects ()
 

Private Attributes

DuckCatalogcatalog
 
CatalogSet subjects
 
CatalogSet dependents
 

Friends

class CatalogSet
 

Detailed Description

The DependencyManager is in charge of managing dependencies between catalog entries.

Constructor & Destructor Documentation

◆ DependencyManager()

duckdb::DependencyManager::DependencyManager ( DuckCatalog catalog)
explicit
25520 : catalog(catalog), subjects(catalog), dependents(catalog) {
25521}

Member Function Documentation

◆ Scan()

void duckdb::DependencyManager::Scan ( ClientContext context,
const std::function< void(CatalogEntry &, CatalogEntry &, const DependencyDependentFlags &)> &  callback 
)

Scans all dependencies, returning pairs of (object, dependent)

26189 {
26190 auto transaction = catalog.GetCatalogTransaction(context);
26191 lock_guard<mutex> write_lock(catalog.GetWriteLock());
26192
26193 // All the objects registered in the dependency manager
26194 catalog_entry_set_t entries;
26195 dependents.Scan(transaction, [&](CatalogEntry &set) {
26196 auto entry = LookupEntry(transaction, set);
26197 entries.insert(*entry);
26198 });
26199
26200 // For every registered entry, get the dependents
26201 for (auto &entry : entries) {
26202 auto entry_info = GetLookupProperties(entry);
26203 // Scan all the dependents of the entry
26204 ScanDependents(transaction, entry_info, [&](DependencyEntry &dependent) {
26205 auto dep = LookupEntry(transaction, dependent);
26206 if (!dep) {
26207 return;
26208 }
26209 auto &dependent_entry = *dep;
26210 callback(entry, dependent_entry, dependent.Dependent().flags);
26211 });
26212 }
26213}
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

◆ AddOwnership()

void duckdb::DependencyManager::AddOwnership ( CatalogTransaction  transaction,
CatalogEntry owner,
CatalogEntry entry 
)
26215 {
26216 if (IsSystemEntry(entry) || IsSystemEntry(owner)) {
26217 return;
26218 }
26219
26220 // If the owner is already owned by something else, throw an error
26221 const auto owner_info = GetLookupProperties(owner);
26222 ScanDependents(transaction, owner_info, [&](DependencyEntry &dep) {
26223 if (dep.Dependent().flags.IsOwnedBy()) {
26224 throw DependencyException("%s can not become the owner, it is already owned by %s", owner.name,
26225 dep.EntryInfo().name);
26226 }
26227 });
26228
26229 // If the entry is the owner of another entry, throw an error
26230 auto entry_info = GetLookupProperties(entry);
26231 ScanSubjects(transaction, entry_info, [&](DependencyEntry &other) {
26232 auto dependent_entry = LookupEntry(transaction, other);
26233 if (!dependent_entry) {
26234 return;
26235 }
26236 auto &dep = *dependent_entry;
26237
26238 auto flags = other.Dependent().flags;
26239 if (!flags.IsOwnedBy()) {
26240 return;
26241 }
26242 throw DependencyException("%s already owns %s. Cannot have circular dependencies", entry.name, dep.name);
26243 });
26244
26245 // If the entry is already owned, throw an error
26246 ScanDependents(transaction, entry_info, [&](DependencyEntry &other) {
26247 auto dependent_entry = LookupEntry(transaction, other);
26248 if (!dependent_entry) {
26249 return;
26250 }
26251
26252 auto &dep = *dependent_entry;
26253 auto flags = other.Subject().flags;
26254 if (!flags.IsOwnership()) {
26255 return;
26256 }
26257 if (&dep != &owner) {
26258 throw DependencyException("%s is already owned by %s", entry.name, dep.name);
26259 }
26260 });
26261
26262 DependencyInfo info {
26263 /*dependent = */ DependencyDependent {GetLookupProperties(owner), DependencyDependentFlags().SetOwnedBy()},
26264 /*subject = */ DependencySubject {GetLookupProperties(entry), DependencySubjectFlags().SetOwnership()}};
26265 CreateDependency(transaction, info);
26266}

◆ ReorderEntries() [1/3]

void duckdb::DependencyManager::ReorderEntries ( catalog_entry_vector_t entries)

Get the order of entries needed by EXPORT, the objects with no dependencies are exported first.

26053 {
26054 // Read all committed entries
26055 CatalogTransaction transaction(catalog.GetDatabase(), TRANSACTION_ID_START - 1, TRANSACTION_ID_START - 1);
26056 ReorderEntries(entries, transaction);
26057}
void ReorderEntries(catalog_entry_vector_t &entries)
Get the order of entries needed by EXPORT, the objects with no dependencies are exported first.
Definition duckdb.cpp:26053
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReorderEntries() [2/3]

void duckdb::DependencyManager::ReorderEntries ( catalog_entry_vector_t entries,
ClientContext context 
)
26047 {
26048 auto transaction = catalog.GetCatalogTransaction(context);
26049 // Read all the entries visible to this snapshot
26050 ReorderEntries(entries, transaction);
26051}

◆ IsSystemEntry()

bool duckdb::DependencyManager::IsSystemEntry ( CatalogEntry entry) const
private
25559 {
25560 if (entry.internal) {
25561 return true;
25562 }
25563
25564 switch (entry.type) {
25565 case CatalogType::DEPENDENCY_ENTRY:
25566 case CatalogType::DATABASE_ENTRY:
25567 case CatalogType::RENAMED_ENTRY:
25568 return true;
25569 default:
25570 return false;
25571 }
25572}

◆ LookupEntry()

optional_ptr< CatalogEntry > duckdb::DependencyManager::LookupEntry ( CatalogTransaction  transaction,
CatalogEntry dependency 
)
private
25791 {
25792 if (dependency.type != CatalogType::DEPENDENCY_ENTRY) {
25793 return &dependency;
25794 }
25795 auto info = GetLookupProperties(dependency);
25796
25797 auto &type = info.type;
25798 auto &schema = info.schema;
25799 auto &name = info.name;
25800
25801 // Lookup the schema
25802 auto schema_entry = catalog.GetSchema(transaction, schema, OnEntryNotFound::RETURN_NULL);
25803 if (type == CatalogType::SCHEMA_ENTRY || !schema_entry) {
25804 // This is a schema entry, perform the callback only providing the schema
25805 return reinterpret_cast<CatalogEntry *>(schema_entry.get());
25806 }
25807 auto entry = schema_entry->GetEntry(transaction, type, name);
25808 return entry;
25809}
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

◆ CollectDependents()

string duckdb::DependencyManager::CollectDependents ( CatalogTransaction  transaction,
catalog_entry_set_t &  entries,
CatalogEntryInfo info 
)
private
25891 {
25892 string result;
25893 for (auto &entry : entries) {
25894 D_ASSERT(!IsSystemEntry(entry.get()));
25895 auto other_info = GetLookupProperties(entry);
25896 result += StringUtil::Format("%s depends on %s.\n", EntryToString(other_info), EntryToString(info));
25897 catalog_entry_set_t entry_dependents;
25898 ScanDependents(transaction, other_info, [&](DependencyEntry &dep) {
25899 auto child = LookupEntry(transaction, dep);
25900 if (!child) {
25901 return;
25902 }
25903 if (!CascadeDrop(false, dep.Dependent().flags)) {
25904 entry_dependents.insert(*child);
25905 }
25906 });
25907 if (!entry_dependents.empty()) {
25908 result += CollectDependents(transaction, entry_dependents, other_info);
25909 }
25910 }
25911 return result;
25912}
static string Format(const string fmt_str, ARGS... params)
Format a string using printf semantics.
Definition duckdb.hpp:4002

◆ CleanupDependencies()

void duckdb::DependencyManager::CleanupDependencies ( CatalogTransaction  transaction,
CatalogEntry entry 
)
private
25811 {
25812 // Collect the dependencies
25813 vector<DependencyInfo> to_remove;
25814
25815 auto info = GetLookupProperties(object);
25816 ScanSubjects(transaction, info,
25817 [&](DependencyEntry &dep) { to_remove.push_back(DependencyInfo::FromSubject(dep)); });
25818 ScanDependents(transaction, info,
25819 [&](DependencyEntry &dep) { to_remove.push_back(DependencyInfo::FromDependent(dep)); });
25820
25821 // Remove the dependency entries
25822 for (auto &dep : to_remove) {
25823 RemoveDependency(transaction, dep);
25824 }
25825}

◆ GetSchema()

string duckdb::DependencyManager::GetSchema ( const CatalogEntry entry)
static
25523 {
25524 if (entry.type == CatalogType::SCHEMA_ENTRY) {
25525 return entry.name;
25526 }
25527 return entry.ParentSchema().name;
25528}

◆ MangleName() [1/2]

MangledEntryName duckdb::DependencyManager::MangleName ( const CatalogEntryInfo info)
static
25530 {
25531 return MangledEntryName(info);
25532}

◆ MangleName() [2/2]

MangledEntryName duckdb::DependencyManager::MangleName ( const CatalogEntry entry)
static
25534 {
25535 if (entry.type == CatalogType::DEPENDENCY_ENTRY) {
25536 auto &dependency_entry = entry.Cast<DependencyEntry>();
25537 return dependency_entry.EntryMangledName();
25538 }
25539 auto type = entry.type;
25540 auto schema = GetSchema(entry);
25541 auto name = entry.name;
25542 CatalogEntryInfo info {type, schema, name};
25543
25544 return MangleName(info);
25545}

◆ GetLookupProperties()

CatalogEntryInfo duckdb::DependencyManager::GetLookupProperties ( const CatalogEntry entry)
static
25779 {
25780 if (entry.type == CatalogType::DEPENDENCY_ENTRY) {
25781 auto &dependency_entry = entry.Cast<DependencyEntry>();
25782 return dependency_entry.EntryInfo();
25783 } else {
25784 auto schema = DependencyManager::GetSchema(entry);
25785 auto &name = entry.name;
25786 auto &type = entry.type;
25787 return CatalogEntryInfo {type, schema, name};
25788 }
25789}

◆ ReorderEntry()

void duckdb::DependencyManager::ReorderEntry ( CatalogTransaction  transaction,
CatalogEntry entry,
catalog_entry_set_t &  visited,
catalog_entry_vector_t order 
)
private
26060 {
26061 auto &catalog_entry = *LookupEntry(transaction, entry);
26062 // We use this in CheckpointManager, it has the highest commit ID, allowing us to read any committed data
26063 bool allow_internal = transaction.start_time == TRANSACTION_ID_START - 1;
26064 if (visited.count(catalog_entry) || (!allow_internal && catalog_entry.internal)) {
26065 // Already seen and ordered appropriately
26066 return;
26067 }
26068
26069 // Check if there are any entries that this entry depends on, those are written first
26070 catalog_entry_vector_t dependents;
26071 auto info = GetLookupProperties(entry);
26072 ScanSubjects(transaction, info, [&](DependencyEntry &dep) { dependents.push_back(dep); });
26073 for (auto &dep : dependents) {
26074 ReorderEntry(transaction, dep, visited, order);
26075 }
26076
26077 // Then write the entry
26078 visited.insert(catalog_entry);
26079 order.push_back(catalog_entry);
26080}

◆ ReorderEntries() [3/3]

void duckdb::DependencyManager::ReorderEntries ( catalog_entry_vector_t entries,
CatalogTransaction  transaction 
)
private
26082 {
26083 catalog_entry_vector_t reordered;
26084 catalog_entry_set_t visited;
26085 for (auto &entry : entries) {
26086 ReorderEntry(transaction, entry, visited, reordered);
26087 }
26088 // If this would fail, that means there are more entries that we somehow reached through the dependency manager
26089 // but those entries should not actually be visible to this transaction
26090 D_ASSERT(entries.size() == reordered.size());
26091 entries.clear();
26092 entries = reordered;
26093}

◆ AddObject()

void duckdb::DependencyManager::AddObject ( CatalogTransaction  transaction,
CatalogEntry object,
const LogicalDependencyList dependencies 
)
private
25760 {
25761 if (IsSystemEntry(object)) {
25762 // Don't do anything for this
25763 return;
25764 }
25765 CreateDependencies(transaction, object, dependencies);
25766}

◆ VerifyExistence()

void duckdb::DependencyManager::VerifyExistence ( CatalogTransaction  transaction,
DependencyEntry object 
)
private
25914 {
25915 auto &subject = object.Subject();
25916
25917 CatalogEntryInfo info;
25918 if (subject.flags.IsOwnership()) {
25919 info = object.SourceInfo();
25920 } else {
25921 info = object.EntryInfo();
25922 }
25923
25924 auto &type = info.type;
25925 auto &schema = info.schema;
25926 auto &name = info.name;
25927
25928 auto &duck_catalog = catalog.Cast<DuckCatalog>();
25929 auto &schema_catalog_set = duck_catalog.GetSchemaCatalogSet();
25930
25931 CatalogSet::EntryLookup lookup_result;
25932 lookup_result = schema_catalog_set.GetEntryDetailed(transaction, schema);
25933
25934 if (type != CatalogType::SCHEMA_ENTRY && lookup_result.result) {
25935 auto &schema_entry = lookup_result.result->Cast<SchemaCatalogEntry>();
25936 EntryLookupInfo lookup_info(type, name);
25937 lookup_result = schema_entry.LookupEntryDetailed(transaction, lookup_info);
25938 }
25939
25940 if (lookup_result.reason == CatalogSet::EntryLookup::FailureReason::DELETED) {
25941 throw DependencyException("Could not commit creation of dependency, subject \"%s\" has been deleted",
25942 object.SourceInfo().name);
25943 }
25944}

◆ VerifyCommitDrop()

void duckdb::DependencyManager::VerifyCommitDrop ( CatalogTransaction  transaction,
transaction_t  start_time,
CatalogEntry object 
)
private
25947 {
25948 if (IsSystemEntry(object)) {
25949 return;
25950 }
25951 auto info = GetLookupProperties(object);
25952 ScanDependents(transaction, info, [&](DependencyEntry &dep) {
25953 auto dep_committed_at = dep.timestamp.load();
25954 if (dep_committed_at > start_time) {
25955 // In the event of a CASCADE, the dependency drop has not committed yet
25956 // so we would be halted by the existence of a dependency we are already dropping unless we check the
25957 // timestamp
25958 //
25959 // Which differentiates between objects that we were already aware of (and will subsequently be dropped) and
25960 // objects that were introduced inbetween, which should cause this error:
25961 throw DependencyException(
25962 "Could not commit DROP of \"%s\" because a dependency was created after the transaction started",
25963 object.name);
25964 }
25965 });
25966 ScanSubjects(transaction, info, [&](DependencyEntry &dep) {
25967 auto dep_committed_at = dep.timestamp.load();
25968 if (!dep.Dependent().flags.IsOwnedBy()) {
25969 return;
25970 }
25971 D_ASSERT(dep.Subject().flags.IsOwnership());
25972 if (dep_committed_at > start_time) {
25973 // Same as above, objects that are owned by the object that is being dropped will be dropped as part of this
25974 // transaction. Only objects that were introduced by other transactions, that this transaction could not
25975 // see, should cause this error:
25976 throw DependencyException(
25977 "Could not commit DROP of \"%s\" because a dependency was created after the transaction started",
25978 object.name);
25979 }
25980 });
25981}

◆ CheckDropDependencies()

catalog_entry_set_t duckdb::DependencyManager::CheckDropDependencies ( CatalogTransaction  transaction,
CatalogEntry object,
bool  cascade 
)
private

Returns the objects that should be dropped alongside the object.

25984 {
25985 if (IsSystemEntry(object)) {
25986 // Don't do anything for this
25987 return catalog_entry_set_t();
25988 }
25989
25990 catalog_entry_set_t to_drop;
25991 catalog_entry_set_t blocking_dependents;
25992
25993 auto info = GetLookupProperties(object);
25994 // Look through all the objects that depend on the 'object'
25995 ScanDependents(transaction, info, [&](DependencyEntry &dep) {
25996 // It makes no sense to have a schema depend on anything
25997 D_ASSERT(dep.EntryInfo().type != CatalogType::SCHEMA_ENTRY);
25998 auto entry = LookupEntry(transaction, dep);
25999 if (!entry) {
26000 return;
26001 }
26002
26003 if (!CascadeDrop(cascade, dep.Dependent().flags)) {
26004 // no cascade and there are objects that depend on this object: throw error
26005 blocking_dependents.insert(*entry);
26006 } else {
26007 to_drop.insert(*entry);
26008 }
26009 });
26010 if (!blocking_dependents.empty()) {
26011 string error_string =
26012 StringUtil::Format("Cannot drop entry \"%s\" because there are entries that depend on it.\n", object.name);
26013 error_string += CollectDependents(transaction, blocking_dependents, info);
26014 error_string += "Use DROP...CASCADE to drop all dependents.";
26015 throw DependencyException(error_string);
26016 }
26017
26018 // Look through all the entries that 'object' depends on
26019 ScanSubjects(transaction, info, [&](DependencyEntry &dep) {
26020 auto flags = dep.Subject().flags;
26021 if (flags.IsOwnership()) {
26022 // We own this object, it should be dropped along with the table
26023 auto entry = LookupEntry(transaction, dep);
26024 to_drop.insert(*entry);
26025 }
26026 });
26027 return to_drop;
26028}
Here is the call graph for this function:

◆ DropObject()

void duckdb::DependencyManager::DropObject ( CatalogTransaction  transaction,
CatalogEntry object,
bool  cascade 
)
private
26030 {
26031 if (IsSystemEntry(object)) {
26032 // Don't do anything for this
26033 return;
26034 }
26035
26036 // Check if there are any entries that block the DROP because they still depend on the object
26037 auto to_drop = CheckDropDependencies(transaction, object, cascade);
26038 CleanupDependencies(transaction, object);
26039
26040 for (auto &entry : to_drop) {
26041 auto set = entry.get().set;
26042 D_ASSERT(set);
26043 set->DropEntry(transaction, entry.get().name, cascade);
26044 }
26045}
catalog_entry_set_t CheckDropDependencies(CatalogTransaction transaction, CatalogEntry &object, bool cascade)
Returns the objects that should be dropped alongside the object.
Definition duckdb.cpp:25983

◆ AlterObject()

void duckdb::DependencyManager::AlterObject ( CatalogTransaction  transaction,
CatalogEntry old_obj,
CatalogEntry new_obj,
AlterInfo info 
)
private
26096 {
26097 if (IsSystemEntry(new_obj)) {
26098 D_ASSERT(IsSystemEntry(old_obj));
26099 // Don't do anything for this
26100 return;
26101 }
26102
26103 const auto old_info = GetLookupProperties(old_obj);
26104 const auto new_info = GetLookupProperties(new_obj);
26105
26106 vector<DependencyInfo> dependencies;
26107 // Other entries that depend on us
26108 ScanDependents(transaction, old_info, [&](DependencyEntry &dep) {
26109 // It makes no sense to have a schema depend on anything
26110 D_ASSERT(dep.EntryInfo().type != CatalogType::SCHEMA_ENTRY);
26111
26112 bool disallow_alter = true;
26113 switch (alter_info.type) {
26114 case AlterType::ALTER_TABLE: {
26115 auto &alter_table = alter_info.Cast<AlterTableInfo>();
26116 switch (alter_table.alter_table_type) {
26117 case AlterTableType::FOREIGN_KEY_CONSTRAINT: {
26118 // These alters are made as part of a CREATE or DROP table statement when a foreign key column is
26119 // present either adding or removing a reference to the referenced primary key table
26120 disallow_alter = false;
26121 break;
26122 }
26123 case AlterTableType::ADD_COLUMN:
26124 case AlterTableType::SET_DEFAULT: {
26125 disallow_alter = false;
26126 break;
26127 }
26128 default:
26129 break;
26130 }
26131 break;
26132 }
26133 case AlterType::SET_COLUMN_COMMENT:
26134 case AlterType::SET_COMMENT: {
26135 disallow_alter = false;
26136 break;
26137 }
26138 default:
26139 break;
26140 }
26141 if (disallow_alter) {
26142 throw DependencyException("Cannot alter entry \"%s\" because there are entries that "
26143 "depend on it.",
26144 old_obj.name);
26145 }
26146
26147 auto dep_info = DependencyInfo::FromDependent(dep);
26148 dep_info.subject.entry = new_info;
26149 dependencies.emplace_back(dep_info);
26150 });
26151
26152 // Keep old dependencies
26153 bool has_new_dependencies = alter_info.new_dependencies.get();
26154 ScanSubjects(transaction, old_info, [&](DependencyEntry &dep) {
26155 if (has_new_dependencies && !dep.Subject().flags.IsOwnership()) {
26156 // The alter provided updated dependencies - skip old non-ownership subject dependencies
26157 // as they will be replaced by the new dependencies
26158 return;
26159 }
26160 auto entry = LookupEntry(transaction, dep);
26161 if (!entry) {
26162 return;
26163 }
26164
26165 auto dep_info = DependencyInfo::FromSubject(dep);
26166 dep_info.dependent.entry = new_info;
26167 dependencies.emplace_back(dep_info);
26168 });
26169
26170 if (has_new_dependencies || !StringUtil::CIEquals(old_obj.name, new_obj.name)) {
26171 // The dependencies have changed (e.g. SET DEFAULT) or the name has changed
26172 // We need to recreate the dependency links
26173 CleanupDependencies(transaction, old_obj);
26174 }
26175
26176 if (has_new_dependencies) {
26177 // Add the new dependencies
26178 CreateDependencies(transaction, new_obj, *alter_info.new_dependencies);
26179 }
26180
26181 // Reinstate any old dependencies
26182 for (auto &dep : dependencies) {
26183 CreateDependency(transaction, dep);
26184 }
26185}
static DUCKDB_API bool CIEquals(const string &l1, const string &l2)
Case insensitive equals.

◆ RemoveDependency()

void duckdb::DependencyManager::RemoveDependency ( CatalogTransaction  transaction,
const DependencyInfo info 
)
private
25649 {
25650 auto &dependent = info.dependent;
25651 auto &subject = info.subject;
25652
25653 // The dependents of the dependency (target)
25654 DependencyCatalogSet dependents(Dependents(), subject.entry);
25655 // The subjects of the dependencies of the dependent
25656 DependencyCatalogSet subjects(Subjects(), dependent.entry);
25657
25658 auto dependent_mangled = MangledEntryName(dependent.entry);
25659 auto subject_mangled = MangledEntryName(subject.entry);
25660
25661 auto dependent_p = dependents.GetEntry(transaction, dependent_mangled);
25662 if (dependent_p) {
25663 // 'dependent' is no longer inhibiting the deletion of 'dependency'
25664 dependents.DropEntry(transaction, dependent_mangled, false);
25665 }
25666 auto subject_p = subjects.GetEntry(transaction, subject_mangled);
25667 if (subject_p) {
25668 // 'dependency' is no longer required by 'dependent'
25669 subjects.DropEntry(transaction, subject_mangled, false);
25670 }
25671}

◆ CreateDependency()

void duckdb::DependencyManager::CreateDependency ( CatalogTransaction  transaction,
DependencyInfo info 
)
private
25695 {
25696 DependencyCatalogSet subjects(Subjects(), info.dependent.entry);
25697 DependencyCatalogSet dependents(Dependents(), info.subject.entry);
25698
25699 auto subject_mangled = MangleName(info.subject.entry);
25700 auto dependent_mangled = MangleName(info.dependent.entry);
25701
25702 auto &dependent_flags = info.dependent.flags;
25703 auto &subject_flags = info.subject.flags;
25704
25705 auto existing_subject = subjects.GetEntry(transaction, subject_mangled);
25706 auto existing_dependent = dependents.GetEntry(transaction, dependent_mangled);
25707
25708 // Inherit the existing flags and drop the existing entry if present
25709 if (existing_subject) {
25710 auto &existing = existing_subject->Cast<DependencyEntry>();
25711 auto existing_flags = existing.Subject().flags;
25712 if (existing_flags != subject_flags) {
25713 subject_flags.Apply(existing_flags);
25714 }
25715 subjects.DropEntry(transaction, subject_mangled, false, false);
25716 }
25717 if (existing_dependent) {
25718 auto &existing = existing_dependent->Cast<DependencyEntry>();
25719 auto existing_flags = existing.Dependent().flags;
25720 if (existing_flags != dependent_flags) {
25721 dependent_flags.Apply(existing_flags);
25722 }
25723 dependents.DropEntry(transaction, dependent_mangled, false, false);
25724 }
25725
25726 // Create an entry in the dependents map of the object that is the target of the dependency
25727 CreateDependent(transaction, info);
25728 // Create an entry in the subjects map of the object that is targeting another entry
25729 CreateSubject(transaction, info);
25730}
void CreateDependent(CatalogTransaction transaction, const DependencyInfo &info)
Definition duckdb.cpp:25684
void CreateSubject(CatalogTransaction transaction, const DependencyInfo &info)
Definition duckdb.cpp:25673

◆ CreateDependencies()

void duckdb::DependencyManager::CreateDependencies ( CatalogTransaction  transaction,
const CatalogEntry object,
const LogicalDependencyList dependencies 
)
private
25733 {
25734 DependencyDependentFlags dependency_flags;
25735 if (object.type != CatalogType::INDEX_ENTRY) {
25736 // indexes do not require CASCADE to be dropped, they are simply always dropped along with the table
25737 dependency_flags.SetBlocking();
25738 }
25739
25740 const auto object_info = GetLookupProperties(object);
25741 // check for each object in the sources if they were not deleted yet
25742 for (auto &dependency : dependencies.Set()) {
25743 if (dependency.catalog != object.ParentCatalog().GetName()) {
25744 throw DependencyException(
25745 "Error adding dependency for object \"%s\" - dependency \"%s\" is in catalog "
25746 "\"%s\", which does not match the catalog \"%s\".\nCross catalog dependencies are not supported.",
25747 object.name, dependency.entry.name, dependency.catalog, object.ParentCatalog().GetName());
25748 }
25749 }
25750
25751 // add the object to the dependents_map of each object that it depends on
25752 for (auto &dependency : dependencies.Set()) {
25753 DependencyInfo info {/*dependent = */ DependencyDependent {GetLookupProperties(object), dependency_flags},
25754 /*subject = */ DependencySubject {dependency.entry, DependencySubjectFlags()}};
25755 CreateDependency(transaction, info);
25756 }
25757}

◆ CreateSubject()

void duckdb::DependencyManager::CreateSubject ( CatalogTransaction  transaction,
const DependencyInfo info 
)
private

Add to the list of objects that 'dependent' has a dependency on

25673 {
25674 auto &from = info.dependent.entry;
25675
25676 DependencyCatalogSet set(Subjects(), from);
25677 auto dep = make_uniq_base<DependencyEntry, DependencySubjectEntry>(catalog, info);
25678 auto entry_name = dep->EntryMangledName();
25679
25681 set.CreateEntry(transaction, entry_name, std::move(dep));
25682}

◆ CreateDependent()

void duckdb::DependencyManager::CreateDependent ( CatalogTransaction  transaction,
const DependencyInfo info 
)
private

Add to the list of object that depend on 'subject'

25684 {
25685 auto &from = info.subject.entry;
25686
25687 DependencyCatalogSet set(Dependents(), from);
25688 auto dep = make_uniq_base<DependencyEntry, DependencyDependentEntry>(catalog, info);
25689 auto entry_name = dep->EntryMangledName();
25690
25692 set.CreateEntry(transaction, entry_name, std::move(dep));
25693}

◆ ScanDependents()

void duckdb::DependencyManager::ScanDependents ( CatalogTransaction  transaction,
const CatalogEntryInfo info,
dependency_callback_t &  callback 
)
private
25640 {
25641 ScanSetInternal(transaction, info, false, callback);
25642}

◆ ScanSubjects()

void duckdb::DependencyManager::ScanSubjects ( CatalogTransaction  transaction,
const CatalogEntryInfo info,
dependency_callback_t &  callback 
)
private
25645 {
25646 ScanSetInternal(transaction, info, true, callback);
25647}

◆ ScanSetInternal()

void duckdb::DependencyManager::ScanSetInternal ( CatalogTransaction  transaction,
const CatalogEntryInfo info,
bool  subjects,
dependency_callback_t &  callback 
)
private
25583 {
25584 catalog_entry_set_t other_entries;
25585
25586 auto cb = [&](CatalogEntry &other) {
25587 D_ASSERT(other.type == CatalogType::DEPENDENCY_ENTRY);
25588 auto &other_entry = other.Cast<DependencyEntry>();
25589#ifdef DEBUG
25590 auto side = other_entry.Side();
25591 if (scan_subjects) {
25592 D_ASSERT(side == DependencyEntryType::SUBJECT);
25593 } else {
25594 D_ASSERT(side == DependencyEntryType::DEPENDENT);
25595 }
25596
25597#endif
25598
25599 other_entries.insert(other_entry);
25600 callback(other_entry);
25601 };
25602
25603 if (scan_subjects) {
25604 DependencyCatalogSet subjects(Subjects(), info);
25605 subjects.Scan(transaction, cb);
25606 } else {
25607 DependencyCatalogSet dependents(Dependents(), info);
25608 dependents.Scan(transaction, cb);
25609 }
25610
25611#ifdef DEBUG
25612 // Verify some invariants
25613 // Every dependency should have a matching dependent in the other set
25614 // And vice versa
25615 auto mangled_name = MangleName(info);
25616
25617 if (scan_subjects) {
25618 for (auto &entry : other_entries) {
25619 auto other_info = GetLookupProperties(entry);
25620 DependencyCatalogSet other_dependents(Dependents(), other_info);
25621
25622 // Verify that the other half of the dependency also exists
25623 auto dependent = other_dependents.GetEntryDetailed(transaction, mangled_name);
25624 D_ASSERT(dependent.reason != CatalogSet::EntryLookup::FailureReason::NOT_PRESENT);
25625 }
25626 } else {
25627 for (auto &entry : other_entries) {
25628 auto other_info = GetLookupProperties(entry);
25629 DependencyCatalogSet other_subjects(Subjects(), other_info);
25630
25631 // Verify that the other half of the dependent also exists
25632 auto subject = other_subjects.GetEntryDetailed(transaction, mangled_name);
25633 D_ASSERT(subject.reason != CatalogSet::EntryLookup::FailureReason::NOT_PRESENT);
25634 }
25635 }
25636#endif
25637}

◆ PrintSubjects()

void duckdb::DependencyManager::PrintSubjects ( CatalogTransaction  transaction,
const CatalogEntryInfo info 
)
private
26278 {
26279 auto name = MangleName(info);
26280 Printer::Print(StringUtil::Format("Subjects of %s", FormatString(name)));
26281 auto subjects = DependencyCatalogSet(Subjects(), info);
26282 subjects.Scan(transaction, [&](CatalogEntry &dependency) {
26283 auto &dep = dependency.Cast<DependencyEntry>();
26284 auto &entry_info = dep.EntryInfo();
26285 auto type = entry_info.type;
26286 auto schema = entry_info.schema;
26287 auto name = entry_info.name;
26288 Printer::Print(StringUtil::Format("Schema: %s | Name: %s | Type: %s | Dependent type: %s | Subject type: %s",
26289 schema, name, CatalogTypeToString(type), dep.Dependent().flags.ToString(),
26290 dep.Subject().flags.ToString()));
26291 });
26292}
static DUCKDB_API void Print(OutputStream stream, const string &str)
Print the object to the stream.

◆ PrintDependents()

void duckdb::DependencyManager::PrintDependents ( CatalogTransaction  transaction,
const CatalogEntryInfo info 
)
private
26294 {
26295 auto name = MangleName(info);
26296 Printer::Print(StringUtil::Format("Dependents of %s", FormatString(name)));
26297 auto dependents = DependencyCatalogSet(Dependents(), info);
26298 dependents.Scan(transaction, [&](CatalogEntry &dependent) {
26299 auto &dep = dependent.Cast<DependencyEntry>();
26300 auto &entry_info = dep.EntryInfo();
26301 auto type = entry_info.type;
26302 auto schema = entry_info.schema;
26303 auto name = entry_info.name;
26304 Printer::Print(StringUtil::Format("Schema: %s | Name: %s | Type: %s | Dependent type: %s | Subject type: %s",
26305 schema, name, CatalogTypeToString(type), dep.Dependent().flags.ToString(),
26306 dep.Subject().flags.ToString()));
26307 });
26308}

◆ Dependents()

CatalogSet & duckdb::DependencyManager::Dependents ( )
private
25574 {
25575 return dependents;
25576}

◆ Subjects()

CatalogSet & duckdb::DependencyManager::Subjects ( )
private
25578 {
25579 return subjects;
25580}

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