sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQL:関数内からsearch_pathを設定するにはどうすればよいですか?

    一般的なソリューション

    set_config()を使用して純粋なSQL関数を作成しました。

    このソリューションは、コンマ区切りの文字列での複数のスキーマの設定をサポートしています。デフォルトでは、変更は現在のセッションに適用されます。 「is_local」パラメータをtrueに設定すると、変更は現在のトランザクションにのみ適用されます。 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;
    

    動的SQLを実行していないため、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;
    

    OPの元のコードに基づくテスト

    mytableのスキーマが事前にわからないため、動的SQLを使用する必要があります。一般的な'ish関数を使用する代わりに、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.
    


    1. #1066-一意ではないテーブル/エイリアス:

    2. 行を同時に SELECT と UPDATE する方法はありますか?

    3. OrderByDoctrineQuerybuilderでISNULLとCOALESCEを使用する

    4. Android:MySQLに保存するデータを送信する