| 968 | } |
| 969 | |
| 970 | void table_storage::drop_table(const std::string& table_name) |
| 971 | { |
| 972 | // Load metadata BEFORE acquiring the DDL lock. |
| 973 | // force_load_table_metadata() may trigger CREATE TABLE (via SPI) for tables |
| 974 | // in the S3 catalog that don't exist in pg_class yet. CREATE TABLE goes |
| 975 | // through the table AM which also acquires the DDL lock — doing that while |
| 976 | // we already hold it would self-deadlock (LWLocks are not recursive). |
| 977 | if (!table_exists(table_name)) { |
| 978 | force_load_table_metadata(); |
| 979 | } |
| 980 | pg::table_ddl_lock_guard ddl_lock; |
| 981 | if (table_exists(table_name)) { |
| 982 | auto& table_data = get_table_data(table_name); |
| 983 | auto creds = session_credentials::get_credentials(); |
| 984 | |
| 985 | // Update stateless catalog if enabled |
| 986 | if (pg::stateless_enabled) { |
| 987 | const auto root_dir = []() { |
| 988 | auto root = session_credentials::get_root_path(); |
| 989 | if (root.empty()) { |
| 990 | root = pg::utils::get_deeplake_root_directory(); |
| 991 | } |
| 992 | return root; |
| 993 | }(); |
| 994 | pg::dl_catalog::ensure_catalog(root_dir, creds); |
| 995 | auto [schema_name, simple_table_name] = split_table_name(table_name); |
| 996 | pg::dl_catalog::table_meta meta; |
| 997 | meta.table_id = schema_name + "." + simple_table_name; |
| 998 | meta.schema_name = schema_name; |
| 999 | meta.table_name = simple_table_name; |
| 1000 | meta.dataset_path = table_data.get_dataset_path().url(); |
| 1001 | meta.state = "dropping"; |
| 1002 | pg::dl_catalog::upsert_table(root_dir, creds, meta); |
| 1003 | pg::dl_catalog::bump_catalog_version(root_dir, session_credentials::get_credentials()); |
| 1004 | catalog_version_ = pg::dl_catalog::get_catalog_version(root_dir, session_credentials::get_credentials()); |
| 1005 | } |
| 1006 | |
| 1007 | try { |
| 1008 | table_data.commit(); // Ensure all changes are committed before deletion |
| 1009 | table_version_tracker::drop_table(table_data.get_table_oid()); |
| 1010 | deeplake_api::delete_dataset(table_data.get_dataset_path(), std::move(creds)).get_future().get(); |
| 1011 | } catch (const storage::storage_key_not_found&) { |
| 1012 | // Dataset does not exist, silently continue with deletion |
| 1013 | elog(DEBUG1, "Dataset not found during table drop, continuing silently"); |
| 1014 | } catch (const base::exception& e) { |
| 1015 | // Dataset deletion failed - log warning but continue with table cleanup |
| 1016 | // This handles cases where dataset was already deleted externally |
| 1017 | elog(WARNING, "Failed to delete dataset during table drop: %s", e.what()); |
| 1018 | } |
| 1019 | erase_table(table_name); |
| 1020 | } |
| 1021 | /// FreeTupleDesc(table_data.tuple_descriptor_); |
| 1022 | erase_table_metadata(table_name); |
| 1023 | } |
| 1024 | |
| 1025 | void table_storage::insert_slot(Oid table_id, TupleTableSlot* slot) |
| 1026 | { |
nothing calls this directly
no test coverage detected