Melewati beberapa nama kolom sebagai string gabungan untuk eksekusi dinamis sangat membutuhkan dekontaminasi. Saya menyarankan VARIADIC
sebagai gantinya, dengan pengidentifikasi yang dikutip dengan benar (menggunakan quote_ident()
dalam hal ini):
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 di sini
Penentu format %I
untuk format()
berurusan dengan tunggal pengenal. Anda harus melakukan lebih banyak pekerjaan untuk banyak pengidentifikasi, terutama untuk sejumlah variabel pengidentifikasi 0-n. Implementasi ini mengutip setiap nama kolom, dan hanya menambahkan ,
jika ada nama kolom yang telah dilewati. Jadi ini berfungsi untuk setiap masukan yang memungkinkan , bahkan tidak ada masukan sama sekali. Catatan VARIADIC cols text[] = NULL
sebagai parameter input terakhir dengan NULL sebagai nilai default:
Terkait:
Nama kolom peka huruf besar/kecil dalam konteks ini!
Panggil contoh Anda (penting!):
SELECT select_by_txt(10,32,33,'col1', 'col2');
Sintaks alternatif:
SELECT select_by_txt(10,32,33, VARIADIC '{col1,col2}');
Panggilan yang lebih terbuka, dengan nama kolom ketiga dan niat jahat (meskipun sia-sia):
SELECT select_by_txt(10,32,33,'col1', 'col2', $$col3'); DROP TABLE table1;--$$);
Tentang nama kolom ketiga yang aneh dan injeksi SQL:
Tentang VAIRADIC
parameter:
- Kembalikan baris yang cocok dengan elemen array input dalam fungsi plpgsql
- Meneruskan beberapa nilai dalam satu parameter
Menggunakan OUT
parameter untuk kesederhanaan. Itu benar-benar opsional. Lihat:
Apa yang saya tidak akan lakukan
Jika Anda benar-benar memercayai input sebagai daftar dengan format 1 atau lebih nama kolom yang valid setiap saat - dan Anda menegaskan bahwa ...
Anda bisa sederhanakan:
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$;
(Bagaimana Anda bisa begitu yakin bahwa input akan selalu dapat diandalkan?)