I have a stored procedure that RETURNS record
:
CREATE OR REPLACE FUNCTION r_rpt_prov_summary()
RETURNS record
AS $$
DECLARE
_fields record;
BEGIN
SELECT INTO _fields
0::integer AS customers,
0::integer AS customers_active;
SELECT INTO _fields.customers count(*) FROM customer;
SELECT INTO _fields.customers_active count(*) FROM customer WHERE active = 't';
RETURN _fields;
END
$$ LANGUAGE 'plpgsql';
However, in order to query it, I would have to explicitly enumerate the returned columns and types:
SELECT * FROM r_rpt_prov_summary() AS (a integer, b integer);
In order to make this palatable to an MVC framework, which by its nature wants to query tables, I wrap it in an SQL
function that RETURNS TABLE
:
CREATE OR REPLACE FUNCTION rpt_prov_summary()
RETURNS TABLE (
customers integer,
customers_active integer
) AS $$
SELECT * FROM r_rpt_prov_summary() AS (customers integer, customers_active integer);
$$ LANGUAGE 'sql';
This works very well as long as both functions reside in the same schema or search_path
space. However, in this case, they live in a nonstandard schema of their own, so I have to query the outer function as myschema.rpt_prov_summary()
, i.e.
SELECT * FROM myschema.rpt_prov_summary();
This doesn't work if my schema and search path are set to public
:
test=> SELECT * FROM myschema.rpt_prov_summary();
ERROR: function r_rpt_prov_summary() does not exist
LINE 2: SELECT * FROM r_rpt_prov_summary() AS (customers integer, ...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Naturally, your thoughts would turn to calling SET SCHEMA 'myschema'
or SET search_path TO myschema
prior to query execution. So did mine. The problem is it's just not going to work for the environment from which I'm calling. The MVC framework is using prepared statements to construct the query, and PostgreSQL frowns upon something like:
SET search_path TO myschema;SELECT * FROM rpt_prov_summary();
Which is to say:
< 2016-03-14 20:50:46.410 EDT >ERROR: cannot insert multiple commands into a prepared statement
So, that's not going to work. Providing the schema as an argument to the outer function isn't going to work, either; I just don't have that flexibility within the constraints of the MVC framework, which wants to be querying plain old tables or things that act like tables.
current_schema
identifies the current schema of the client session, so that's not going to help. Already tried this:
CREATE OR REPLACE FUNCTION rpt_prov_summary()
RETURNS TABLE (
customers integer,
customers_active integer
) AS $$
BEGIN
RAISE NOTICE 'Current schema: %', current_schema;
RETURN QUERY EXECUTE 'SELECT * FROM ' || current_schema || '.r_rpt_prov_summary() AS (customers integer, customers_active integer)';
END
$$ LANGUAGE 'plpgsql';
No dice - Current schema: public
, as expected.
Is there any way to somehow capture the schema space of the outer call and propagate that into the encapsulated query?