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 |
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: Переменные в |