web-dev-qa-db-ja.com

OID演算子がないため、pgAdmin4のテーブルからデータを出力できません

私は現在Postgresql 10.6をローカルで実行していますが、PgAdmin 4.12を使用してインターフェイスします。今日まで、すべてが正常に実行されていました。しかし、今日はpgAdminクエリエディターで次のクエリを実行しました。

SELECT * FROM test_table LIMIT 100

次のエラーが発生しました:

ERROR:  operator does not exist: - oid at character 125
HINT:  No operator matches the given name and argument type. You might need to add an explicit type cast.
STATEMENT:  SELECT at.attname, at.attnum, ty.typname
        FROM pg_attribute at LEFT JOIN pg_type ty ON (ty.oid = at.atttypid)
        WHERE attrelid=-1519044407::oid AND attnum = ANY (
            (SELECT con.conkey FROM pg_class rel LEFT OUTER JOIN pg_constraint con ON con.conrelid=rel.oid
            AND con.contype='p' WHERE rel.relkind IN ('r','s','t', 'p') AND rel.oid = -1519044407::oid)::oid[])

奇妙なことに、昨日作成されたテーブルで同じコマンドを実行すると、データがPgadminデータ出力ウィンドウに正常に出力されます。また、psqlで同じコマンドを実行してみました。

psql -U postgres -d geodata -c 'SELECT * FROM test_table LIMIT 100'

これも成功しました。 Pgadminでテーブルを作成できますが、直接出力することはできません。私が作成した新しいテーブルはすべて、一番上のエラーで終了します。唯一の違いは、OIDの変更です。 Pgadminをアンインストールし、残っているすべてのフォルダーを削除して、変更せずに再インストールしました。

誰が問題が何であるかについて何か考えがありますか?問題はpgadminが原因ですか、それともPostgresqlサーバーが何らかの方法で破損していますか?

5
Trashmonk

negativeOIDを見たことがない。これは一流の「犯罪現場」です!

... attrelid=-1519044407::oid ...
... rel.oid = -1519044407::oid ...

事実

0。

2^32 - 1519044407 = 2775922889

また、OID 2775922889が実際にDBに存在することを確認しました。テスト:

SELECT * FROM pg_class WHERE oid = 2775922889;
SELECT * FROM pg_class WHERE oid = '-1519044407';
SELECT * FROM pg_class WHERE relname = 'test_table';

1。

オブジェクト識別子タイプに関するマニュアル:

oid型は現在、符号なし4バイト整数として実装されています。

2。

とにかくPostgresキャストはsigned整数を受け入れます(!)

文字列リテラルからのPostgres I/O変換、およびintegercurrently(12ページ)からのキャストは、負の整数値/リテラル​​を入力として受け入れます。符号付き4バイト整数を符号なし4バイト整数にバイナリで強制変換するように、またはその逆のように見えます。少なくとも心に留めておく価値があります。

これらは、奇妙に働きます:

test=# SELECT '-1519044407'::oid, '-1519044407'::int::oid;
    oid     |    oid     
------------+------------
 2775922889 | 2775922889

intbigintにキャストすると、異なる表現になります。

test=# SELECT (oid '2775922889')::int
test-#      , (oid '2775922889')::bigint;
    int4     |    int8    
-------------+------------
 -1519044407 | 2775922889  -- !!

3。

数値定数に関するマニュアル

先頭のプラス記号またはマイナス記号は、実際には定数の一部とは見なされないことに注意してください。これは定数に適用される演算子です。

4。

キャスト演算子::優先されます 単項マイナス演算子(-)よりも優先されます。

結論

1。

これまでにシステムカタログでその範囲のOID番号を見たことがなく、あらゆる種類の大きなデータベースで作業してきました。DB(クラスター)に問題があります。

DanielVéritéからのコメントで改善:

いずれかOIDの数値をめちゃくちゃな速度で燃やしています-すでに28億の数値OIDラップアラウンドまで、約15億が残ります。 WITH OIDSで作成されたテーブルはありますか? (これ以上誰もすべきではありません。この機能は非推奨で、 Postgres 12で削除 です。)または、新しいオブジェクトを過剰に作成/削除するコードがありますか? OIDカウンターはインスタンスごとであり、データベースごとではないため、すべてのデータベースがOID消費に貢献しています。
OIDの衝突がラップアラウンド後にどのように処理されるかについて、 GetNewOidWithIndex のソースコードにコメントがあります。衝突により、パフォーマンスが若干低下します。

または誰か/何かがシステムカタログをめちゃくちゃにしました。

2。

上記のクエリがpgAdmin4によって生成された場合、重大なバグがあります

システムカタログでその範囲のOIDがまだ誰もいないので、それはまだ浮上しなかったのでしょうか?

OIDのinteger表現で動作し、クエリで誤って符号を含む数値リテラルとして単純に貼り付けているようです。 stringリテラルが機能します:'-1519044407'::oid。または、括弧を使用すると機能します:(-1519044407)::oid

しかし、これはnotを行います:

-1519044407::oid 

理由:

    1. 1519044407は数値リテラルとして解釈され、最初はintegerに強制変換されます。
    1. キャスト演算子::は、符号演算子-よりも優先され、整数は(間違った!!)oidにキャストされます。
    1. 最後に、Postgresは符号演算子を適用しようとしますが、幸い、報告されたエラーメッセージで失敗します。
    ERROR:  operator does not exist: - oid at character 125
    

    そこで失敗しないと、重大なナンセンスが発生する可能性があります。

db <> fiddle ここ

pgadmin-hackersリストへのメモ を投稿しました。
A 関連するバグがそこに記録される前 も。 (Postgresコミュニティアカウントを使用してアクセスします。)32ビットバージョンのOIDに誤ったデータ型を使用しているpsycopg2の問題が原因でした。psycopg2バージョン2.8.4で修正する必要があります(pgAdmin4が依存します)。

5

この問題はすでに記録されています@ https://redmine.postgresql.org/projects/pgadmin4 。この問題はpsycopg2ライブラリで発生し、報告されています。

2
Khushboo Vashi