PostgreSQL の psql で関数のソースコードを取得する


psql コマンドで関数ソースコード取得方法

PgAdmin3 あるいは PgAdmin4 等の GUI ツールを使っていると難なく PL/PgSQL 関数の ソースコードを取得することが出来ますが、いざ psql コマンド上で関数のソースコードを取得しようとすると方法が分かりませんでしたが、最終的に完全な形で関数のソースコードを取得する方法を見つけましたので解説します。





まずソースコードを取得したい関数を探します。

ここでは情報スキーマ(information_schema)内にある下記関数のソースコードを取得してみます。もちろんご自身で作成したソースコードに置き換えても 同じことが出来ます。
=> \df information_schema._pg_char_max_length;
                                        List of functions
--------------------+---------------------+------------------+---------------------------+--------
       Schema       |        Name         | Result data type |    Argument data types    |  Type
--------------------+---------------------+------------------+---------------------------+--------
 information_schema | _pg_char_max_length | integer          | typid oid, typmod integer | normal
--------------------+---------------------+------------------+---------------------------+--------
(1 row)

上記 "_pg_char_max_length" という関数のソースコードを取得するつもりで、"pg_catalog.pg_proc" というテーブルを以下のように検索してみました。確かに内容は取得できますが、"CREATE FUNCTION" あるいは "CREATE OR REPLACE FUNCTION" が無かったり引数情報がなく、そのままでは利用できません。
=> SELECT proname, prosrc FROM pg_proc WHERE proname = '_pg_char_max_length';
---------------------+----------------------------------------------------
       proname       |                       prosrc
---------------------+----------------------------------------------------
 _pg_char_max_length | SELECT                                            +
                     |   CASE WHEN $2 = -1 /* default typmod */          +
                     |        THEN null                                  +
                     |        WHEN $1 IN (1042, 1043) /* char, varchar */+
                     |        THEN $2 - 4                                +
                     |        WHEN $1 IN (1560, 1562) /* bit, varbit */  +
                     |        THEN $2                                    +
                     |        ELSE null                                  +
                     |   END
---------------------+----------------------------------------------------
(1 row)

そこで色々調べた結果、pg_get_functiondef という関数を見つけました。早速以下のように 実行してみると、見事に関数のソースコードが完全な形で取得できました。
=> SELECT pg_get_functiondef((SELECT oid FROM pg_proc WHERE proname = '_pg_char_max_length'));
----------------------------------------------------------------------------------------------
                                      pg_get_functiondef
----------------------------------------------------------------------------------------------
 CREATE OR REPLACE FUNCTION information_schema._pg_char_max_length(typid oid, typmod integer)+
  RETURNS integer                                                                            +
  LANGUAGE sql                                                                               +
  IMMUTABLE STRICT                                                                           +
 AS $function$SELECT                                                                         +
   CASE WHEN $2 = -1 /* default typmod */                                                    +
        THEN null                                                                            +
        WHEN $1 IN (1042, 1043) /* char, varchar */                                          +
        THEN $2 - 4                                                                          +
        WHEN $1 IN (1560, 1562) /* bit, varbit */                                            +
        THEN $2                                                                              +
        ELSE null                                                                            +
   END$function$                                                                             +

----------------------------------------------------------------------------------------------
(1 row)