aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/dbsize.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/dbsize.c')
-rw-r--r--src/backend/utils/adt/dbsize.c39
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));
}