6

我偶然发现了一个奇怪的函数签名pg_catalog.pg_stat_get_activity

CREATE OR REPLACE FUNCTION pg_stat_get_activity(
    IN pid integer, 
    OUT datid oid,
    OUT pid integer, 
    -- more parameters...)
  RETURNS SETOF record AS 'pg_stat_get_activity'
  LANGUAGE internal STABLE
  COST 1
  ROWS 100;

该函数两次声明了相同的参数名称,也是从information_schema.

select 
  parameter_mode,
  parameter_name
from information_schema.parameters
where specific_schema = 'pg_catalog'
and specific_name like 'pg_stat_get_activity%'
order by ordinal_position

以上产量(另请参阅此SQLFiddle):

+--------------+----------------+
|parameter_mode|parameter_name  |
+--------------+----------------+
|IN            |pid             |
|OUT           |datid           |
|OUT           |pid             |
|...           |...             |
+--------------+----------------+

天真地,我尝试创建一个类似的功能,但无济于事:

CREATE FUNCTION f_2647(p1 IN int, p1 OUT int)
AS $$
BEGIN
    p1 := p1;
END;
$$ LANGUAGE plpgsql;

我的问题:

  1. 为什么内部pg_stat_get_activity函数会两次重新声明相同的参数名称?这样做的目的是什么?例如,为什么不只使用一个INOUT参数?
  2. pg_stat_get_activity内部函数和我的有什么不同?为什么我不能使用这种语法?

我知道这些是相当学术的问题,但我需要正确理解这一点才能解决jOOQ代码生成器中的问题

4

1 回答 1

3

我注意到它出现在 9.2 中。在 9.1 版中,out 字段被命名为procpid

参数模式 | 参数名称  
-----------------+--------------------
 输入 | PID
 输出 | 数据
 输出 | procpid
 输出 | 使用sysid
 ...

寻找 postgres git 历史的变化会导致这个提交:

提交 4f42b546fd87a80be30c53a0f2c897acb826ad52
作者:马格努斯·哈根德
日期:2012 年 1 月 19 日星期四 14:19:20 +0100

    在 pg_stat_activity 中将状态与查询字符串分开

    这将状态(运行/空闲/空闲事务等)分为
    它是自己的字段(“状态”),并让查询字段仅包含
    查询文本。

    当查询正在运行时,查询文本现在将表示“当前查询”
    和其他州的“最后查询”。因此,该领域已
    从 current_query 重命名为 query。

    由于无论如何都破坏了向后兼容性,因此 procpid
    字段也已重命名为 pid - 与
    pg_stat_replication 以保持一致性。

    Scott Mead 和 Magnus Hagander,Greg Smith 的评论作品

在更改的行中,这是一个有趣的行:

-DATA(插入 OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 0 ffffts 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,25,23 }" "{i,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,current_query,waiting,xact_start,query_start ,backend_start,client_addr,client_hostname,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
+DATA(插入 OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 0 ffffts 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,1184,869 ,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name ,状态,查询,等待,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
 

在这种预先消化的形式中,作者没有注意到 的双重使用是合理的pid,或者他们不在乎,因为它在实践中是无害的。

之所以允许通过,是因为这些内部函数是在initdb跳过普通用户函数的创建检查的快速路径中创建的。

于 2013-09-20T20:30:16.280 回答