====== Eingabeprüfung mit Triggern ====== ---- Es werden grundsätzlich **keine Regeln** (Rules) für die Prüfung von Nutzereingaben verwendet, sondern ausschließlich **Trigger**! Die Prüfung von nutzerseitigen Eingaben in kvwmap erfolgt ausschließlich über Trigger und Triggerfunktionen. Der Trigger wird bei der entsprechenden Tabelle notiert und verweist auf die Triggerfunktion(en). Triggerfunktionen werden beim zugehörigen Schema gespeichert. \\ \\ Der Weg ist: Zuerst die Triggerfunktionen und anschließend der Trigger. \\ \\ ===== Triggerfunktion ===== Die Triggerfunktion für die Prüfung der Nutzereingaben erhält den Namen der Tabelle, die geprüft wird, dahinter "//_check_entries//". Beispiel: kindertagespflege_person_check_entries Die Funktion ist transaktional auszuführen, die ganze Anweisung steht also in BEGIN ... RETURN NEW; END; **RETURN NEW** wird immer vor dem letzten END notiert, das die Transaktion beendet und bedeutet, dass das INSERT bzw. das UPDATE auch tatsächlich ausgeführt wird. **RETURN NEW** muss notiert werden. In der Transaktion kann die Anwendungsoperation unterschieden werden, bei Prüfungen also INSERT oder UPDATE. Dafür wird je ein IF notiert in der Form IF (TG_OP = 'INSERT') THEN ... END IF; IF (TG_OP = 'UPDATE') THEN ... END IF; Wenn diese IFs weggelassen werden, wird die Prüfung bei beiden Anwendungsoperationen ausgeführt. Diese IFs können auch schon weitere Bedingungen enthalten, es ist aber übersichtlicher, die Prüfung in ein eigenes IF zu schreiben: IF (TG_OP = 'INSERT') THEN IF THEN ... END IF; END IF; Das Ergebnis der Prüfung mündet immer in einen Text, den der Nutzer bekommt. Dieser Text muss ihm alle notwendigen Informationen an die Hand geben, damit er weiß, was passiert ist. Die Prüfung mündet in drei mögliche Zustände: * Die Prüfung mündet in einen **Hinweis** (INSERT bzw. UPDATE soll trotzdem durchgeführt werden) IF (TG_OP = 'INSERT') THEN IF THEN RAISE INFO 'Hier kommt der Hinweistext für den Nutzer'; END IF; END IF; \\ \\ * Die Prüfung mündet in eine **Warnung** (INSERT bzw. UPDATE soll trotzdem durchgeführt werden) IF (TG_OP = 'INSERT') THEN IF THEN RAISE WARNING 'Hier kommt die Warnung für den Nutzer'; END IF; END IF; \\ \\ * Die Prüfung ergibt einen **Fehler** (INSERT bzw. UPDATE soll **NICHT** durchgeführt werden) IF (TG_OP = 'INSERT') THEN IF THEN RAISE EXCEPTION 'Hier kommt die Fehlermeldung für den Nutzer'; END IF; END IF; \\ \\ Statt RAISE INFO kann auch RAISE NOTICE verwendet werden. IF (TG_OP = 'INSERT') THEN IF THEN RAISE NOTICE 'Text, den der Nutzer lesen soll'; END IF; END IF; Es kann statt des einfachen Textes ein JSON-String übergeben werden. kvwmap passt dann die Darstellung des Textes und des Hintergrundes an. IF (TG_OP = 'INSERT') THEN IF THEN RAISE NOTICE '{"success" : false, "msg_type" : "warning", "msg" : "Text, den der Nutzer lesen soll"}'; END IF; END IF; "success" entscheidet nur über die Hintergrundfarbe der Message und ist unwichtig für die Behandlung des Datensatzes. Ob die Verarbeitung des Datensatzes im Fehlerfall abgelehnt wird oder nicht, entscheidet ausschließlich ein gegebenenfalls danach notiertes **RETURN NULL**! RETURN NULL bedeutet, dass die ganze Transaktion sofort abgebrochen wird und lediglich die NOTICE ausgeliefert wird. Beachte: Bei RAISE EXCEPTION ist das **nicht** nötig. Wenn bei RAISE NOTICE die Prüfung ergeben soll, dass der Datensatz **nicht** gespeichert wird, dann muss zusätzlich **RETURN NULL** notiert werden! IF (TG_OP = 'INSERT') THEN IF THEN RAISE NOTICE 'Text, den der Nutzer lesen soll'; RETURN NULL; END IF; END IF; \\ \\ Bei RAISE-Texten können auch Werte aus new bzw. old eingefügt werden. An die Stelle im Text, wo der Wert stehen soll, wird ein Prozentzeichen gesetzt, nach dem Text wird mit Komma getrennt der Wert definiert: THEN RAISE EXCEPTION 'Auftragsnummer % ist bereits vergeben!', upper(new.antragsnr); END IF; \\ \\ ===== Trigger ===== Trigger zur Prüfung der Nutzereingaben sind grundsätzlich BEFORE-Trigger: create trigger before insert or update on for each row execute procedure (); Der Trigger könnte auch nur before insert oder nur before update sein, aber in der Regel sind beide Fälle nötig. Außerdem kann man den jeweiligen Anwendungsfall in der Triggerfunktion definieren, siehe oben. Der Trigger sollte prinzipiell getrennt werden von sonstigen Triggern, die vielleicht auch noch an der Tabelle hängen und sonst was machen. Pro Tabelle sollte es im Regelfall höchstens genau einen Trigger zur Prüfung der Nutzereingaben geben. Der Trigger zur Prüfung der Nutzereingaben soll grundsätzlich "**check_entries**" heißen: create trigger check_entries before insert or update on geodaten_landkreis.kindertagespflege_verantwortliche for each row execute procedure geodaten_landkreis.kindertagespflege_person_check_entries();