Довольно часто перед разработчиками встает задача создания инструментов для консолидации данных из нескольких удаленных информационных баз. Разберем интересную ситуацию: у нас есть обработка, отправляющая запросы к удаленным базам через HTTP-сервисы. Текст запроса пишется вручную, но мы хотим упростить жизнь пользователям и дать им возможность использовать стандартный визуальный конструктор запросов, чтобы он показывал структуру удаленной базы. Выясним причину, почему это не работает "из коробки", и подробно проанализируем доступные пути решения этой архитектурной задачи.
Первое, что мы должны понимать — стандартный КонструкторЗапросов в платформе 1С:Предприятие имеет жесткую привязку к метаданным текущей информационной базы, то есть к объекту Метаданные. Платформа физически не позволяет программно передать в этот визуальный интерфейс "чужое" дерево метаданных из внешнего источника. Конструктор всегда будет показывать только те справочники, документы и регистры, которые существуют в конфигурации, где он был запущен.
Рассмотрим подробнее несколько практических подходов, которые помогут нам обойти это ограничение и реализовать удобную работу с запросами для внешних баз.
Если ваши базы имеют одинаковую структуру (например, это узлы РИБ или просто клоны одной конфигурации), мы можем воспользоваться самым простым и логичным путем. Нам не нужно пытаться загрузить метаданные из удаленного узла.
Посмотрим на алгоритм действий в этом случае:
Этот метод работает идеально, но только до тех пор, пока структуры баз идентичны. Если текущая конфигурация отличается от базы-источника, этот подход применять нельзя.
Проанализируем ситуацию, когда структуры баз отличаются. Как заставить конструктор увидеть чужие таблицы? Мы можем задействовать механизм Внешние источники данных.
Этот механизм позволяет подключаться к сторонним базам данных (в том числе к другим базам 1С) на уровне SQL-запросов через ODBC или ADO. Разберем по шагам:
Теперь мы можем визуально собирать запрос. Текст запроса будет валиден для текущей базы. Важно: в этом случае данные извлекаются напрямую из SQL, в обход HTTP-сервиса удаленной базы 1С. Если обязательным требованием является использование именно HTTP-сервисов, перейдем к следующему варианту.
Если мы хотим остаться в рамках HTTP-взаимодействия и не имеем доступа к прямому SQL-соединению, нам потребуется реализовать свой собственный мини-конструктор. Начиная с версии платформы 8.3.5, у нас появился мощнейший объект СхемаЗапроса.
Разберем, как это реализовать:
Метаданные.Справочники, Метаданные.Документы и их реквизиты) и возвращает эту структуру в формате JSON.ДеревоЗначений. Это будет визуальная замена стандартному дереву таблиц конструктора.СхемаЗапроса формируем текст запроса.Посмотрим на пример того, как программно добавить поле в выборку через схему:
Схема = Новый СхемаЗапроса;
Пакет = Схема.ПакетЗапросов[0];
Оператор = Пакет.Операторы[0];
// Добавляем таблицу источника
Источник = Оператор.Источники.Добавить("Справочник.Номенклатура", "Номенклатура");
// Добавляем поля
Оператор.ВыбираемыеПоля.Добавить("Номенклатура.Ссылка");
Оператор.ВыбираемыеПоля.Добавить("Номенклатура.Наименование");
ТекстСгенерированногоЗапроса = Схема.ПолучитьТекстЗапроса();
После получения текста ТекстСгенерированногоЗапроса, мы отправляем его на выполнение через HTTP-сервис в удаленную базу.
Проанализируем крайне важный архитектурный аспект, о котором часто забывают. Выполнение произвольного текста запроса, пришедшего извне (через HTTP) — это огромная дыра в безопасности. Это классическая уязвимость.
Риски передачи "сырого" текста запроса:
Как сделать правильно?
Вместо передачи сырого текста запроса, рекомендуется передавать структурированные параметры фильтрации (например, структуру с именами полей и значениями отборов). На стороне базы-приемника (в модуле HTTP-сервиса) должен быть жестко запрограммированный безопасный запрос, в который просто подставляются пришедшие параметры. Если же требуется именно произвольная выборка, необходимо реализовать жесткий парсинг входящего текста запроса или использовать объект СхемаЗапроса на стороне сервера для валидации выбранных таблиц и полей перед выполнением.
Мы подробно рассмотрели проблему работы с Конструктором запросов для удаленных баз. Как мы выяснили, платформа не позволяет "подсунуть" чужие метаданные в стандартное окно конструктора. Однако мы можем элегантно обойти это ограничение: либо используя идентичную конфигурацию для генерации текста, либо подключая таблицы через Внешние источники данных, либо создавая собственный интерфейс выбора полей с программной сборкой текста с помощью объекта СхемаЗапроса. Главное при реализации обмена через HTTP — всегда помнить о безопасности и не допускать бесконтрольного выполнения произвольного кода на стороне сервера-приемника.