Generisk løsning
Jeg oprettede en ren sql-funktion ved at bruge set_config().
Denne løsning understøtter indstilling af flere skemaer i en kommasepareret streng. Som standard gælder ændringen for den aktuelle session. Indstilling af parameteren "is_local" til sand gør, at ændringen kun gælder for den aktuelle transaktion, se http://www.postgresql.org/docs/9.4/static/functions-admin.html for flere detaljer.
CREATE OR REPLACE FUNCTION public.set_search_path(path TEXT, is_local BOOLEAN DEFAULT false) RETURNS TEXT AS $$
SELECT set_config('search_path', regexp_replace(path, '[^\w ,]', '', 'g'), is_local);
$$ LANGUAGE sql;
Da vi ikke kører nogen dynamisk sql, burde der være mindre chance for sql-injektion. Bare for at være sikker tilføjede jeg noget naivt sanering af teksten ved at fjerne alle tegn undtagen alfanumerik, mellemrum og komma. At undslippe/citere strengen var ikke trivielt, men jeg er ikke ekspert, så.. =)
Husk, at der ikke er nogen feedback, hvis du angiver en forkert udformet sti.
Her er en prøvekode til test:
DROP SCHEMA IF EXISTS testschema CASCADE;
CREATE SCHEMA testschema;
CREATE TABLE testschema.mytable ( id INTEGER );
SELECT set_search_path('testschema, public');
SHOW search_path;
INSERT INTO mytable VALUES(123);
SELECT * FROM mytable;
En test baseret på OP's originale kode
Da vi ikke kender skemaet for mytable på forhånd, skal vi bruge dynamisk sql. Jeg indlejrede set_config-oneliner i get_sections()-funktionen i stedet for at bruge den generiske funktion.
Bemærk: Jeg var nødt til at indstille is_local=false i set_config() for at dette kunne virke. Det betyder, at den ændrede sti forbliver efter funktionen er kørt. Jeg ved ikke hvorfor.
DROP SCHEMA IF EXISTS testschema CASCADE;
CREATE SCHEMA testschema;
SET search_path TO public;
CREATE TABLE testschema.mytable ( id INTEGER, name varchar, type varchar );
INSERT INTO testschema.mytable VALUES (123,'name', 'some-type');
INSERT INTO testschema.mytable VALUES (567,'name2', 'beer');
CREATE OR REPLACE FUNCTION get_sections(schema_name TEXT) RETURNS
TABLE(id integer, name varchar, type varchar) AS $$
BEGIN
PERFORM set_config('search_path', regexp_replace(schema_name||', public', '[^\w ,]', '', 'g'), true);
EXECUTE 'SELECT id, name, type FROM mytable';
END;
$$ LANGUAGE plpgsql;
SET search_path TO public;
SELECT * FROM get_sections('testschema');
SHOW search_path; -- Unfortunately this has modified the search_path for the whole session.