我正在玩pg_size_pretty(),我发现当我传递一个很大的值时,它会开始返回负值。 这是我的考验:
select pg_size_pretty(9223370000000000000); -- "8388606 TB"
select pg_size_pretty(9223371000000000000); -- "8388607 TB"
select pg_size_pretty(9223372000000000000); -- "-8388607 TB"
你能解释一下为什么吗?
感谢。
答案 0 :(得分:5)
最高签名64位int是922337203685477587.这只是比有问题的数字略多一点。肯定在pg_size_pretty
的某个地方有一个溢出。
根据评论中提到的代码,pg_size_pretty
尝试对数字进行舍入,并使用大于最大有符号64位int的中间值进行舍入。 9223372000000000000 + 1024 * 1024 * 1024 * 1024/2 = 9223372549755813888,大于922337203685477587。
更新:添加了第二段,并澄清溢出不在调用者中。
答案 1 :(得分:5)
你没有溢出,pg_size_pretty
正在溢出。 pg_size_pretty
函数应该采用bigint
:
pg_size_pretty(bigint)
text
将字节大小转换为人类可读格式,大小单位为
而9223372000000000000 < 9223372036854775808
因此9223372000000000000
是完全有效的bigint
,pg_size_pretty
应该使用它做正确的事。您应该向PostgreSQL人报告错误并赢得赞誉。
更新:检查PostgreSQL源代码(感谢Jeremiah Peschka提供链接)向我们展示了错误的位置:
491 else
492 {
493 mult *= 1024;
494 snprintf(buf, sizeof(buf), INT64_FORMAT " TB",
495 (size + mult / 2) / mult); /* OVERFLOW! */
496 }
如果size
接近int64
的限制,则向mult/2
添加mult
将会溢出,然后由{{1}}进行后续划分才能将其恢复到范围内。< / p>