Mit einem trigger externe Programme verständigen

Liebe Gemeinschaft,

ich bin auf der Suche nach einer Möglichkeit, nach einem update, insert oder delet externe Programme(jave) zu verständigen, dass es neue Daten gibt.
Als erstes dachte ich an einen Trigger. Ich möchte gerne eine Methode eines Java-Programs aufrufen, um diesem mitzuteilen, dass es neue Daten zu laden gibt.
Ein ständiges laden der Tabellen und anschließend im Programm zu vergelichen ob es Änderungen gibt ist kein Lösungsansatz für mich.

Ist es Möglich mit einem Trigger ein Programm zu verständigen? Fallen euch bessere Möglickeiten dazu ein?
Ich verwende die Version 9.4

mit freundlichen Grüßen
andreas

LISTEN / NOTIFY würde mir da spontan einfallen.

Dein Java Program macht ein LISTEN, der Trigger verschickt ein NOTIFY.

Ein Beispiel dafür gibt’s in der Doku für den JDBC Treiber: https://jdbc.postgresql.org/documentation/94/listennotify.html

Neben Listen/Nofify, schon genannt, ginge evtl. auch eine Art ‘Jobtabelle’, die Du via Trigger füllst und aus Deiner anderen Software zyklisch abfragst. Aber Listen&Notify ist eigentlich genau dafür gedacht.

Disclamer: Ich arbeite am gleichen Project wie andreas600

Wir haben es nun so gelöst (falls es irgendwen noch interessiert):

Es gibt ein “Script”-Erweiterung für PostgreSql die sich PL/sh Procedural Language Handler for PostgreSQL (https://github.com/petere/plsh)

Da kann man in Funktionen sowas wie

CREATE or REPLACE FUNCTION test(text) RETURNS text AS '
#!/bin/bash
 echo Test: $1 is working
' LANGUAGE plsh;

machen

Damit setzt man dann zum Beispiel einen Before-Input-Trigger auf eine Tabelle

CREATE TRIGGER tbefore BEFORE INSERT OR UPDATE OR DELETE ON tabellenname
    FOR EACH ROW EXECUTE PROCEDURE test('meh');

Ich hoffe das hilft auch Anderen bei ähnlich gesuchten Funktionalität

Nachteile:

  • ausführender User braucht Superuserrechte, weil pl/sh untrusted ist
  • die Ausführung ist relativ teuer

wollt ich nur gesagt haben …

Hallo,

ich würde hier akretschmer Recht geben und finde die Lösung auch nicht so optimal.
Auch hat man hier ja dann das Problem, dass man nochmal ne Komponente mit rein nimmt, was unter Umständen das ganze unnötig komplex und Fehleranfällig macht.
Von der möglichen Performanceproblematik mal abgesehen, die bei einem Trigger ja früher oder später oft auftauchen. Je nachdem wie oft die Daten da angepasst werden. Bei 2-3 Aktualisierungen die Minute, ist das natürlich eher Wurscht.
Mein Vorschlag:

Eine Statustabelle, welche den Tabellennamen und ein Boolean enthält. Die Anwendung prüft hier den Boolean zu der Tabelle. Ist dieser True sind neue Daten vorhanden und müssen neu eingelesen werden. Sobald die Anwendung das mitbekommt, setzt Sie das Feld auf False und liest ein. Falls so in der Zwischenzeit neue Daten kommen, wird das Feld wenigstens direkt wieder auf True gesetzt und es geht nix verloren.
Um das Feld auf True zu setzen, würde ich sagen, kann der Trigger gesetzt werden, der dann prüft, ob das Feld auf True steht und ggf. korrigiert. Hat man immer noch das eventuelle Performancethema, aber es sind wenigstens keine großen Dritt-Funktionen beteiligt.
Alternativ könnte auch einfach der Mechanismus, welcher da die Daten manipuliert das Feld anpassen, wenn der Commit durch ist. So ist auch gleich sichergestellt, dass die Daten nur dann neu eingelesen werden, wenn da auch wirklich alles sicher drin ist.

Am elegantesten ist hier aber am Ende die LISTEN/NOTIFY-Variante und die würde ich, wenn ich schon in Java arbeiten muss und das ganze “nativ” vom Treiber unterstützt, auch nutzen. :slight_smile: