I need to decode a base64 string and take a chunk of binary.
Is there a SQL function in Postgres to simply convert a bytea
into a binary string representation?
(Like "00010001010101010".)
I need to decode a base64 string and take a chunk of binary.
Is there a SQL function in Postgres to simply convert a bytea
into a binary string representation?
(Like "00010001010101010".)
If your Postgres installation runs with the default setting bytea_output = 'hex'
, there is a very simple hack:
SELECT right(bytea_col::text, -1)::varbit;
Example:
SELECT right((bytea '\xDEADBEEF')::text, -1)::varbit;
Result:
'11011110101011011011111011101111'
right(text, -1)
is just the cheapest way to remove the leading backslash from the text representation.
varbit
(standard SQL name bit varying
) is for bit strings of arbitrary length. Cast the result to text
or varchar
if you like.
Related, with explanation:
You could put the following code into a function:
WITH byte AS ( -- 1
SELECT E'\\xDEADBEEF'::bytea as value
)
SELECT
string_agg( -- 5
get_byte(value, gs)::bit(8)::text -- 4
, ''
)
FROM
byte,
generate_series( -- 3
0,
length(value) - 1 -- 2
) gs
I demonstrated the development of the query within the fiddle.
WITH
clause encapsulates the bytea
value for double usage in further codelength()
calculates the binary length of the bytea
valuegenerate_series()
creates a list from 0
to length - 1
(0 - 3
in my example)get_byte()
takes the bytea
value a second time and gives out the byte at position gs
(the previous calculated values 0-3
). This gives an integer
representation of the the byte. After that the cast to bit(8)
type converts the result of this function to its binary representation (1 byte = 8 bit)string_agg()
finally aggregates all for binary strings into one. (taking its text
representations instead of bit
type, with no delimiters) A function could look like this:
CREATE OR REPLACE FUNCTION to_bit(value bytea) RETURNS SETOF text AS
$$
BEGIN
RETURN QUERY
SELECT
string_agg(get_byte(value, gs)::bit(8)::text, '')
FROM
generate_series(0, length(value) - 1) gs;
END;
$$ LANGUAGE plpgsql;
After that you could call it:
SELECT to_bit(E'\\xDEADBEEF'::bytea)
You could try it using get_bit()
instead of get_byte()
. This safes you the ::bit(8)
cast but of course you need to multiply the length with factor 8
indeed.
The resulting bit string has another bit order but maybe it fits your use case better:
WITH byte AS (
SELECT E'\\xDEADBEEF'::bytea as value
)
SELECT
string_agg(get_bit(value, gs)::text, '')
FROM
byte,
generate_series(0, length(value) * 8 - 1) gs
© 2022 - 2024 — McMap. All rights reserved.