将多个列名作为串联字符串传递以进行动态执行迫切需要去污。我建议使用一个VARIADIC
函数参数,并使用正确引用的标识符(quote_ident()
在这种情况下使用):
CREATE OR REPLACE FUNCTION select_by_txt(z int, x int, y int, VARIADIC cols text[] = NULL, OUT res text)
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format(
$$
SELECT ST_AsMVT(mvtgeom, 'public.select_by_txt')
FROM (
SELECT ST_AsMVTGeom(ST_Transform(t.geom, 3857), bounds.geom) AS geom%s
FROM table1 t
JOIN (SELECT ST_TileEnvelope($1, $2, $3)) AS bounds(geom)
ON ST_Intersects(t.geom, ST_Transform(bounds.geom, 4326))
) mvtgeom
$$, (SELECT ', ' || string_agg(quote_ident (col), ', ') FROM unnest(cols) col)
)
INTO res
USING z, x, y;
END
$func$;
db<>在这里摆弄
%I
用于format()
处理单个标识符的格式说明符。您必须为多个标识符投入更多工作,尤其是对于可变数量的 0-n 标识符。此实现引用每个列名,并且仅在,
已传递任何列名时添加 a。所以它适用于所有可能的输入,甚至根本没有输入。注意VARIADIC cols text[] = NULL
作为最后一个输入参数,默认值为 NULL:
有关的:
在这种情况下,列名区分大小写!
打电话给你的例子(重要!):
SELECT select_by_txt(10,32,33,'col1', 'col2');
替代语法:
SELECT select_by_txt(10,32,33, VARIADIC '{col1,col2}');
更具启发性的调用,带有第三列名称和恶意(尽管徒劳)意图:
SELECT select_by_txt(10,32,33,'col1', 'col2', $$col3'); DROP TABLE table1;--$$);
About that odd third column name and SQL injection:
About VAIRADIC
parameters:
Using an OUT
parameter for simplicity. That's totally optional. See:
What I would not do
If you really, really trust the input to be a properly formatted list of 1 or more valid column names at all times - and you asserted that ...
the names of the columns inside cols will be checked before calling the function that they are valid columns
You could simplify:
CREATE OR REPLACE FUNCTION select_by_txt(z int, x int, y int, cols text, OUT res text)
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format(
$$
SELECT ST_AsMVT(mvtgeom, 'public.select_by_txt')
FROM (
SELECT ST_AsMVTGeom(ST_Transform(t.geom, 3857), bounds.geom) AS geom, %s
FROM table1 t
JOIN (SELECT ST_TileEnvelope($1, $2, $3)) AS bounds(geom)
ON ST_Intersects(t.geom, ST_Transform(bounds.geom, 4326))
) mvtgeom
$$, cols
)
INTO res
USING z, x, y;
END
$func$;
(How can you be so sure that the input will always be reliable?)