Можно ли обнаружить типы столбцов с помощью функции Postgres? - PullRequest
9 голосов
/ 08 декабря 2010

Я работаю над утилитой, которая использует шаблоны для создания слоя доступа к данным из базы данных Postgres. В рамках этого я пытаюсь динамически обнаружить типы возвращаемых хранимых процедур. Это достаточно просто в простых случаях, когда возвращается один стандартный тип, но я с трудом возвращаюсь к определенному пользователем типу.

Буду признателен, если кто-нибудь предоставит необходимый SQL для возврата этих данных.

Спасибо Mark

Я ценю ответы, которые у меня есть, которые эффективно сводятся к следующему SQL

SELECT p.proname, t.typname, p,proretset
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
INNER JOIN pg_type t ON p.prorettype = t.oid
WHERE n.nspname = 'public'
--and proname = 'foo'
ORDER BY proname;

Это вернет имя возвращаемых типов. Однако мне все еще нужно разложить тип на свойства, которые составляют его, когда он возвращает определенный пользователем тип.

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

Ответы [ 6 ]

3 голосов
/ 09 декабря 2010

psql метакоманды - это быстрый способ поиска информации информационной схемы.

попробуйте test=# \d?, чтобы найти информацию для самоанализа.

затем psql -E -c '\df' покажет sql после команды show function:

d$ psql -E -c '\df+'
********* QUERY **********
SELECT n.nspname as "Schema",
 p.proname as "Name",
 pg_catalog.pg_get_function_result(p.oid) as "Result data type",
 pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
CASE
 WHEN p.proisagg THEN 'agg'
 WHEN p.proiswindow THEN 'window'
 WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
 ELSE 'normal'
END as "Type",
CASE
 WHEN p.provolatile = 'i' THEN 'immutable'
 WHEN p.provolatile = 's' THEN 'stable'
 WHEN p.provolatile = 'v' THEN 'volatile'
END as "Volatility",
 pg_catalog.pg_get_userbyid(p.proowner) as "Owner",
 l.lanname as "Language",
 p.prosrc as "Source code",
 pg_catalog.obj_description(p.oid, 'pg_proc') as "Description"
FROM pg_catalog.pg_proc p
    LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
    LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang
WHERE pg_catalog.pg_function_is_visible(p.oid)
     AND n.nspname <> 'pg_catalog'
     AND n.nspname <> 'information_schema'
ORDER BY 1, 2, 4;
**************************

В вашем случае это будет то, что вы хотите:

 pg_catalog.pg_get_function_result(p.oid) as "Result data type",
2 голосов
/ 02 августа 2012

В этом запросе будут перечислены хранимые процедуры с типами.

SELECT  proname, proargnames as arguments,
        oidvectortypes(proargtypes) as arguments_type, 
        t.typname as return_type,prosrc as source
FROM    pg_catalog.pg_namespace n
JOIN    pg_catalog.pg_proc p   ON    pronamespace = n.oid     
JOIN    pg_type t ON p.prorettype = t.oid  
WHERE   nspname = 'public'  

Вы всегда можете отфильтровать по имени.

1 голос
/ 13 декабря 2010

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

Однако вот SQL, который я искал, чтобы получить определение функции, которая возвращает составной тип:

SELECT t.typname, attname, a.typname
from pg_type t
JOIN pg_class on (reltype = t.oid)
JOIN pg_attribute on (attrelid = pg_class.oid)
JOIN pg_type a on (atttypid = a.oid)
WHERE t.typname = (
    SELECT t.typname
    FROM pg_catalog.pg_proc p
    LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
    INNER JOIN pg_type t ON p.prorettype = t.oid
    WHERE n.nspname = 'public'
    and proname = 'foo'
    ORDER BY proname
);
1 голос
/ 08 декабря 2010

если функция возвращает record, то тип не известен до времени выполнения, продемонстрировано с помощью:

create or replace function func() returns record language plpgsql immutable as $$
declare 
  r record;
  q record;
begin
  select 10, 'hello' into r;
  select 11, 'hello', 'helloagain' into q;
  if random()>0.5 then
    return r;
  else
    return q;
  end if;
end;$$;

другими словами, вы не можете знать тип до после Вы вызываете функцию .После вызова функции вы можете динамически определять информацию о record, передавая ее в функцию на языке C, на которую ссылается здесь

1 голос
/ 08 декабря 2010

Вы ищете это?

SELECT proname, 
       pg_get_function_result(oid)
FROM pg_proc
WHERE proname = 'foo';

1 голос
/ 08 декабря 2010

Просто для начала:

SELECT 
  * 
FROM 
  pg_proc 
    JOIN pg_type ON pg_type.oid = ANY(proallargtypes) 
WHERE 
  proname = 'foo';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...