Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a ResultSet into a Postgresql Function

Is it possible to pass the results of a postgres query as an input into another function?

As a very contrived example, say I have one query like

SELECT id, name
FROM users
LIMIT 50

and I want to create a function my_function that takes the resultset of the first query and returns the minimum id. Is this possible in pl/pgsql?

SELECT my_function(SELECT id, name FROM Users LIMIT 50); --returns 50
like image 239
Ben Hamner Avatar asked Aug 13 '13 22:08

Ben Hamner


2 Answers

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; 
like image 160
Le Droid Avatar answered Oct 05 '22 22:10

Le Droid


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$
BEGIN

EXECUTE 'SELECT min(id) FROM ' || _tbl
INTO min_id;

END  
$func$ LANGUAGE plpgsql;

Call:

CREATE TEMP TABLE foo ON COMMIT DROP AS
SELECT id, name
FROM   users
LIMIT  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.

-> SQLfiddle demo

like image 33
Erwin Brandstetter Avatar answered Oct 05 '22 23:10

Erwin Brandstetter