Re: Переме - Mailing list pgsql-ru-general
From | Андрей Зевакин |
---|---|
Subject | Re: Переме |
Date | |
Msg-id | 441CE1DF.9030003@tsogu.ru Whole thread Raw |
In response to | Переменные в БД (Serik <uge@pochtamt.ru>) |
List | pgsql-ru-general |
Alexander M. Pravking пишет:
CREATE TABLE session_vars
(
username name NOT NULL DEFAULT current_user,
var text NOT NULL,
value text NOT NULL,
PRIMARY KEY (username, var)
) WITHOUT OIDS;
CREATE OR REPLACE FUNCTION get_session_var(text) RETURNS text AS
'
SELECT value FROM session_vars WHERE username = current_user AND var = $1;
'
LANGUAGE 'sql';
CREATE OR REPLACE FUNCTION set_session_var(text, text) RETURNS text AS
'
DECLARE
_var ALIAS FOR $1;
_value ALIAS FOR $2;
BEGIN
IF get_session_var(_var) IS NULL THEN
INSERT INTO session_vars VALUES (DEFAULT, _var, _value);
ELSE
UPDATE session_vars SET value = _value WHERE username = current_user AND var = _var;
END IF;
RETURN _value;
END;
'
LANGUAGE 'plpgsql';
чтобы не нагружать системные таблицы, можно сделать так: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; BEGINSELECT 1 INTO _x FROM pg_classWHERE 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; BEGINSELECT 1 INTO _x FROM pg_classWHERE 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
CREATE TABLE session_vars
(
username name NOT NULL DEFAULT current_user,
var text NOT NULL,
value text NOT NULL,
PRIMARY KEY (username, var)
) WITHOUT OIDS;
CREATE OR REPLACE FUNCTION get_session_var(text) RETURNS text AS
'
SELECT value FROM session_vars WHERE username = current_user AND var = $1;
'
LANGUAGE 'sql';
CREATE OR REPLACE FUNCTION set_session_var(text, text) RETURNS text AS
'
DECLARE
_var ALIAS FOR $1;
_value ALIAS FOR $2;
BEGIN
IF get_session_var(_var) IS NULL THEN
INSERT INTO session_vars VALUES (DEFAULT, _var, _value);
ELSE
UPDATE session_vars SET value = _value WHERE username = current_user AND var = _var;
END IF;
RETURN _value;
END;
'
LANGUAGE 'plpgsql';
pgsql-ru-general by date: