web-dev-qa-db-ja.com

「regclass」値をテキストに変換するときに「public」スキーマが欠落している

テーブルの名前を解析する必要があるスクリプトを書いています(regclass内)。これまでのところ、解析(parse_ident()を使用)は機能します。ただし、テーブルがpublicスキーマにある場合、PostgreSQL(10.3)はスキーマ名を自動的に削除するため、スクリプトは失敗します。

たとえば、テーブルttが非publicスキーマexにある場合、regclassのテキスト値は元の値と同じです。

=> select 'ex.tt'::regclass::text;
 text  
-------
 ex.tt

publicにある場合、スキーマ名は失われます。

=> select 'public.tt'::regclass::text;
 text 
------
 tt

この動作を無効にする方法、またはスキーマ名を失うことなくtextに変換する方法はありますか?

1
tinlyx

これは、スキーマpublic自体とは関係ありません。これは、デフォルトで作成されることを除いて特別な権限を持たない別のスキーマであり、デフォルトでsearch_pathに含まれています。

現在のsearch_pathはこの背後にあります。 regclass 値のテキスト表現はそれに基づいています。いずれにせよ、スキーマがsearch_pathで最初に一致しない場合にのみ、テーブル名はスキーマ修飾されます。 マニュアル

regclass入力コンバーターは、スキーマパス設定に従ってテーブルルックアップを処理するため、「正しいこと」を自動的に実行します。同様に、テーブルのOIDをregclassにキャストすると、数値OIDをシンボリック表示するのに便利です。

空のsearch_path(ローカル)を設定することで、Postgresにスキーマ名を強制的に出力させることができます。

SET LOCAL search_path = '';
SELECT 'public.tt'::regclass::text;

ただし、そのため、トランザクションの残りの部分、またはsearch_pathを再度設定するまで、すべてをスキーマ修飾する必要があります。ええと、ほとんどすべて、pg_catalogpg_tempは特別です。見る:

または、特別なキャストとsearch_pathを避けて、pg_classからスキーマ名を直接取得します。

SELECT relnamespace::regnamespace::text
FROM   pg_catalog.pg_class
WHERE  oid = 'public.tt'::regclass;
1