pg_size_pretty: Format negative values similar to positive ones.
authorRobert Haas <[email protected]>
Fri, 6 Nov 2015 16:03:02 +0000 (11:03 -0500)
committerRobert Haas <[email protected]>
Fri, 6 Nov 2015 16:03:02 +0000 (11:03 -0500)
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
src/test/regress/expected/dbsize.out [new file with mode: 0644]
src/test/regress/parallel_schedule
src/test/regress/serial_schedule
src/test/regress/sql/dbsize.sql [new file with mode: 0644]

index 82311b4ca95a87a010b748eca6151defa9562725..5ee59d0a2e250be6990131a2e1a6f980754b7346 100644 (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));
                }
            }
diff --git a/src/test/regress/expected/dbsize.out b/src/test/regress/expected/dbsize.out
new file mode 100644 (file)
index 0000000..aa513e7
--- /dev/null
@@ -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)
+
index c63abf4b0ad57cd5f1a6c7027fc118005b5d4b2e..3987b4c700fd1ca6dd3a2b62e31c69d7efa14a9c 100644 (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
index 88dcd64dfce3b2e82bf07bf813bfc1404538e12b..379f2729be4951c097ddb20d002c13c1b50e6a19 100644 (file)
@@ -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 (file)
index 0000000..c118090
--- /dev/null
@@ -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);