В отличие от PL/pgSQL
функций, функции языка SQL
принимают записи и массивы записей.Работает следующий скрипт:
create type testtyp1 as ( a int, b unknown );
create type testtyp2 as ( a int, b text );
create type testtyp3 as ( a int, b varchar(8000) );
create or replace function xdecode(variadic args anyarray) RETURNS text AS $$
select 'x'::text;
$$ LANGUAGE sql;
-- the function should support all these:
select xdecode( (1,'a'),(2,'b') );
select xdecode( (1,'a')::testtyp1, (2,'b')::testtyp1 );
select xdecode( (1,'a')::testtyp2, (2,'b')::testtyp2 );
select xdecode( (1,'a')::testtyp3, (2,'b')::testtyp3 );
И важно, это тоже:
select xdecode( (0.1,now()), (0.2,now()) );
Теперь мне нужно изменить функцию, чтобы она возвращала 2-й столбец элемента массива, чей 1-й столбецсоответствует определенному условию.
Проблема в том, что столбцы записи могут иметь любое имя или вообще не иметь имени.Другая проблема заключается в том, что символьные константы в PostgreSQL
имеют тип: unknown
.
Если я попытаюсь привести строку к любому другому типу, вызов завершится неудачно:
create or replace function xdecode(variadic args anyarray) RETURNS text AS $$
select args[1]::testtyp1::text
$$ LANGUAGE sql;
...
> select xdecode( (1,'a'),(2,'b') );
cannot cast type record to testtyp1
> select xdecode( (1,'a')::testtyp3, (2,'b')::testtyp3 );
cannot cast type testtyp3 to testtyp1
Iмогу обойтись без знания имен столбцов с помощью вспомогательной функции:
create or replace function hlp(arg anyelement) RETURNS record AS $$
select arg;
$$ LANGUAGE sql;
create or replace function xdecode(variadic args anyarray) RETURNS text AS $$
select b::text from hlp( args[1] ) AS T(a int , b unknown);
$$ LANGUAGE sql;
Но я ничего не могу поделать, не зная, unknown
или text
:
> select xdecode( (1,'a'),(2,'b') );
a
> select xdecode( (1,'a')::testtyp1, (2,'b')::testtyp1 );
a
> select xdecode( (1,'a')::testtyp2, (2,'b')::testtyp2 );
Returned type text at ordinal position 2, but query expects unknown.
> select xdecode( (1,'a')::testtyp3, (2,'b')::testtyp3 );
Returned type text at ordinal position 2, but query expects unknown.
Не указание типов невозможно:
create or replace function xdecode(variadic args anyarray) RETURNS text AS $$
select b::text from hlp( args[1] ) AS T(a, b);
$$ LANGUAGE sql;
> select xdecode( (1,'a'),(2,'b') );
a column definition list is required for functions returning "record"