I am attempting to write a PL/PgSQL function which will execute a query stored within a PostgreSQL table like so:
CREATE OR REPLACE FUNCTION evaluate_scenario(scenario_id int)
RETURNS TABLE(line_item_id int, organization_id int, data_element_id int, value varchar) AS $$
BEGIN
RETURN QUERY
SELECT
li.id,
li.organization_id,
de.id,
(EXECUTE 'SELECT ' || de.query)::varchar
FROM
line_items AS li INNER JOIN
summary_files AS sf ON li.summary_file_id = sf.id INNER JOIN
scenarios AS s ON s.summary_file_id = sf.id CROSS JOIN
data_elements AS de
WHERE
s.id = 1 AND
de.scope = 3 AND (
de.model_id = s.model_id OR
de.scenario_id = s.id OR
de.organization_id = s.organization_id
);
END;
$$ LANGUAGE plpgsql;
When I try to run this query:
select line_item_id, data_element_id, value from evaluate_scenario(1)
I receive the following error:
********** Error **********
ERROR: type "execute" does not exist
SQL state: 42704
Context: PL/pgSQL function "evaluate_scenario" line 3 at RETURN QUERY
Any help would be greatly appreciated. Note that if I remove the “EXECUTE” and just do SELECT de.query inside those parens, I receive the value for that column as expected, but I can’t figure out how to make de.query an acceptable query string for “EXECUTE”.
EXECUTEtakes a query string as parameter and executes it, but you cannot nestEXECUTEin a query.There are a couple of variants for
EXECUTEin plpgsql. For your case,RETURN QUERY EXECUTE querymight be best. Read the manual.This could work – I am not trying to fix all the mess, just demonstrate a working example.
Note that it is inherently unsafe to execute text literals as code. If someone can smuggle a
DROP * FROM tblor some such into the tabledata_elements, you are in big trouble. I am speaking of SQL injection.Read more about SQLi at bobby-tables.com.