One article (The Next Platform) had published_at 2026-07-15 while scraped 2026-06-19 -- an article cannot be published after it was scraped. One-time clamp to the scrape date + BEFORE INSERT/UPDATE trigger to prevent recurrence.
33 lines
1.5 KiB
PL/PgSQL
33 lines
1.5 KiB
PL/PgSQL
-- sql/127-news-future-date-guard.sql
|
|
-- News published_at cannot be in the future: an article cannot be published after
|
|
-- we scraped it. One future-dated row found 2026-07-06 (The Next Platform, pub
|
|
-- 2026-07-15 but created/scraped 2026-06-19). One-time correction + ingest guard so
|
|
-- it cannot recur (a CHECK with now() is not immutable/allowed -> BEFORE trigger).
|
|
-- Idempotent; safe to re-run.
|
|
|
|
-- One-time: clamp any future published_at to the scrape date (created_at), else now().
|
|
update news_articles
|
|
set published_at = least(published_at, coalesce(created_at, now()))
|
|
where published_at is not null and published_at > now();
|
|
|
|
create or replace function news_published_at_guard() returns trigger
|
|
language plpgsql as $$
|
|
begin
|
|
if NEW.published_at is not null and NEW.published_at > now() then
|
|
NEW.published_at := least(coalesce(NEW.created_at, now()), now());
|
|
end if;
|
|
return NEW;
|
|
end $$;
|
|
|
|
comment on function news_published_at_guard() is
|
|
'BEFORE INSERT/UPDATE on news_articles: clamps a future published_at to the scrape date (created_at) or now(). Prevents future-dated news polluting the feed.';
|
|
|
|
drop trigger if exists trg_news_published_at_guard on news_articles;
|
|
create trigger trg_news_published_at_guard
|
|
before insert or update on news_articles
|
|
for each row execute function news_published_at_guard();
|
|
|
|
insert into _migrations (filename, applied_at)
|
|
select '127-news-future-date-guard.sql', now()
|
|
where not exists (select 1 from _migrations where filename = '127-news-future-date-guard.sql');
|