Trigger mit Update

Servus!

Ich habe vor, folgendes funktionierendes Statement in einen Trigger zu packen:

UPDATE test
SET flaeche_qm = area(geometry)

area(geometry) ist eine PostGIS-Funktion.

Ich habe zwei Varianten versucht.

Variante 1:

BEGIN
 IF (TG_OP = 'UPDATE') THEN 
UPDATE test SET flaeche_qm = area(geometry);
RETURN NEW;
 END IF;
END;

Fehler:

ERROR:  stack depth limit exceeded
TIP:  Increase the configuration parameter "max_stack_depth", after ensuring the platform's stack depth limit is adequate.

Variante 2:

BEGIN
 IF (TG_OP = 'UPDATE') THEN 
NEW.flaeche_qm = area(geometry);
RETURN NEW;
 END IF;
END;

Fehler:

ERROR:  column "geometry" does not exist
ZEILE 1: SELECT area(geometry)
                     ^

Die Spalte geometry existiert aber.

Was könnte denn bei beiden das Problem sein?

gruß,
johannes

Rekursion ohne Ende, Du rufst für ein Update wieder Update auf, welches wieder Update aufruft, was ein Update auslöst, welches …


Variante 2:

BEGIN
IF (TG_OP = ‘UPDATE’) THEN
NEW.flaeche_qm = area(geometry);
RETURN NEW;
END IF;
END;

>
> Fehler:
>
> ```text
ERROR:  column "geometry" does not exist
ZEILE 1: SELECT area(geometry)
                     ^

Schnellschuß: area(NEW.geometry) verwenden.

Falls mein Schnellschuß flasch ist: sorry.


Andreas

Hallo Andreas,

Dass der erste Versuch eine endlos-schleife ist, hab ich schon vermutet, jetzt hab ichs gecheckt. Danke.

Ich hab weiter rumprobiert und hab folgende (Halb-)Lösung:

BEGIN

 IF (TG_OP = 'INSERT') THEN
UPDATE test SET flaeche_qm = area(geometry);

 END IF;
END;

Funktioniert einwandfrei bei INSERT. Wenns aber um ein UPDATE geht, weiß ich nicht weiter. Der Schnellschuss von Dir Andreas funktioniert leider nicht.

ELSIF (TG_OP = 'UPDATE') THEN
flaeche_qm = area(NEW.geometry);
RETURN NEW;

meldet einen Syntax-Fehler.
Bei

 NEW.flaeche_qm = area(NEW.geometry);

gibts zwar keine Fehlermeldung und man kann auch Updaten ohne Meldung, aber es passiert halt leider auch keine Berechnung.

Hat jemand vielleicht noch ne Idee?

Gruß,
Johannes

Prinzipiell kann ich keinen Fehler sehen, vielleicht liegt es im Zusammenspiel mit PostGIS.

Hier noch mal ein Bleistift:

test=# create or replace function tg() returns trigger as $$begin if (TG_OP = 'INSERT') then NEW.name='foo_insert'; elsif (TG_OP = 'UPDATE') then NEW.name='foo_update'; end if; return NEW; end;$$ language plpgsql;
CREATE FUNCTION

test=# create trigger tg1 before insert or update on animals for each row execute procedure tg();
CREATE TRIGGER
test=# select * from animals ;
 id |  name
----+--------
  5 | cat
  5 | dog
  5 | turtle
(3 rowtest=*# select * from animals ;
 id |    name
----+------------
  1 | foo_update
  1 | foo_update
  1 | foo_update

test=*# insert into animals (id) values (2);
INSERT 0 1
Time: 1.308 ms
test=*# select * from animals ;
 id |    name
----+------------
  1 | foo_update
  1 | foo_update
  1 | foo_update
  2 | foo_insert
(4 rows)

Andreas

Servus,

Ich hab jetzt auch mal nach deinem Beispiel rumgespielt und es funktionierte, wie es sollte, solange keine geometry-Spalte im Spiel war. Auch das Aufrufen einer (Nicht-PostGIS-)Funktion bei NEW.bla hat geklappt. Zum Beispiel:

 NEW.datum=now();

Es liegt anscheinend tatsächlich an PostGIS. Ich hab da mal an die mailing-liste geschrieben.

[EDIT]:

Es liegt NICHT an PostGIS, sondern an mir. Ich habe den TRIGGER mit AFTER INSERT OR UPDATE deklariert, was anscheinend falsch ist.
Bei BEFORE INSERT OR UPDATE funktioniert die ganze Sache mit

NEW.flaeche_qm = area(NEW.geometry);

Komplette Lösung in der Abteilung PostGIS.

Gruß,
Johannes