]> granicus.if.org Git - postgresql/commitdiff
pg_size_pretty: Format negative values similar to positive ones.
authorRobert Haas <rhaas@postgresql.org>
Fri, 6 Nov 2015 16:03:02 +0000 (11:03 -0500)
committerRobert Haas <rhaas@postgresql.org>
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);