Как настроить RLS к табличной части в 1С и обойти ограничения на агрегатные функции?

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

Разберем интересную и достаточно сложную задачу, с которой регулярно сталкиваются разработчики 1С: настройка ограничения доступа на уровне записей (RLS) к объекту на основе данных его табличной части. Проанализируем исходную ситуацию. У нас есть справочник, который имеет табличную часть (ТЧ) с реквизитами вида «Свойство» (План видов характеристик) и «Значение». Также в системе существует регистр сведений, где для каждого пользователя указаны разрешенные ему типы и значения этих свойств. Наша задача — настроить RLS так, чтобы пользователь видел элемент справочника только в том случае, если для всех видов свойств в его табличной части у пользователя есть хотя бы одно разрешенное значение.

Очевидное, но нерабочее решение (SQL-подход)

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


ВЫБРАТЬ
    НоменклатураХарактеристики.Ссылка КАК Ссылка
ИЗ
    Справочник.Номенклатура.Характеристики КАК НоменклатураХарактеристики
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Фильтр КАК Фильтр
        ПО (Фильтр.Свойство = НоменклатураХарактеристики.Свойство)
            И (Фильтр.Значение = НоменклатураХарактеристики.Значение)
СГРУППИРОВАТЬ ПО
    НоменклатураХарактеристики.Ссылка
ИМЕЮЩИЕ
    СУММА(1) = &КоличествоХарактеристик

Или вариант с использованием вложенного запроса в условии:


Справочник ГДЕ Справочник.Ссылка В
    (ВЫБРАТЬ
        ТЧ.Ссылка КАК Ссылка
    ИЗ
        Справочник.Справочник4.ТЧ КАК ТЧ
            ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.РегистрСведений2 КАК Рег
            ПО ТЧ.А = Рег.А И ТЧ.Б = Рег.Б
    СГРУППИРОВАТЬ ПО
        ТЧ.Ссылка
    ИМЕЮЩИЕ
        КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ТЧ.Свойство) = &КоличествоСвойств)

Выясним причину, почему такие варианты не будут работать в качестве RLS. Согласно официальной документации 1С:Предприятие, в текстах ограничений доступа к данным категорически запрещено использовать агрегатные функции (такие как СУММА, КОЛИЧЕСТВО) и группировки (операторы СГРУППИРОВАТЬ ПО и ИМЕЮЩИЕ). Платформа накладывает этот запрет из соображений производительности, так как запрос RLS неявно прикрепляется платформой к каждому чтению целевой таблицы. Более того, использование сложных соединений (со связью «многое ко многим») или тяжелых вложенных запросов приведет к критическому замедлению работы системы: динамические списки начнут "висеть", а проведение документов растянется на минуты.

Правильное решение: архитектурный подход (Стандарт БСП)

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

Разберем этот механизм по шагам:

  1. Создание служебного регистра: Разработаем дополнительный регистр сведений (назовем его, например, НаборыЗначенийДоступа или КлючиДоступа). Его ведущим измерением будет Ссылка на наш справочник, а в других измерениях будут храниться подготовленные "плоские" ключи доступа (свойства и значения).
  2. Заполнение регистра при записи: В модуле объекта справочника или через подписку на событие ПриЗаписи добавим обработчик. При сохранении элемента справочника система должна проанализировать его табличную часть, сопоставить её со структурой свойств и рассчитать, к каким группам прав относится этот объект. Результат этого анализа в простом виде записывается в наш служебный регистр сведений.
  3. Настройка простого RLS: В самом тексте ограничения доступа на уровне записей мы настраиваем элементарное левое соединение со служебным регистром прав. Запрос получается плоским, без использования операторов В (ВЫБРАТЬ...), без группировок и агрегатных функций.

В типовых конфигурациях на базе Библиотеки стандартных подсистем (БСП) для этого используются стандартные шаблоны ограничения доступа, например #ПоЗначениям(). Применение так называемого «Производительного RLS» позволяет системе выполнять проверки прав максимально быстро, не перегружая СУБД вычислениями в реальном времени.

Итоги

Проанализировав ситуацию, мы пришли к выводу, что применение RLS к табличной части с динамическим вычислением условий напрямую в 1С невозможно из-за ограничений синтаксиса платформы. Единственный верный и масштабируемый путь — это вычисление доступности "на лету" при записи объекта и сохранение разрешающих комбинаций в отдельный регистр. Это потребует дополнительного кода в обработчиках записи, но обеспечит стабильную и быструю работу базы данных при любом количестве пользователей и объеме справочника.

← На главную