pg_size_pretty: Format negative values similar to positive ones.

Previously, negative values were always displayed in bytes, regardless
of how large they were.

Adrian Vondendriesch, reviewed by Julien Rouhaud and myself
This commit is contained in:
Robert Haas 2015-11-06 11:03:02 -05:00
parent dde5f09fad
commit 8a1fab36ab
5 changed files with 89 additions and 24 deletions

View File

@ -31,6 +31,8 @@
#include "utils/relmapper.h"
#include "utils/syscache.h"
/* Divide by two and round towards positive infinity. */
#define half_rounded(x) (((x) + ((x) < 0 ? 0 : 1)) / 2)
/* Return physical size of directory contents, or 0 if dir doesn't exist */
static int64
@ -534,31 +536,31 @@ pg_size_pretty(PG_FUNCTION_ARGS)
int64 limit = 10 * 1024;
int64 limit2 = limit * 2 - 1;
if (size < limit)
if (Abs(size) < limit)
snprintf(buf, sizeof(buf), INT64_FORMAT " bytes", size);
else
{
size >>= 9; /* keep one extra bit for rounding */
if (size < limit2)
if (Abs(size) < limit2)
snprintf(buf, sizeof(buf), INT64_FORMAT " kB",
(size + 1) / 2);
half_rounded(size));
else
{
size >>= 10;
if (size < limit2)
if (Abs(size) < limit2)
snprintf(buf, sizeof(buf), INT64_FORMAT " MB",
(size + 1) / 2);
half_rounded(size));
else
{
size >>= 10;
if (size < limit2)
if (Abs(size) < limit2)
snprintf(buf, sizeof(buf), INT64_FORMAT " GB",
(size + 1) / 2);
half_rounded(size));
else
{
size >>= 10;
snprintf(buf, sizeof(buf), INT64_FORMAT " TB",
(size + 1) / 2);
half_rounded(size));
}
}
}
@ -593,17 +595,34 @@ numeric_is_less(Numeric a, Numeric b)
}
static Numeric
numeric_plus_one_over_two(Numeric n)
numeric_absolute(Numeric n)
{
Datum d = NumericGetDatum(n);
Datum result;
result = DirectFunctionCall1(numeric_abs, d);
return DatumGetNumeric(result);
}
static Numeric
numeric_half_rounded(Numeric n)
{
Datum d = NumericGetDatum(n);
Datum zero;
Datum one;
Datum two;
Datum result;
zero = DirectFunctionCall1(int8_numeric, Int64GetDatum(0));
one = DirectFunctionCall1(int8_numeric, Int64GetDatum(1));
two = DirectFunctionCall1(int8_numeric, Int64GetDatum(2));
result = DirectFunctionCall2(numeric_add, d, one);
result = DirectFunctionCall2(numeric_div_trunc, result, two);
if (DatumGetBool(DirectFunctionCall2(numeric_ge, d, zero)))
d = DirectFunctionCall2(numeric_add, d, one);
else
d = DirectFunctionCall2(numeric_sub, d, one);
result = DirectFunctionCall2(numeric_div_trunc, d, two);
return DatumGetNumeric(result);
}
@ -632,7 +651,7 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS)
limit = int64_to_numeric(10 * 1024);
limit2 = int64_to_numeric(10 * 1024 * 2 - 1);
if (numeric_is_less(size, limit))
if (numeric_is_less(numeric_absolute(size), limit))
{
result = psprintf("%s bytes", numeric_to_cstring(size));
}
@ -642,20 +661,18 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS)
/* size >>= 9 */
size = numeric_shift_right(size, 9);
if (numeric_is_less(size, limit2))
if (numeric_is_less(numeric_absolute(size), limit2))
{
/* size = (size + 1) / 2 */
size = numeric_plus_one_over_two(size);
size = numeric_half_rounded(size);
result = psprintf("%s kB", numeric_to_cstring(size));
}
else
{
/* size >>= 10 */
size = numeric_shift_right(size, 10);
if (numeric_is_less(size, limit2))
if (numeric_is_less(numeric_absolute(size), limit2))
{
/* size = (size + 1) / 2 */
size = numeric_plus_one_over_two(size);
size = numeric_half_rounded(size);
result = psprintf("%s MB", numeric_to_cstring(size));
}
else
@ -663,18 +680,16 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS)
/* size >>= 10 */
size = numeric_shift_right(size, 10);
if (numeric_is_less(size, limit2))
if (numeric_is_less(numeric_absolute(size), limit2))
{
/* size = (size + 1) / 2 */
size = numeric_plus_one_over_two(size);
size = numeric_half_rounded(size);
result = psprintf("%s GB", numeric_to_cstring(size));
}
else
{
/* size >>= 10 */
size = numeric_shift_right(size, 10);
/* size = (size + 1) / 2 */
size = numeric_plus_one_over_two(size);
size = numeric_half_rounded(size);
result = psprintf("%s TB", numeric_to_cstring(size));
}
}

View File

@ -0,0 +1,37 @@
SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM
(VALUES (10::bigint), (1000::bigint), (1000000::bigint),
(1000000000::bigint), (1000000000000::bigint),
(1000000000000000::bigint)) x(size);
size | pg_size_pretty | pg_size_pretty
------------------+----------------+----------------
10 | 10 bytes | -10 bytes
1000 | 1000 bytes | -1000 bytes
1000000 | 977 kB | -977 kB
1000000000 | 954 MB | -954 MB
1000000000000 | 931 GB | -931 GB
1000000000000000 | 909 TB | -909 TB
(6 rows)
SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM
(VALUES (10::numeric), (1000::numeric), (1000000::numeric),
(1000000000::numeric), (1000000000000::numeric),
(1000000000000000::numeric),
(10.5::numeric), (1000.5::numeric), (1000000.5::numeric),
(1000000000.5::numeric), (1000000000000.5::numeric),
(1000000000000000.5::numeric)) x(size);
size | pg_size_pretty | pg_size_pretty
--------------------+----------------+----------------
10 | 10 bytes | -10 bytes
1000 | 1000 bytes | -1000 bytes
1000000 | 977 kB | -977 kB
1000000000 | 954 MB | -954 MB
1000000000000 | 931 GB | -931 GB
1000000000000000 | 909 TB | -909 TB
10.5 | 10.5 bytes | -10.5 bytes
1000.5 | 1000.5 bytes | -1000.5 bytes
1000000.5 | 977 kB | -977 kB
1000000000.5 | 954 MB | -954 MB
1000000000000.5 | 931 GB | -931 GB
1000000000000000.5 | 909 TB | -909 TB
(12 rows)

View File

@ -89,7 +89,7 @@ test: brin gin gist spgist privileges security_label collate matview lock replic
# ----------
# Another group of parallel tests
# ----------
test: alter_generic alter_operator misc psql async
test: alter_generic alter_operator misc psql async dbsize
# rules cannot run concurrently with any test that creates a view
test: rules

View File

@ -117,6 +117,7 @@ test: alter_operator
test: misc
test: psql
test: async
test: dbsize
test: rules
test: select_views
test: portals_p2

View File

@ -0,0 +1,12 @@
SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM
(VALUES (10::bigint), (1000::bigint), (1000000::bigint),
(1000000000::bigint), (1000000000000::bigint),
(1000000000000000::bigint)) x(size);
SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM
(VALUES (10::numeric), (1000::numeric), (1000000::numeric),
(1000000000::numeric), (1000000000000::numeric),
(1000000000000000::numeric),
(10.5::numeric), (1000.5::numeric), (1000000.5::numeric),
(1000000000.5::numeric), (1000000000000.5::numeric),
(1000000000000000.5::numeric)) x(size);