Thread: Function returning SETOF returns nothing
Hi all, I have a monster function full of IF ELSIF branches that is supposed to return a SETOF value, though regardless of its route through the logic it only returns an empty row. Fortunately, reduced to almost nothing I have the sme problem so it will likely be a simply matter. Function and table definition follow: CREATE TABLE ForecastData(type TEXT, item TEXT, descr TEXT, unit TEXT, qty FLOAT, rate FLOAT, amt FLOAT); CREATE OR REPLACE FUNCTION CreateDefaultForecasts(INTEGER) RETURNS SETOF ForecastData AS ' BEGIN RETURN (SELECT ''old'' as type, ''item'' as item, ''descr'' as descr, ''unit'' as unit, 0 as qty, 0 rate, 0 as amt); END; ' LANGUAGE 'plpgsql'; dbtestvanek=# select * from CreateDefaultForecasts(314028); type | item | descr | unit | qty | rate | amt ------+------+-------+------+-----+------+----- (0 rows) The actual function inserts into ForecastData and then returns (SELECT * from ForecastData where type = ''new''); or rather should do, but no matter what it returns the same 0 rows. What am I doing wrong, and, bonus question, where should I have found the answer in the docs? Thanks for your time and attention! Coby psql 7.4.27 on a Linux server.
Coby Beck <coby101@gmail.com> writes: > CREATE OR REPLACE FUNCTION CreateDefaultForecasts(INTEGER) RETURNS > SETOF ForecastData AS ' > BEGIN > RETURN (SELECT ''old'' as type, ''item'' as item, ''descr'' as > descr, ''unit'' as unit, 0 as qty, 0 rate, 0 as amt); > END; > ' LANGUAGE 'plpgsql'; Um ... what Postgres version are you using? Everything since about 8.0 will tell you pretty clearly what is wrong with this function: ERROR: RETURN cannot have a parameter in function returning set LINE 4: RETURN (SELECT ''old'' as type, ''item'' as item, ''desc... ^ HINT: Use RETURN NEXT or RETURN QUERY. In a SETOF function, plain RETURN is just a flow-of-control command, and you need to use RETURN NEXT (or possibly RETURN QUERY) to feed actual rows back to the output. If you really are using 7.x, you need to update. Soon, before it eats your data. regards, tom lane
On Wed, Apr 4, 2012 at 11:53 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Coby Beck <coby101@gmail.com> writes: >> CREATE OR REPLACE FUNCTION CreateDefaultForecasts(INTEGER) RETURNS >> SETOF ForecastData AS ' >> BEGIN >> RETURN (SELECT ''old'' as type, ''item'' as item, ''descr'' as >> descr, ''unit'' as unit, 0 as qty, 0 rate, 0 as amt); >> END; >> ' LANGUAGE 'plpgsql'; > > Um ... what Postgres version are you using? Everything since about 8.0 > will tell you pretty clearly what is wrong with this function: > > ERROR: RETURN cannot have a parameter in function returning set > LINE 4: RETURN (SELECT ''old'' as type, ''item'' as item, ''desc... > ^ > HINT: Use RETURN NEXT or RETURN QUERY. > > In a SETOF function, plain RETURN is just a flow-of-control command, > and you need to use RETURN NEXT (or possibly RETURN QUERY) to feed > actual rows back to the output. Thanks for the advice, Tom...I am still having trouble as many variations tried all give compile errors. This is what I thought should work based on your mail and the "37.7.1.2. RETURN NEXT" section of this page http://www.postgresql.org/docs/7.4/static/plpgsql-control-structures.html : CREATE TABLE ForecastData(type TEXT, item TEXT, descr TEXT, unit TEXT, qty FLOAT, rate FLOAT, amt FLOAT); CREATE OR REPLACE FUNCTION CreateDefaultForecasts() RETURNS SETOF ForecastData AS ' BEGIN RETURN NEXT (SELECT ''old'' as type, ''item'' as item, ''descr'' as descr, ''unit'' as unit, 0 as qty, 0 rate, 0 as amt); RETURN; END; ' LANGUAGE 'plpgsql'; but results are: dbtestvanek=# select * from CreateDefaultForecasts(); ERROR: incorrect argument to RETURN NEXT at or near "(" CONTEXT: compile of PL/pgSQL function "createdefaultforecasts" near line 2 QUERY, no brackets, other thrashing around brings similar results. The above stub function aside, not being able to pass in a parameter is going to be a problem. What would a clever person do if they want some complexity based on one or more parameters to determine a set of rows for return? I am not sure what limits I will run into if I use LANGUAGE 'sql', I know I can pass a parameter(s) but the only 'sql' functions in this application are very simple. > If you really are using 7.x, you need to update. Soon, before it > eats your data. 7.4 is hungry...point taken. I knew I would be scolded! Cheers, Coby
Coby Beck <coby101@gmail.com> writes: > Thanks for the advice, Tom...I am still having trouble as many > variations tried all give compile errors. More modern versions give a more useful error message: ERROR: RETURN NEXT must specify a record or row variable in function returning row LINE 4: RETURN NEXT (SELECT ''old'' as type, ''item'' as item, '... ^ So what you need to do is declare a variable of type ForecastData, assign into the fields of that variable, and then "RETURN NEXT varname". regards, tom lane
On Thu, Apr 5, 2012 at 11:43 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Coby Beck <coby101@gmail.com> writes: >> Thanks for the advice, Tom...I am still having trouble as many >> variations tried all give compile errors. > > More modern versions give a more useful error message: > > ERROR: RETURN NEXT must specify a record or row variable in function returning row > LINE 4: RETURN NEXT (SELECT ''old'' as type, ''item'' as item, '... > ^ > > So what you need to do is declare a variable of type ForecastData, > assign into the fields of that variable, and then "RETURN NEXT varname". > > regards, tom lane Thank you Tom, I am up and running now. For the archives, the following code is performing as expected: CREATE TABLE ForecastData(type TEXT, item TEXT, descr TEXT, unit TEXT, qty FLOAT, rate FLOAT, amt FLOAT); CREATE OR REPLACE FUNCTION CreateDefaultForecasts(INTEGER) RETURNS SETOF ForecastData AS ' DECLARE Answers ForecastData; BEGIN SELECT ''old'' as type, ''item'' as item, ''descr'' as descr, ''unit'' as unit, $1 as qty, 0 as rate, 0 as amt into answers; RETURN NEXT Answers; SELECT ''old'' as type, ''item'' as item, ''descr'' as descr, ''unit'' as unit, $1 + 1 as qty, 0 as rate, 0 as amt into answers; RETURN NEXT Answers; RETURN; END; ' LANGUAGE 'plpgsql'; Cheers, Coby