1. Capitulo 1
-- Necessário para remover acentos ao gerar o slug (café -> cafe).
create extension if not exists "unaccent";
-- ----------------------------------------------------------------------------
-- slugify: minúsculo, sem acento, tudo que não for [a-z0-9] vira hífen,
-- hífens repetidos colapsam, sem hífen nas pontas.
-- ----------------------------------------------------------------------------
create function public.slugify(value text)
returns text
language sql
stable
as $$
select trim(both '-' from
regexp_replace(
regexp_replace(lower(unaccent(coalesce(value, ''))), '[^a-z0-9]+', '-', 'g'),
'-{2,}', '-', 'g'
)
);
$$;
-- ----------------------------------------------------------------------------
-- Garante unicidade: se o slug base já existir, anexa -2, -3, ... até achar
-- um livre. exclude_id evita que uma linha colida "com ela mesma" num update.
-- ----------------------------------------------------------------------------
create function public.generate_unique_content_slug(base_slug text, exclude_id uuid default null)
returns text
language plpgsql
stable
as $$
declare
normalized_base text := coalesce(nullif(base_slug, ''), 'conteudo');
candidate text := normalized_base;
suffix int := 1;
begin
while exists (
select 1 from public.content
where slug = candidate
and (exclude_id is null or id <> exclude_id)
) loop
suffix := suffix + 1;
candidate := normalized_base || '-' || suffix;
end loop;
return candidate;
end;
$$;
-- ============================================================================
-- content.slug
-- ============================================================================
alter table public.content add column slug text;
update public.content
set slug = public.generate_unique_content_slug(public.slugify(titulo), id)
where slug is null;
alter table public.content
alter column slug set not null,
add constraint content_slug_key unique (slug);
-- ----------------------------------------------------------------------------
-- Gera o slug automaticamente a partir do título quando ele não é informado
-- (insert sem slug, ou update que limpa o campo). Se o admin definir/editar
-- o slug manualmente, o trigger não mexe nele.
-- ----------------------------------------------------------------------------
create function public.set_content_slug()
returns trigger
language plpgsql
as $$
begin
if new.slug is null or btrim(new.slug) = '' then
new.slug := public.generate_unique_content_slug(public.slugify(new.titulo), new.id);
end if;
return new;
end;
$$;
create trigger content_set_slug
before insert or update on public.content
for each row execute function public.set_content_slug();