I am trying to call a function within a function using sql on postgres 9.3.
This question is related to another post by me.
I have written the below function. So far I have failed to incorporate any kind of save-output (COPY) statement, so I am trying to work around this by creating a nested function print-out function.
CREATE FUNCTION retrieve_info(TEXT, TEXT) RETURNS SETOF
retrieve_info_tbl AS $$
SELECT tblA.id, tblA.method, tblA.species, tblA.location
FROM tblA
WHERE method=$1 AND species=$2
GROUP BY id, method, species
ORDER BY location
$$ LANGUAGE 'sql';
The above function works.
An attempt to create a nested function.
CREATE FUNCTION print_out(TEXT, TEXT) RETURNS void AS $$
COPY (SELECT * FROM retrieve_info($1, $2)) TO 'myfilepath/test.csv'
WITH CSV HEADER;
$$ LANGUAGE 'sql';
Calling nested function.
SELECT * FROM print_out('mtd1','sp1');
OUTPUT
The above gives this ERROR: column "$1" does not exist SQL state: 42P02 Context: SQL function "print_out" statement 1
. However, when substituting the arg1, arg2 in print_out() with 'mtd1','sp1' the correct output is printed to test.csv (as seen below)
id | method | ind | location
----------------------------
1a | mtd1 | sp3 | locA
1d | mtd1 | sp3 | locB
How would I get the arg1, arg2 of retrieve_info() to call arg1, arg2 properly within print_out()?
I am completely stuck. Would appreciate any pointers, thanks
Are
x
andy
quoted intentionally?You are not sending the
x
andy
arguments ofprint_out
toretrieve_info
- rather, you are sending the strings'x'
and'y'
. Assuming you don't have records withmethod='x' AND species='y'
, it's of little wonder you get no results.Try this instead:
COPY is a bit odd as it sort of treats its
query
argument as a string even though it isn't written as a string. The result is that thequery
:isn't executed in the context of the function, it is executed in the context of COPY itself. Even though you say:
it is treated more as though you wrote:
so by the time the query is executed, the function parameters no longer have any meaning, the
query
argument to COPY may look like it would behave like a closure in other languages but it doesn't, it acts more like a string that gets passed toeval
.You can get around this strangeness by using the usual Kludge of Last Resort: dynamic SQL. You should get better results if you write your function to use string wrangling and EXECUTE: