Never seen a negative OID before. This is a first-class "crime scene"!
... attrelid=-1519044407::oid ...
... rel.oid = -1519044407::oid ...
2^32 - 1519044407 = 2775922889
And we have verified that OID
2775922889 indeed exists in your DB. Tests:
SELECT * FROM pg_class WHERE oid = 2775922889;
SELECT * FROM pg_class WHERE oid = '-1519044407';
SELECT * FROM pg_class WHERE relname = 'test_table';
The manual about object identifier types:
oid type is currently implemented as an unsigned four-byte integer.
Postgres cast accepts signed integer anyway (!)
The Postgres I/O conversion from string literals, as well as the cast from
integercurrently (pg 12) accepts negative integer values / literals as input anyway. Seems to just binary coerce a signed four-byte integer to unsigned four-byte integer and vice versa. Worth keeping in mind at least.
These, oddly, work:
test=# SELECT '-1519044407'::oid, '-1519044407'::int::oid;
oid | oid
2775922889 | 2775922889
Leads to different representation when casting to
test=# SELECT (oid '2775922889')::int
test-# , (oid '2775922889')::bigint;
int4 | int8
-1519044407 | 2775922889 -- !!
The manual on Numeric Constants:
Note that any leading plus or minus sign is not actually considered part of the constant; it is an operator applied to the constant.
The cast operator
:: takes precedence over the unary minus operator (
I have never seen OID numbers in that range in system catalogs before, and I have been working with all kinds of big databases. You have a problem in your DB (cluster).
Improved with comments from Daniel Vérité:
Either you are burning OID numbers at an insane rate - already 2.8 billion numbers. ~ 1.5 billion remain until OID wraparound. Do you have any tables created with
WITH OIDS? (Nobody should any more. The feature is deprecated and removed in Postgres 12.) Or some code excessively creating / dropping new objects? The OID counter is per instance, not per database, so all dbs contribute to OID consumption.
There is a comment in the source code for
GetNewOidWithIndex for how OID collisions are dealt with after wraparound. Collisions incur a minor performance penalty.
Or somebody/something messed with your system catalogs.
If the above query was generated by pgAdmin4, there is a serious bug.
Maybe that did not surface, yet, as nobody had OIDs in that range in the system catalogs, yet?
Seems like it operates with the integer representation of OIDs, and naively pastes those as numeric literals including the sign by mistake in queries. A string literal would work:
'-1519044407'::oid. Or parentheses would make it work:
But this does not:
I have posted a note to the pgadmin-hackers list.
A related bug has been logged before there, too. (Access with Postgres community account.) It was traced back to a psycopg2 issue using the wrong data type for OID in 32 bit versions. Should be fixed in psycopg2 version 2.8.4 (which pgAdmin4 depends upon).