Re: Переме - Mailing list pgsql-ru-general

From Alexander M. Pravking
Subject Re: Переме
Date
Msg-id 20060318212744.GF97707@dyatel.antar.bryansk.ru
Whole thread Raw
In response to Re: Переменные в  (Oleg Bartunov <oleg@sai.msu.su>)
List pgsql-ru-general
On Sat, 2006-03-18 at 14:04 +0300, Oleg Bartunov wrote:
> On Sat, 18 Mar 2006, Serik wrote:
>
> >Добрый день !
> >Можно в PostgreSQL объявлять свои переменные , типа client_encoding,
> >timezone и т.д.,
> >чтобы их значения были видны только одному пользователю в пределах сессии ?
>
> можно, set client_encoding = 'koi8=r';
> А можно еще и документацию почитать.
> http://www.postgresql.org/docs/8.1/static/sql-set.html

Скорее всего, имелись в виду не PG'шные встроенные, а именно
user-defined переменные.

Мне интересна эта тема, поскольку я в своё время не нашёл положительного
ответа на подобный вопрос, однако нашёл другой способ - через создание
временной таблицы, у которой срок жизни - как раз сессия. Однако такой
подход делает нагрузку на системные таблицы (pg_class, pg_attribute),
что иногда заметно сказывается на производительности. Так что было бы
неплохо, если бы в PG появился более стандартный способ.

Привожу функции для управления такими "переменными":


CREATE OR REPLACE FUNCTION get_session_var(text) RETURNS text AS '
DECLARE
    _x    record;
BEGIN
    SELECT    1 INTO _x FROM pg_class
    WHERE    relname = ''session_vars''
    AND    relkind = ''r''
    AND    CASE WHEN has_schema_privilege(relnamespace,''USAGE'')
            THEN pg_table_is_visible(oid)
            ELSE false
        END;

    IF NOT FOUND THEN RETURN NULL; END IF;

    FOR _x IN EXECUTE ''SELECT value FROM session_vars WHERE var = '' || quote_literal($1)
    LOOP
        RETURN _x.value;
    END LOOP;
    RETURN    NULL;
END' LANGUAGE 'plPgSQL' STRICT;


CREATE OR REPLACE FUNCTION set_session_var(text, text) RETURNS text AS '
DECLARE
    _x    integer;
BEGIN
    SELECT    1 INTO _x FROM pg_class
    WHERE    relname = ''session_vars''
    AND    relkind = ''r''
    AND    CASE WHEN has_schema_privilege(relnamespace,''USAGE'')
            THEN pg_table_is_visible(oid)
            ELSE false
        END;

    IF NOT FOUND THEN
        EXECUTE ''CREATE TEMP TABLE session_vars (var text, value text) WITHOUT OIDS'';
    ELSE
        EXECUTE ''DELETE FROM session_vars WHERE var = ''||quote_literal($1);
    END IF;
    EXECUTE ''INSERT INTO session_vars VALUES ('' ||
        quote_literal($1) || '', '' || coalesce(quote_literal($2), ''NULL'') ||
        '')'';
    RETURN $2;
END' LANGUAGE 'plPgSQL';



Замечу также, что проверка pg_table_is_visible() без has_schema_privilege()
в функциях недостаточна, на этот счёт я уже писал в -hackers:

http://archives.postgresql.org/pgsql-hackers/2005-06/msg00319.php


--
Fduch M. Pravking

pgsql-ru-general by date:

Previous
From: Oleg Bartunov
Date:
Subject: Re: Переменные в
Next
From: Андрей Зевакин
Date:
Subject: Re: Переме