sql >> Database >  >> RDS >> PostgreSQL

Hoe tekstinvoer te gebruiken als kolomnaam (-namen) in een Postgres-functie?

Het doorgeven van meerdere kolomnamen als aaneengeschakelde tekenreeks voor dynamische uitvoering vereist dringend decontaminatie. Ik raad een VARIADIC functieparameter in plaats daarvan, met correct geciteerde identifiers (met behulp van quote_ident() in dit geval):

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

De formaatspecificatie %I voor format() behandelt een enkele identificatie. Je moet meer werk verzetten voor meerdere identifiers, vooral voor een variabel aantal 0-n identifiers. Deze implementatie citeert elke kolomnaam en voegt alleen een , . toe als er kolomnamen zijn doorgegeven. Dus het werkt voor elke mogelijke invoer , zelfs helemaal geen invoer. Opmerking VARIADIC cols text[] = NULL als laatste invoerparameter met NULL als standaardwaarde:

Gerelateerd:

Kolomnamen zijn in deze context hoofdlettergevoelig!

Bel voor uw voorbeeld (belangrijk!):

SELECT select_by_txt(10,32,33,'col1', 'col2');

Alternatieve syntaxis:

SELECT select_by_txt(10,32,33, VARIADIC '{col1,col2}');

Meer onthullende oproep, met een derde kolomnaam en kwaadaardige (hoewel zinloze) bedoeling:

SELECT select_by_txt(10,32,33,'col1', 'col2', $$col3'); DROP TABLE table1;--$$);

Over die vreemde derde kolomnaam en SQL-injectie:

Over VAIRADIC parameters:

Een OUT gebruiken parameter voor de eenvoud. Dat is volledig optioneel. Zie:

Wat ik niet zou doen doen

Als u er echt op vertrouwt dat de invoer altijd een correct opgemaakte lijst is van 1 of meer geldige kolomnamen - en u beweerde dat ...

Je zou vereenvoudigen:

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$;

(Hoe weet je zo zeker dat de invoer altijd betrouwbaar is?)



  1. Aankondiging van repmgr 2.0RC2

  2. Oracle ALS Bestaat DAN, ANDERS

  3. Hoe ziet de Alter Table-syntaxis eruit voor het toevoegen van een DATETIME-kolom?

  4. Probleem met het bijwerken van een MySQL-veld met PHP