From 8a1fab36aba7506fcf4559c4ef95fcacdd0b439a Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Fri, 6 Nov 2015 11:03:02 -0500 Subject: [PATCH] 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 --- src/backend/utils/adt/dbsize.c | 61 +++++++++++++++++----------- src/test/regress/expected/dbsize.out | 37 +++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/serial_schedule | 1 + src/test/regress/sql/dbsize.sql | 12 ++++++ 5 files changed, 89 insertions(+), 24 deletions(-) create mode 100644 src/test/regress/expected/dbsize.out create mode 100644 src/test/regress/sql/dbsize.sql diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 82311b4ca9..5ee59d0a2e 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -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)); } } diff --git a/src/test/regress/expected/dbsize.out b/src/test/regress/expected/dbsize.out new file mode 100644 index 0000000000..aa513e7eff --- /dev/null +++ b/src/test/regress/expected/dbsize.out @@ -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) + diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index c63abf4b0a..3987b4c700 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -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 diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 88dcd64dfc..379f2729be 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -117,6 +117,7 @@ test: alter_operator test: misc test: psql test: async +test: dbsize test: rules test: select_views test: portals_p2 diff --git a/src/test/regress/sql/dbsize.sql b/src/test/regress/sql/dbsize.sql new file mode 100644 index 0000000000..c118090cc6 --- /dev/null +++ b/src/test/regress/sql/dbsize.sql @@ -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);