为什么pg_size_pretty返回负值?

时间:2011-04-24 01:37:14

标签: postgresql bigint

我正在玩pg_size_pretty(),我发现当我传递一个很大的值时,它会开始返回负值。 这是我的考验:

select pg_size_pretty(9223370000000000000); -- "8388606 TB"
select pg_size_pretty(9223371000000000000); -- "8388607 TB"
select pg_size_pretty(9223372000000000000); -- "-8388607 TB"
你能解释一下为什么吗? 感谢。

2 个答案:

答案 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是完全有效的bigintpg_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>