Почему в RLS-запросах 1С появляется загадочное условие «ИЛИ NULL» и как его исправить?

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

При проектировании систем прав доступа на уровне записей (Record Level Security, или RLS) разработчики часто сталкиваются со странным или неочевидным поведением запросов. Одной из таких загадок является появление конструкции ИЛИ NULL в ограничениях доступа. На первый взгляд это выглядит как синтаксическая ошибка или неаккуратность, но за этим скрываются важные архитектурные особенности работы платформы «1С:Предприятие» и СУБД.

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

Разбираем проблему: суть странного RLS-запроса

Представим ситуацию: в одной из ролей самописной конфигурации было обнаружено следующее условие ограничения доступа на чтение документа (секция «Прочие поля»):

ГДЕ Пользователь В (&Пользователи) ИЛИ NULL

Здесь Пользователь — это общий реквизит или обычный реквизит документа со ссылкой на справочник пользователей, а &Пользователи — параметр сеанса, содержащий фиксированный массив разрешенных пользователей. Возникает логичный вопрос: зачем в конце добавлено ИЛИ NULL? Позволяет ли это прочитать документы с незаполненными авторами, или это просто бесполезный «мусорный» код?

Работа конструкции «ИЛИ NULL» на уровне СУБД: трехзначная логика

Чтобы понять, как данное выражение обрабатывается СУБД, нам необходимо обратиться к понятию трехзначной логики (3VL — Three-Valued Logic), которая используется в современных реляционных базах данных (MS SQL Server, PostgreSQL, IBM DB2).

В отличие от классической булевой логики, где выражение может быть только истинным или ложным, в базах данных любое логическое сравнение с участием NULL может вернуть три состояния: ИСТИНА (True), ЛОЖЬ (False) или НЕИЗВЕСТНО (Unknown/NULL). Оператор ИЛИ (OR) при взаимодействии с NULL вычисляется по следующим правилам:

Таким образом, добавление конструкции ИЛИ NULL абсолютно ни на что не влияет. Оно никогда не сможет сделать ложное условие истинным. В секции ГДЕ эта конструкция ведет себя точно так же, как обычное ИЛИ ЛОЖЬ. Сравнение NULL = NULL или просто логический литерал NULL без операторов проверки никогда не вернут истину.

Откуда берется «ИЛИ NULL» в RLS-запросах?

Если данное условие математически бесполезно, выясним причины его появления в реальных конфигурациях 1С. Как правило, это связано со следующими факторами:

  1. Результат работы динамического шаблона (генератора RLS). В типовых конфигурациях (особенно в БСП — Библиотеке Стандартных Подсистем) шаблоны ограничений доступа собираются программно. Разработчик мог написать универсальный шаблон вида: ГДЕ Пользователь В (&Пользователи) [ДополнительноеУсловие] Если при формировании прав выясняется, что дополнительное условие не требуется, алгоритм заменяет заглушку на нейтральное значение. Если вместо пустой строки или конструкции ИЛИ ИСТИНА по ошибке подставляется ИЛИ NULL, запрос приобретает именно такой некорректный вид.
  2. Ошибки автозамены параметров препроцессором. Платформа 1С поддерживает инструкции препроцессора в RLS (например, конструкции с символом «#»). При определенных условиях неинициализированные параметры или пустые макросы могут транслироваться парсером платформы в литерал NULL.
  3. Ошибочная заготовка разработчика. Программист мог планировать написать проверку на незаполненное значение (например, ИЛИ Пользователь ЕСТЬ NULL), но поспешил или отвлекся, оставив незавершенную конструкцию, которая тем не менее успешно прошла синтаксический контроль платформы.

Влияние на производительность и оптимизацию

С технической точки зрения наличие «мусорного» кода в RLS-запросах нежелательно, однако современные СУБД легко справляются с этой проблемой:

Как правильно предоставить доступ к документам с пустым пользователем?

Если изначальная задумка автора RLS действительно состояла в том, чтобы разрешить пользователям просматривать документы, у которых реквизит Пользователь не заполнен, то текущий запрос эту задачу не решал. Нам нужно переписать его правильно.

В платформе 1С пустые значения могут храниться по-разному в зависимости от типа данных реквизита:

Способ 1. Если реквизит имеет ссылочный тип

Если реквизит Пользователь ссылается на справочник (например, СправочникСсылка.Пользователи), то в базе данных незаполненное значение хранится как пустая ссылка, а не как NULL. Нам нужно явно проверить реквизит на равенство пустой ссылке:


ГДЕ Пользователь В (&Пользователи)
    ИЛИ Пользователь = ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка)

Способ 2. Если используется левое соединение (физический NULL)

Если ограничение RLS строится через левое соединение с другой таблицей, и искомое поле действительно может физически отсутствовать в результирующей выборке, только тогда в запросе появится настоящий NULL. Для его проверки мы должны использовать строго оператор ЕСТЬ NULL:


ГДЕ Пользователь В (&Пользователи)
    ИЛИ Пользователь ЕСТЬ NULL

Проанализировав логику работы СУБД и платформы, мы можем сделать вывод: встретив конструкцию ИЛИ NULL в ограничениях доступа, ее можно и нужно смело удалять из кода, предварительно убедившись, что под ней не скрывалась попытка проверить поле на пустую ссылку или использовать оператор ЕСТЬ NULL.

← На главную