是否可以从Postgres函数中发现列类型?

时间:2010-12-08 10:54:20

标签: postgresql stored-procedures

我正在开发一个使用模板生成针对Postgres数据库的数据访问层的实用程序。作为其中的一部分,我试图动态发现存储过程的返回类型。在返回单个标准类型的简单情况下,这很容易,但是当它返回用户定义的类型时,我很挣扎。

如果有人能提供必要的SQL来返回这些数据,我将不胜感激。

由于 标记

我很欣赏我到目前为止的答案,这些答案实际上归结为以下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 个答案:

答案 0 :(得分:3)

psql元命令是查找信息模式内容的简便快捷方式。

尝试test=# \d?查找内省信息。

然后psql -E -c '\df'将显示show function命令后面的sql:

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",

答案 1 :(得分:2)

此查询将列出包含类型的存储过程。

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'  

您始终可以按名称进行过滤。

答案 2 :(得分:1)

刚开始:

SELECT 
  * 
FROM 
  pg_proc 
    JOIN pg_type ON pg_type.oid = ANY(proallargtypes) 
WHERE 
  proname = 'foo';

答案 3 :(得分:1)

你在找这个吗?

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

答案 4 :(得分:1)

如果函数返回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}}的信息{/ 3}}

答案 5 :(得分:1)

感谢帮助人员,我认为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
);