96 lines
3.2 KiB
PL/PgSQL
96 lines
3.2 KiB
PL/PgSQL
-- 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();
|
|
|
|
|