Как правильно использовать ключевое слово РАЗРЕШЕННЫЕ в сложных запросах 1С с объединениями?

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

При разработке сложных отчетов или выборок данных в системе 1С:Предприятие программисты часто сталкиваются с необходимостью объединения данных из различных таблиц (например, нескольких видов документов или справочников). Если в системе настроены ограничения прав доступа на уровне записей (RLS), использование ключевого слова РАЗРЕШЕННЫЕ становится обязательным. Однако попытка добавить это слово во все части объединения приводит к ошибке: «Ключевое слово РАЗРЕШЕННЫЕ доступно только у первого запроса». В этой статье мы подробно разберем, как правильно структурировать запрос, чтобы избежать этой ошибки и обеспечить корректную работу механизмов безопасности.

Разбор синтаксической ошибки и правила платформы

Прежде всего, проанализируем, почему возникает эта ошибка. Платформа 1С:Предприятие проектировалась таким образом, что директива управления доступом РАЗРЕШЕННЫЕ является глобальной для всего текста запроса (или одного запроса в пакете). Она сообщает оптимизатору запросов, что при генерации SQL-кода необходимо добавить условия, ограничивающие выборку в соответствии с настройками RLS текущего пользователя.

Рассмотрим основные правила синтаксиса:

Решение проблемы при использовании ОБЪЕДИНИТЬ ВСЕ

Если нам необходимо собрать данные из разных таблиц (например, Документ.ПоступлениеТоваровУслуг и Документ.РеализацияТоваровУслуг), мы должны указать РАЗРЕШЕННЫЕ только в самом первом операторе. Платформа автоматически распространит это ограничение на все последующие таблицы в объединении.

Посмотрим на пример правильного динамического формирования текста запроса:


// Формируем текст запроса динамически для разных типов документов
ТекстЗапроса = "";
Для Каждого КлючИЗначение Из СписокТиповДокументов Цикл
    Если ТекстЗапроса = "" Тогда
        // Только в первом ВЫБРАТЬ указываем РАЗРЕШЕННЫЕ
        ТекстЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ ";
    Иначе
        ТекстЗапроса = ТекстЗапроса + "ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ";
    КонецЕсли;
    
    ТекстЗапроса = ТекстЗапроса + "Ссылка, Дата, Номер ИЗ Документ." + КлючИЗначение.Ключ;
КонецЦикла;

В данном случае, даже если у пользователя есть доступ только к части документов «Поступление», а к «Реализации» доступа нет вовсе (в рамках RLS), запрос отработает без критической ошибки, просто исключив недоступные записи.

Использование вложенных запросов как способ обхода ограничений

Иногда логика запроса требует сложной обработки данных уже после их объединения. В таких случаях мы можем использовать вложенный запрос. Рассмотрим ситуацию: нам нужно объединить данные, а затем упорядочить их или сгруппировать. Мы можем применить РАЗРЕШЕННЫЕ к «внешнему» запросу, который обращается к результату объединения.

Проанализируем пример структуры такого запроса:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ПодчиненныеДокументы.Дата КАК Дата,
    ПодчиненныеДокументы.Ссылка КАК Ссылка
ИЗ (
    ВЫБРАТЬ
        Дата, Ссылка
    ИЗ
        Документ.ПоступлениеТоваровУслуг
    ГДЕ
        Ссылка В (&СписокСсылок)
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Дата, Ссылка
    ИЗ
        Документ.РеализацияТоваровУслуг
    ГДЕ
        Ссылка В (&СписокСсылок)
) КАК ПодчиненныеДокументы
УПОРЯДОЧИТЬ ПО
    Дата

Важно понимать: хотя внутри вложенного запроса слово РАЗРЕШЕННЫЕ отсутствует, оно указано в корневом операторе ВЫБРАТЬ. Платформа распознает это и применит фильтры RLS ко всем базовым таблицам, участвующим во вложенной выборке.

Различия между правами на метаданные и RLS

Выясним важную причину, по которой РАЗРЕШЕННЫЕ может не спасать от ошибки доступа. Необходимо строго различать два вида ограничений:

  1. Права на объект (Метаданные): Если в роли пользователя снята галочка «Чтение» на объект Документ.РеализацияТоваровУслуг, то никакое использование слова РАЗРЕШЕННЫЕ не поможет. Запрос упадет с ошибкой «Нарушение прав доступа».
  2. Ограничение на уровне записей (RLS): Если право на «Чтение» есть, но установлено условие (например, «ГДЕ Организация = &ТекущаяОрганизация»), то РАЗРЕШЕННЫЕ просто отфильтрует те записи, которые не подходят под условие, не прерывая выполнение кода.

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

Применение временных таблиц для оптимизации

Разберем еще один продвинутый подход — использование временных таблиц (ВТ). Это особенно полезно в пакетных запросах, когда данные из объединения используются несколько раз в разных частях алгоритма. Посмотрим, как это реализовать:


// Пакет запросов: первый запрос помещает данные в ВТ
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    Ссылка, Дата
ПОМЕСТИТЬ ВТ_Данные
ИЗ
    Документ.ПоступлениеТоваровУслуг
ГДЕ
    Ссылка В (&МассивСсылок);

// Второй запрос в пакете использует уже отфильтрованные данные
ВЫБРАТЬ
    ВТ.Ссылка,
    ВТ.Дата
ИЗ
    ВТ_Данные КАК ВТ

При использовании временных таблиц хорошим тоном считается указывать РАЗРЕШЕННЫЕ именно в том запросе, который осуществляет выборку из физической таблицы базы данных. В последующих запросах пакета, выбирающих данные из ВТ_Данные, писать это слово не обязательно, так как в таблицу попали только те записи, которые уже прошли проверку прав.

Программное формирование через Схему запроса

Для тех, кто занимается разработкой сложных универсальных механизмов, наиболее надежным способом будет использование объекта СхемаЗапроса. Этот объект позволяет манипулировать структурой запроса на уровне объектов метаданных, а не текста. У объекта ЗапросСхемы есть свойство ВыбиратьРазрешенные.

Рассмотрим, как это работает программно:


Схема = Новый СхемаЗапроса;
Пакет = Схема.ПакетЗапросов[0]; // Первый запрос в пакете
Пакет.ВыбиратьРазрешенные = Истина; // Устанавливаем флаг RLS

// Добавляем источники и выбираемые поля
Оператор = Пакет.Операторы[0];
Источник = Оператор.Источники.Добавить("Документ.ПоступлениеТоваровУслуг", "Поступление");
Оператор.ВыбираемыеПоля.Добавить("Ссылка", 0);

// Получаем итоговый текст запроса
Текст = Схема.ПолучитьТекстЗапроса();

Использование СхемаЗапроса гарантирует, что платформа сама расставит ключевые слова в нужных местах в соответствии с актуальными правилами синтаксиса текущей версии платформы.

Влияние на производительность и достоверность данных

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

Также помните о «молчаливом» искажении итогов. Если вы строите отчет по остаткам или взаиморасчетам и используете РАЗРЕШЕННЫЕ, пользователь увидит только те цифры, к которым у него есть доступ. Это может привести к тому, что общие итоги по компании не сойдутся, и пользователь может не догадаться, что часть данных была скрыта механизмом RLS. В критически важных финансовых отчетах методически правильнее либо выполнять запрос под полными правами (в привилегированном модуле), либо явно информировать пользователя о том, что данные ограничены его правами доступа.

← На главную