Skip to content

Commit

Permalink
pg_size_pretty: Format negative values similar to positive ones.
Browse files Browse the repository at this point in the history
Previously, negative values were always displayed in bytes, regardless
of how large they were.

Adrian Vondendriesch, reviewed by Julien Rouhaud and myself
  • Loading branch information
robertmhaas committed Nov 6, 2015
1 parent dde5f09 commit 8a1fab3
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 24 deletions.
61 changes: 38 additions & 23 deletions src/backend/utils/adt/dbsize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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));
}
}
}
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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));
}
Expand All @@ -642,39 +661,35 @@ 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
{
/* 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));
}
}
Expand Down
37 changes: 37 additions & 0 deletions src/test/regress/expected/dbsize.out
Original file line number Diff line number Diff line change
@@ -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)

2 changes: 1 addition & 1 deletion src/test/regress/parallel_schedule
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/test/regress/serial_schedule
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ test: alter_operator
test: misc
test: psql
test: async
test: dbsize
test: rules
test: select_views
test: portals_p2
Expand Down
12 changes: 12 additions & 0 deletions src/test/regress/sql/dbsize.sql
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit 8a1fab3

Please sign in to comment.