Как программно получить реальный текст запроса и параметры из СКД в 1С

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

Разработчики при работе с Системой компоновки данных (СКД) часто сталкиваются с задачей получить тот самый финальный текст запроса, который платформа 1С отправляет в СУБД. Напрямую вытащить его из схемы компоновки данных не получится, так как СКД динамически модифицирует исходный запрос в зависимости от настроек пользователя, установленных отборов, выбранных полей и параметров.

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

Почему запрос в схеме СКД отличается от выполняемого в СУБД?

Когда мы пишем запрос в конструкторе макета СКД, мы проектируем лишь "шаблон". В момент формирования отчета СКД выполняет колоссальную работу по оптимизации этого шаблона:

  1. Внедрение отборов. Пользовательские отборы и параметры динамически интегрируются прямо в условия ГДЕ, в параметры виртуальных таблиц или во временные таблицы.
  2. Оптимизация состава полей. Из секции ВЫБРАТЬ удаляются все поля, которые не были выбраны пользователем в настройках компоновки и не участвуют в группировках или расчетах ресурсов. Это позволяет существенно снизить нагрузку на базу данных.
  3. Генерация параметров. СКД автоматически заменяет понятные имена параметров (например, &Номенклатура) на внутренние идентификаторы (например, &П1, &П2 и так далее).
  4. Объединение наборов данных. Если в схеме используется несколько наборов данных, связанных между собой, СКД выполняет их последовательно, используя результаты предыдущих запросов в качестве параметров для последующих.

Попытка взять "сырой" запрос из структуры СхемаКомпоновкиДанных.НаборыДанных.ИмяНабора.Запрос приведет к тому, что вы получите исходный неоптимизированный текст без учета пользовательских отборов. Выполнение такого запроса вручную может вызвать зависание системы из-за попытки прочитать миллионы лишних записей.

Шаг 1. Перехват компоновки в модуле отчета

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

Рассмотрим структуру этой процедуры:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Отключаем стандартный вывод, если планируем выводить отчет полностью программно
    // СтандартнаяОбработка = Ложь;
    
КонецПроцедуры

Шаг 2. Получение реального текста запроса через Компоновщик макета

Чтобы заставить СКД сгенерировать итоговый текст запроса с учетом всех фильтров, нам необходимо задействовать объект КомпоновщикМакетаКомпоновкиДанных. Именно он транслирует схему компоновки и пользовательские настройки в исполняемый макет.

Разберем по шагам код получения реального текста запроса:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

    // 1. Получаем настройки отчета с учетом настроек пользователя на форме
    НастройкиОтчета = КомпоновщикНастроек.ПолучитьНастройки();
    
    // 2. Инициализируем компоновщик макета компоновки
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    
    // 3. Формируем макет компоновки. На этом этапе СКД компилирует итоговые запросы
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкиОтчета, ДанныеРасшифровки);
    
    // 4. Обходим все наборы данных, сгенерированные в макете
    Для Каждого НаборДанных Из МакетКомпоновки.НаборыДанных Цикл
        
        // Нам интересны только наборы данных типа "Запрос"
        Если ТипЗнч(НаборДанных) = Тип("НаборДанныхЗапросМакетаКомпоновкиДанных") Тогда
            
            ИмяНабора = НаборДанных.Имя;
            РеальныйТекстЗапроса = НаборДанных.Запрос;
            
            // Теперь в переменной РеальныйТекстЗапроса находится оптимизированный текст запроса,
            // содержащий реальные конструкции ГДЕ и параметры виртуальных таблиц.
            ЗаписатьВЛогИлиВывестиВТабло(ИмяНабора, РеальныйТекстЗапроса);
            
        КонецЕсли;
        
    КонецЦикла;

КонецПроцедуры

Шаг 3. Извлечение реальных значений параметров запроса

Просто получить текст запроса недостаточно — его невозможно будет запустить без параметров, имена которых СКД изменила. Значения всех параметров также содержатся в сформированном макете компоновки.

Проанализируем ситуацию и напишем код, который перенесет параметры из макета СКД в стандартный объект Запрос:


// Создаем стандартный объект Запрос для последующего выполнения вручную
НовыйЗапрос = Новый Запрос;
НовыйЗапрос.Текст = РеальныйТекстЗапроса; // Используем текст, полученный на предыдущем шаге

// Заполняем параметры запроса из макета компоновки
Для Каждого Параметр Из МакетКомпоновки.ЗначенияПараметров Цикл
    
    // Некоторые параметры могут быть выражениями/формулами СКД, их необходимо вычислить
    Если ТипЗнч(Параметр.Значение) = Тип("ВыражениеКомпоновкиДанных") Тогда
        ЗначениеПараметра = Вычислить(Параметр.Значение);
    Иначе
        ЗначениеПараметра = Параметр.Значение;
    КонецЕсли;
    
    // Устанавливаем параметры в наш ручной запрос
    НовыйЗапрос.УстановитьПараметр(Параметр.Имя, ЗначениеПараметра);
    
КонецЦикла;

// Теперь этот запрос полностью готов к безопасному и быстрому выполнению!
РезультатЗапроса = НовыйЗапрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();

Особенности работы с несколькими наборами данных

Часто в отчетах используется связь нескольких наборов данных (например, Документы, ОсновнаяАналитика и ОборотнаяАналитика). Если они связаны на вкладке "Связи наборов данных" схемы СКД, то важно понимать следующее:

Какое решение применить? Если ваша цель — просто получить готовую таблицу со всеми связями, расчетами ресурсов и группировками, не нужно пытаться эмулировать запросы вручную. Позвольте СКД выполнить всю работу в памяти сервера и выгрузите результат в коллекцию значений.

Программный вывод СКД в Таблицу значений

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

Разберем по шагам, как программно запустить СКД и выгрузить результат в ТаблицаЗначений:


// 1. Инициализируем компоновщик макета и строим макет
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(
    СхемаКомпоновкиДанных, 
    КомпоновщикНастроек.ПолучитьНастройки(), 
    ДанныеРасшифровки
);

// 2. Инициализируем процессор компоновки данных, который соберет данные из всех наборов
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);

// 3. Создаем таблицу значений, в которую будет осуществлен вывод
ТаблицаРезультат = Новый ТаблицаЗначений;

// 4. Используем ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);

// 5. Выводим результат компоновки в таблицу значений
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

// Теперь в переменной ТаблицаРезультат содержатся полностью готовые и рассчитанные данные!

Полезные инструменты разработчика для отладки СКД

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

  1. Консоль компоновки данных (с диска ИТС). Позволяет открыть любую внешнюю схему компоновки (файл .erf) или выгруженную схему в формате XML, применить настройки пользователя и нажать кнопку "Анализ исполняемых запросов". Вы увидите точные тексты запросов для каждого набора данных.
  2. Инструменты разработчика (автор Tormozit). Мощнейший комплекс, содержащий функции перехвата СКД. Позволяет прямо во время выполнения любого отчета перехватить его схему со всеми временными таблицами, параметрами и открыть их во встроенной консоли запросов для детального анализа.
  3. Технологический журнал 1С (ТЖ). Настройка сбора событий DBMSSQL (для СУБД Microsoft SQL Server) или SDBL (внутренний язык СУБД 1С) позволит зафиксировать точные запросы, уходящие на уровень базы данных во время формирования вашего отчета.
← На главную