Whenever you need to convert user input to identifiers
or code
in an SQL statement, you need dynamic SQL. Either concatenate the statement in your client an send it to the DB engine or (more efficiently) do it in PL/pgSQL (or some procedural server-side language) dynamically with EXECUTE
. More details:
Solution
CREATE OR REPLACE FUNCTION f_get_columns(_cols text[])
RETURNS TABLE (col text, val text) AS
$func$
DECLARE
_col text;
BEGIN
FOREACH _col IN ARRAY _cols LOOP
RETURN QUERY EXECUTE
format('SELECT %1$L::text, %1$I::text FROM tbl t', _col);
END LOOP;
END
$func$ LANGUAGE plpgsql;
Call:
SELECT * FROM f_array_of_columns('{column1,column2}');
Returns (random values):
col | val
--------+-----
column1 | 001
column1 | 002
column1 | 003
column2 | {foo,boo,foo}
column2 | {"",for,test}
column2 | {test,foo,boo}
Key elements:
- A matching
RETURNS
declaration.
- A way to ruturn your results,
RETURN QUERY EXECUTE
here.
- A
FOREACH
loop in this particular case.
format()
to simplify string concatenation and escape names and values properly.
Note the specifiers:
%1$L
... first parameter as quoted literal.
%1$I
... first parameter as properly escaped Identifier.
Note how I cast both columns to text
(::text
) to match the return type and make it work for any data type. Depending on exact requirements, this could be more specific.