public inbox for [email protected]
help / color / mirror / Atom feedFrom: 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, 27 Feb 2023 09:34:10 +0100
Message-ID: <[email protected]> (raw)
In-Reply-To: <CAApHDvrn9aznj=h1srcjyPpQVBA_B+d7izYvtUa-5ni+GZ7z0A@mail.gmail.com>
References: <[email protected]>
<[email protected]>
<[email protected]>
<CAApHDvrn9aznj=h1srcjyPpQVBA_B+d7izYvtUa-5ni+GZ7z0A@mail.gmail.com>
On 22.02.23 03:39, David Rowley wrote:
> hmm. I didn't really code pg_size_pretty with aliases in mind. I don't
> think you can do this. There's code in pg_size_pretty() and
> pg_size_pretty_numeric() that'll not work correctly. We look ahead to
> the next unit to check if there is one so we know we must use this
> unit if there are no other units to convert to.
> 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.)
From 4e493128adddc2656f3f139b2ca402f0d13721ba Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Mon, 27 Feb 2023 09:28:25 +0100
Subject: [PATCH v3] 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 | 2 +-
src/backend/utils/adt/dbsize.c | 34 +++++++++++++++++++++++++---
src/test/regress/expected/dbsize.out | 15 ++++++------
src/test/regress/sql/dbsize.sql | 2 +-
4 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 0cbdf63632..718d0cb550 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -27176,7 +27176,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, B, kB, MB, GB or TB 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..338e990aeb 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -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;
+ const char *base;
+};
+
+/* When adding units here also update the error message in pg_size_bytes */
+static const struct size_bytes_unit_alias size_bytes_aliases[] = {
+ {"B", "bytes"},
+ {NULL, 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,22 @@ 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)
+ {
+ for (unit = size_pretty_units; unit->name != NULL; unit++)
+ {
+ if (pg_strcasecmp(a->base, unit->name) == 0)
+ break;
+ }
+ }
}
}
@@ -813,7 +839,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: a6cd1fc692eff708fd42c72b03f756fa1860530e
--
2.39.2
Attachments:
[text/plain] v3-0001-Add-support-for-unit-B-to-pg_size_bytes.patch (6.4K, ../[email protected]/2-v3-0001-Add-support-for-unit-B-to-pg_size_bytes.patch)
download | inline diff:
From 4e493128adddc2656f3f139b2ca402f0d13721ba Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Mon, 27 Feb 2023 09:28:25 +0100
Subject: [PATCH v3] 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 | 2 +-
src/backend/utils/adt/dbsize.c | 34 +++++++++++++++++++++++++---
src/test/regress/expected/dbsize.out | 15 ++++++------
src/test/regress/sql/dbsize.sql | 2 +-
4 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 0cbdf63632..718d0cb550 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -27176,7 +27176,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, B, kB, MB, GB or TB 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..338e990aeb 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -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;
+ const char *base;
+};
+
+/* When adding units here also update the error message in pg_size_bytes */
+static const struct size_bytes_unit_alias size_bytes_aliases[] = {
+ {"B", "bytes"},
+ {NULL, 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,22 @@ 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)
+ {
+ for (unit = size_pretty_units; unit->name != NULL; unit++)
+ {
+ if (pg_strcasecmp(a->base, unit->name) == 0)
+ break;
+ }
+ }
}
}
@@ -813,7 +839,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: a6cd1fc692eff708fd42c72b03f756fa1860530e
--
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