sql >> Database teknologi >  >> RDS >> PostgreSQL

PostgreSQL:hvordan indstiller jeg søgestien inde fra en funktion?

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.


  1. Hvad er nødvendigt for at arbejde med Oracle fra Visual Studio 2010?

  2. Hvad er nyt i MySQL Galera Cluster 4.0

  3. Problem med at køre en Proc - Oracle PL/SQL

  4. VÆLG * FRA hjælp