Att skicka flera kolumnnamn som sammanlänkade strängar för dynamisk exekvering kräver akut dekontaminering. Jag föreslår en VARIADIC
funktionsparameter istället, med korrekt citerade identifierare (med quote_ident()
i det här fallet):
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<>fiol här
Formatspecifikationen %I
för format()
handlar om en singel identifierare. Du måste lägga ner mer arbete för flera identifierare, speciellt för ett variabelt antal 0-n identifierare. Denna implementering citerar varje enskilt kolumnnamn och lägger bara till en ,
om några kolumnnamn har passerats. Så det fungerar för alla möjliga indata , även ingen input alls. Notera VARIADIC cols text[] =NULL
som sista indataparameter med NULL som standardvärde:
Relaterat:
Kolumnnamn är skiftlägeskänsliga i detta sammanhang!
Ring för ditt exempel (viktigt!):
SELECT select_by_txt(10,32,33,'col1', 'col2');
Alternativ syntax:
SELECT select_by_txt(10,32,33, VARIADIC '{col1,col2}');
Mer avslöjande samtal, med ett tredje kolumnnamn och skadliga (men meningslösa) avsikter:
SELECT select_by_txt(10,32,33,'col1', 'col2', $$col3'); DROP TABLE table1;--$$);
Om det udda tredje kolumnnamnet och SQL-injektion:
Om VAIRADIC
parametrar:
- Returnera rader som matchar element i indatamatrisen i plpgsql-funktionen
- Skicka flera värden i en enda parameter
Använda en OUT
parameter för enkelhetens skull. Det är helt valfritt. Se:
Vad jag inte skulle gör
Om du verkligen, verkligen litar på att indata är en korrekt formaterad lista med 1 eller flera giltiga kolumnnamn hela tiden - och du hävdade att ...
Du kunde förenkla:
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$;
(Hur kan du vara så säker på att indata alltid kommer att vara tillförlitlig?)