Passing a ResultSet into a Postgresql Function
You could use a cursor, but that very impractical for computing a minimum.
I would use a temporary table for that purpose, and pass the table name for use in dynamic SQL:
CREATE OR REPLACE FUNCTION f_min_id(_tbl regclass, OUT min_id int) AS $func$BEGINEXECUTE 'SELECT min(id) FROM ' || _tblINTO min_id;END $func$ LANGUAGE plpgsql;
Call:
CREATE TEMP TABLE foo ON COMMIT DROP ASSELECT id, nameFROM usersLIMIT 50;SELECT f_min_id('foo');
Major points
The first parameter is of type
regclass
to prevent SQL injection. More info in this related answer on dba.SE.I made the temp table
ON COMMIT DROP
to limit its lifetime to the current transaction. May or may not be what you want.You can extend this example to take more parameters. Search for code examples for dynamic SQL with
EXECUTE
.
I would take the problem on the other side, calling an aggregate function for each record of the result set. It's not as flexible but can gives you an hint to work on.
As an exemple to follow your sample problem:
CREATE OR REPLACE FUNCTION myMin ( int,int ) RETURNS int AS $$ SELECT CASE WHEN $1 < $2 THEN $1 ELSE $2 END;$$ LANGUAGE SQL STRICT IMMUTABLE;CREATE AGGREGATE my_function ( int ) ( SFUNC = myMin, STYPE = int, INITCOND = 2147483647 --maxint);SELECT my_function(id) from (SELECT * FROM Users LIMIT 50) x;
It is not possible to pass an array of generic type RECORD to a plpgsql function which is essentially what you are trying to do.
What you can do is pass in an array of a specific user defined TYPE or of a particular table row type. In the example below you could also swap out the argument data type for the table name users[] (though this would obviously mean getting all data in the users table row).
CREATE TYPE trivial {"ID" integer,"NAME" text}CREATE OR REPLACE FUNCTION trivial_func(data trivial[]) RETURNS integer AS$BODY$DECLARE BEGIN --Implementation here using data return 1;END$BODY$ LANGUAGE 'plpgsql' VOLATILE;