2014-05-21 13 views
5

Mam bazę danych PostgreSQL z kilkoma tabelami, które chcę obejrzeć na bieżąco, a jeśli są jakieś aktualizacje, chcę wystrzelić aktualizację "hej, coś się zmieniło". Działa to w podstawowym przypadku, ale teraz nadszedł czas na poprawę.Wykrywanie zmian kolumn w wyzwalaczu aktualizacji PostgreSQL

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; 

działa dobrze. I dołączyć go do stołu tak:

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

(Na marginesie pytanie: czy jest jakiś lepszy/łatwiejszy sposób JSON.stringify mój wynik wyzwalania niż mess'o $$ 'w funkcji wyzwalania, proszę dać mi znać. Wyrównanie cudzysłowów nie jest zabawne).

Co chcę zrobić, to dołączyć do wywołania pg_notify listę kolumn, które uległy zmianie. Nie wydaje się, że jest to jeden prosty sposób, aby zrobić to inaczej niż iterowanie po kolumnach w tabeli i sprawdzanie, czy NEW.col różni się od OLD.col. Złym sposobem na to byłoby sztywne kodowanie nazw kolumn w mojej procedurze powiadamiania (delikatna, kolejna rzecz do aktualizacji, jeśli zmienię swój schemat, itp.).

Jestem również poza moim zasięgiem pisania naprawdę, więc nie jestem pewien, gdzie szukać pomocy. Idealnie (jeśli nie ma żadnej zmiennej blokującej updated_columns, której nie widziałem w dokumentacji), istnieje sposób na uzyskanie schematu tabeli wewnątrz bloku powiadomień bez powodowania zbyt poważnych obciążeń związanych z wydajnością (ponieważ te tabele zostaną zaktualizowane uczciwy bit).

Odpowiedz

6

Czytaj na rozszerzeniu hstore. W szczególności można utworzyć hstore z rzędu, co oznacza, że ​​można zrobić coś takiego:

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

To nieco więcej informacji niż chciałeś (zawiera nowe wartości). Możesz użyć akeys(changed), jeśli chcesz tylko klucze.

+0

To było idealne - zrobiłem pg_notify ... hstore_to_json (hstore (NEW) - hstore (OLD)) ..., która działa z wyjątkiem wielkich zmian w kolumnach typu array (oni trafiają do munged ciągi, które wyglądają jak tablice Postgres "{1, 2, 3}" zamiast rzeczywistych "val": [1, 2, 3] faceci w wynikowym jsonie, ale mogę sobie z tym poradzić po stronie klienta, ponieważ jest to parsowanie wydanie: – pfooti

+0

Istnieje typ json w wersji 9.3 i wiele ulepszeń przychodzących w wersji 9.4 (obecnie beta). Warto sprawdzić. –

0

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

TD["table_name"] 

mam dokładnie ten sam typ zawiadomić, że pętla przez wszystkie kolumny, takich jak ten:

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

changed.append (k) buduje mój powiadamiania ciąg. Gdzie indziej słucham, a następnie publikuję wyniki poza pub/sub dla klientów gniazd internetowych.

-g