Ошибка PostgreSQL 42P13: invalid_function_definition — определение функций
- Ошибка
ERROR: invalid function definition: ... (SQLSTATE 42P13)при компиляции функции или процедуры. - Несоответствие объявленного типа возвращаемого значения (
RETURNS) и реального типа выражения в теле функции. - Ошибки указания внешних разделяемых библиотек в функциях на языке Си.
1. Проверка соответствия возвращаемого типа
Если функция объявлена как RETURNS TABLE или RETURNS RECORD, типы выходных колонок обязаны строго совпадать:
-- Ошибочная функция (типы не совпадают):
CREATE OR REPLACE FUNCTION get_user(p_id int)
RETURNS TABLE(user_id int, user_name varchar(50)) AS $$
BEGIN
-- Ошибка 42P13: user_name возвращает text вместо varchar(50) или типы перепутаны
RETURN QUERY SELECT u.name, u.id FROM users u WHERE u.id = p_id;
END;
$$ LANGUAGE plpgsql;
-- Исправленная функция:
CREATE OR REPLACE FUNCTION get_user(p_id int)
RETURNS TABLE(user_id int, user_name varchar(50)) AS $$
BEGIN
RETURN QUERY SELECT u.id, u.name::varchar(50) FROM users u WHERE u.id = p_id;
END;
$$ LANGUAGE plpgsql;2. Проверка функций на языке C
Убедитесь, что динамическая библиотека и символ точки входа существуют:
CREATE OR REPLACE FUNCTION fast_hash(text)
RETURNS int4
AS '$libdir/custom_hasher', 'fast_hash_v1'
LANGUAGE C STRICT;3. Валидация параметров параллелизма (PARALLEL SAFE)
Если функция помечена как PARALLEL SAFE, она не должна выполнять запись в таблицы или изменять состояние транзакции.
Частые вопросы (FAQ)
В чем разница между RETURNS RECORD и RETURNS TABLE(...) ?
RETURNS TABLE явно описывает имена и типы выходных колонок при создании функции. RETURNS RECORD требует от вызывающей стороны описывать структуру результата в каждом SQL-запросе (через AS (col1 type, ...)).
Что произойдет, если функция VOLATILE будет объявлена как IMMUTABLE?
Оптимизатор вычислит результат функции один раз на этапе планирования. Это приведет к возврату устаревших или некорректных данных.
Как объявить функцию, возвращающую пустой результат (аналог void)?
Укажите директиву RETURNS void или используйте синтаксис хранимых процедур CREATE PROCEDURE ... LANGUAGE plpgsql без секции RETURNS.
Почему компилятор PL/pgSQL не находит синтаксические ошибки внутри неиспользуемых веток IF?
PL/pgSQL выполняет валидацию SQL выражений при первом реальном исполнении ветки кода (если не установлено расширение plpgsql_check).