2014-05-21 14 views
5

Ich habe eine Postgres-Datenbank mit mehreren Tabellen, die ich auf Updates beobachten möchte, und wenn es Updates gibt, möchte ich ein "hey, etwas geändert" update. Dies funktioniert im Basisfall, aber jetzt ist es an der Zeit, Dinge zu verbessern.Erkennen von Spaltenänderungen in einem Postgres-Update-Trigger

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; 

funktioniert gut. Ich lege es auf den Tisch, wie so:

CREATE TRIGGER document_update_body 
AFTER UPDATE ON documents 
FOR EACH ROW EXECUTE PROCEDURE notify_update(); 

(Als Neben Frage: ob es besser/einfacher Weg, um mein Trigger Ergebnis als die mess'o '$$ in der Trigger-Funktion JSON.stringify, Bitte lass es mich wissen. Das Ausgleichen von Anführungszeichen macht keinen Spaß.

Ich möchte an den Aufruf pg_notify eine Liste der geänderten Spalten anhängen. Es ist nicht scheinen wie es gibt eine einfache Möglichkeit, dies zu tun als Iterieren über die Spalten in der Tabelle und überprüfen, ob NEW.col unterscheidet sich von OLD.col. Der schlechte Weg, dies zu tun, wäre, die Spaltennamen in meiner Benachrichtigungsprozedur hart zu codieren (zerbrechlich, eine andere Sache, die zu aktualisieren ist, wenn ich mein Schema usw. ändere).

Ich bin auch nicht in meiner Tiefe plpgsql zu schreiben, wirklich, so bin ich mir nicht sicher, wo ich nach Hilfe suchen. Im Idealfall (wenn keine Blockvariable "update_columns" vorhanden ist, die ich in der Dokumentation nicht sah), gibt es eine Möglichkeit, das Schema der Tabelle innerhalb des Benachrichtigungsblocks abzurufen, ohne einen zu hohen Leistungsaufwand zu verursachen (da diese Tabellen aktualisiert werden) faires Bit).

Antwort

6

Lesen Sie auf der hstore Erweiterung. Insbesondere Sie eine hstore aus einer Reihe schaffen kann, was bedeutet, dass Sie so etwas wie zu tun:

changes := hstore(NEW) - hstore(OLD); 
...pg_notify(... changes::text ...) 

Das ist etwas mehr Informationen, als Sie wollten (enthält neue Werte). Sie können akeys(changed) verwenden, wenn Sie nur die Schlüssel möchten.

+0

Das war perfekt - ich habe pg_notify ... hstore_to_json (hstore (NEW) - hstore (OLD)) ..., die große ausnehmend Änderungen in Array-Typ Spalten arbeitet (sie erhalten munged in Zeichenfolgen, die wie Postgres-Arrays "{1, 2, 3}" anstelle von "val" aussehen: [1, 2, 3] Typen im resultierenden json, aber ich kann auf der Client-Seite damit umgehen, da es sich um ein Parsing handelt – pfooti

+0

Es gibt den JSON-Typ in 9.3 und viele Verbesserungen kommen in 9.4 (Beta ab sofort). –

0

http://www.postgresql.org/docs/9.3/static/plpython-trigger.html

TD["table_name"] 

ich genau die gleiche Art von benachrichtigen, ich Schleife durch alle Spalten wie folgt aus:

for k in TD["new"]: 
     if TD["old"][k] != TD["new"][k]: 
      changed.append(k) 

changed.append (k) baut meine Meldung String. Irgendwo höre ich zu und sende dann die Ergebnisse aus Pub/Sub an die Web-Socket-Clients.

-g

Verwandte Themen