Расширение pg_variables в PostgreSQL часто позволяет избежать использования временных таблиц. Я его использовал, и поэтому, при тестировании PostgreSQL 18 так же установил и его из репозитория на github. Я не проверял на PostgreSQL 16 и 17, поэтому описываемая ниже проблема может возникать и там. В PostgreSQL 15 и более ранних версиях эта проблема не проявлялась.
По умолчанию pg_variables может сам определять тип констант, передаваемых ему. Это управляется конфигурационной переменной pg_variables.convert_unknownoid. Если она не задана, то её значение 1 (true).
На PostgreSQL 18 при тестировании это привело к очень странным последствиям. Попробуем вставить запись, содержащую два текстовых поля:
CREATE EXTENSION IF NOT EXISTS pg_variables;
SELECT pgv_insert('var1', 'rec1', ('value1','value2'));
pgv_insert|
----------+
|Пока всё нормально. Теперь попробует её прочитать:
SELECT pgv_select('var1', 'rec1');
SQL Error [XX000]: ERROR: invalid memory alloc request size 18446744073709551613Уже само это сообщение заставляет насторожиться. Немного изменим нашу запись:
SELECT pgv_insert('var1', 'rec2', ('value1'::varchar,'value2'));
pgv_insert|
----------+
|
SELECT pgv_select('var1', 'rec2');
pgv_select |
-----------+
(value1,"")|Значение второго поля записи вообще пропало.
Теперь попробуем явно указать типы констант и запросить результат:
SELECT pgv_insert('var1', 'rec3', ('value1'::text,'value2'::text));
pgv_insert|
----------+
|
SELECT pgv_select('var1', 'rec3');
pgv_select |
---------------+
(value1,value2)|Никаких проблем.
Могу предположить, что при указании строковых констант расширение pg_variables некорректно определяет их тип, если он явно не указан. Запретить распознавание типа, как я уже указывал выше, можно конфигурационной переменной:
ALTER SYSTEM SET pg_variables.convert_unknownoid = 0;
SELECT pg_reload_conf();Теперь установить значение записи вообще без указания типа строковых констант pgv_insert не даст:
SELECT pgv_insert('var1', 'rec1', ('value1','value2'));
SQL Error [42883]: ERROR: could not identify a hash function for type unknownЧто интересно, но запись, у которой указан тип только первой константы вставлять позволяется:
SELECT pgv_insert('var1', 'rec5', ('value1'::varchar,'value2'));
pgv_insert|
----------+
|
SELECT pgv_select('var1', 'rec5');
pgv_select |
---------------+
(value1,value2)|При этом запись возвращается в корректном виде. Однако, я бы всё равно не рекомендовал не указывать тип строковых констант внутри записей при вызове pgv_insert.
А вот задание конфигурационной переменной pg_variables.convert_unknownoid = 0 настоятельно рекомендую.