public inbox for [email protected]  
help / color / mirror / Atom feed
From: Peter Eisentraut <[email protected]>
To: David Rowley <[email protected]>
Cc: Justin Pryzby <[email protected]>
Cc: [email protected]
Subject: Re: Add support for unit "B" to pg_size_pretty()
Date: Mon, 6 Mar 2023 09:13:41 +0100
Message-ID: <[email protected]> (raw)
In-Reply-To: <CAApHDvpzxuo5F8-zbDoK7ZFmVjMbvVK3XQjNcZZuGcMhBc0V5w@mail.gmail.com>
References: <[email protected]>
	<[email protected]>
	<[email protected]>
	<CAApHDvrn9aznj=h1srcjyPpQVBA_B+d7izYvtUa-5ni+GZ7z0A@mail.gmail.com>
	<[email protected]>
	<CAApHDvpzxuo5F8-zbDoK7ZFmVjMbvVK3XQjNcZZuGcMhBc0V5w@mail.gmail.com>

On 02.03.23 20:58, David Rowley wrote:
> On Mon, 27 Feb 2023 at 21:34, Peter Eisentraut
> <[email protected]> wrote:
>>
>> On 22.02.23 03:39, David Rowley wrote:
>>> I think you'll need to find another way to make the aliases work.
>>> Maybe another array with the name and an int to reference the
>>> corresponding index in size_pretty_units.
>>
>> Ok, here is a new patch with a separate table of aliases.  (Might look
>> like overkill, but I think the "PiB" etc. example you had could actually
>> be a good use case for this as well.)
> 
> I think I'd prefer to see the size_bytes_unit_alias struct have an
> index into size_pretty_units[] array. i.e:

Ok, done that way.  (I had thought about that, but I was worried that 
that would be too error-prone to maintain.  But I suppose the tables 
don't change that often, and test cases would easily catch mistakes.)

I also updated the documentation a bit more.

From bb0fb6eb3364195838a9c7e387ee4237c8cd30b4 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Mon, 6 Mar 2023 09:10:50 +0100
Subject: [PATCH v4] Add support for unit "B" to pg_size_bytes()

This makes it consistent with the units support in GUC.

Discussion: https://www.postgresql.org/message-id/flat/0106914a-9eb5-22be-40d8-652cc88c827d%40enterprisedb.com
---
 doc/src/sgml/func.sgml               |  9 +++++---
 src/backend/utils/adt/dbsize.c       | 33 ++++++++++++++++++++++++----
 src/test/regress/expected/dbsize.out | 15 +++++++------
 src/test/regress/sql/dbsize.sql      |  2 +-
 4 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 97b3f1c1a6..fa5f60cf4c 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -27166,8 +27166,11 @@ <title>Database Object Size Functions</title>
         <returnvalue>bigint</returnvalue>
        </para>
        <para>
-        Converts a size in human-readable format (as returned
-        by <function>pg_size_pretty</function>) into bytes.
+        Converts a size in human-readable format (as returned by
+        <function>pg_size_pretty</function>) into bytes.  Valid units are
+        <literal>bytes</literal>, <literal>B</literal>, <literal>kB</literal>,
+        <literal>MB</literal>, <literal>GB</literal>, <literal>TB</literal>,
+        and <literal>PB</literal>.
        </para></entry>
       </row>
 
@@ -27185,7 +27188,7 @@ <title>Database Object Size Functions</title>
        </para>
        <para>
         Converts a size in bytes into a more easily human-readable format with
-        size units (bytes, kB, MB, GB or TB as appropriate).  Note that the
+        size units (bytes, kB, MB, GB, TB, etc. as appropriate).  Note that the
         units are powers of 2 rather than powers of 10, so 1kB is 1024 bytes,
         1MB is 1024<superscript>2</superscript> = 1048576 bytes, and so on.
        </para></entry>
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index dbd404101f..8d5ca41c8b 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -46,7 +46,7 @@ struct size_pretty_unit
 								 * unit */
 };
 
-/* When adding units here also update the error message in pg_size_bytes */
+/* When adding units here also update the docs and the error message in pg_size_bytes */
 static const struct size_pretty_unit size_pretty_units[] = {
 	{"bytes", 10 * 1024, false, 0},
 	{"kB", 20 * 1024 - 1, true, 10},
@@ -57,6 +57,19 @@ static const struct size_pretty_unit size_pretty_units[] = {
 	{NULL, 0, false, 0}
 };
 
+/* Additional unit aliases acceted by pg_size_bytes */
+struct size_bytes_unit_alias
+{
+	const char *alias;
+	int			unit_index;		/* corresponding size_pretty_units element */
+};
+
+/* When adding units here also update the docs and the error message in pg_size_bytes */
+static const struct size_bytes_unit_alias size_bytes_aliases[] = {
+	{"B", 0},
+	{NULL}
+};
+
 /* Return physical size of directory contents, or 0 if dir doesn't exist */
 static int64
 db_dir_size(const char *path)
@@ -801,9 +814,19 @@ pg_size_bytes(PG_FUNCTION_ARGS)
 		{
 			/* Parse the unit case-insensitively */
 			if (pg_strcasecmp(strptr, unit->name) == 0)
-			{
-				multiplier = ((int64) 1) << unit->unitbits;
 				break;
+		}
+
+		/* If not found, look in table of aliases */
+		if (unit->name == NULL)
+		{
+			for (const struct size_bytes_unit_alias *a = size_bytes_aliases; a->alias != NULL; a++)
+			{
+				if (pg_strcasecmp(strptr, a->alias) == 0)
+				{
+					unit = &size_pretty_units[a->unit_index];
+					break;
+				}
 			}
 		}
 
@@ -813,7 +836,9 @@ pg_size_bytes(PG_FUNCTION_ARGS)
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("invalid size: \"%s\"", text_to_cstring(arg)),
 					 errdetail("Invalid size unit: \"%s\".", strptr),
-					 errhint("Valid units are \"bytes\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\".")));
+					 errhint("Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\".")));
+
+		multiplier = ((int64) 1) << unit->unitbits;
 
 		if (multiplier > 1)
 		{
diff --git a/src/test/regress/expected/dbsize.out b/src/test/regress/expected/dbsize.out
index d8d6686b5f..f1121a87aa 100644
--- a/src/test/regress/expected/dbsize.out
+++ b/src/test/regress/expected/dbsize.out
@@ -81,12 +81,13 @@ SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM
 
 -- pg_size_bytes() tests
 SELECT size, pg_size_bytes(size) FROM
-    (VALUES ('1'), ('123bytes'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
+    (VALUES ('1'), ('123bytes'), ('256 B'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
             ('1TB'), ('3000 TB'), ('1e6 MB'), ('99 PB')) x(size);
    size   |   pg_size_bytes    
 ----------+--------------------
  1        |                  1
  123bytes |                123
+ 256 B    |                256
  1kB      |               1024
  1MB      |            1048576
   1 GB    |         1073741824
@@ -95,7 +96,7 @@ SELECT size, pg_size_bytes(size) FROM
  3000 TB  |   3298534883328000
  1e6 MB   |      1048576000000
  99 PB    | 111464090777419776
-(10 rows)
+(11 rows)
 
 -- case-insensitive units are supported
 SELECT size, pg_size_bytes(size) FROM
@@ -153,15 +154,15 @@ SELECT size, pg_size_bytes(size) FROM
 SELECT pg_size_bytes('1 AB');
 ERROR:  invalid size: "1 AB"
 DETAIL:  Invalid size unit: "AB".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('1 AB A');
 ERROR:  invalid size: "1 AB A"
 DETAIL:  Invalid size unit: "AB A".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('1 AB A    ');
 ERROR:  invalid size: "1 AB A    "
 DETAIL:  Invalid size unit: "AB A".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('9223372036854775807.9');
 ERROR:  bigint out of range
 SELECT pg_size_bytes('1e100');
@@ -171,7 +172,7 @@ ERROR:  value overflows numeric format
 SELECT pg_size_bytes('1 byte');  -- the singular "byte" is not supported
 ERROR:  invalid size: "1 byte"
 DETAIL:  Invalid size unit: "byte".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('');
 ERROR:  invalid size: ""
 SELECT pg_size_bytes('kb');
@@ -189,6 +190,6 @@ ERROR:  invalid size: ".+912"
 SELECT pg_size_bytes('+912+ kB');
 ERROR:  invalid size: "+912+ kB"
 DETAIL:  Invalid size unit: "+ kB".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('++123 kB');
 ERROR:  invalid size: "++123 kB"
diff --git a/src/test/regress/sql/dbsize.sql b/src/test/regress/sql/dbsize.sql
index 7df865271b..b34cf33385 100644
--- a/src/test/regress/sql/dbsize.sql
+++ b/src/test/regress/sql/dbsize.sql
@@ -29,7 +29,7 @@
 
 -- pg_size_bytes() tests
 SELECT size, pg_size_bytes(size) FROM
-    (VALUES ('1'), ('123bytes'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
+    (VALUES ('1'), ('123bytes'), ('256 B'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
             ('1TB'), ('3000 TB'), ('1e6 MB'), ('99 PB')) x(size);
 
 -- case-insensitive units are supported

base-commit: 46d490ac19a7ca93a5c0f47e5a0e759b5385a8ae
-- 
2.39.2



Attachments:

  [text/plain] v4-0001-Add-support-for-unit-B-to-pg_size_bytes.patch (7.4K, ../[email protected]/2-v4-0001-Add-support-for-unit-B-to-pg_size_bytes.patch)
  download | inline diff:
From bb0fb6eb3364195838a9c7e387ee4237c8cd30b4 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Mon, 6 Mar 2023 09:10:50 +0100
Subject: [PATCH v4] Add support for unit "B" to pg_size_bytes()

This makes it consistent with the units support in GUC.

Discussion: https://www.postgresql.org/message-id/flat/0106914a-9eb5-22be-40d8-652cc88c827d%40enterprisedb.com
---
 doc/src/sgml/func.sgml               |  9 +++++---
 src/backend/utils/adt/dbsize.c       | 33 ++++++++++++++++++++++++----
 src/test/regress/expected/dbsize.out | 15 +++++++------
 src/test/regress/sql/dbsize.sql      |  2 +-
 4 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 97b3f1c1a6..fa5f60cf4c 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -27166,8 +27166,11 @@ <title>Database Object Size Functions</title>
         <returnvalue>bigint</returnvalue>
        </para>
        <para>
-        Converts a size in human-readable format (as returned
-        by <function>pg_size_pretty</function>) into bytes.
+        Converts a size in human-readable format (as returned by
+        <function>pg_size_pretty</function>) into bytes.  Valid units are
+        <literal>bytes</literal>, <literal>B</literal>, <literal>kB</literal>,
+        <literal>MB</literal>, <literal>GB</literal>, <literal>TB</literal>,
+        and <literal>PB</literal>.
        </para></entry>
       </row>
 
@@ -27185,7 +27188,7 @@ <title>Database Object Size Functions</title>
        </para>
        <para>
         Converts a size in bytes into a more easily human-readable format with
-        size units (bytes, kB, MB, GB or TB as appropriate).  Note that the
+        size units (bytes, kB, MB, GB, TB, etc. as appropriate).  Note that the
         units are powers of 2 rather than powers of 10, so 1kB is 1024 bytes,
         1MB is 1024<superscript>2</superscript> = 1048576 bytes, and so on.
        </para></entry>
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index dbd404101f..8d5ca41c8b 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -46,7 +46,7 @@ struct size_pretty_unit
 								 * unit */
 };
 
-/* When adding units here also update the error message in pg_size_bytes */
+/* When adding units here also update the docs and the error message in pg_size_bytes */
 static const struct size_pretty_unit size_pretty_units[] = {
 	{"bytes", 10 * 1024, false, 0},
 	{"kB", 20 * 1024 - 1, true, 10},
@@ -57,6 +57,19 @@ static const struct size_pretty_unit size_pretty_units[] = {
 	{NULL, 0, false, 0}
 };
 
+/* Additional unit aliases acceted by pg_size_bytes */
+struct size_bytes_unit_alias
+{
+	const char *alias;
+	int			unit_index;		/* corresponding size_pretty_units element */
+};
+
+/* When adding units here also update the docs and the error message in pg_size_bytes */
+static const struct size_bytes_unit_alias size_bytes_aliases[] = {
+	{"B", 0},
+	{NULL}
+};
+
 /* Return physical size of directory contents, or 0 if dir doesn't exist */
 static int64
 db_dir_size(const char *path)
@@ -801,9 +814,19 @@ pg_size_bytes(PG_FUNCTION_ARGS)
 		{
 			/* Parse the unit case-insensitively */
 			if (pg_strcasecmp(strptr, unit->name) == 0)
-			{
-				multiplier = ((int64) 1) << unit->unitbits;
 				break;
+		}
+
+		/* If not found, look in table of aliases */
+		if (unit->name == NULL)
+		{
+			for (const struct size_bytes_unit_alias *a = size_bytes_aliases; a->alias != NULL; a++)
+			{
+				if (pg_strcasecmp(strptr, a->alias) == 0)
+				{
+					unit = &size_pretty_units[a->unit_index];
+					break;
+				}
 			}
 		}
 
@@ -813,7 +836,9 @@ pg_size_bytes(PG_FUNCTION_ARGS)
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("invalid size: \"%s\"", text_to_cstring(arg)),
 					 errdetail("Invalid size unit: \"%s\".", strptr),
-					 errhint("Valid units are \"bytes\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\".")));
+					 errhint("Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\".")));
+
+		multiplier = ((int64) 1) << unit->unitbits;
 
 		if (multiplier > 1)
 		{
diff --git a/src/test/regress/expected/dbsize.out b/src/test/regress/expected/dbsize.out
index d8d6686b5f..f1121a87aa 100644
--- a/src/test/regress/expected/dbsize.out
+++ b/src/test/regress/expected/dbsize.out
@@ -81,12 +81,13 @@ SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM
 
 -- pg_size_bytes() tests
 SELECT size, pg_size_bytes(size) FROM
-    (VALUES ('1'), ('123bytes'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
+    (VALUES ('1'), ('123bytes'), ('256 B'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
             ('1TB'), ('3000 TB'), ('1e6 MB'), ('99 PB')) x(size);
    size   |   pg_size_bytes    
 ----------+--------------------
  1        |                  1
  123bytes |                123
+ 256 B    |                256
  1kB      |               1024
  1MB      |            1048576
   1 GB    |         1073741824
@@ -95,7 +96,7 @@ SELECT size, pg_size_bytes(size) FROM
  3000 TB  |   3298534883328000
  1e6 MB   |      1048576000000
  99 PB    | 111464090777419776
-(10 rows)
+(11 rows)
 
 -- case-insensitive units are supported
 SELECT size, pg_size_bytes(size) FROM
@@ -153,15 +154,15 @@ SELECT size, pg_size_bytes(size) FROM
 SELECT pg_size_bytes('1 AB');
 ERROR:  invalid size: "1 AB"
 DETAIL:  Invalid size unit: "AB".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('1 AB A');
 ERROR:  invalid size: "1 AB A"
 DETAIL:  Invalid size unit: "AB A".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('1 AB A    ');
 ERROR:  invalid size: "1 AB A    "
 DETAIL:  Invalid size unit: "AB A".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('9223372036854775807.9');
 ERROR:  bigint out of range
 SELECT pg_size_bytes('1e100');
@@ -171,7 +172,7 @@ ERROR:  value overflows numeric format
 SELECT pg_size_bytes('1 byte');  -- the singular "byte" is not supported
 ERROR:  invalid size: "1 byte"
 DETAIL:  Invalid size unit: "byte".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('');
 ERROR:  invalid size: ""
 SELECT pg_size_bytes('kb');
@@ -189,6 +190,6 @@ ERROR:  invalid size: ".+912"
 SELECT pg_size_bytes('+912+ kB');
 ERROR:  invalid size: "+912+ kB"
 DETAIL:  Invalid size unit: "+ kB".
-HINT:  Valid units are "bytes", "kB", "MB", "GB", "TB", and "PB".
+HINT:  Valid units are "bytes", "B", "kB", "MB", "GB", "TB", and "PB".
 SELECT pg_size_bytes('++123 kB');
 ERROR:  invalid size: "++123 kB"
diff --git a/src/test/regress/sql/dbsize.sql b/src/test/regress/sql/dbsize.sql
index 7df865271b..b34cf33385 100644
--- a/src/test/regress/sql/dbsize.sql
+++ b/src/test/regress/sql/dbsize.sql
@@ -29,7 +29,7 @@
 
 -- pg_size_bytes() tests
 SELECT size, pg_size_bytes(size) FROM
-    (VALUES ('1'), ('123bytes'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
+    (VALUES ('1'), ('123bytes'), ('256 B'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
             ('1TB'), ('3000 TB'), ('1e6 MB'), ('99 PB')) x(size);
 
 -- case-insensitive units are supported

base-commit: 46d490ac19a7ca93a5c0f47e5a0e759b5385a8ae
-- 
2.39.2



view thread (9+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected]
  Subject: Re: Add support for unit "B" to pg_size_pretty()
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox