debugsqlMinor
Custom Postgres function not working
Viewed 0 times
postgresworkingfunctioncustomnot
Problem
I wrote this function that is supposed to iterate through a text array and convert each element (which is a typecasted integer) to hex, append to a text variable, then return the hex. However, I get nothing back.
Does anybody see any issues with the function that would cause it not to return anything?
Does anybody see any issues with the function that would cause it not to return anything?
CREATE OR REPLACE FUNCTION array_convert_to_hex(text[])
RETURNS text
AS
$
DECLARE
arrInts ALIAS FOR $1;
retVal text;
BEGIN
FOR I IN array_lower(arrInts, 1)..array_upper(arrInts, 1) LOOP
retVal := retVal || lpad(cast(to_hex(arrInts[I]::integer) as varchar), 2, '0');
END LOOP;
RETURN retVal;
END;
$
LANGUAGE plpgsql
STABLE
RETURNS NULL ON NULL INPUT;Solution
Peter's quite right about the problem, of course. However, this entire function is unnecessarily slow and complex - that repeated string concatenation will be horrible for performance, and PL/PgSQL loops are best avoided when you can anyway.
You can do the same job with an ordinary SQL function using
The above version expects an integer array, but you can accept text arrays with an overload:
Note that no sanity check is done to make sure the hex string is two digits or less. You should really add a check where you use a CASE statement to execute a PL/PgSQL function that raises an error if there's bad input. Here's a complete example:
You can do the same job with an ordinary SQL function using
generate_subscripts:CREATE OR REPLACE FUNCTION intarr_to_hex_string(integer[]) RETURNS text AS $
SELECT
string_agg(
lpad(to_hex($1[x]),2,'0'),
''
order by x
)
FROM generate_subscripts($1,1) x;
$ LANGUAGE sql;The above version expects an integer array, but you can accept text arrays with an overload:
CREATE OR REPLACE FUNCTION intarr_to_hex_string(text[]) RETURNS text AS $
SELECT intarr_to_hex_string($1::integer[])
$ LANGUAGE sql;Note that no sanity check is done to make sure the hex string is two digits or less. You should really add a check where you use a CASE statement to execute a PL/PgSQL function that raises an error if there's bad input. Here's a complete example:
CREATE OR REPLACE FUNCTION raise_exception(text)
RETURNS void LANGUAGE plpgsql AS
$BODY$
BEGIN
RAISE EXCEPTION '%', $1;
END;
$BODY$;
CREATE OR REPLACE FUNCTION intarr_to_hex_string(integer[]) RETURNS text AS $
SELECT
string_agg(lpad(
CASE WHEN $1[x] < 256 THEN
to_hex($1[x])
ELSE
raise_exception('Argument to intarr_to_hex_string contained value '||coalesce($1[x]::text,'NULL')||', expected all values in i[] to be 0 <= i < 256. Full argument was '||quote_literal($1)||'.')::text
END,
2, '0'),
''
order by x)
FROM generate_subscripts($1,1) x;
$ LANGUAGE sql;Code Snippets
CREATE OR REPLACE FUNCTION intarr_to_hex_string(integer[]) RETURNS text AS $$
SELECT
string_agg(
lpad(to_hex($1[x]),2,'0'),
''
order by x
)
FROM generate_subscripts($1,1) x;
$$ LANGUAGE sql;CREATE OR REPLACE FUNCTION intarr_to_hex_string(text[]) RETURNS text AS $$
SELECT intarr_to_hex_string($1::integer[])
$$ LANGUAGE sql;CREATE OR REPLACE FUNCTION raise_exception(text)
RETURNS void LANGUAGE plpgsql AS
$BODY$
BEGIN
RAISE EXCEPTION '%', $1;
END;
$BODY$;
CREATE OR REPLACE FUNCTION intarr_to_hex_string(integer[]) RETURNS text AS $$
SELECT
string_agg(lpad(
CASE WHEN $1[x] < 256 THEN
to_hex($1[x])
ELSE
raise_exception('Argument to intarr_to_hex_string contained value '||coalesce($1[x]::text,'NULL')||', expected all values in i[] to be 0 <= i < 256. Full argument was '||quote_literal($1)||'.')::text
END,
2, '0'),
''
order by x)
FROM generate_subscripts($1,1) x;
$$ LANGUAGE sql;Context
StackExchange Database Administrators Q#31204, answer score: 7
Revisions (0)
No revisions yet.