@@ -21,24 +21,24 @@ extern "C" {
2121#include < utils/guc.h>
2222#include < utils/lsyscache.h>
2323#include < utils/rel.h>
24- #include < utils/syscache.h>
2524#include < utils/snapmgr.h>
25+ #include < utils/syscache.h>
2626
2727#ifdef __cplusplus
2828}
2929#endif
3030
3131#include " table_storage.hpp"
3232
33- #include " exceptions.hpp"
3433#include " dl_catalog.hpp"
35- #include < storage/ exceptions.hpp>
34+ #include " exceptions.hpp"
3635#include " logger.hpp"
3736#include " memory_tracker.hpp"
3837#include " nd_utils.hpp"
3938#include " table_ddl_lock.hpp"
4039#include " table_scan.hpp"
4140#include " utils.hpp"
41+ #include < storage/exceptions.hpp>
4242
4343#include < icm/json.hpp>
4444#include < icm/string_map.hpp>
@@ -276,7 +276,13 @@ void table_storage::load_table_metadata()
276276 auto * rel = makeRangeVar (pstrdup (meta.schema_name .c_str ()), pstrdup (meta.table_name .c_str ()), -1 );
277277 Oid relid = RangeVarGetRelid (rel, NoLock, true );
278278 if (!OidIsValid (relid)) {
279- // Attempt to create missing table from catalog entry.
279+ // Table exists in catalog but not in PostgreSQL.
280+ if (in_ddl_context ()) {
281+ // During DDL (CREATE TABLE), skip auto-creation to avoid races.
282+ // The table might be in the middle of being created by another backend.
283+ continue ;
284+ }
285+ // Not in DDL context (e.g., SET root_path) - safe to auto-create.
280286 pg::utils::memory_context_switcher context_switcher;
281287 pg::utils::spi_connector connector;
282288 bool pushed_snapshot = false ;
@@ -293,14 +299,10 @@ void table_storage::load_table_metadata()
293299 SPI_execute (buf.data , false , 0 );
294300
295301 resetStringInfo (&buf);
296- appendStringInfo (&buf,
297- " SELECT create_deeplake_table(%s, %s)" ,
298- quote_literal_cstr (qualified_name.c_str ()),
299- qpath);
302+ appendStringInfo (
303+ &buf, " SELECT create_deeplake_table(%s, %s)" , quote_literal_cstr (qualified_name.c_str ()), qpath);
300304 if (SPI_execute (buf.data , false , 0 ) != SPI_OK_SELECT) {
301- elog (WARNING,
302- " Failed to auto-create deeplake table %s from catalog" ,
303- qualified_name.c_str ());
305+ elog (WARNING, " Failed to auto-create deeplake table %s from catalog" , qualified_name.c_str ());
304306 }
305307 if (pushed_snapshot) {
306308 PopActiveSnapshot ();
@@ -334,7 +336,8 @@ void table_storage::load_table_metadata()
334336 return ;
335337 }
336338
337- struct snapshot_guard {
339+ struct snapshot_guard
340+ {
338341 bool active = false ;
339342 snapshot_guard ()
340343 {
@@ -355,22 +358,21 @@ void table_storage::load_table_metadata()
355358 // If not, drop and recreate the table with the correct schema
356359 if (!pg::utils::check_column_exists (" pg_deeplake_tables" , " table_oid" )) {
357360 base::log_warning (base::log_channel::generic,
358- " Detected old schema for pg_deeplake_tables without table_oid column. "
359- " Dropping and recreating table to match current schema." );
361+ " Detected old schema for pg_deeplake_tables without table_oid column. "
362+ " Dropping and recreating table to match current schema." );
360363
361364 pg::utils::spi_connector connector;
362365 const char * drop_query = " DROP TABLE IF EXISTS public.pg_deeplake_tables CASCADE" ;
363366 if (SPI_execute (drop_query, false , 0 ) != SPI_OK_UTILITY) {
364367 base::log_warning (base::log_channel::generic, " Failed to drop old pg_deeplake_tables table" );
365368 }
366369
367- const char * create_query =
368- " CREATE TABLE public.pg_deeplake_tables ("
369- " id SERIAL PRIMARY KEY,"
370- " table_oid OID NOT NULL UNIQUE,"
371- " table_name NAME NOT NULL UNIQUE,"
372- " ds_path TEXT NOT NULL UNIQUE"
373- " )" ;
370+ const char * create_query = " CREATE TABLE public.pg_deeplake_tables ("
371+ " id SERIAL PRIMARY KEY,"
372+ " table_oid OID NOT NULL UNIQUE,"
373+ " table_name NAME NOT NULL UNIQUE,"
374+ " ds_path TEXT NOT NULL UNIQUE"
375+ " )" ;
374376 if (SPI_execute (create_query, false , 0 ) != SPI_OK_UTILITY) {
375377 base::log_warning (base::log_channel::generic, " Failed to create new pg_deeplake_tables table" );
376378 }
@@ -445,8 +447,10 @@ void table_storage::load_table_metadata()
445447 // Use the actual relation name from PostgreSQL catalog, not the cached metadata name
446448 // This ensures we have the current name even if the table was renamed
447449 std::string actual_table_name = get_qualified_table_name (rel);
448- elog (DEBUG1, " Loading table from metadata: cached_name=%s, actual_name=%s" ,
449- table_name, actual_table_name.c_str ());
450+ elog (DEBUG1,
451+ " Loading table from metadata: cached_name=%s, actual_name=%s" ,
452+ table_name,
453+ actual_table_name.c_str ());
450454 table_data td (
451455 relid, actual_table_name, CreateTupleDescCopy (RelationGetDescr (rel)), std::string (ds_path), creds);
452456 auto it2status = tables_.emplace (relid, std::move (td));
@@ -570,10 +574,11 @@ void table_storage::create_table(const std::string& table_name, Oid table_id, Tu
570574 // Use provided dataset path or construct default path
571575 if (!options.dataset_path ().empty ()) {
572576 if (!pg::allow_custom_paths) {
573- ereport (ERROR,
574- (errcode (ERRCODE_INVALID_PARAMETER_VALUE),
575- errmsg (" Custom dataset_path is disabled" ),
576- errhint (" Set deeplake.allow_custom_paths=on or omit dataset_path and configure deeplake.root_path" )));
577+ ereport (
578+ ERROR,
579+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE),
580+ errmsg (" Custom dataset_path is disabled" ),
581+ errhint (" Set deeplake.allow_custom_paths=on or omit dataset_path and configure deeplake.root_path" )));
577582 }
578583 // Explicit path provided via WITH clause
579584 dataset_path = options.dataset_path ();
0 commit comments