PostgreSQL. User data in the session

Recently, I had an interesting challenge in storing some data in the session work with the database PostgreSQL (TTL = life time of a single connection to the database). The original question was...
Is it possible that instead of this design:
the
some_procedure1(user_id, param1, ... , paramN);
...
some_procedureX(user_id, param1, ... , paramN);

use this:
the
set_user(id);
some_procedure1(param1, ... , paramN);
....
some_procedureX(param1, ... , paramN);

i.e. to use some kind of global variable within the session to store the user ID value, which will be available to all procedures in the database.
Digging on Google, asked around on the forum, I found not even one solution, and as many as 3! Than with you and share...

the First option. Using a temporary table.


As stated in documentation, quote:
PostgreSQL instead requires each session to issue its own CREATE TEMPORARY TABLE command for each temporary table to be used.

for each session we need to re-create the temporary table. Well, that is what we had! Let's try...
An example taken from the forum sql.ru:
the
CREATE OR REPLACE FUNCTION set_var(p_var_name varchar p_var_value varchar) RETURNS void AS
$$
DECLARE
v_cnt integer;
BEGIN
SELECT Count(pc.relname) into v_cnt
FROM pg_catalog.pg_class pc, pg_namespace pn
WHERE pc.relname = 'session_var_tbl'
AND pc.relnamespace = pn.oid 
AND pn.oid = pg_my_temp_schema();
IF v_cnt = 0 THEN
EXECUTE 'CREATE GLOBAL TEMPORARY TABLE session_var_tbl (var_name varchar(100) not null, var_value varchar(100)) <br />
ON COMMIT preserve ROWS';
END IF;
UPDATE session_var_tbl 
SET var_value = p_var_value
WHERE var_name = p_var_name;
IF NOT FOUND THEN
INSERT INTO session_var_tbl(var_name, var_value)
VALUES (p_var_name, p_var_value);
END IF;
END;
$$
LANGUAGE 'plpgsql';

the
CREATE OR REPLACE FUNCTION get_var(p_var_name varchar) RETURNS varchar AS
$$
DECLARE
v_cnt integer;
v_result varchar(100);
BEGIN
SELECT Count(pc.relname) 
INTO v_cnt
FROM pg_catalog.pg_class pc, pg_namespace pn
WHERE pc.relname='session_var_tbl' 
AND pc.relnamespace=pn.oid 
AND pn.oid=pg_my_temp_schema();
IF v_cnt = 0 THEN
v_result := null;
ELSE
SELECT var_value
INTO v_result
FROM session_var_tbl
WHERE var_name = p_var_name;
IF NOT FOUND THEN
v_result := null;
END IF;
END IF;
RETURN v_result;
END;
$$
LANGUAGE 'plpgsql';

of Dignity this method consists in the fact that there is no need for additional settings or modules and the language PL/PgSQL is almost always.
a Lack this method is the need for a decent number of additional operations that perform a given procedure, including queries to system tables.

Second option. Use GlobalData array.


He tells us documentation, we can use ka languages PL/Perl, PL/Tcl, PL/Python is a special array of data visible within the session.
Example taken from official documentation:
the
CREATE OR REPLACE FUNCTION set_var(name text, val text) RETURNS text AS $$
if ($_SHARED{$_[0]} = $_[1]) {
return 'ok';
} else {
return "cannot  set  shared variable $_[0] to $_[1]";
}
$$ LANGUAGE plperl;

the
CREATE OR REPLACE FUNCTION get_var(name text) RETURNS text AS $$
return $_SHARED{$_[0]};
$$ LANGUAGE plperl;

the Advantage this method is the minimum number of operations and ease of use.
a Lack is a need for additional language module for PostgreSQL (postgresql-plperl). It is necessary to install yourself, but on shared hosting this is often not possible.

Third option. The Use Of Customized Options.


Several non-standard use of additional parameters in PostgreSQL. Configuration variable custom_variable_classes originally designed to create additional classes of configuration variables that can use additional modules PostgreSQL. But in the course of research it became clear that if you do not define variables in the class from postgresql.conf, they "live" exactly current session.
To use this method, it is necessary to register in postgresql.the relevant conf settings:
the
custom_variable_classes = 'usrvar'

Example:
the
CREATE OR REPLACE FUNCTION set_var(p_var_name varchar p_var_value varchar) RETURNS void AS
$body$
BEGIN
PERFORM set_config('usrvar.'||p_var_name, p_var_value, false);
END;
$body$
LANGUAGE 'plpgsql';

the 
CREATE OR REPLACE FUNCTION get_var(p_var_name varchar) RETURNS varchar AS
$body$
DECLARE
v_var_value varchar;
BEGIN
SELECT INTO v_var_value current_setting('usrvar.'||p_var_name);
RETURN v_var_value;
EXCEPTION
WHEN syntax_error_or_access_rule_violation THEN
v_var_value := null;
RETURN v_var_value;
END;
$body$
LANGUAGE 'plpgsql';

of Dignity this method is to use internal resources PostgreSQL and no need for extra languages or frameworks.
a Lack is the need for access to the configuration file of the server.
Well, that's probably all. Choose one of the three solutions is completely dependent on the capabilities of Your setup the database. For myself, I chose the 3rd solution.
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

March Habrameeting in Kiev

PostgreSQL load testing using JMeter, Yandex.Tank and Overload

Monitoring PostgreSQL with Zabbix