diff options
Diffstat (limited to 'src/backend/utils/adt/dbsize.c')
-rw-r--r-- | src/backend/utils/adt/dbsize.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index bdaa341be7b..ab4b6ee55e3 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -31,8 +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) +/* Divide by two and round away from zero */ +#define half_rounded(x) (((x) + ((x) < 0 ? -1 : 1)) / 2) /* Return physical size of directory contents, or 0 if dir doesn't exist */ static int64 @@ -542,25 +542,29 @@ pg_size_pretty(PG_FUNCTION_ARGS) snprintf(buf, sizeof(buf), INT64_FORMAT " bytes", size); else { - size >>= 9; /* keep one extra bit for rounding */ + /* + * We use divide instead of bit shifting so that behavior matches for + * both positive and negative size values. + */ + size /= (1 << 9); /* keep one extra bit for rounding */ if (Abs(size) < limit2) snprintf(buf, sizeof(buf), INT64_FORMAT " kB", half_rounded(size)); else { - size >>= 10; + size /= (1 << 10); if (Abs(size) < limit2) snprintf(buf, sizeof(buf), INT64_FORMAT " MB", half_rounded(size)); else { - size >>= 10; + size /= (1 << 10); if (Abs(size) < limit2) snprintf(buf, sizeof(buf), INT64_FORMAT " GB", half_rounded(size)); else { - size >>= 10; + size /= (1 << 10); snprintf(buf, sizeof(buf), INT64_FORMAT " TB", half_rounded(size)); } @@ -629,15 +633,13 @@ numeric_half_rounded(Numeric n) } static Numeric -numeric_shift_right(Numeric n, unsigned count) +numeric_truncated_divide(Numeric n, int64 divisor) { Datum d = NumericGetDatum(n); - Datum divisor_int64; Datum divisor_numeric; Datum result; - divisor_int64 = Int64GetDatum((int64) (1 << count)); - divisor_numeric = DirectFunctionCall1(int8_numeric, divisor_int64); + divisor_numeric = DirectFunctionCall1(int8_numeric, divisor); result = DirectFunctionCall2(numeric_div_trunc, d, divisor_numeric); return DatumGetNumeric(result); } @@ -660,8 +662,8 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS) else { /* keep one extra bit for rounding */ - /* size >>= 9 */ - size = numeric_shift_right(size, 9); + /* size /= (1 << 9) */ + size = numeric_truncated_divide(size, 1 << 9); if (numeric_is_less(numeric_absolute(size), limit2)) { @@ -670,8 +672,9 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS) } else { - /* size >>= 10 */ - size = numeric_shift_right(size, 10); + /* size /= (1 << 10) */ + size = numeric_truncated_divide(size, 1 << 10); + if (numeric_is_less(numeric_absolute(size), limit2)) { size = numeric_half_rounded(size); @@ -679,8 +682,8 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS) } else { - /* size >>= 10 */ - size = numeric_shift_right(size, 10); + /* size /= (1 << 10) */ + size = numeric_truncated_divide(size, 1 << 10); if (numeric_is_less(numeric_absolute(size), limit2)) { @@ -689,8 +692,8 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS) } else { - /* size >>= 10 */ - size = numeric_shift_right(size, 10); + /* size /= (1 << 10) */ + size = numeric_truncated_divide(size, 1 << 10); size = numeric_half_rounded(size); result = psprintf("%s TB", numeric_to_cstring(size)); } |