PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да използвам въвеждане на текст като име(на) на колона във функция на Postgres?

Предаването на няколко имена на колони като конкатениран низ за динамично изпълнение изисква спешно обеззаразяване. Предлагам 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 параметри:

Използване на 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$;

(Как можете да сте толкова сигурни, че входът винаги ще бъде надежден?)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. postgres jsonb_set актуализация на множество ключове

  2. Как да напиша Pandas Dataframe към Django модел

  3. psql:сървърът неочаквано затвори връзката

  4. Postgresql -- почистване на HTML тагове в средата на низа

  5. Запазете изхода на PL/pgSQL от PostgreSQL в CSV файл