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