F.37. pg_variables
Модуль pg_variables содержит функции для работы с переменными различных типов. Созданные переменные существуют в течение текущей пользовательской сессии.
F.37.1. Установка
Расширение pg_variables включено в состав Postgres Pro. Установив Postgres Pro, вы должны выполнить команду CREATE EXTENSION, чтобы подготовить pg_variables к работе, следующим образом: 
CREATE EXTENSION pg_variables;
F.37.2. Использование
Модуль pg_variables содержит функции, позволяющие создавать переменные скалярных типов, переменные-записи и переменные-массивы, читать их и управлять ими. Синтаксис и описания функций представлены в следующих разделах: 
- В Подразделе F.37.3.1 описываются функции для скалярных переменных. 
- В Подразделе F.37.3.2 описываются функции для переменных-записей. 
- В Подразделе F.37.3.3 описываются функции для переменных-массивов. 
- В Подразделе F.37.3.4 перечисляются функции, позволяющие управлять всеми переменными в текущем сеансе. 
Разобранные примеры использования вы можете найти в Подразделе F.37.4.
F.37.2.1. Использование транзакционных переменных
По умолчанию переменные создаются как нетранзакционные. Успешно созданная переменная продолжает существовать на протяжении всего сеанса, вне зависимости от возможных откатов транзакций. Например:
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 в последнем параметре функции, создающей переменную:
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Вы должны указывать флаг is_transactional при каждом изменении значения транзакционной переменной с помощью функций pgv_set() и pgv_insert(). В противном случае произойдёт ошибка. Другим функциям передавать этот флаг не нужно.
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
SELECT pgv_delete('pack', 'var_record', 123::int);
    Если вызовы функций pgv_free() или pgv_remove() откатываются, затрагиваемые транзакционные переменные восстанавливаются, в отличие от нетранзакционных, которые удаляются необратимо. Например: 
SELECT pgv_set('pack', 'var_reg', 123);
SELECT pgv_set('pack', 'var_trans', 456, true);
BEGIN;
SELECT pgv_free();
ROLLBACK;
SELECT * FROM pgv_list();
 package |   name    | is_transactional 
---------+-----------+------------------
 pack    | var_trans | tF.37.3. Функции
F.37.3.1. Скалярные переменные
Следующие функции поддерживают скалярные переменные:
| Функция | Возвращает | 
|---|---|
| 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 | 
Для функции pgv_get() вы должны сначала создать пакет и переменную, воспользовавшись функцией pgv_set(). Если указанный пакет или переменная не существуют, происходит ошибка:
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" valueF.37.3.2. Записи
Следующие функции поддерживают наборы переменных типа запись.
| Функция | Возвращает | Описание | 
|---|---|---|
| pgv_insert(package text, name text, r record, is_transactional bool default false) | void | Вставляет запись в набор переменных для заданного пакета. Если пакет или переменная не существуют, они создаются автоматически. Первый столбец записи r— первичный ключ. Если запись с таким же первичным ключом уже существует или этот набор переменных имеет другую структуру, выдаётся ошибка. | 
| pgv_update(package text, name text, r record) | boolean | Изменяет запись с соответствующим первичным ключом (он задаётся в первом столбце r). Возвращаетtrue, если запись была найдена. Если этот набор переменных имеет другую структуру, выдаётся ошибка. | 
| pgv_delete(package text, name text, value anynonarray) | boolean | Удаляет запись с соответствующим первичным ключом (он задаётся в первом столбце r). Возвращаетtrue, если запись была найдена. | 
| pgv_select(package text, name text) | set of records | Возвращает записи из набора переменных. | 
| pgv_select(package text, name text, value anynonarray) | record | Возвращает записи из набора переменных с соответствующими первичными ключами (первичный ключ задаётся в первом столбце r). | 
| pgv_select(package text, name text, value anyarray) | set of records | Возвращает записи из набора переменных с соответствующими первичными ключами (первичный ключ задаётся в первом столбце r). | 
Для использования функций pgv_update(), pgv_delete() and pgv_select() вы должны сначала создать пакет и переменную, воспользовавшись функцией pgv_insert(). Тип переменной и тип записи должны быть одинаковыми, иначе выдаётся ошибка.
F.37.3.3. Массивы
Следующие функции поддерживают переменные-массивы:
| Функция | Возвращает | 
|---|---|
| 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 | 
Инструкции по использованию этих функций совпадают с приведёнными в Подразделе F.37.3.1 для скалярных переменных.
F.37.3.4. Функции разного назначения
| Функция | Возвращает | Описание | 
|---|---|---|
| pgv_exists(package text, name text) | bool | Возвращает true, если существует пакет и переменная. | 
| pgv_exists(package text) | bool | Возвращает true, если существует указанный пакет. | 
| pgv_remove(package text, name text) | void | Удаляет переменную с заданным именем. Указанный пакет и переменная должны существовать, иначе выдаётся ошибка. | 
| pgv_remove(package text) | void | Удаляет заданный пакет и все его переменные. Указанный пакет должен существовать, иначе выдаётся ошибка. | 
| pgv_free() | void | Удаляет все пакеты и переменные. | 
| pgv_list() | table(package text, name text, is_transactional bool) | Выводит список всех существующих переменных с именем соответствующего пакета и признаком того, что переменная транзакционная. | 
| pgv_stats() | table(package text, allocated_memory bigint) | Возвращает список созданных пакетов и объём памяти, используемый переменными, в байтах. Если вы используете транзакционные переменные, в этот список также включаются все удалённые пакеты, которые могут быть восстановлены командой ROLLBACK. Эта функция поддерживается только в Postgres Pro версии 9.6 и новее. | 
F.37.3.5. Устаревшие функции
F.37.3.5.1. Целочисленные переменные
Следующие функции считаются устаревшими. Используйте вместо них универсальные функции для скалярных переменных.
| Функция | Возвращает | 
|---|---|
| pgv_set_int(package text, name text, value int, is_transactional bool default false) | void | 
| pgv_get_int(package text, name text, strict bool default true) | int | 
F.37.3.5.2. Текстовые переменные
Следующие функции считаются устаревшими. Используйте вместо них универсальные функции для скалярных переменных.
| Функция | Возвращает | 
|---|---|
| pgv_set_text(package text, name text, value text, is_transactional bool default false) | void | 
| pgv_get_text(package text, name text, strict bool default true) | text | 
F.37.3.5.3. Числовые переменные
Следующие функции считаются устаревшими. Используйте вместо них универсальные функции для скалярных переменных.
| Функция | Возвращает | 
|---|---|
| pgv_set_numeric(package text, name text, value numeric, is_transactional bool default false) | void | 
| pgv_get_numeric(package text, name text, strict bool default true) | numeric | 
F.37.3.5.4. Переменные даты/времени
Следующие функции считаются устаревшими. Используйте вместо них универсальные функции для скалярных переменных.
| Функция | Возвращает | 
|---|---|
| pgv_set_timestamp(package text, name text, value timestamp, is_transactional bool default false) | void | 
| pgv_get_timestamp(package text, name text, strict bool default true) | timestamp | 
F.37.3.5.5. Переменные даты/времени с часовым поясом
Следующие функции считаются устаревшими. Используйте вместо них универсальные функции для скалярных переменных.
| Функция | Возвращает | 
|---|---|
| pgv_set_timestamptz(package text, name text, value timestamptz, is_transactional bool default false) | void | 
| pgv_get_timestamptz(package text, name text, strict bool default true) | timestamptz | 
F.37.3.5.6. Переменные даты
Следующие функции считаются устаревшими. Используйте вместо них универсальные функции для скалярных переменных.
| Функция | Возвращает | 
|---|---|
| pgv_set_date(package text, name text, value date, is_transactional bool default false) | void | 
| pgv_get_date(package text, name text, strict bool default true) | date | 
F.37.3.5.7. Переменные Jsonb
Следующие функции считаются устаревшими. Используйте вместо них универсальные функции для скалярных переменных.
| Функция | Возвращает | 
|---|---|
| pgv_set_jsonb(package text, name text, value jsonb, is_transactional bool default false) | void | 
| pgv_get_jsonb(package text, name text, strict bool default true) | jsonb | 
F.37.4. Примеры
Определение скалярных переменных с помощью функции pgv_set() и получение их значений с помощью pgv_get():
SELECT pgv_set('vars', 'int1', 101);
SELECT pgv_set('vars', 'int2', 102);
SELECT pgv_set('vars', 'text1', 'text variable'::text);
SELECT pgv_get('vars', 'int1', NULL::int);
 pgv_get
-------------
         101
SELECT pgv_get('vars', 'int2', NULL::int);
 pgv_get
-------------
         102
SELECT pgv_get('vars', 'text1', NULL::text);
 pgv_get
---------------
 text variableВ предположении, что создана следующая таблица 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)Проанализируйте поведение транзакционной переменной var_text при изменении до и после точки сохранения:
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;Просмотреть имеющиеся пакеты и переменные:
SELECT * FROM pgv_list() ORDER BY package, name; package | name | is_transactional ---------+----------+------------------ pack | var_text | t vars | int1 | f vars | int2 | f vars | r1 | f vars | text1 | f
Получение объёма памяти, занятой переменными, в байтах:
SELECT * FROM pgv_stats() ORDER BY package; package | allocated_memory ---------+------------------ pack | 16384 vars | 32768
Удаление избранных переменных или пакетов:
SELECT pgv_remove('vars', 'int1');
SELECT pgv_remove('vars');Удаление всех пакетов и переменных:
SELECT pgv_free();
F.37.5. Авторы
Postgres Professional, Москва, Россия