почему pg_size_pretty возвращает отрицательное значение? - PullRequest
3 голосов
/ 24 апреля 2011

Я играл с 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 ]

5 голосов
/ 24 апреля 2011

Вы не переполнены, pg_size_pretty переполнен.Функция pg_size_pretty должна принимать bigint:

pg_size_pretty(bigint)
text
Преобразует размер в байтах в человеческий размер.читаемый формат с единицами измерения размера

И 9223372000000000000 < 9223372036854775808, поэтому 9223372000000000000 является вполне допустимым bigint, и pg_size_pretty должен делать правильные вещи с ним.Вы должны сообщить об ошибке сотрудникам PostgreSQL и выиграть похвалы.

ОБНОВЛЕНИЕ : Изучение исходного кода PostgreSQL (спасибо Джереми Пешке за предоставление ссылки) показывает нам, где ошибка:

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 сможет вернуть его в диапазон.

5 голосов
/ 24 апреля 2011

64-разрядное целое число со старшим знаком - 922337203685477587. Это немного больше, чем рассматриваемое число. Конечно, переполнение где-то в pg_size_pretty.

На основании кода, упомянутого в комментарии, pg_size_pretty пытается округлить число и делает это, используя промежуточное значение, которое больше, чем максимальное 64-битное целое число со знаком. 9223372000000000000 + 1024 *1024* 1024 * 1024/2 = 9223372549755813888, что больше 922337203685477587.

Обновление : добавлен второй абзац и уточнено, что переполнения нет в вызывающей стороне.

...