diff --git a/src/duckdb/src/catalog/catalog_set.cpp b/src/duckdb/src/catalog/catalog_set.cpp index d374f6999..94913185a 100644 --- a/src/duckdb/src/catalog/catalog_set.cpp +++ b/src/duckdb/src/catalog/catalog_set.cpp @@ -564,12 +564,17 @@ optional_ptr CatalogSet::CreateDefaultEntry(CatalogTransaction tra // no defaults either: return null return nullptr; } - read_lock.unlock(); + auto unlock = !defaults->LockDuringCreate(); + if (unlock) { + read_lock.unlock(); + } // this catalog set has a default map defined // check if there is a default entry that we can create with this name auto entry = defaults->CreateDefaultEntry(transaction, name); - read_lock.lock(); + if (unlock) { + read_lock.lock(); + } if (!entry) { // no default entry return nullptr; @@ -582,7 +587,9 @@ optional_ptr CatalogSet::CreateDefaultEntry(CatalogTransaction tra // we found a default entry, but failed // this means somebody else created the entry first // just retry? - read_lock.unlock(); + if (unlock) { + read_lock.unlock(); + } return GetEntry(transaction, name); } @@ -653,6 +660,7 @@ void CatalogSet::CreateDefaultEntries(CatalogTransaction transaction, unique_loc if (!defaults || defaults->created_all_entries) { return; } + auto unlock = !defaults->LockDuringCreate(); // this catalog set has a default set defined: auto default_entries = defaults->GetDefaultEntries(); for (auto &default_entry : default_entries) { @@ -660,13 +668,17 @@ void CatalogSet::CreateDefaultEntries(CatalogTransaction transaction, unique_loc if (!entry_value) { // we unlock during the CreateEntry, since it might reference other catalog sets... // specifically for views this can happen since the view will be bound - read_lock.unlock(); + if (unlock) { + read_lock.unlock(); + } auto entry = defaults->CreateDefaultEntry(transaction, default_entry); if (!entry) { throw InternalException("Failed to create default entry for %s", default_entry); } - read_lock.lock(); + if (unlock) { + read_lock.lock(); + } CreateCommittedEntry(std::move(entry)); } } diff --git a/src/duckdb/src/function/table/version/pragma_version.cpp b/src/duckdb/src/function/table/version/pragma_version.cpp index 28003047c..8c9b4c745 100644 --- a/src/duckdb/src/function/table/version/pragma_version.cpp +++ b/src/duckdb/src/function/table/version/pragma_version.cpp @@ -1,5 +1,5 @@ #ifndef DUCKDB_PATCH_VERSION -#define DUCKDB_PATCH_VERSION "5-dev2" +#define DUCKDB_PATCH_VERSION "5-dev4" #endif #ifndef DUCKDB_MINOR_VERSION #define DUCKDB_MINOR_VERSION 4 @@ -8,10 +8,10 @@ #define DUCKDB_MAJOR_VERSION 1 #endif #ifndef DUCKDB_VERSION -#define DUCKDB_VERSION "v1.4.5-dev2" +#define DUCKDB_VERSION "v1.4.5-dev4" #endif #ifndef DUCKDB_SOURCE_ID -#define DUCKDB_SOURCE_ID "32ae75b320" +#define DUCKDB_SOURCE_ID "b6fbc09f79" #endif #include "duckdb/function/table/system_functions.hpp" #include "duckdb/main/database.hpp" diff --git a/src/duckdb/src/include/duckdb/catalog/default/default_generator.hpp b/src/duckdb/src/include/duckdb/catalog/default/default_generator.hpp index 02480084a..88161f7c4 100644 --- a/src/duckdb/src/include/duckdb/catalog/default/default_generator.hpp +++ b/src/duckdb/src/include/duckdb/catalog/default/default_generator.hpp @@ -28,6 +28,12 @@ class DefaultGenerator { virtual unique_ptr CreateDefaultEntry(CatalogTransaction transaction, const string &entry_name); //! Get a list of all default entries in the generator virtual vector GetDefaultEntries() = 0; + //! Whether or not we should keep the lock while calling CreateDefaultEntry + //! If this is set to false, CreateDefaultEntry might be called multiple times in parallel also for the same entry + //! Otherwise it will be called exactly once per entry + virtual bool LockDuringCreate() const { + return false; + } }; } // namespace duckdb diff --git a/src/duckdb/src/include/duckdb/main/secret/secret_manager.hpp b/src/duckdb/src/include/duckdb/main/secret/secret_manager.hpp index 80fb46044..482281801 100644 --- a/src/duckdb/src/include/duckdb/main/secret/secret_manager.hpp +++ b/src/duckdb/src/include/duckdb/main/secret/secret_manager.hpp @@ -217,6 +217,9 @@ class DefaultSecretGenerator : public DefaultGenerator { unique_ptr CreateDefaultEntry(CatalogTransaction transaction, const string &entry_name) override; unique_ptr CreateDefaultEntry(ClientContext &context, const string &entry_name) override; vector GetDefaultEntries() override; + bool LockDuringCreate() const override { + return true; + } protected: unique_ptr CreateDefaultEntryInternal(const string &entry_name);