Предаването на няколко имена на колони като конкатениран низ за динамично изпълнение изисква спешно обеззаразяване. Предлагам 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<>fiddle тук
Спецификаторът на формата %I
за format()
се занимава с единичен идентификатор. Трябва да положите повече работа за множество идентификатори, особено за променлив брой 0-n идентификатори. Тази реализация цитира всяко име на колона и добавя само ,
ако са предадени имена на колони. Така че работи за всеки възможен вход , дори никакво въвеждане. Забележка 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;--$$);
Относно това странно трето име на колона и SQL инжекция:
Относно VAIRADIC
параметри:
- Връща редове, съответстващи на елементи от входен масив във функцията plpgsql
- Предаване на множество стойности в един параметър
Използване на OUT
параметър за простота. Това не е задължително. Вижте:
Какво не бих направи
Ако наистина, наистина вярвате, че входът е правилно форматиран списък от 1 или повече валидни имена на колони по всяко време - и сте заявили, че ...
Вие можете опростяване:
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$;
(Как можете да сте толкова сигурни, че входът винаги ще бъде надежден?)