F.53. pg_variables#

F.53. pg_variables

F.53. pg_variables

F.53.1. О pg_variables

Версия: 1.2

GitHub

Этот модуль распространяется под лицензией PostgreSQL.

F.53.2. Введение

pg_variables является расширением, которое предоставляет функции для работы с переменными различных типов. Созданные переменные существуют только в рамках текущей сессии пользователя.

По умолчанию переменные создаются вне транзакции (таким образом, они не влияют на BEGIN, COMMIT или ROLLBACK). Это можно контролировать с помощью аргумента is_transactional в функции pgv_set():

SELECT pgv_set('vars', 'int1', 101);
BEGIN;
SELECT pgv_set('vars', 'int2', 102);
ROLLBACK;

SELECT * FROM pgv_list() order by package, name;
 package | name | is_transactional
---------+------+------------------
 vars    | int1 | f
 vars    | int2 | f

Но если переменная создана с помощью is_transactional flag:

BEGIN;
SELECT pgv_set('vars', 'trans_int', 101, true);
SAVEPOINT sp1;
SELECT pgv_set('vars', 'trans_int', 102, true);
ROLLBACK TO sp1;
COMMIT;
SELECT pgv_get('vars', 'trans_int', NULL::int);
 pgv_get
---------
     101

Вы можете группировать переменные в пакеты. Это делается для того, чтобы иметь переменные с разными именами или быстро удалить их. Если пакет становится пустым, он автоматически удаляется.

F.53.3. Установка

Типичная установка:

CREATE EXTENSION pg_variables;

F.53.4. Функции

Доступные функции в pg_variables расширения описаны в таблице ниже.

Чтобы использовать pgv_get() function, пакет и переменная должны существовать. Необходимо установить переменную с pgv_set() функция для использования pgv_get() function.

Если пакет не существует, вы получите следующую ошибку:

SELECT pgv_get('vars', 'int1', NULL::int);
ERROR:  unrecognized package "vars"

Если переменная не существует, вы получите следующую ошибку:

SELECT pgv_get('vars', 'int1', NULL::int);
ERROR:  unrecognized variable "int1"

Столбец pgv_get() функция проверяет тип переменной. Если тип переменной не соответствует типу в функции, вы получите следующую ошибку:

SELECT pgv_get('vars', 'int1', NULL::text);
ERROR:  variable "int1" requires "integer" value

F.53.5. Функции скалярных переменных

Функция Результат
pgv_set(package text, name text, value anynonarray, is_transactional bool default false) void
pgv_get(package text, name text, var_type anynonarray, strict bool default true) anynonarray

F.53.6. Функции массивов переменных

Функция Результат
pgv_set(package text, name text, value anyarray, is_transactional bool default false) void
pgv_get(package text, name text, var_type anyarray, strict bool default true) anyarray

pgv_set аргументы:

  • package - имя пакета, который должен быть создан, если он не существует.

  • name - имя переменной, она будет создана, если не существует. pgv_set завершается с ошибкой, если переменная уже существует и ее транзакционность не соответствует аргументу is_transactional.

  • value - новое значение переменной. pgv_set завершается неудачно, если переменная уже существует и ее тип не соответствует типу нового значения.

  • is_transactional - Транзакционность вновь созданной переменной, по умолчанию false.

pgv_get аргументы:

  • package - это имя существующего пакета. Если пакет не существует, результат зависит от аргумента strict: если он равен false, то pgv_get возвращает NULL, в противном случае происходит ошибка.

  • name - имя существующей переменной. Если переменная не существует, результат зависит от аргумента strict: если он равен false, то pgv_get возвращает NULL, в противном случае происходит ошибка.

  • var_type - тип существующей переменной. Его необходимо передать, чтобы получить правильный тип возвращаемого значения.

  • strict - передайте значение false, если pgv_get не должен вызывать ошибку, если переменная или пакет не были созданы ранее, по умолчанию значение true.

F.53.7. Функции переменных записей

Модуль предоставляет следующие функции для работы с коллекциями типов записей.

Для использования функций pgv_update(), pgv_delete() и pgv_select() необходимо наличие соответствующего пакета и переменной. В противном случае будет сгенерирована ошибка. Чтобы использовать эти функции, необходимо установить переменную с помощью функции pgv_insert().

Функции pgv_update(), pgv_delete() и pgv_select() проверяют тип переменной. Если тип переменной не соответствует записанному типу, будет вызвана ошибка.

Таблица F.27. Функции переменных записей

Функция

Возвращает

Описание

pgv_insert(package text, name text, r record, is_transactional bool default false)

пусто

Вставляет запись в переменную коллекцию. Если пакет и переменная не существуют, они будут созданы. Первый столбец r будет первичным ключом. Если существует запись с таким же первичным ключом, будет вызвана ошибка. Если у этой переменной коллекции есть другая структура, будет вызвана ошибка.

pgv_update(package text, name text, r record)

логическое значение

Обновляет запись с соответствующим первичным ключом (первый столбец) r является первичным ключом). Возвращает 1 если запись была найдена. Если у этой переменной коллекции другая структура, будет вызвана ошибка.

pgv_delete(package text, name text, value anynonarray)

логическое значение

Удаляет запись с соответствующим первичным ключом (первый столбец) r является первичным ключом). Возвращает 1 если запись была найдена.

pgv_select(package text, name text)

set of record

Возвращает записи коллекции переменных.

pgv_select(package text, name text, value anynonarray)

запись

Возвращает запись с соответствующим первичным ключом (первым столбцом) r является первичным ключом).

pgv_select(package text, name text, value anyarray)

set of record

Возвращает записи коллекции переменных с соответствующими первичными ключами (первый столбец) r является первичным ключом).


F.53.7.1. Различные функции

Таблица F.28. Различные функции

Функция

Возвращает

Описание

pgv_exists(package text, name text)

bool

Возвращает 1 если пакет и переменная существуют.

pgv_exists(package text)

bool

Возвращает 1 если пакет существует.

pgv_remove(package text, name text)

пусто

Удаляет переменную с соответствующим именем. Требуется наличие пакета и переменной, в противном случае будет вызвана ошибка.

pgv_remove(package text)

пусто

Удаляет пакет и все переменные пакета с соответствующим именем. Требуемый пакет должен существовать, в противном случае будет вызвана ошибка.

pgv_free()

пусто

Удаляет все пакеты и переменные.

pgv_list()

таблица (package text, name text, is_transactional bool)

Возвращает набор записей назначенных пакетов и переменных.

pgv_stats()

таблица (package text, allocated_memory bigint)

Возвращает список назначенных пакетов и используемую память в байтах.


F.53.8. Примеры

Использование функций для работы с скалярными и массивными переменными очень просто:

SELECT pgv_set('vars', 'int1', 101);
SELECT pgv_set('vars', 'text1', 'text variable'::text);

SELECT pgv_get('vars', 'int1', NULL::int);
 pgv_get_int
-------------
         101

SELECT SELECT pgv_get('vars', 'text1', NULL::text);
    pgv_get
---------------
 text variable

SELECT pgv_set('vars', 'arr1', '{101,102}'::int[]);

SELECT pgv_get('vars', 'arr1', NULL::int[]);
  pgv_get
-----------
 {101,102}

Предположим, у нас есть tab таблица:

CREATE TABLE tab (id int, t varchar);
INSERT INTO tab VALUES (0, 'str00'), (1, 'str11');

Затем вы можете использовать функции для работы с переменными-записями:

SELECT pgv_insert('vars', 'r1', tab) FROM tab;

SELECT pgv_select('vars', 'r1');
 pgv_select
------------
 (1,str11)
 (0,str00)

SELECT pgv_select('vars', 'r1', 1);
 pgv_select
------------
 (1,str11)

SELECT pgv_select('vars', 'r1', 0);
 pgv_select
------------
 (0,str00)

SELECT pgv_select('vars', 'r1', ARRAY[1, 0]);
 pgv_select
------------
 (1,str11)
 (0,str00)

SELECT pgv_delete('vars', 'r1', 1);

SELECT pgv_select('vars', 'r1');
 pgv_select
------------
 (0,str00)

Вы можете перечислить пакеты и переменные:

SELECT * FROM pgv_list() order by package, name;
 package | name  | is_transactional
---------+-------+------------------
 vars    | arr1  | f
 vars    | int1  | f
 vars    | r1    | f
 vars    | text1 | f

И мы получаем используемую память в байтах:

SELECT * FROM pgv_stats() order by package;
 package | allocated_memory
---------+------------------
 vars    |            49152

Вы можете удалить переменные или целые пакеты:

SELECT pgv_remove('vars', 'int1');
SELECT pgv_remove('vars');

Вы можете удалить все пакеты и переменные:

SELECT pgv_free();

Если вам нужны транзакционные переменные с возможностью использования точек сохранения, вы должны добавить флаг is_transactional = true в качестве последнего аргумента в функции pgv_set() или pgv_insert(). Ниже приведены примеры использования транзакционных переменных:

SELECT pgv_set('pack', 'var_text', 'before transaction block'::text, true);
BEGIN;
SELECT pgv_set('pack', 'var_text', 'before savepoint'::text, true);
SAVEPOINT sp1;
SELECT pgv_set('pack', 'var_text', 'savepoint sp1'::text, true);
SAVEPOINT sp2;
SELECT pgv_set('pack', 'var_text', 'savepoint sp2'::text, true);
RELEASE sp2;
SELECT pgv_get('pack', 'var_text', NULL::text);
    pgv_get
---------------
 savepoint sp2

ROLLBACK TO sp1;
SELECT pgv_get('pack', 'var_text', NULL::text);
     pgv_get
------------------
 before savepoint

ROLLBACK;
SELECT pgv_get('pack', 'var_text', NULL::text);
         pgv_get
--------------------------
 before transaction block

Если вы создаете транзакционную переменную после оператора BEGIN или SAVEPOINT и затем возвращаетесь к предыдущему состоянию, переменная не будет существовать:

BEGIN;
SAVEPOINT sp1;
SAVEPOINT sp2;
SELECT pgv_set('pack', 'var_int', 122, true);
RELEASE SAVEPOINT sp2;
SELECT pgv_get('pack', 'var_int', NULL::int);
pgv_get
---------
     122

ROLLBACK TO sp1;
SELECT pgv_get('pack','var_int', NULL::int);
ERROR:  unrecognized variable "var_int"
COMMIT;

Вы можете отменить удаление транзакционной переменной с помощью ROLLBACK, но если вы удалите весь пакет, все обычные переменные будут удалены навсегда:

SELECT pgv_set('pack', 'var_reg', 123);
SELECT pgv_set('pack', 'var_trans', 456, true);
BEGIN;
SELECT pgv_free();
SELECT * FROM pgv_list();
 package | name | is_transactional
---------+------+------------------
(0 rows)

-- Memory is allocated yet
SELECT * FROM pgv_stats();
 package | allocated_memory
---------+------------------
 pack    |            24576

ROLLBACK;
SELECT * FROM pgv_list();
 package |   name    | is_transactional
---------+-----------+------------------
 pack    | var_trans | t

Если вы создали транзакционную переменную однажды, вы должны использовать флаг is_transactional каждый раз, когда вы хотите изменить значение переменной с помощью устаревших функций установки pgv_set() и pgv_insert() (т.е. pgv_set_int()). Если вы попытаетесь изменить это настройку, вы получите сообщение об ошибке:

SELECT pgv_insert('pack', 'var_record', row(123::int, 'text'::text), true);

SELECT pgv_insert('pack', 'var_record', row(456::int, 'another text'::text));
ERROR:  variable "var_record" already created as TRANSACTIONAL

Функции pgv_update() и pgv_delete() не требуют этого флага.