Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

track revisions in postgresql

I have to keep track of revisions of records in a table. What I've done is create a second table that inherits from the first and adds a revision counter.

CREATE TABLE A (
id SERIAL,
foo TEXT,
PRIMARY KEY (id));

CREATE TABLE B (
revision INTEGER NOT NULL) INHERITS (A);

Then I created a trigger that would update table B every time A is inserted/updated. What I can't figure out is how to make B.revision keep an individual "sequence" for each id.

Example: table A has 2 rows, i & j.
i has been updated 3 times and should have 3 revisions: (1, 2, 3).
j has been updated 2 times and should have two revisions: (1, 2).

Here is what I have so far, maybe I'm going down the wrong path and someone can help me!

CREATE OR REPLACE FUNCTION table_update() RETURNS TRIGGER AS $table_update$
    DECLARE
        last_revision INTEGER;
    BEGIN
        SELECT INTO last_revision MAX(revision) FROM B WHERE id = NEW.id;

        IF NOT FOUND THEN
            last_revision := 0;
        END IF;

        INSERT INTO B SELECT NEW.*;

        RETURN NEW;
    END;
$table_update$ LANGUAGE plpgsql;

CREATE TRIGGER table_update
AFTER INSERT OR UPDATE ON A
    FOR EACH ROW EXECUTE PROCEDURE table_update();
like image 950
veilig Avatar asked Feb 13 '10 21:02

veilig


People also ask

How to track database changes in PostgreSQL?

The easiest way to track changes made to tables in PostgreSWL is to write and use a generic PL/pgSQL function. Let suppose, you create a table to store history: CREATE SCHEMA logging; CREATE TABLE logging.

How do you find when was the table last updated in Postgres?

You can do it via checking last modification time of table's file. In postgresql,every table correspond one or more os files,like this: select relfilenode from pg_class where relname = 'test'; the relfilenode is the file name of table "test".

What is CDC in PostgreSQL?

Change Data Capture (CDC) allows you to track and propagate changes in a Postgres database to downstream consumers based on its Write-Ahead Log (WAL). In this guide, we'll cover how to use Materialize to create and efficiently maintain real-time materialized views on top of CDC data.


1 Answers

If you need the version numbers just for ordering, and don't specifically need them to be an integer that increase by one for each identifier, the easiest way to do it is to use a sequence for the revision and just let it do the tracking for you:

CREATE TABLE A (
    id SERIAL,
    foo TEXT,
    PRIMARY KEY (id)
);

CREATE TABLE B ( revision SERIAL NOT NULL) INHERITS (A);

CREATE OR REPLACE FUNCTION table_update() RETURNS TRIGGER AS $table_update$
    BEGIN
        INSERT INTO B SELECT NEW.*;
        RETURN NEW;
    END;
$table_update$ LANGUAGE plpgsql;

CREATE TRIGGER table_update
AFTER INSERT OR UPDATE ON A
    FOR EACH ROW EXECUTE PROCEDURE table_update();

Then do the inserts as usual:

    try=# insert into a (foo) values ('bar');
    INSERT 0 1
    try=# insert into a (foo) values ('bar');
    INSERT 0 1
    try=# update a set foo = 'you' where id = 1;
    UPDATE 2
    try=# select * from b;
     id | foo | revision 
    ----+-----+----------
      2 | bar |        2
      1 | you |        1
      1 | you |        3
    (3 rows)

So you can get all revisions for a given row like so:

    try=# select * from b where id = 1 order by revision;
     id | foo | revision 
    ----+-----+----------
      1 | you |        1
      1 | you |        3
    (2 rows)
like image 192
theory Avatar answered Sep 28 '22 15:09

theory