Tra*_*onk 5 postgresql select table pgadmin-4 objectid
我目前在本地运行 Postgresql 10.6,我使用 PgAdmin 4.12 与之交互,直到今天一切都运行良好。但是今天我在 pgAdmin 查询编辑器中运行了以下查询:
SELECT * FROM test_table LIMIT 100
Run Code Online (Sandbox Code Playgroud)
并得到以下错误:
Run Code Online (Sandbox Code Playgroud)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'
Run Code Online (Sandbox Code Playgroud)
这也很成功。我能够在 Pgadmin 中创建表,只是不直接输出它们。我创建的任何新表然后输出都以最高错误结束,唯一的区别是 oid 更改。我已经卸载了 Pgadmin 并确保删除所有剩余的文件夹并重新安装而不做任何更改。
有没有人有任何想法是什么问题?问题是来自 pgadmin 还是我的 Postgresql 服务器以某种方式损坏了?
以前从未见过负OID。这是一流的“犯罪现场”!
Run Code Online (Sandbox Code Playgroud)... attrelid=-1519044407::oid ... ... rel.oid = -1519044407::oid ...
2^32 - 1519044407 = 2775922889
Run Code Online (Sandbox Code Playgroud)
我们已经验证 OID2775922889确实存在于您的数据库中。测试:
SELECT * FROM pg_class WHERE oid = 2775922889;
SELECT * FROM pg_class WHERE oid = '-1519044407';
SELECT * FROM pg_class WHERE relname = 'test_table';
Run Code Online (Sandbox Code Playgroud)
该
oid类型当前实现为无符号四字节整数。
Postgres cast无论如何都接受有符号整数(!)
字符串文字的 Postgres I/O 转换,以及integer当前 (pg 12) 的转换都接受负整数值/文字作为输入。似乎只是将一个有符号的四字节整数二进制强制转换为无符号的四字节整数,反之亦然。至少值得记住。
奇怪的是,这些工作:
test=# SELECT '-1519044407'::oid, '-1519044407'::int::oid;
oid | oid
------------+------------
2775922889 | 2775922889
Run Code Online (Sandbox Code Playgroud)
转换为intvs时导致不同的表示bigint:
test=# SELECT (oid '2775922889')::int
test-# , (oid '2775922889')::bigint;
int4 | int8
-------------+------------
-1519044407 | 2775922889 -- !!
Run Code Online (Sandbox Code Playgroud)
请注意,任何前导加号或减号实际上不被视为常量的一部分;它是应用于常量的运算符。
强制转换运算符:: 优先于一元减运算符 ( -)。
我以前从未在系统目录中看到该范围内的 OID 编号,并且我一直在使用各种大型数据库。您的数据库(集群)有问题。
改进了 Daniel Vérité 的评论:
要么你以疯狂的速度燃烧 OID 号码——已经 28 亿个号码。大约 15 亿剩余,直到 OID 环绕。你有任何用创建的表WITH OIDS吗?(没有人应该再这样了。该功能在 Postgres 12 中已弃用并删除。)或者某些代码过度创建/删除新对象?OID 计数器是按实例计算的,而不是按数据库计算的,因此所有数据库都会消耗 OID。源代码中
有一条关于如何在环绕后处理 OID 冲突的注释GetNewOidWithIndex。碰撞会导致轻微的性能损失。
或者某人/某事弄乱了您的系统目录。
如果上述查询是由 pgAdmin4 生成的,则存在严重错误。
也许这还没有浮出水面,因为在系统目录中没有人拥有该范围内的 OID?
似乎它使用OID的整数表示进行操作,并天真地将它们粘贴为数字文字,包括查询中错误的符号。一个字符串字面将工作:'-1519044407'::oid。或者括号可以使它工作:(-1519044407)::oid.
但这不是:
-1519044407::oid
Run Code Online (Sandbox Code Playgroud)
因为:
1519044407被视为数字文字并最初被强制为integer.::优先于符号运算符-,并且整数被强制转换为 (wrong!!) oid。Run Code Online (Sandbox Code Playgroud)ERROR: operator does not exist: - oid at character 125
如果它不会在那里失败,可能会发生严重的废话。
db<>在这里摆弄
我已经在 pgadmin-hackers list上贴了一张便条。在那里之前也记录了
一个相关的错误。(使用 Postgres 社区帐户访问。)它被追溯到在 32 位版本中使用错误的 OID 数据类型的 psycopg2 问题。应该在 psycopg2 版本 2.8.4 中修复(pgAdmin4 依赖于此)。
| 归档时间: |
|
| 查看次数: |
2340 次 |
| 最近记录: |