I have a plpgsql function in PostgreSQL 9.2 which returns a table. The function runs several SELECTs that return the same columns as the function and then either returns those results or raises an exception, depending on some checks. The only way I can see of doing this is with FOR ... LOOP, but I can't figure out a convenient way of returning the row.
I want to do something like this:
CREATE OR REPLACE FUNCTION my_function()
RETURNS TABLE(column1 integer, column2 boolean, ...)
AS $BODY$
DECLARE
result_row RECORD;
BEGIN
FOR result_row IN (SELECT * FROM other_function_returning_same_columns()) LOOP
IF something_wrong_with(result_row) THEN
RAISE EXCEPTION 'Something went wrong';
END IF;
RETURN NEXT result_row;
END LOOP;
END
$BODY$ LANGUAGE plpgsql STABLE;
This gives me an error:
ERROR: RETURN NEXT cannot have a parameter in function with OUT parameters
I'm not sure why Postgres is complaining here, because my code looks a lot like the example in the documentation, except that my function returns TABLE instead of SETOF. There are no OUT parameters.
I eventually managed to get it to work using:
RETURN QUERY SELECT result_row.column1, result_row.column2, ...;
But having to list all the columns all the time is ugly and harder to maintain. I'm sure there must be a better way.
RETURN NEXTjust returns what output parameters currently hold. The manual:You object:
Output parameters are declared among function parameters with the keyword
OUTorINOUT, or implicitly in yourRETURNSclause:Here,
column1andcolumn2areOUTparameters, too.This should do it:
Simpler with a registered type
You can further simplify with a registered composite type:
Or, if your type happens to match a table definition, you already have that type, because every table name can be used as type name in PostgreSQL. Then simplify:
Reorganize!
If you integrate the
RAISEcommand into your helper functionsomething_wrong_with(), invert the logic and more conveniently name iteverything_groovy(), then you can completely replacemy_function()with this simple query:Or integrate the
RAISEinto the base functionother_function_returning_same_columns()to further simplify (and make it faster). If you only want toRAISE EXCEPTIONin certain situations, you can always add a parameter (with a default) to switch it on / off.