F.54. pg_variables#
F.54. pg_variables #
F.54.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.54.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.54.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.54.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.54.7. Функции переменных записей #
Модуль предоставляет следующие функции для работы с коллекциями типов записей.
Для использования функций pgv_update(), pgv_delete() и pgv_select() необходимо наличие соответствующего пакета и переменной. В противном случае будет сгенерирована ошибка. Чтобы использовать эти функции, необходимо установить переменную с помощью функции pgv_insert().
Функции pgv_update(), pgv_delete() и pgv_select() проверяют тип переменной. Если тип переменной не соответствует записанному типу, будет вызвана ошибка.
Таблица F.29. Функции переменных записей
Функция |
Возвращает |
Описание |
---|---|---|
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.54.7.1. Различные функции #
Таблица F.30. Различные функции
Функция |
Возвращает |
Описание |
---|---|---|
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.54.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()
не требуют этого флага.