-- Files table augments and storage GC hooks -- 1) Add columns to files if missing do $$ begin if not exists ( select 1 from information_schema.columns where table_schema='public' and table_name='files' and column_name='uploaded_by' ) then alter table public.files add column uploaded_by uuid references public.profiles(id); end if; if not exists ( select 1 from information_schema.columns where table_schema='public' and table_name='files' and column_name='size_bytes' ) then alter table public.files add column size_bytes bigint; end if; if not exists ( select 1 from information_schema.columns where table_schema='public' and table_name='files' and column_name='source' ) then alter table public.files add column source text default 'uploader-web'; end if; end $$; -- 2) Unique index for cabinet/path combo create unique index if not exists uq_files_cabinet_path on public.files(cabinet_id, path); -- 3) Storage GC helpers (ported from neoFS with storage schema) create or replace function public._delete_storage_objects(p_bucket text, p_path text) returns void language plpgsql security definer set search_path to 'public', 'storage' as $$ begin if p_bucket is null or p_path is null then return; end if; delete from storage.objects where bucket_id = p_bucket and name = p_path; delete from storage.objects where bucket_id = p_bucket and name like p_path || '/%'; end $$; create or replace function public._storage_gc_sql() returns trigger language plpgsql security definer set search_path to 'public', 'storage' as $$ begin if tg_op = 'DELETE' then perform public._delete_storage_objects(old.bucket, old.path); elsif tg_op = 'UPDATE' then if (old.bucket is distinct from new.bucket) or (old.path is distinct from new.path) then perform public._delete_storage_objects(old.bucket, old.path); end if; end if; return null; end $$; -- 4) Attach GC trigger to files bucket/path changes drop trigger if exists trg_files_gc on public.files; create trigger trg_files_gc after delete or update of bucket, path on public.files for each row execute function public._storage_gc_sql(); -- 5) Document artefacts GC: remove artefact objects from storage when rows change/delete create or replace function public._artefact_gc_sql() returns trigger language plpgsql security definer set search_path to 'public', 'storage' as $$ declare v_bucket text; begin if tg_op = 'DELETE' then select f.bucket into v_bucket from public.files f where f.id = old.file_id; perform public._delete_storage_objects(v_bucket, old.rel_path); return old; elsif tg_op = 'UPDATE' then if (old.rel_path is distinct from new.rel_path) or (old.file_id is distinct from new.file_id) then select f.bucket into v_bucket from public.files f where f.id = old.file_id; perform public._delete_storage_objects(v_bucket, old.rel_path); end if; return new; end if; end $$; drop trigger if exists trg_document_artefacts_gc on public.document_artefacts; create trigger trg_document_artefacts_gc before delete or update of file_id, rel_path on public.document_artefacts for each row execute function public._artefact_gc_sql();