Allmän lösning
Jag skapade en ren sql-funktion genom att använda set_config().
Den här lösningen stöder inställning av flera scheman i en kommaseparerad sträng. Som standard gäller ändringen den aktuella sessionen. Om du ställer in parametern "is_local" till sant gör att ändringen endast gäller den aktuella transaktionen, se http://www.postgresql.org/docs/9.4/static/functions-admin.html för mer information.
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;
Eftersom vi inte kör någon dynamisk sql borde det vara mindre chans för sql-injektion. Bara för att vara säker har jag lagt till lite naiv sanering av texten genom att ta bort alla tecken utom alfanumeriska tecken, mellanslag och kommatecken. Att fly/citera strängen var inte trivialt, men jag är ingen expert, så.. =)
Kom ihåg att det inte finns någon feedback om du ställer in en felaktig sökväg.
Här är några exempelkoder för testning:
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;
Ett test baserat på OP:s ursprungliga kod
Eftersom vi inte känner till schemat för mytable i förväg måste vi använda dynamisk sql. Jag bäddade in set_config-oneliner i get_sections()-funktionen istället för att använda den generiska funktionen.
Obs! Jag var tvungen att ställa in is_local=false i set_config() för att detta skulle fungera. Det betyder att den ändrade sökvägen finns kvar efter att funktionen har körts. Jag är inte säker på varför.
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.