2014-05-21 10 views
5

Ho un database postgres con diverse tabelle su cui voglio guardare gli aggiornamenti, e se ci sono aggiornamenti, voglio lanciare un aggiornamento "hey, qualcosa cambiato". Questo funziona nel caso di base, ma ora è il momento di migliorare le cose.Rilevamento delle modifiche alle colonne in un trigger di aggiornamento postgres

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; 

funziona bene. Allego al tavolo in questo modo:

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

(Come un lato-domanda: se non c'è alcun/modo migliore più facile da JSON.stringify mio risultato grilletto rispetto al mess'o '$$ nella funzione di innesco, per favore fatemelo sapere. Il bilanciamento delle virgolette non è divertente).

Quello che voglio fare è allegare alla chiamata pg_notify una lista delle colonne che sono state cambiate. Non è come come se ci fosse un modo semplice per farlo a parte l'iterazione sulle colonne nella tabella e controllare se NEW.col è distinto da OLD.col. Il modo peggiore per farlo sarebbe quello di codificare i nomi delle colonne nella mia procedura di notifica (fragile, un'altra cosa da aggiornare se cambio il mio schema, ecc.).

Sono anche fuori dalla mia profondità nello scrivere plpgsql, davvero, quindi non sono sicuro di dove cercare aiuto. Idealmente, (se non c'è una variabile di blocco updated_columns che non ho visto nella documentazione) ci sarebbe un modo per ottenere lo schema della tabella all'interno del blocco di notifica senza causare un sovraccarico di prestazioni troppo serio (dato che queste tabelle verranno aggiornate bel po ').

risposta

6

Leggere sull'estensione hstore. In particolare è possibile creare un hstore da una fila, il che significa che si può fare qualcosa di simile:

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

che è leggermente più informazioni di quanto si voleva (include nuovi valori). È possibile utilizzare akeys(changed) se si desidera solo le chiavi.

+0

Questo era perfetto - ho fatto pg_notify ... hstore_to_json (hstore (NEW) - hstore (OLD)) ..., che funziona ad eccezione di grandi cambiamenti in colonne array-tipo (ottengono munged in stringhe che assomigliano agli array di Postgres "{1, 2, 3}" invece di "val" effettivi: [1, 2, 3] ragazzi nel risultante json, ma posso gestirlo dal lato client in quanto è un parsing numero – pfooti

+0

C'è il tipo json in 9.3 e molte improvvisazioni in arrivo in 9.4 (beta al momento). –

0

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

TD["table_name"] 

devo fare esattamente lo stesso tipo di notifica, ho ciclo attraverso tutte le colonne di questo tipo:

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

changed.append (k) costruisce la mia stringa di notifica. Da qualche altra parte ascolto, quindi trasmetto i risultati da pub/sub a client socket web.

-g

Problemi correlati