为什么pg_size_pretty返回负值?

Nic*_*ssu 3 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"
Run Code Online (Sandbox Code Playgroud)

你能解释一下为什么吗?谢谢.

ike*_*ami 5

最高签名的64位int是922337203685477587.这只是比有问题的数字略多一点.当然在某处有溢出pg_size_pretty.

基于注释中提到的代码,pg_size_pretty尝试对数字进行舍入,并使用大于最大有符号64位int的中间值来实现.9223372000000000000 + 1024*1024*1024*1024/2 = 9223372549755813888,大于922337203685477587.

更新:添加第二段并澄清溢出不在调用者中.

  • 对于额外的参考优点,这里是[dbsize.c]中的函数(http://git.postgresql.org/gitweb?p=postgresql.git;a=blob;f=src/backend/utils/adt /dbsize.c;hb=HEAD#l466) (3认同)

mu *_*ort 5

你没有溢出,pg_size_pretty溢出来了.该pg_size_pretty函数应该采取bigint:

pg_size_pretty(bigint)
text
将大小以字节为单位转换为具有大小单位的人类可读格式

并9223372000000000000 < 9223372036854775808因此9223372000000000000是完全有效的bigint和pg_size_pretty应该做正确的事吧.您应该向PostgreSQL人员报告错误并赢得赞誉.

更新:检查PostgreSQL源代码(感谢Jeremiah Peschka提供的链接)向我们展示了bug的位置:

491                 else
492                 {
493                     mult *= 1024;
494                     snprintf(buf, sizeof(buf), INT64_FORMAT " TB",
495                              (size + mult / 2) / mult); /* OVERFLOW! */
496                 }
Run Code Online (Sandbox Code Playgroud)

如果size接近极限int64,那么mult/2在下面的除法之前加上它就会溢出,mult可以把它带回范围.