Почему возникает ошибка «22003: ОШИБКА: целое вне диапазона» в 1С на PostgreSQL и как ее исправить

Программист 1С v8.3 (Управляемые формы) 1С:Комплексная автоматизация IT и автоматизация бизнеса
← На главную

При работе с базами данных 1С, развернутыми на СУБД PostgreSQL, разработчики и администраторы иногда сталкиваются с весьма специфической проблемой. У пользователей с ограниченными правами при формировании отчетов, проведении или записи документов (например, заказов клиентов) платформа выдает критическую ошибку выполнения запроса: 22003: ОШИБКА: целое вне диапазона. При этом под полными правами или в файловом варианте базы данных та же самая операция проходит абсолютно корректно и без сбоев.

Рассмотрим подробнее, почему возникает данная ситуация, как она связана с ограничениями доступа на уровне записей (RLS) и какие шаги необходимо предпринять для устранения этой аппаратной ошибки СУБД.

Проанализируем суть ошибки СУБД PostgreSQL

В первую очередь выясним причину на уровне самой базы данных. Код ошибки 22003 в терминологии PostgreSQL означает numeric_value_out_of_range, то есть числовое значение вышло за пределы допустимого диапазона для выделенного типа данных.

СУБД PostgreSQL отличается строгой типизацией данных. Стандартный 4-байтовый тип integer (внутреннее название int4) способен хранить значения в диапазоне от -2 147 483 648 до +2 147 483 647. Если в процессе выполнения математической операции, агрегации или неявного приведения типов формируется число, превышающее этот лимит, СУБД немедленно прерывает выполнение запроса и возвращает ошибку переполнения.

В файловой версии 1С или в Microsoft SQL Server обработка промежуточных вычислений и неявное приведение типов происходят более мягко — система может автоматически расширить тип на лету. Именно поэтому проблема носит плавающий характер и проявляется исключительно на PostgreSQL.

Выясним причину: почему ошибка возникает только при ограниченных правах?

Разберем, как платформа 1С:Предприятие транслирует запросы к базе данных. Когда запрос выполняет пользователь с полными правами, SQL-код формируется в прямом виде. Но если у пользователя настроены ограничения прав (RLS), платформа неявно добавляет к базовому тексту запроса огромный объем дополнительных условий для проверки доступа к каждой конкретной записи.

Здесь мы сталкиваемся с недоработкой (багом) транслятора запросов самой платформы 1С при работе с PostgreSQL. Проанализируем, что происходит "под капотом":

  1. При использовании конструкции РАЗРЕШЕННЫЕ в запросах 1С, система отсеивает недоступные записи. В некоторых случаях вместо запрещенных данных в промежуточные таблицы попадают значения NULL.
  2. Транслятор платформы при преобразовании шаблонов RLS может некорректно обрабатывать ссылки, битовые маски доступа или эти самые NULL-значения, пытаясь привести их к целочисленному типу int4 на стороне СУБД.
  3. Если в запросе происходит математическая операция с таким «битым» значением или суммируются большие агрегатные показатели, тип int4 переполняется.
  4. По логике работы платформы, в случае проблем с RLS она должна была корректно перехватить ситуацию и выдать пользователю понятное предупреждение: «Ошибка доступа к данным на уровне записей». Однако из-за ошибки трансляции SQL-запрос падает на самом низком уровне — уровне движка PostgreSQL.

Рассмотрим по шагам методы диагностики и решения

Чтобы оперативно вернуть систему в рабочее состояние и исправить ошибку для пользователей, рассмотрим несколько практических подходов. Разберем их от локализации до изменения кода.

Шаг 1. Локализация проблемного запроса через Технологический журнал

Поскольку ошибка возвращается СУБД, нам необходимо увидеть "сырой" SQL-запрос и точный запрос 1С, на котором происходит падение. Для этого настроим Технологический журнал (ТЖ).

Вам потребуется включить сбор событий DBPOSTGRS (для фиксации обращений к СУБД) и EXCP (для фиксации исключений). Поймав момент ошибки, вы сможете в логах найти огромный сгенерированный SQL-запрос. Проанализируем его: обычно проблема кроется в блоках, где идет сложение или используются агрегатные функции СУММА() внутри вложенных запросов, которые платформа обернула в проверки RLS. Для разбора сырых логов и быстрого поиска проблемного места можно применить утилиту для парсинга технологического журнала.

Шаг 2. Использование функций ЕСТЬNULL() и ВЫРАЗИТЬ()

Когда проблемное поле или выражение в запросе найдено, нам необходимо принудительно заставить платформу (и, следовательно, PostgreSQL) выделить для этого поля более вместительный тип данных — numeric (число) или bigint (большое целое), чтобы избежать переполнения.

Посмотрим на пример. Предположим, у нас есть запрос, который суммирует некие показатели, и из-за RLS там может появиться NULL или произойти переполнение. Мы должны обернуть это поле в безопасную конструкцию.

Пример исправления в коде 1С:


ВЫБРАТЬ
    ЕСТЬNULL(ВЫРАЗИТЬ(Документ.СуммаДокумента КАК ЧИСЛО(15, 2)), 0) КАК СуммаБезопасная
ИЗ
    Документ.ЗаказКлиента КАК Документ

Используя конструкцию ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 2)) совместно с ЕСТЬNULL, мы жестко задаем разрядность. PostgreSQL воспримет это указание и переведет вычисления в тип, лимиты которого практически невозможно превысить стандартными бизнес-операциями.

Шаг 3. Анализ и корректировка шаблонов RLS

Если ошибка возникает при записи объекта (например, при вызове ЗаписатьОбъект), проанализируем текущие роли пользователя. Если в вашей конфигурации используются нетиповые, доработанные шаблоны ограничений доступа на уровне записей, обратите на них пристальное внимание. Часто в самописных шаблонах разработчики используют конструкции со сложением или вложенными группировками без явного указания размерности. Добавление оператора ВЫРАЗИТЬ() непосредственно внутрь текста шаблона RLS для проблемных полей может полностью снять проблему. Для детального анализа ролей, профилей и ограничений доступа пользователей можно использовать инструмент для проверки и настройки прав доступа.

Шаг 4. Обновление платформы 1С:Предприятие

Так как описанное поведение является признанной недоработкой механизма трансляции RLS-запросов для PostgreSQL, самым надежным и системным решением будет обновление платформы. Фирма "1С" регулярно выпускает патчи и исправления для работы с открытыми СУБД. Рекомендуется обновить серверную часть и клиентские машины до актуальных стабильных релизов (например, старше 8.3.21.x или 8.3.22.x, в зависимости от вашей текущей ветки), где алгоритмы генерации SQL-кода для ограничений прав доступа были оптимизированы и исправлены.

Подводя итог, при встрече с ошибкой 22003: ОШИБКА: целое вне диапазона не стоит паниковать. Мы с вами разобрали, что это сбой транслятора платформы, пытающегося уместить сложные маски RLS или пустые значения в 4-байтовое целое число. Локализуйте запрос через ТЖ, обезопасьте проблемные числовые поля строгой типизацией через запрос 1С и запланируйте обновление версии платформы.

← На главную