I have a postgres database with several tables that I want to watch for updates on, and if there's any updates, I want to fire a "hey, something changed" update. This works in the basic case, but now it's time to improve things.
CREATE FUNCTION notify_update() RETURNS trigger AS $notifyfunction$
BEGIN
PERFORM pg_notify('update_watchers',
$${"event":"update", "type": "$$ || TG_TABLE_NAME || $$", "payload": {"id": $$ || new.id || $$}}$$);
RETURN new;
END;
$notifyfunction$ LANGUAGE plpgsql;
works just fine. I attach it to the table like so:
CREATE TRIGGER document_update_body
AFTER UPDATE ON documents
FOR EACH ROW EXECUTE PROCEDURE notify_update();
(As a side-question: if there's any better / easier way to json.stringify my trigger result than the mess'o'$$ in the trigger function, please let me know. Balancing quotation marks isn't fun).
What I want to do is attach to the pg_notify call a list of the columns that have changed. It doesn't seem like there's any simple way to do this other than iterating over the columns in the table and checking if NEW.col is distinct from OLD.col. The bad way to do this would be to hard-code the column names in my notify procedure (fragile, another thing to update if I change my schema, etc).
I'm also out of my depth on writing plpgsql, really, so I'm not sure where to look for help. Ideally, (if there's no updated_columns block variable that I didn't see in the documentation) there'd be a way to get the table's schema inside the notification block without causing too serious of a performance overhead (as these tables will get updated a fair bit).
Read up on the hstore extension. In particular you can create a hstore from a row, which means you can do something like:
changes := hstore(NEW) - hstore(OLD);
...pg_notify(... changes::text ...)
That's slightly more information than you wanted (includes new values). You can use akeys(changed)
if you just want the keys.
http://www.postgresql.org/docs/9.3/static/plpython-trigger.html
TD["table_name"]
I do exactly the same type of notify, I loop through all of the columns like this:
for k in TD["new"]:
if TD["old"][k] != TD["new"][k]:
changed.append(k)
changed.append(k) builds my notification string. Somewhere else I do a listen, then broadcast the results out pub/sub to web socket clients.
-g
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With