Как правильно настроить RLS по табличной части документа в 1С

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

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

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

Почему не работает обращение через точку вида «ЕСТЬ NULL»

Попытка написать условие RLS следующим образом приводит к тому, что из списка полностью пропадают все документы:


ПоступлениеТоваровУслуг ГДЕ ПоступлениеТоваровУслуг.Товары.Номенклатура ЕСТЬ NULL

Выясним причину такого поведения платформы 1С. При обращении через точку к реквизитам табличной части (например, ПоступлениеТоваровУслуг.Товары.Номенклатура) транслятор запросов 1С автоматически преобразует данное выражение во внутреннее соединение (INNER JOIN) таблицы шапки документа с таблицей его табличной части.

Если табличная часть документа пуста, в правой таблице соединительных данных нет ни одной строки. Из-за особенностей внутреннего соединения вся запись шапки документа исключается из выборки ещё до того, как СУБД начнет проверять условия в секции ГДЕ. В результате условия ЕСТЬ NULL или равенство пустой ссылке возвращают пустой результат выборки.

Решение 1. Оптимальный вариант — флаг или реквизит в шапке документа

Самым правильным и производительным решением задачи ограничения доступа является отказ от прямой проверки табличной части внутри RLS. Любая проверка табличных частей в RLS создает существенную нагрузку на СУБД при формировании динамических списков и отчетов.

Рассмотрим пошагово реализацию этого подхода:

  1. Добавим в шапку документа ПоступлениеТоваровУслуг реквизит с типом Булево (например, ЕстьТовары).
  2. При обработке события ПередЗаписью или ПриЗаписи документа заполняем этот реквизит автоматически: СодержитТовары = (Товары.Количество() > 0);
  3. В настройке RLS для таблицы документа указываем простое условие по реквизиту шапки: ПоступлениеТоваровУслуг ГДЕ НЕ ПоступлениеТоваровУслуг.СодержитТовары

Преимущество метода: СУБД выполняет выборку исключительно по одной таблице шапки документа. Это полностью исключает тяжелые операции соединения таблиц при каждом отображении списка документов пользователю.

Решение 2. Явное левое соединение с проверкой первой строки

Если дорабатывать структуру документа или добавлять реквизиты нельзя, можно применить явное ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN) с ограничением по первой строке табличной части.

Проанализируем пример условия RLS:


ТекущаяТаблица ИЗ Документ.ПоступлениеТоваровУслуг КАК ТекущаяТаблица
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары
    ПО (ТекущаяТаблица.Ссылка = ПоступлениеТоваровУслугТовары.Ссылка
        И ПоступлениеТоваровУслугТовары.НомерСтроки = 1)
ГДЕ ПоступлениеТоваровУслугТовары.Ссылка ЕСТЬ NULL

В данном случае используется левое соединение, поэтому документы с пустой табличной частью не отсекаются на этапе соединения. Если строка с номером 1 отсутствует, поле ПоступлениеТоваровУслугТовары.Ссылка будет иметь значение NULL, и документ попадет в итоговую выборку.

Решение 3. Использование конструкции с отрицанием «НЕ В»

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

ПоступлениеТоваровУслуг ГДЕ НЕ ПоступлениеТоваровУслуг.Товары.НомерСтроки В (1)

При использовании конструкции вида НЕ ТабличнаяЧасть.Реквизит В (...) платформа 1С генерирует запрос к СУБД с использованием подзапроса проверки отсутствия записей (NOT EXISTS / NOT IN), а не внутреннего соединения. По этой причине документы без строк в табличной части Товары успешно проходят фильтрацию.

Сравнение подходов и рекомендации по производительности

Выбирая метод реализации ограничения прав, следует учитывать особенности работы СУБД:

  1. Использование реквизита шапки (Решение 1) — лучшее решение для рабочих баз с большим объемом данных. Обеспечивает максимальное быстродействие динамических списков и исключает эскалацию блокировок.
  2. Запросы к табличным частям в RLS (Решения 2 и 3) — подходят для небольших баз или в условиях невозможности изменения структуры метаданных. При увеличении количества документов такие условия могут вызывать задержки при открытии списков и построении отчетов.
← На главную