18.11.2009

Зависимость результата ограничений доступа к данным от плана запроса СУБД

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

Условия возникновения проблемы

Проблема возможной зависимости результата ограничений доступа к данным от плана запроса СУБД может возникнуть при выполнении запроса к базе данных без ключевого слова РАЗРЕШЕННЫЕ, если для текущего пользователя имеются ограничения доступа к данным, и при этом запрос содержит одно или несколько сравнений вида:

Если в этом случае <Вложенный запрос> использует таблицы базы данных, на которые наложены ограничения доступа, то возможно, что на одних СУБД запрос будет выполняться успешно, а на других будет выдаваться сообщение У пользователя недостаточно прав на исполнение операции над базой данных при условии полной идентичности данных в информационных базах.

Причина различий

Возможная разница в поведении объясняется реализацией ограничений доступа к данным без ключевого слова РАЗРЕШЕННЫЕ в 1С:Предприятии.

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

Такое же сигнальное поле добавляется и к результатам запросов, вложенных в сравнение В/НЕ В. Причем проверка значения сигнальной колонки в этом случае выполняется средствами СУБД. Таким образом, если в процессе выполнения вложенного запроса происходило обращение к запрещенным данным, то выполнение запроса должно завершиться с ошибкой У пользователя недостаточно прав на исполнение операции над базой данных.

Однако, при построении плана запроса СУБД может не получать полную выборку <Вложенным запросом>, а получать только те записи, которые фактически необходимы для проверки условия В/НЕ В. В этом случае выполнение запроса может оказаться успешным даже если при выполнении <Вложенного запроса>, как самостоятельного запроса, могли бы произойти обращения к запрещенным данным.

Пример и рекомендации

Рассмотрим простой пример. Пусть на таблицу Справочник.ФизическиеЛица наложены ограничения доступа к данным. В этом случае запрос:

Копировать в буфер обмена
ВЫБРАТЬ
    Таблица.ФизЛицо КАК ФизЛица
ИЗ
    Справочник.ФизическиеЛица КАК Таблица

будет выполнен с ошибкой из-за попытки обращения к запрещенным данным. Если же этот запрос участвует в сравнении, например:

Копировать в буфер обмена
ВЫБРАТЬ
    ДоговорНаВыполнениеРаботСФизЛицом.Сотрудник.Физлицо
ИЗ
    Документ.ДоговорНаВыполнениеРаботСФизЛицом КАК ДоговорНаВыполнениеРаботСФизЛицом
ГДЕ
    ДоговорНаВыполнениеРаботСФизЛицом.Сотрудник.Физлицо В (
        ВЫБРАТЬ
            Таблица.ФизЛицо КАК ФизЛица
        ИЗ
            Справочник.ФизическиеЛица КАК Таблица)

то в зависимости от выбранного СУБД плана запроса запрос может быть выполнен как успешно, так и с ошибкой. Такое поведение запроса не является ошибочным, поскольку обращение к запрещенным данным в процессе выполнения этого запроса может произойти, а может и не произойти. Для получения более предсказуемого результата необходимо построить запрос таким образом, чтобы вложенный запрос гарантированно не выполнял обращений к заведомо ненужным данным. В частности, если предыдущий запрос переписать так:

Копировать в буфер обмена
ВЫБРАТЬ
    ДоговорНаВыполнениеРаботСФизЛицом.Сотрудник.Физлицо
ИЗ
    Документ.ДоговорНаВыполнениеРаботСФизЛицом КАК ДоговорНаВыполнениеРаботСФизЛицом
ГДЕ
    ДоговорНаВыполнениеРаботСФизЛицом.Сотрудник.Физлицо В (
        ВЫБРАТЬ
            Таблица.ФизЛицо КАК ФизЛица
        ИЗ
            Справочник.ФизическиеЛица КАК Таблица
        ГДЕ
            Таблица.ФизЛицо = ДоговорНаВыполнениеРаботСФизЛицом.Сотрудник.Физлицо)

Данный запрос отличается от предыдущего тем, что вложенный запрос не выбирает записей, которые заведомо не требуются для выполнения сравнения В. Поэтому он завершится успешно, если ДоговорНаВыполнениеРаботСФизЛицом.Сотрудник.Физлицо ссылается только на разрешенные записи таблицы Справочник.ФизическиеЛица, и аварийно, если среди ДоговорНаВыполнениеРаботСФизЛицом.Сотрудник.Физлицо имеются ссылки на запрещенные записи.