PostgreSQL uses POSIX regular expressions. If we had a regular expression, we could see if the input matched. If so feed it to decode, otherwise return it as-is. This question's answer provides us one such regex,
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
Keep in mind, decode returns bytea
. We explicitly cast name
to bytea here because if it isn't Base64, we need to be sure we return the same type. This would look like this,
SELECT name, CASE
WHEN name ~ '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$'
THEN decode(name,'base64')
ELSE name::bytea
END AS name_maybe_decoded
FROM abc;
This will return
name
decoded as Base64, if the input looks to be Base64.
name
as-is.
Try it..
SELECT name, CASE
WHEN name ~ '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$'
THEN decode(name,'base64')
ELSE name::bytea
END AS name_maybe_decoded
FROM ( VALUES
('VGhpcyBpcyB0ZXN0IGRhdGE='),
('foobar'),
('SEFMTE8='),
('NOTBase64=')
) AS t(name);
Now remember, that's still the binary representation of the text, and the base64 decoded. You can output that as text using convert_from
WITH t2 AS (
SELECT name, CASE
WHEN name ~ '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$'
THEN decode(name,'base64')
ELSE name::bytea
END AS name_maybe_decoded
FROM ( VALUES
('VGhpcyBpcyB0ZXN0IGRhdGE='),
('foobar'),
('SEFMTE8='),
('NOTBase64=')
) AS t(name)
)
SELECT convert_from(name_maybe_decoded, 'UTF8')
FROM t2;
abc
table in your questionINSERT INTO abc (name) VALUES (chr(0)::varchar(500));
You will getERROR: null character not permitted