Обсуждение: Переменные в БД
Добрый день ! Можно в PostgreSQL объявлять свои переменные , типа client_encoding, timezone и т.д., чтобы их значения были видны только одному пользователю в пределах сессии ? Спасибо.
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 > > Спасибо. > > ---------------------------(end of broadcast)--------------------------- > TIP 3: Have you checked our extensive FAQ? > > http://www.postgresql.org/docs/faq > Regards, Oleg _____________________________________________________________ Oleg Bartunov, Research Scientist, Head of AstroNet (www.astronet.ru), Sternberg Astronomical Institute, Moscow University, Russia Internet: oleg@sai.msu.su, http://www.sai.msu.su/~megera/ phone: +007(495)939-16-83, +007(495)939-23-83
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
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';
On Sun, 19 Mar 2006, Alexander M. Pravking wrote: > 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 переменные. не уверен, но по твоей теме был тред http://www.pgsql.ru/db/pgsearch/index.html?group=1&page=1&site=archives.postgresql.org%2F&tmpl=%F0%D2%C9%D7%C5%D4&q=session%20variables&ps=10 Там через view реализовано > > Мне интересна эта тема, поскольку я в своё время не нашёл положительного > ответа на подобный вопрос, однако нашёл другой способ - через создание > временной таблицы, у которой срок жизни - как раз сессия. Однако такой > подход делает нагрузку на системные таблицы (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 > > > Regards, Oleg _____________________________________________________________ Oleg Bartunov, Research Scientist, Head of AstroNet (www.astronet.ru), Sternberg Astronomical Institute, Moscow University, Russia Internet: oleg@sai.msu.su, http://www.sai.msu.su/~megera/ phone: +007(495)939-16-83, +007(495)939-23-83