PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

PostgreSQL:bagaimana cara mengatur search_path dari dalam suatu fungsi?

Solusi generik

Saya membuat fungsi sql murni dengan menggunakan set_config().

Solusi ini mendukung pengaturan beberapa skema dalam string yang dipisahkan koma. Secara default, perubahan berlaku untuk sesi saat ini. Menyetel parameter "is_local" ke true membuat perubahan hanya berlaku untuk transaksi saat ini, lihat http://www.postgresql.org/docs/9.4/static/functions-admin.html untuk lebih jelasnya.

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;

Karena kami tidak menjalankan sql dinamis apa pun, kemungkinan injeksi sql lebih kecil. Hanya untuk memastikan saya menambahkan beberapa sanitasi naif dari teks dengan menghapus semua karakter kecuali alfanumerik, spasi dan koma. Melarikan diri/mengutip string itu tidak sepele, tapi saya bukan ahlinya, jadi.. =)

Ingatlah bahwa tidak ada umpan balik jika Anda menetapkan jalur yang salah.

Berikut adalah beberapa contoh kode untuk pengujian:

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;

Tes berdasarkan kode asli OP

Karena kita tidak mengetahui skema untuk mytable sebelumnya, kita perlu menggunakan sql dinamis. Saya menyematkan set_config-oneliner ke dalam fungsi get_sections() daripada menggunakan fungsi generik.

Catatan: Saya harus mengatur is_local=false di set_config() agar ini berfungsi. Itu berarti jalur yang dimodifikasi tetap ada setelah fungsi dijalankan. Saya tidak yakin mengapa.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kueri postgres jsonb berdasarkan nilai terlepas dari kuncinya

  2. Memilih indeks yang tepat untuk kueri PostgreSQL

  3. dblink tidak ada bahkan ketika ekstensi sudah ada?

  4. Gunakan pemicu pada tabel yang diwarisi untuk mengganti kunci asing

  5. psql:tidak dapat terhubung ke server:Koneksi ditolak Kesalahan saat menghubungkan ke basis data jarak jauh