PostGIS触发功能 - 达到最大堆栈深度

时间:2015-01-22 08:22:38

标签: postgresql triggers stack-overflow postgis

尝试在PostGIS中创建动态触发器功能,但获得" max_stack_depth"错误信息。

我在PostGRES / GIS中有两个表格,包含几何的testzone.carsurtest和political.localities,我试图更新地点' testzone.carsurtest中的字段来自' locality_name'使用ST_Intersects的field political.localities。我已经成功地专门为testzone.carsurtest创建了一个触发器函数,但是我想创建一个动态触发器函数,用于想要从locality表更新的多个表。

CREATE OR REPLACE FUNCTION tf_locality_test()
  RETURNS trigger AS
$BODY$

DECLARE
    tbl text := TG_TABLE_NAME;
    scm text := TG_TABLE_SCHEMA;

BEGIN

EXECUTE 'UPDATE '|| quote_ident(cast(scm as text)) ||'.'|| quote_ident(cast(tbl as text)) ||' AS dyntbl
        SET locality = political.locality.locality_name
        FROM  political.locality 
        WHERE ST_Intersects(dyntbl.wkb_geometry, political.locality.wkb_geometry)';

    RETURN NEW;
 END;
 $BODY$
   LANGUAGE plpgsql VOLATILE
   COST 100;
 ALTER FUNCTION tf_locality_test() OWNER TO postgres;

当我在QGIS中创建新的多边形记录时,我收到以下错误消息:

>

 Could not commit changes to layer carsurtest
> 
> Errors: ERROR: 1 feature(s) not added.
>      Provider errors:
>       PostGIS error while adding features: ERROR:  stack depth limit exceeded
>     HINT:  Increase the configuration parameter "max_stack_depth", after ensuring the platform's stack depth limit is adequate.
>     CONTEXT:  PL/pgSQL function "tf_locality_test" line 8 at EXECUTE statement
>     SQL statement "UPDATE test_zone.carsurtest AS dyntbl
>     SET locality = political.locality.locality_name
>     FROM  political.locality 
>     WHERE ST_Intersects(dyntbl.wkb_geometry, political.locality.wkb_geometry)"

任何建议都将不胜感激。 谢谢, 克里斯

1 个答案:

答案 0 :(得分:2)

这里的问题是你在一个表上有一个BEFORE UPDATE触发器,它有一个更新同一个表的语句:递归。过了一会儿,有很多触发器等待EXECUTE语句完成(每个调用相同的触发器函数),堆栈被填满。不要在触发器函数中执行动态UPDATE,只需使用locality隐式参数设置字段NEW的值:

CREATE OR REPLACE FUNCTION tf_locality_test() RETURNS trigger AS $BODY$
BEGIN
  SELECT loc.locality_name INTO NEW.locality
  FROM political.localities loc
  WHERE ST_Intersects(NEW.wkb_geometry, loc.wkb_geometry);
  RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;

只要其他表的localitywkb_geometry列具有足够的定义,每个列都可以有一个BEFORE UDPATE触发器来调用相同的触发器函数。