Re: Переме

From: Андрей Зевакин <zevakin(at)tsogu(dot)ru>
To: "Alexander M(dot) Pravking" <fduch(at)antar(dot)bryansk(dot)ru>
Cc: pgsql-ru-general <pgsql-ru-general(at)postgresql(dot)org>
Subject: Re: Переме
Date: 2006-03-19 04:45:19
Message-ID: 441CE1DF.9030003@tsogu.ru
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-ru-general

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=KOI8-R" http-equiv="Content-Type">
<title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
Alexander M. Pravking пишет:
<blockquote cite="mid20060318212744(dot)GF97707(at)dyatel(dot)antar(dot)bryansk(dot)ru"
type="cite">
<pre wrap="">On Sat, 2006-03-18 at 14:04 +0300, Oleg Bartunov wrote:
</pre>
<blockquote type="cite">
<pre wrap="">On Sat, 18 Mar 2006, Serik wrote:

</pre>
<blockquote type="cite">
<pre wrap="">Добрый день !
Можно в PostgreSQL объявлять свои переменные , типа client_encoding,
timezone и т.д.,
чтобы их значения были видны только одному пользователю в пределах сессии ?
</pre>
</blockquote>
<pre wrap="">можно, set client_encoding = 'koi8=r';
А можно еще и документацию почитать.
<a class="moz-txt-link-freetext" href="http://www.postgresql.org/docs/8.1/static/sql-set.html">http://www.postgresql.org/docs/8.1/static/sql-set.html</a>
</pre>
</blockquote>
<pre wrap=""><!---->
Скорее всего, имелись в виду не 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:

<a class="moz-txt-link-freetext" href="http://archives.postgresql.org/pgsql-hackers/2005-06/msg00319.php">http://archives.postgresql.org/pgsql-hackers/2005-06/msg00319.php</a>

</pre>
</blockquote>
чтобы не нагружать системные таблицы, можно сделать так:<br>
<br>
CREATE TABLE session_vars <br>
(<br>
    username name NOT NULL DEFAULT current_user, <br>
    var text NOT NULL, <br>
    value text NOT NULL, <br>
    PRIMARY KEY (username, var)<br>
) WITHOUT OIDS;<br>
<br>
<br>
CREATE OR REPLACE FUNCTION get_session_var(text) RETURNS text AS<br>
'<br>
    SELECT value FROM session_vars WHERE username = current_user AND
var = $1;<br>
'<br>
LANGUAGE 'sql';<br>
<br>
<br>
CREATE OR REPLACE FUNCTION set_session_var(text, text) RETURNS text AS<br>
'<br>
DECLARE<br>
    _var ALIAS FOR $1;<br>
    _value ALIAS FOR $2;<br>
BEGIN<br>
    IF get_session_var(_var) IS NULL THEN<br>
        INSERT INTO session_vars VALUES (DEFAULT, _var, _value);<br>
    ELSE<br>
        UPDATE session_vars SET value = _value WHERE username =
current_user AND var = _var;<br>
    END IF;<br>
    RETURN _value;<br>
END;<br>
'<br>
  LANGUAGE 'plpgsql';<br>
<br>
</body>
</html>

Attachment Content-Type Size
unknown_filename text/html 4.0 KB

In response to

Browse pgsql-ru-general by date

  From Date Subject
Next Message Oleg Bartunov 2006-03-19 06:18:10 Re: Переме
Previous Message Oleg Bartunov 2006-03-18 11:04:40 Re: Переменные в