जेनेरिक'श समाधान
मैंने set_config() का उपयोग करके एक शुद्ध sql फ़ंक्शन बनाया है।
यह समाधान अल्पविराम से अलग की गई स्ट्रिंग में एकाधिक स्कीमा सेट करने का समर्थन करता है। डिफ़ॉल्ट रूप से परिवर्तन वर्तमान सत्र पर लागू होता है। "is_local" पैरामीटर को सही पर सेट करने से परिवर्तन केवल वर्तमान लेनदेन पर लागू होता है, देखें http://www.postgresql.org/docs/9.4/static/functions-admin.html अधिक जानकारी के लिए।
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;
चूंकि हम कोई गतिशील एसक्यूएल नहीं चला रहे हैं, इसलिए एसक्यूएल इंजेक्शन की संभावना कम होनी चाहिए। बस यह सुनिश्चित करने के लिए कि मैंने अल्फ़ान्यूमेरिक्स, स्पेस और कॉमा को छोड़कर सभी वर्णों को हटाकर टेक्स्ट के कुछ भोले-भाले स्वच्छता को जोड़ा। स्ट्रिंग से बचना/उद्धृत करना मामूली नहीं था, लेकिन मैं विशेषज्ञ नहीं हूं, इसलिए.. =)
याद रखें कि यदि आप विकृत पथ सेट करते हैं तो कोई प्रतिक्रिया नहीं होती है।
परीक्षण के लिए यहां कुछ नमूना कोड दिए गए हैं:
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;
ओपी के मूल कोड पर आधारित परीक्षण
चूंकि हम पहले से mytable के लिए स्कीमा नहीं जानते हैं, इसलिए हमें डायनेमिक sql का उपयोग करने की आवश्यकता है। मैंने set_config-oneliner को जेनेरिक'इश फ़ंक्शन का उपयोग करने के बजाय get_sections () - फ़ंक्शन में एम्बेड किया है।
नोट: काम करने के लिए मुझे set_config() में is_local=false सेट करना पड़ा। इसका मतलब है कि फ़ंक्शन चलाने के बाद संशोधित पथ बना रहता है। मुझे पता नहीं क्यों।
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.