Переменные уровня сеанса qhb-variables
ВНИМАНИЕ!
В релизе QHB 1.5.2 эта функциональность является экспериментальной, ее использование в установке на производственной среде не рекомендовано.
Описание
qhb-variables позволяет создавать переменные, которые будут удалены по
завершении сеанса. Этот механизм является альтернативой временным таблицам в
местах, где их производительности недостаточно. Переменные хранятся в пакетах.
Существует два типа переменных: скалярные и табличные. В скалярных переменных за
раз можно хранить только одно значение любого типа, в табличных же можно
хранить множество строк. Также переменные подразделяются на транзакционные и
нетранзакционные. Состояние первых не зависит от результата транзакции, а вторые
меняют свое значение, учитывая COMMIT
и ROLLBACK
. Тип переменной нельзя менять
после создания до полного удаления (в случае транзакционной переменной до выполнения
COMMIT
).
Функции qhb-variables
Функции для работы со скалярными переменными
Функция |
||
---|---|---|
Описание |
||
var_set ( пакет text, переменная text, значение (non)anynonarray, is_transactional bool default false ) → void | ||
Установка значения переменной, в том числе обновление. | ||
var_get ( пакет text, переменная text, тип_переменной (non)anynonarray, strict bool default true ) → anynonarray | ||
Получение значения переменной. |
Примеры использования
SELECT var_set('pack', 'var', 0);
var_set
---------
(1 row)
SELECT var_get('pack', 'var', NULL::int);
var_get
---------
0
(1 row)
BEGIN;
SELECT var_set('pack', 'var', 'before savepoint'::text, true);
var_set
---------
(1 row)
SAVEPOINT zero;
SELECT var_set('pack', 'var', 'after savepoint'::text, true);
var_set
---------
(1 row)
SELECT var_get('pack', 'var', NULL::text);
var_get
-----------------
after savepoint
(1 row)
ROLLBACK TO zero;
SELECT var_get('pack', 'var', NULL::text);
var_get
------------------
before savepoint
(1 row)
Функции для работы с табличными переменными
Функция |
||
---|---|---|
Описание |
||
var_insert ( пакет text, переменная text, запись record, is_transactional bool default false ) → void | ||
Вставляет новую запись в табличную переменную. Первый столбец записи является первичным ключом. Возвращает ошибку, если запись с таким ключом уже есть или запись имеет другую сигнатуру. | ||
var_update ( пакет text, переменная text, запись record ) → boolean | ||
Обновляет запись в табличной переменной, опираясь на поле ключа. Возвращает true, если запись была обновлена. Если сигнатура переменной отличается от предоставленной строки, то возникнет ошибка. | ||
var_delete ( пакет text, переменная text, значение anynonarray ) → boolean | ||
Удаляет запись по ключу. Возвращает true, если запись была удалена. | ||
var_select ( пакет text, переменная text ) → set of record | ||
Возвращает текущее значение переменной. | ||
var_select ( пакет text, переменная text, значение anynonarray ) → record | ||
Возвращает текущее значение переменной по ключу. | ||
var_select ( пакет text, переменная text, значение anyarray ) → set of record | ||
Возвращает текущее значение переменной по ключам. |
Примеры использования
SELECT var_insert('pac', 'var', ROW(NULL::int, 0::int));
var_insert
------------
(1 row)
SELECT var_insert('pac', 'var', ROW(0::int, 1::int));
var_insert
------------
(1 row)
SELECT var_insert('pac', 'var1', ROW(0::int, 2::int));
var_insert
------------
(1 row)
SELECT var_insert('pac', 'var1', ROW(2::int, 2::int));
var_insert
------------
(1 row)
SELECT var_select('pac', 'var');
var_select
------------
(,0)
(0,1)
(2 rows)
SELECT var_select('pac', 'var1', 0);
var_select
------------
(0,2)
(1 row)
SELECT var_select('pac', 'var1', ARRAY[0, 1]);
var_select
------------
(0,2)
(1 row)
Общие функции переменных
Функция |
||
---|---|---|
Описание |
||
var_exists ( пакет text, переменная text, is_record bool ) → bool | ||
Возвращает true, если переменная существует в данном пакете. | ||
var_exists ( пакет text ) → bool | ||
Возвращает true, если пакет существует. | ||
var_remove ( пакет text, переменная text, is_record bool) → void | ||
Удаляет переменную по имени. Если переменной или пакета не существует, то будет возвращена ошибка. | ||
var_remove ( пакет text ) → void | ||
Удаляет пакет со всеми переменными внутри него. Если пакета не существует, то будет возвращена ошибка. | ||
var_free () → void | ||
Удаляет все пакеты со всеми переменными внутри. | ||
var_list () → table ( пакет text, переменная text, тип_переменной text, is_transactional bool ) | ||
Возвращает список всех пакетов и переменных с указанием их транзакционности и типа. | ||
var_stats () → table ( выделенная_память bigint ) | ||
Возвращает объем памяти, занимаемый переменными. Обратите внимание, что эта функция возвращает выделенное место, которое может быть использовано не полностью. Для получения более подробной информацией используйте функцию pg_backend_memory_contexts(). |
В одном пакете могут быть две переменные с одинаковым именем, но только при условии, что одна из них табличная, а другая скалярная. По умолчанию функции var_exists и var_remove удаляют обе переменные, поэтому если вам нужно выбрать только табличную переменную, передайте последним параметром true, а для удаления только скалярной переменной передайте false. Этот параметр является необязательным.
Пример:
BEGIN;
SELECT var_set('pack', 'var', 0, true);
var_set
---------
(1 row)
SELECT var_insert('pack', 'var', ROW(0::int, 1::int), true);
var_insert
------------
(1 row)
SELECT * FROM var_list();
package | variable | variable_type | is_transactional
---------+----------+-------------------------------+------------------
pack | var | Scalar(integer) | t
pack | var | Record(row(integer, integer)) | t
(2 rows)
SAVEPOINT first;
SELECT var_remove('pack', 'var', true);
var_remove
------------
(1 row)
SELECT var_exists('pack', 'var', true);
var_exists
------------
f
(1 row)
SELECT var_exists('pack', 'var', false);
var_exists
------------
t
(1 row)
SELECT var_exists('pack', 'var');
var_exists
------------
t
(1 row)
SELECT var_remove('pack', 'var');
var_remove
------------
(1 row)
SELECT var_exists('pack', 'var', false);
var_exists
------------
f
(1 row)
ROLLBACK TO first;
SELECT var_exists('pack', 'var');
var_exists
------------
t
(1 row)
Примеры использования
BEGIN;
SELECT var_set('pack', 'var', 'non-transactional'::text);
var_set
---------
(1 row)
SELECT var_set('pack', 'var1', 'transactional'::text, true);
var_set
---------
(1 row)
SELECT * FROM var_list();
package | variable | variable_type | is_transactional
---------+----------+---------------+------------------
pack | var | Scalar(text) | f
pack | var1 | Scalar(text) | t
(2 rows)
SAVEPOINT first;
SELECT var_free();
var_free
----------
(1 row)
SELECT var_stats();
var_stats
-----------
8192
(1 row)
SELECT * FROM var_list();
package | variable | variable_type | is_transactional
---------+----------+---------------+------------------
(0 rows)
ROLLBACK TO first;
SELECT * FROM var_list();
package | variable | variable_type | is_transactional
---------+----------+---------------+------------------
pack | var1 | Scalar(text) | t
(1 row)
Другие примеры использования
Вставка из таблицы и деструктуризация SELECT
:
CREATE TABLE test_table (id int, t text);
INSERT INTO test_table VALUES (0, 'first'), (1, 'second');
SELECT var_insert('pack', 'var', test_table) FROM test_table;
var_insert
------------
(2 rows)
SELECT var_select('pack', 'var');
var_select
------------
(1,second)
(0,first)
(2 rows)
SELECT * FROM var_select('pack', 'var') AS (id int, t text);
id | t
----+--------
1 | second
0 | first
(2 rows)
Изменение типа при полном удалении переменной:
SELECT var_set('pack', 'var', 1::int);
var_set
---------
(1 row)
SELECT var_set('pack', 'var_transactional', 1::int, true);
var_set
---------
(1 row)
SELECT * FROM var_list();
package | variable | variable_type | is_transactional
---------+-------------------+-----------------+------------------
pack | var_transactional | Scalar(integer) | t
pack | var | Scalar(integer) | f
(2 rows)
BEGIN;
SELECT var_free();
var_free
----------
(1 row)
SELECT var_set('pack', 'var', 1::text); -- успешно
var_set
---------
(1 row)
-- SELECT var_set('pack', 'var_transactional', 1::text, true); -- Ошибка
COMMIT;
SELECT var_set('pack', 'var_transactional', 1::text, true); -- Успешно
var_set
---------
(1 row)
SELECT * FROM var_list();
package | variable | variable_type | is_transactional
---------+-------------------+---------------+------------------
pack | var_transactional | Scalar(text) | t
pack | var | Scalar(text) | f
(2 rows)
Этот пример работает, потому что переменные были безвозвратно удалены при вызове var_free.
Сохранение элементов таблицы. При вставке в переменную создается независимая копия данных.
CREATE TABLE test_table (id int, t text);
INSERT INTO test_table VALUES (0, 'first'), (1, 'second'), (2, 'third');
SELECT var_insert('pack', 'var', test_table) FROM test_table WHERE id < 2;
var_insert
------------
(2 rows)
DROP TABLE test_table;
CREATE TABLE test_table AS SELECT * FROM var_select('pack', 'var') AS (id int, t text);
SELECT * FROM test_table;
id | t
----+--------
1 | second
0 | first
(2 rows)
SELECT
+ CURSOR
При вызове var_select создается мгновенная копия данных, поэтому на результат
SELECT
var_update не повлияет. Однако если переменная была удалена, то
получение оставшихся данных станет невозможным.
CREATE TABLE test_table (id int, t text);
INSERT INTO test_table VALUES (0, 'first'), (1, 'second'), (2, 'third');
SELECT var_insert('pack', 'var', test_table, true) FROM test_table;
var_insert
------------
(3 rows)
BEGIN;
DECLARE r1_cur CURSOR FOR SELECT var_select('pack', 'var');
FETCH 1 in r1_cur;
var_select
------------
(2,third)
(1 row)
SELECT var_remove('pack');
var_remove
------------
(1 row)
FETCH 1 in r1_cur;
ERROR: var_select: Existence: Variable with name `var` does not exist in package `pack`
-- ОШИБКА: var_select: Существование: В пакете `pack` не существует переменной с именем `var`
ROLLBACK;
SELECT var_select('pack', 'var');
var_select
------------
(2,third)
(1,second)
(0,first)
(3 rows)