[PATCH] Add reverse(bytea)
Hi,
The proposed patch adds reverse(bytea) function.
This allows converting between big-endian and little-endian binary
strings, which works nicely with previous commits [1]https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=760162fedb4f and [2]https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=6da469badaff.
[1]: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=760162fedb4f
[2]: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=6da469badaff
--
Best regards,
Aleksander Alekseev
Attachments:
v1-0001-Add-reverse-bytea-function.patchapplication/octet-stream; name=v1-0001-Add-reverse-bytea-function.patchDownload
From 223ce1438acf1b415677e509ef9ea02b96dcb1fc Mon Sep 17 00:00:00 2001
From: Aleksander Alekseev <aleksander@timescale.com>
Date: Mon, 10 Mar 2025 09:35:28 +0300
Subject: [PATCH v1] Add reverse(bytea) function
This allows converting between big-endian and little-endian binary strings,
which works nicely with previous commits 760162fedb4f and 6da469badaff.
Aleksander Alekseev, reviewed by TODO FIXME
Discussion: TODO FIXME
!!! BUMP CATVERSION !!!
---
doc/src/sgml/func.sgml | 17 +++++++++++++++++
src/backend/utils/adt/varlena.c | 24 ++++++++++++++++++++++++
src/include/catalog/pg_proc.dat | 3 +++
src/test/regress/expected/strings.out | 21 +++++++++++++++++++++
src/test/regress/sql/strings.sql | 8 ++++++++
5 files changed, 73 insertions(+)
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 51dd8ad6571..2dde6e22799 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -4660,6 +4660,23 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three');
</para></entry>
</row>
+ <row>
+ <entry role="func_table_entry"><para role="func_signature">
+ <indexterm>
+ <primary>reverse</primary>
+ </indexterm>
+ <function>reverse</function> ( <type>bytea</type> )
+ <returnvalue>bytea</returnvalue>
+ </para>
+ <para>
+ Reverses the order of the bytes in the binary string.
+ </para>
+ <para>
+ <literal>reverse('\xAABBCC' :: bytea)</literal>
+ <returnvalue>\xCCBBAA</returnvalue>
+ </para></entry>
+ </row>
+
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index cdf185ea00b..4597e80e37c 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -4153,6 +4153,30 @@ int8_bytea(PG_FUNCTION_ARGS)
return int8send(fcinfo);
}
+/*
+ * Return reversed bytea
+ */
+Datum
+bytea_reverse(PG_FUNCTION_ARGS)
+{
+ bytea *v = PG_GETARG_BYTEA_PP(0);
+ int len = VARSIZE_ANY_EXHDR(v);
+ const char *p = VARDATA_ANY(v);
+ const char *endp = p + len;
+ bytea *result;
+ char *dst;
+
+ result = palloc(len + VARHDRSZ);
+ dst = (char *) VARDATA(result) + len;
+ SET_VARSIZE(result, len + VARHDRSZ);
+
+ while (p < endp)
+ *(--dst) = *p++;
+
+ PG_RETURN_BYTEA_P(result);
+}
+
+
/*
* appendStringInfoText
*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index cede992b6e2..d460c55776f 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -1183,6 +1183,9 @@
{ oid => '8582', descr => 'convert bytea to int8',
proname => 'int8', prorettype => 'int8',
proargtypes => 'bytea', prosrc => 'bytea_int8' },
+{ oid => '8583', descr => 'reverse bytea',
+ proname => 'reverse', prorettype => 'bytea', proargtypes => 'bytea',
+ prosrc => 'bytea_reverse' },
{ oid => '449', descr => 'hash',
proname => 'hashint2', prorettype => 'int4', proargtypes => 'int2',
diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out
index f8cba9f5b24..c9f761f8332 100644
--- a/src/test/regress/expected/strings.out
+++ b/src/test/regress/expected/strings.out
@@ -2460,6 +2460,27 @@ SELECT '\x8000000000000000'::bytea::int8 AS "-9223372036854775808",
-9223372036854775808 | 9223372036854775807
(1 row)
+--
+-- reversing a bytea
+--
+SELECT reverse(''::bytea);
+ reverse
+---------
+ \x
+(1 row)
+
+SELECT reverse('\xAA'::bytea);
+ reverse
+---------
+ \xaa
+(1 row)
+
+SELECT reverse('\xAABBCC'::bytea);
+ reverse
+----------
+ \xccbbaa
+(1 row)
+
--
-- test behavior of escape_string_warning and standard_conforming_strings options
--
diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql
index 4deb0683d57..5f1ca98edad 100644
--- a/src/test/regress/sql/strings.sql
+++ b/src/test/regress/sql/strings.sql
@@ -780,6 +780,14 @@ SELECT '\x80000000'::bytea::int4 AS "-2147483648", '\x7FFFFFFF'::bytea::int4 AS
SELECT '\x8000000000000000'::bytea::int8 AS "-9223372036854775808",
'\x7FFFFFFFFFFFFFFF'::bytea::int8 AS "9223372036854775807";
+
+--
+-- reversing a bytea
+--
+SELECT reverse(''::bytea);
+SELECT reverse('\xAA'::bytea);
+SELECT reverse('\xAABBCC'::bytea);
+
--
-- test behavior of escape_string_warning and standard_conforming_strings options
--
--
2.48.1
On Mon, Mar 10, 2025 at 10:40:01AM +0300, Aleksander Alekseev wrote:
The proposed patch adds reverse(bytea) function.
We already have array_reverse() and text_reverse(), so I see no strong
reason against also having a bytea_reverse().
--
nathan
On 10 Mar 2025, at 22:06, Nathan Bossart <nathandbossart@gmail.com> wrote:
On Mon, Mar 10, 2025 at 10:40:01AM +0300, Aleksander Alekseev wrote:
The proposed patch adds reverse(bytea) function.
We already have array_reverse() and text_reverse(), so I see no strong
reason against also having a bytea_reverse().
+1
--
Daniel Gustafsson
Nathan, Daniel,
We already have array_reverse() and text_reverse(), so I see no strong
reason against also having a bytea_reverse().+1
I also considered adding reverse(bit) however to my knowledge there is
no practical usage for it.
--
Best regards,
Aleksander Alekseev
Here is what I have staged for commit. The only differences from v1 are
some very light edits.
--
nathan
Attachments:
v2-0001-Add-reverse-for-bytea.patchtext/plain; charset=us-asciiDownload
From aa0cc332c6fbadfa6f49ab072dd97c5c8d78fdf8 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathan@postgresql.org>
Date: Tue, 11 Mar 2025 11:01:32 -0500
Subject: [PATCH v2 1/1] Add reverse() for bytea.
This commit introduces a function for reversing the order of the
bytes in binary strings.
NEEDS CATVERSION BUMP
Author: Aleksander Alekseev <aleksander@timescale.com>
Discussion: https://postgr.es/m/CAJ7c6TMe0QVRuNssUArbMi0bJJK32%2BzNA3at5m3osrBQ25MHuw%40mail.gmail.com
---
doc/src/sgml/func.sgml | 17 +++++++++++++++++
src/backend/utils/adt/varlena.c | 21 +++++++++++++++++++++
src/include/catalog/pg_proc.dat | 3 +++
src/test/regress/expected/strings.out | 18 ++++++++++++++++++
src/test/regress/sql/strings.sql | 4 ++++
5 files changed, 63 insertions(+)
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 51dd8ad6571..1c3810e1a04 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -4660,6 +4660,23 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three');
</para></entry>
</row>
+ <row>
+ <entry role="func_table_entry"><para role="func_signature">
+ <indexterm>
+ <primary>reverse</primary>
+ </indexterm>
+ <function>reverse</function> ( <type>bytea</type> )
+ <returnvalue>bytea</returnvalue>
+ </para>
+ <para>
+ Reverses the order of the bytes in the binary string.
+ </para>
+ <para>
+ <literal>reverse('\xabcd'::bytea)</literal>
+ <returnvalue>\xcdab</returnvalue>
+ </para></entry>
+ </row>
+
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index cdf185ea00b..95631eb2099 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -3398,6 +3398,27 @@ byteaSetBit(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(res);
}
+/*
+ * Return reversed bytea
+ */
+Datum
+bytea_reverse(PG_FUNCTION_ARGS)
+{
+ bytea *v = PG_GETARG_BYTEA_PP(0);
+ const char *p = VARDATA_ANY(v);
+ int len = VARSIZE_ANY_EXHDR(v);
+ const char *endp = p + len;
+ bytea *result = palloc(len + VARHDRSZ);
+ char *dst = (char *) VARDATA(result) + len;
+
+ SET_VARSIZE(result, len + VARHDRSZ);
+
+ while (p < endp)
+ *(--dst) = *p++;
+
+ PG_RETURN_BYTEA_P(result);
+}
+
/* text_name()
* Converts a text type to a Name type.
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 42e427f8fe8..890822eaf79 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -1518,6 +1518,9 @@
{ oid => '6163', descr => 'number of set bits',
proname => 'bit_count', prorettype => 'int8', proargtypes => 'bytea',
prosrc => 'bytea_bit_count' },
+{ oid => '8694', descr => 'reverse bytea',
+ proname => 'reverse', prorettype => 'bytea', proargtypes => 'bytea',
+ prosrc => 'bytea_reverse' },
{ oid => '725',
proname => 'dist_pl', prorettype => 'float8', proargtypes => 'point line',
diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out
index f8cba9f5b24..fbe7d7be71f 100644
--- a/src/test/regress/expected/strings.out
+++ b/src/test/regress/expected/strings.out
@@ -236,6 +236,24 @@ SELECT E'De\\678dBeEf'::bytea;
ERROR: invalid input syntax for type bytea
LINE 1: SELECT E'De\\678dBeEf'::bytea;
^
+SELECT reverse(''::bytea);
+ reverse
+---------
+ \x
+(1 row)
+
+SELECT reverse('\xaa'::bytea);
+ reverse
+---------
+ \xaa
+(1 row)
+
+SELECT reverse('\xabcd'::bytea);
+ reverse
+---------
+ \xcdab
+(1 row)
+
SET bytea_output TO escape;
SELECT E'\\xDeAdBeEf'::bytea;
bytea
diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql
index 4deb0683d57..ed054e6e99c 100644
--- a/src/test/regress/sql/strings.sql
+++ b/src/test/regress/sql/strings.sql
@@ -77,6 +77,10 @@ SELECT E'De\123dBeEf'::bytea;
SELECT E'De\\123dBeEf'::bytea;
SELECT E'De\\678dBeEf'::bytea;
+SELECT reverse(''::bytea);
+SELECT reverse('\xaa'::bytea);
+SELECT reverse('\xabcd'::bytea);
+
SET bytea_output TO escape;
SELECT E'\\xDeAdBeEf'::bytea;
SELECT E'\\x De Ad Be Ef '::bytea;
--
2.39.5 (Apple Git-154)