Центр Диагностики & База Системных Ошибок

Решения для Windows Server, Active Directory, 1С, СУБД, Linux, Cisco, MikroTik и IP-телефонии.

⚠️ Важная информация Все материалы, инструкции, команды и скрипты предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, баз данных и сетевого оборудования. Перед выполнением действий обязательно создайте резервную копию. При отсутствии необходимой квалификации обратитесь к ИТ-специалистам.

Ошибка PostgreSQL 39000: external_routine_invocation_exception — исправление

Обновлено: 26.08.2026  ·  Официальная база знаний
  • Прерывание транзакции с ошибкой ERROR: external routine invocation exception (SQLSTATE 39000).
  • Исключение возникает непосредственно в момент передачи аргументов во внешнюю подпрограмму или при возврате результата.
  • Сбои при передаче NULL значений в C-функции без проверки макроса PG_ARGISNULL().

1. Проверка определения внешней функции в PostgreSQL

SELECT p.proname, p.prosrc, p.probin, p.proisstrict 
FROM pg_proc p 
WHERE p.proname = 'my_custom_c_func';

2. Корректная обработка NULL (Атрибут STRICT)

Если внешняя функция не умеет самостоятельно обрабатывать значения NULL, объявите ее с директивой STRICT (в этом случае ядро автоматически вернет NULL без вызова функции):

CREATE OR REPLACE FUNCTION my_custom_c_func(text, integer)
RETURNS text
AS '$libdir/custom_mod', 'my_custom_c_func'
LANGUAGE C STRICT;

3. Безопасная работа с аргументами на уровне Си-кода

При написании функций версии V1 всегда используйте стандартные макросы ядра:

PG_FUNCTION_INFO_V1(my_custom_c_func);

Datum my_custom_c_func(PG_FUNCTION_ARGS)
{
    if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
        PG_RETURN_NULL();

    text *arg0 = PG_GETARG_TEXT_PP(0);
    int32 arg1 = PG_GETARG_INT32(1);

    // Логика функции
    PG_RETURN_TEXT_P(arg0);
}

4. Проверка совпадения типов SQL и Си

Убедитесь, что int4 соответствует int32, int8int64, а строковые типы varchar/text обрабатываются как структуры varlena.

Практический опыт инженера: При работе с текстом в C-модулях всегда используйте PG_GETARG_TEXT_PP() вместо устаревшего PG_GETARG_TEXT_P(), чтобы корректно поддерживать TOAST-сжатые и неупакованные заголовки 1-byte header.

Частые вопросы (FAQ)

Чем ошибка 39000 отличается от 38000?

39000 сигнализирует об ошибке протокола вызова и маршалинга параметров (неверный формат аргументов, стек, переполнение буфера входных данных), тогда как 38000 указывает на общее исключение внутри самой внешней подпрограммы.

Что означает директива RETURNS NULL ON NULL INPUT?

Это синоним директивы STRICT. Она предотвращает вызов внешней функции, если хотя бы один из переданных параметров равен NULL.

Может ли некорректная кодировка строки вызвать 39000?

Да, если внешняя процедура ожидает валидный UTF-8, а клиент передает поврежденные байты в кодировке WIN1251 без предварительной перекодировки.

Как перезагрузить обновленную библиотеку .so в PostgreSQL без рестарта сервера?

Вызовите команду DISCARD ALL или завершите текущую сессию подключения.