Das Übergeben mehrerer Spaltennamen als verkettete Zeichenfolge zur dynamischen Ausführung erfordert dringend eine Dekontaminierung. Ich schlage einen VARIADIC
Funktionsparameter stattdessen mit korrekt in Anführungszeichen gesetzten Bezeichnern (unter Verwendung von quote_ident()
in diesem Fall):
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 hier
Der Formatbezeichner %I
für format()
befasst sich mit einer Single Kennung. Für mehrere müssen Sie mehr Arbeit investieren Identifikatoren, insbesondere für eine variable Anzahl von 0-n Identifikatoren. Diese Implementierung zitiert jeden einzelnen Spaltennamen und fügt nur einen ,
hinzu ob irgendwelche Spaltennamen übergeben wurden. Es funktioniert also für jede mögliche Eingabe , sogar überhaupt keine Eingabe. Beachten Sie VARIADIC cols text[] =NULL
als letzter Eingabeparameter mit NULL als Standardwert:
Verwandte:
Bei Spaltennamen muss in diesem Zusammenhang zwischen Groß- und Kleinschreibung unterschieden werden!
Fordern Sie Ihr Beispiel an (wichtig!):
SELECT select_by_txt(10,32,33,'col1', 'col2');
Alternative Syntax:
SELECT select_by_txt(10,32,33, VARIADIC '{col1,col2}');
Aufschlussreicherer Aufruf mit einem dritten Spaltennamen und böswilliger (wenn auch vergeblicher) Absicht:
SELECT select_by_txt(10,32,33,'col1', 'col2', $$col3'); DROP TABLE table1;--$$);
Über diesen seltsamen dritten Spaltennamen und die SQL-Injektion:
Über VAIRADIC
Parameter:
- Gib Zeilen zurück, die mit Elementen des Eingabearrays in der plpgsql-Funktion übereinstimmen
- Übergeben Sie mehrere Werte in einem einzigen Parameter
Mit einem OUT
Parameter der Einfachheit halber. Das ist völlig optional. Siehe:
Was ich nicht tun würde tun
Wenn Sie wirklich, wirklich darauf vertrauen, dass die Eingabe zu jeder Zeit eine richtig formatierte Liste von 1 oder mehr gültigen Spaltennamen ist - und Sie haben behauptet, dass ...
Sie könnten vereinfachen:
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$;
(Wie können Sie so sicher sein, dass die Eingabe immer zuverlässig ist?)