При обновлении конфигураций на базе 1С:УНФ (или отраслевых решений, таких как "1С:Автосервис") пользователи и программисты могут столкнуться с загадочной ошибкой при записи документов. Система выдает сообщение об ошибке в коде, указывая на номер строки, которого физически не существует в модулях конфигурации.
Рассмотрим конкретную ситуацию: при попытке записать документ (например, "Заявка на ремонт") возникает ошибка ограничения доступа к данным со следующим текстом:
{(127, 2)}: Ожидается выражение ")"
<>>ЕСТЬNULL(СтруктурнаяЕдиница, НЕОПРЕДЕЛЕНО) <> НЕОПРЕДЕЛЕНО
Глобальный поиск по конфигурации не дает результатов: строки ЕСТЬNULL(СтруктурнаяЕдиница, НЕОПРЕДЕЛЕНО) нигде нет. В этой статье мы разберем природу этой ошибки, выясним, откуда берется "призрачный" код, и рассмотрим способы решения проблемы.
Первое, что сбивает с толку — указание на строку (в примере это строка 127), которой нет ни в модуле объекта, ни в модуле менеджера. Чтобы понять причину, нам нужно углубиться в механику работы RLS (Record Level Security — ограничение прав на уровне записей).
Когда в 1С настроены ограничения доступа (например, пользователь видит документы только по своей организации или структурной единице), платформа не просто выполняет запрос к базе данных. Она динамически модифицирует этот запрос "на лету", добавляя к нему условия фильтрации из ролей пользователя.
Процесс выглядит так:
Ошибка {(127, 2)} относится именно к этому динамически сформированному запросу, который существует только в оперативной памяти сервера в момент выполнения транзакции. Именно поэтому найти этот текст через Ctrl+F в конфигураторе невозможно — его там просто нет в явном виде.
Внимательно посмотрим на проблемный фрагмент:
ЕСТЬNULL(СтруктурнаяЕдиница, НЕОПРЕДЕЛЕНО) <> НЕОПРЕДЕЛЕНО
Эта конструкция выглядит подозрительно для языка запросов 1С. Обычно поля ссылочного типа (каким является СтруктурнаяЕдиница) сравниваются с ЗНАЧЕНИЕ(Справочник.СтруктурнаяЕдиница.ПустаяСсылка), а не с НЕОПРЕДЕЛЕНО. Значение НЕОПРЕДЕЛЕНО чаще применяется для полей составного типа, когда тип не выбран.
Ошибка «Ожидается выражение ")"» говорит о том, что транслятор запроса 1С в SQL не смог корректно обработать литерал НЕОПРЕДЕЛЕНО внутри функции ЕСТЬNULL в данном контексте, что привело к нарушению синтаксиса скобок в итоговом SQL-запросе. В таких случаях может помочь подсистема прав доступа с гибкими отборами, позволяющая обойти стандартные механизмы.
Чаще всего это происходит из-за рассинхронизации шаблонов RLS в Библиотеке Стандартных Подсистем (БСП). Например, если при обновлении конфигурации обновились общие модули, отвечающие за права, но в ролях (или расширениях) остались старые вызовы шаблонов, подставляющие неверные параметры.
Хотя глобальный поиск не работает, мы можем локализовать место, где формируется шаблон ограничения. Давайте выполним следующие действия:
К сожалению, стандартный поиск (Ctrl+F) в этом окне может не работать, но мы можем использовать кнопку "Отбор" или вывести список в табличный документ (через меню "Все действия" — "Вывести список") и искать уже там.
Искать следует фрагменты текста, похожие на часть ошибки, например NULL или вызовы шаблонов доступа (обычно они начинаются с символа #, например #ПоЗначениям). Это поможет понять, какая именно Роль накладывает некорректное ограничение на документ.
Если быстро исправить код шаблонов затруднительно (например, ошибка находится внутри защищенного модуля отраслевого решения или сложного расширения), мы можем воспользоваться особенностью механизма прав доступа в 1С.
Принцип работы прав: Доступ к объекту разрешен, если он разрешен хотя бы в одной из назначенных пользователю ролей. Условия RLS разных ролей объединяются через логическое "ИЛИ".
Это значит, что если мы добавим пользователю роль, в которой доступ к документу разрешен без ограничений (условие "Истина"), то платформа может проигнорировать сложный и ошибочный RLS запрос из другой роли.
Пошаговое решение:
ПолныеПраваНаЗаявки.ЗаявкаНаРемонт). Аналогичным образом работает установка разрешения или запрета редактирования справочников.После этих действий документ должен начать записываться. Поскольку в новой роли нет RLS, условие доступа превращается в ГДЕ ИСТИНА, и платформа успешно выполняет запись, минуя ошибочный блок кода.
Если метод с дополнительной ролью не подходит (например, вам критически важно сохранить ограничение видимости документов), необходимо точно найти ошибку в запросе. Для этого используем Технологический журнал (ТЖ).
Настроим файл logcfg.xml на сбор событий EXCP (исключения) и DBMSSQL (запросы к SQL) или RLS (если версия платформы позволяет). В логах мы увидим полный текст запроса, который платформа пыталась выполнить. Это будет выглядеть примерно так:
SELECT
T1._IDRRef,
T1._Marked,
...
FROM dbo._Document355 T1
WHERE ((T1._Fld1234RRef = ... OR ... ) AND (CASE WHEN ... THEN 1 ELSE 0 END = 1))
Анализируя полный текст SQL-запроса в логах, мы увидим, во что именно развернулся шаблон RLS и почему возникла синтаксическая ошибка. Это позволит скорректировать шаблон в конфигураторе: заменить НЕОПРЕДЕЛЕНО на ЗНАЧЕНИЕ(...) или исправить параметры шаблона БСП.
Ошибка "Ожидается выражение" с указанием на несуществующую строку при записи документа — это проблема в динамическом запросе RLS. Самый быстрый способ восстановить работоспособность — создать расширяющую роль с полными правами на данный конкретный документ без ограничений RLS. Для полного исправления требуется анализ и корректировка шаблонов доступа в ролях конфигурации.