\d コマンドは、PostgreSQLのテーブルの情報を確認するためのpsqlのコマンドである。しかし、環境によっては実行時に以下のようなエラーが出て失敗してしまうことがある。relhasoids
はそもそもテーブルに存在しないはずのカラムだったため、原因について調べてみた。
postgres=> \d table_name ERROR: column c.relhasoids does not exist LINE 1: ...riggers, c.relrowsecurity, c.relforcerowsecurity, c.relhasoi...
原因
サーバ側のPostgreSQLのバージョンと、クライアント側のpsqlのバージョンが違っている場合に発生することがある。
上記のエラーで does not exist
と言われているカラム relhasoids
は、PostgreSQLのシステムカタログ*1に存在するカラムであり、バージョン11までは存在していたが、バージョン12からは削除されている。
PostgreSQL 11.5文書 - 52.11. pg_class
PostgreSQL 12.4文書 - 51.11. pg_class
今回の場合はサーバ側のバージョンが13、クライアント側のバージョンが11であったため、psqlが relhasoids
を参照しようとしてエラーとなった。
psql のソースコードを確認すると、バージョンごとに \d で利用される実装が細かく分かれており、PostgreSQLのシステムカタログの実装の変更に合わせていることが分かる。
- postgresql/src/bin/psql/describe.c
対処法
基本的にはクライアント側のpsqlのバージョンを、サーバ側のPostgreSQLのバージョンと合わせることで解消するしかない。
ただ、どんなカラムがあるかを確認するだけであれば、SELECT * FROM table_name
で全カラム取得すれば事足りる。
どうしても\dコマンドと同じ情報を取得したいのであれば、サーバ側のバージョンに対応するpsqlで実装されているSQLを実行すればよいということになるが、おそらくそこまでするよりは、上述のpsqlのバージョンアップかSELECT
のどちらかで対応するのが良いかと思われる。
参考サイト
- OIDs demoted to normal columns: a glance at the past
*1:リレーショナルデータベース管理システムにおいて、テーブルや列の情報などのスキーマメタデータと内部的な情報を格納する場所