Skip to content

Instantly share code, notes, and snippets.

@tangrammer
Created May 22, 2018 09:54
Show Gist options
  • Save tangrammer/63285d9002d37c39490ba317d94a6df8 to your computer and use it in GitHub Desktop.
Save tangrammer/63285d9002d37c39490ba317d94a6df8 to your computer and use it in GitHub Desktop.
CREATE OR REPLACE FUNCTION history.log_change() RETURNS trigger AS $_$
DECLARE
c refcursor;
tt tstzrange;
r record;
str text;
my_new text;
BEGIN
str := '';
my_new := '';
FOR r IN SELECT (each(hstore(NEW))).*
LOOP
RAISE NOTICE '% value is %', r.key, quote_nullable(r.value);
str := str || ',' || r.key;
my_new := my_new || ',$1.' || r.key;
END LOOP;
str := SUBSTRING(str FROM 2);
my_new := SUBSTRING(my_new FROM 2);
RAISE NOTICE 'str: %', str;
RAISE NOTICE 'my_new: %', my_new;
IF TG_OP = 'INSERT' THEN
-- RAISE NOTICE 'SELECT % from %', str, NEW;
EXECUTE 'INSERT INTO history.' || TG_TABLE_NAME || ' (_validrange, ' || str || ' )'
' SELECT tstzrange(now(), $$infinity$$, $$[)$$), '|| my_new ||'' USING NEW;
RETURN NEW;
ELSIF TG_OP = 'UPDATE' THEN
OPEN c FOR EXECUTE 'SELECT _validrange FROM history.' || TG_TABLE_NAME ||
' WHERE id = $1 ORDER BY _validrange DESC LIMIT 1 FOR UPDATE'
USING NEW.id;
FETCH FROM c INTO tt;
IF isempty(tstzrange(lower(tt), now(), $$[)$$)) THEN
EXECUTE 'DELETE FROM history.' || TG_TABLE_NAME ||
' WHERE CURRENT OF ' || quote_ident(c::text);
ELSE
EXECUTE 'UPDATE history.' || TG_TABLE_NAME || ' SET _validrange = tstzrange($1, now(), $$[)$$)' ||
' WHERE CURRENT OF ' || quote_ident(c::text) USING lower(tt);
END IF;
EXECUTE 'INSERT INTO history.' || TG_TABLE_NAME || ' (_validrange, ' || str || ' )'
' SELECT tstzrange(now(), $$infinity$$, $$[)$$), '|| my_new ||'' USING NEW;
RETURN NEW;
ELSIF TG_OP = 'DELETE' THEN
OPEN c FOR EXECUTE 'SELECT _validrange FROM history.' || TG_TABLE_NAME ||
' WHERE id = $1 ORDER BY _validrange DESC LIMIT 1 FOR UPDATE' USING OLD.id;
FETCH FROM c into tt;
IF isempty(tstzrange(lower(tt), now(), $$[)$$)) THEN
EXECUTE 'DELETE FROM history.' || TG_TABLE_NAME ||
' WHERE CURRENT OF ' || quote_ident(c::text);
RETURN OLD;
END IF;
EXECUTE 'UPDATE history.' || TG_TABLE_NAME ||
' SET _validrange = tstzrange($1, now(), $$[)$$) WHERE CURRENT OF ' ||
quote_ident(c::text) USING lower(tt);
RETURN OLD;
END IF;
RETURN NULL;
END;
$_$ LANGUAGE plpgsql;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment