I would like to know how to use a dynamic query inside a function. I've tried lots of ways, however, when I try to compile my function a message SQL 42601 is displayed.
The code that I use:
CREATE OR REPLACE FUNCTION prc_tst_bulk(sql text)
RETURNS TABLE (name text, rowcount integer) AS
$$
BEGIN
WITH v_tb_person AS (return query execute sql)
select name, count(*) from v_tb_person where nome like '%a%' group by name
union
select name, count(*) from v_tb_person where gender = 1 group by name;
END
$$ LANGUAGE plpgsql;
Error message I receive:
ERROR: syntax error at or near "return"
LINE 5: WITH v_tb_person AS (return query execute sql)
I tried using:
WITH v_tb_person AS (execute sql)
WITH v_tb_person AS (query execute)
WITH v_tb_person AS (return query execute)
What is wrong? How can I solve this problem?
Its a question related to PostgreSQL equivalent of Oracle “bulk collect”
The error message “syntax error at or near 'grant'” is one of the most common PostgreSQL database errors. However, it can easily be identified and resolved. To understand this issue, you need to know that SQL distinguishes between reserved and non-reserved key word tokens.
Your function would work like this:
CREATE OR REPLACE FUNCTION prc_tst_bulk(sql text)
RETURNS TABLE (name text, rowcount integer) AS
$$
BEGIN
RETURN QUERY EXECUTE '
WITH v_tb_person AS (' || sql || $x$)
SELECT name, count(*)::int FROM v_tb_person WHERE nome LIKE '%a%' GROUP BY name
UNION
SELECT name, count(*)::int FROM v_tb_person WHERE gender = 1 GROUP BY name$x$;
END
$$ LANGUAGE plpgsql;
Call:
SELECT * FROM prc_tst_bulk($$SELECT a AS name, b AS nome, c AS gender FROM tbl$$)
You cannot mix plain and dynamic SQL the way you tried to do it. The whole statement is either all dynamic or all plain SQL. So I am building one dynamic statement to make this work. You may be interested in the chapter about executing dynamic commands in the manual.
The aggregate function count()
returns bigint
, but you had rowcount
defined as integer
, so you need an explicit cast ::int
to make this work
I use dollar quoting to avoid quoting hell.
However, is this supposed to be a honeypot for SQL injection attacks or are you seriously going to use it? For your very private and secure use, it might be ok-ish - though I wouldn't even trust myself with a function like that. If there is any possible access for untrusted users, such a function is a loaded footgun. It's impossible to make this secure.
Craig (a sworn enemy of SQL injection!) might get a light stroke, when he sees what you forged from his piece of code in the answer to your preceding question. :)
The query itself seems rather odd, btw. But that's beside the point here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With