Страница 1 из 1

триггер примитивного контроля топологии

Добавлено: 13 фев 2012, 00:34
SS_Rebelious
За последнее время видел несколько обсуждений топологии в PostGIS и решил придумать для одного из своих слоёв некий костыль для примитивного контроля пересечения полигонов.

Вот так я представляю себе искомый триггер:

Код: Выделить всё

CREATE TRIGGER enforce_topology
    BEFORE INSERT OR UPDATE OF the_geom ON settlement_polygon
    FOR EACH ROW
    WHEN (EXISTS(ST_Intersects(NEW.the_geom, OLD.the_geom) 
                 and NEW.gid <> OLD.giid 
                 and not   ST_Touches(NEW.the_geom, OLD.the_geom)))
EXECUTE PROCEDURE on insert restrict, on update restrict;
Но получаю ошибку: syntax error at or near "exists", а если убрать exists, то

Код: Выделить всё

ERROR:  syntax error at or near "on"
LINE 5: EXECUTE PROCEDURE on insert restrict, on update restrict;
                          ^
********** Error **********
Как правильно записывается в данном случае команда на запрещение модификации, и почему не нравится "exists"?

Хорошего (популярного) описания работы триггеров в Postgre/PostGIS, к сожалению, не нашёл, поэтому плохо представляю, какие основные команды используются в триггерах postgres. Если знаете такое - ткните пожалуйста.

Re: триггер примитивного контроля топологии

Добавлено: 13 фев 2012, 01:56
Aleksandr Dezhin
Вообще триггер в postgresql состоит из двух частей:

1) триггер-функция, в которой описано какие операции нужно прозивести с данными, для plpgsql описано тут
2) непосредственно триггер, который описывает как и когда нужно вызвать триггер-функцию, описано тут

Простенький пример с проверкой топологии (для такого на самом деле триггер то и не нужен, делается простым CONSTRAINT):

Код: Выделить всё

CREATE OR REPLACE FUNCTION check_geom() RETURNS trigger AS $$
BEGIN
  IF NOT ST_IsValid(NEW.geom) THEN
    RAISE EXCEPTION 'Invalid geometry!';
  END IF;
  RETURN NEW;
END; $$ LANGUAGE 'plpgsql';

CREATE TRIGGER sometable_check_geom_trigger BEFORE INSERT OR UPDATE
ON sometable FOR EACH ROW EXECUTE PROCEDURE check_geom();    
Судя по вашему коду вам нужно проверить не пересекается ли новый полигон с другими полигонами слоя. В этом случае триггер-функция будет выглядеть приблизительно так (по-мелочи в синтаксисе мог напутать):

Код: Выделить всё

CREATE OR REPLACE FUNCTION check_geom() RETURNS trigger AS $$
DECLARE
  gid integer;
BEGIN
  SELECT INTO gid c.gid
    FROM sometable c WHERE c.gid <> NEW.gid AND ST_Overlaps(c.geom, NEW.geom);

  IF gid IS NOT NULL THEN
    RAISE EXCEPTION 'Modified feature % overlaps with feature %!', NEW.gid, gid;
  END IF;
  RETURN NEW;
END; $$ LANGUAGE 'plpgsql';

CREATE TRIGGER sometable_check_geom_trigger BEFORE INSERT OR UPDATE
ON sometable FOR EACH ROW EXECUTE PROCEDURE check_geom();    
Как-то так.

Re: триггер примитивного контроля топологии

Добавлено: 13 фев 2012, 02:36
SS_Rebelious
Спасибо! Будем разбираться.