Могу ли я объявить функцию postgres, которая принимает массив любого типа? - PullRequest
0 голосов
/ 15 мая 2018

Т.е. мне нужна функция, которую можно вызывать вот так

select myfunc({1,'foo', true})

или

select myfunc({42.0,7, false, x'ff'})

, чтобы быть на 100% прозрачным, на самом деле я хочу

select myfunc(array[col1,col2,col3])

где col1, col2, col3 имеют разные типы.Может быть, это имеет значение для ответов

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Нет, Вы не можете этого сделать - ответ @Vao Tsun абсолютно верный. Язык SQL PostgreSQL довольно статичен - как C или Pascal. Существует несколько динамических функций, но они ограничены.

Любой запрос имеет два этапа - планирование и выполнение. И типы данных любого значения должны быть известны во время планирования (динамические запросы и тип записи являются исключением - но только локально в PLpgSQL). Поскольку все типы должны быть известны до выполнения, PostgreSQL не позволяет использовать функции, которые могут содержать динамические значения типов, например полиморфные коллекции.

Для константных значений может быть обходной путь для вашего случая. Вы можете написать переменную функцию с параметрами любого типа. Это имеет смысл только для постоянных значений - типы известны во время планирования, и эти функции могут быть реализованы только на языке Си. Например, функция format такого типа.

Необходимость проделать некоторую динамическую работу является сигналом «сломанного» дизайна "сломан" с точки зрения PostgreSQL. Некоторые шаблоны не могут быть реализованы в Postgres, и лучше реализовать их снаружи или с помощью другого типа программного обеспечения.

0 голосов
/ 15 мая 2018

https://www.postgresql.org/docs/current/static/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC

Каждая позиция (аргумент или возвращаемое значение), объявленная как anyelement, может иметь любой конкретный фактический тип данных, но в любом данном вызове все они должны бытьтот же фактический тип .Каждая позиция, объявленная как anyarray, может иметь любой тип данных массива, но аналогично они должны быть одного типа.

функция может принимать anyarray, который фактически является массивом значений любого одного типа, а не массивом любого типа, смешанным в одном массиве ...

что вы, вероятно, смотритевместо этого было бы что-то вроде:

so=# create function ae(i anyelement) returns anyelement as $$
begin
raise info '%',i::text; return i;
end;
$$ language plpgsql
;
CREATE FUNCTION
so=# create table pm100(f float,b bool, t bytea);
CREATE TABLE
so=# select ae((42.0, false, '\xff')::pm100);
INFO:  (42,f,"\\xff")
       ae
----------------
 (42,f,"\\xff")
(1 row)
...