传递函数名称作为参数

时间:2014-01-15 14:17:42

标签: postgresql postgis plpgsql

在尝试处理PostGIS中的GEOMETRYCOLLECTION时,我发现here似乎解决了将GEOMETRYCOLLECTION转换为简单的GEOMETRY的问题,但它只适用于ST_Intersect内部函数。

由于我很懒,我认为通过将函数作为参数执行来使其更强大会更好,但它不会以这种方式工作。

CREATE OR REPLACE FUNCTION ST_GeoCollConv_(geofunction, geometry, geometry) RETURNS boolean AS $$
        DECLARE
                is1collection boolean;
                is2collection boolean;
        BEGIN

                is1collection := GeometryType($1) = 'GEOMETRYCOLLECTION';
                is2collection := GeometryType($2) = 'GEOMETRYCOLLECTION';

                IF NOT is1collection AND NOT is2collection THEN
                        return PERFORM geofunction($1, $2);
                END IF;


                IF NOT is1collection THEN
                        FOR i IN 1..ST_NumGeometries($2) LOOP
                                IF PERFORM geofunction($1, ST_GeometryN($2, i)) THEN
                                        RETURN true;
                                END IF;
                        END LOOP;
                ELSIF NOT is2collection THEN
                        FOR i IN 1..ST_NumGeometries($1) LOOP
                                IF PERFORM geofunction(ST_GeometryN($1, i), $2) THEN
                                        RETURN true;
                                END IF;
                        END LOOP;
                ELSE
                        FOR i IN 1..ST_NumGeometries($1) LOOP
                                IF ST_GeoCollConv_(geofunction, $1, $2) THEN
                                        RETURN true;
                                END IF;
                        END LOOP;
                END IF;

                RETURN false;

        END;
$$ LANGUAGE 'plpgsql';

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

函数不是postgres中的一等公民(我不能想到它们所在的RDBMS)并且不能作为参数传递。接下来最接近的是枚举所有可能的函数(st_overlaps,st_intersects,st_within等),传递一个标志,指出你正在谈论的函数,并将其合并到你的if语句中,例如: “如果func ='重叠'和st_overlaps(geom1,geom2),否则如果func ='在'和'st_within(geom1,geom2)......”。

几何集合处理起来有点令人沮丧。你被迫使用它们吗?你可以改用多边形吗?

另请注意,功能本身有点过分。您可以使用st_dump枚举所有几何图形(即使您只有一个简单的几何图形也可以工作)然后加入结果。例如:

create or replace function st_intersects_gc(geometry, geometry)
returns boolean
as
$$
    select exists (
             select 1
             from st_dump($1) a
                    join st_dump($2) b
                      on st_intersects(a.geom, b.geom)
             limit 1
           )
    ;
$$
language sql
immutable
;

示例用法(还应该有一个示例说明这适用于集合,但我手头没有):

-- returns false
select st_intersects_gc('POINT(0 0)'::geometry, 'LINESTRING ( 2 0, 0 2 )'::geometry)

-- returns true
select st_intersects_gc('POINT(0 0)'::geometry, 'LINESTRING ( 0 0, 0 2 )'::geometry)

在你的鞋子里,我会为你计划使用的每个功能写下其中一个。