Разработка и поддержка сложных систем на платформе 1С часто сопряжена с необходимостью разбирать «тяжелое наследство» в виде запутанного программного кода. Одной из самых трудозатратных задач является анализ «узловых» запросов. Это объемные пакетные запросы с десятками временных таблиц, множеством соединений и динамически формируемыми параметрами. Читать такой код «с листа» в конфигураторе крайне сложно, особенно если он лишен комментариев.
В этой статье мы подробно разберем, как упростить жизнь разработчику и реализовать механизм передачи объекта Запрос непосредственно из точки остановки отладчика в консоль запросов. Это позволит нам получить полную раскладку: текст запроса, все установленные параметры и, что немаловажно, содержимое временных таблиц.
Прежде чем приступать к написанию собственного велосипеда, проанализируем существующие мощные решения, которые уже де-факто стали стандартом в сообществе 1С-программистов. Рассмотрим наиболее популярные инструменты.
Инструменты разработчика (ИР) Сергея Старых. Это один из самых продвинутых комплексов. Его консоль запросов обладает уникальной функцией «Снять снимок запроса». Когда мы находимся в режиме отладки на строке с объектом Запрос, мы можем вызвать специальный метод через табло отладчика. Консоль автоматически подхватывает контекст:
МенеджерВременныхТаблиц.Управляемая консоль запросов Евгения Люлюка. Еще одно крайне эффективное решение. Программа позволяет получить объект Запрос со всеми «вкусностями» прямо из отладки. Она умеет восстанавливать состояние запроса в удобном интерфейсе, что позволяет «крутить» его, менять условия и мгновенно видеть результат, не перезапуская сеанс отладки.
Если по каким-то причинам использование сторонних расширений невозможно, разберем, как реализовать подобный функционал самостоятельно. Идея заключается в двухэтапном процессе: сохранение данных в файл и их последующее чтение в консоли.
Шаг 1. Экспорт данных в общем модуле. Создадим в конфигурации общий серверный модуль (например, РаботаСОтладкой) с экспортной функцией. Проанализируем пример кода, который сериализует основные свойства запроса:
Процедура СохранитьЗапросДляКонсоли(ТекущийЗапрос) Экспорт
ДанныеЗапроса = Новый Структура;
ДанныеЗапроса.Вставить("Текст", ТекущийЗапрос.Текст);
ПараметрыСтруктура = Новый Структура;
Для Каждого Параметр Из ТекущийЗапрос.Параметры Цикл
ПараметрыСтруктура.Вставить(Параметр.Ключ, Параметр.Значение);
КонецЦикла;
ДанныеЗапроса.Вставить("Параметры", ПараметрыСтруктура);
// Используем ЗначениеВФайл для сохранения структуры на диск
ПутьКФайлу = "C:\Temp\QueryData.dat";
ЗначениеВФайл(ПутьКФайлу, ДанныеЗапроса);
Сообщить("Данные запроса сохранены в: " + ПутьКФайлу);
КонецПроцедуры
Шаг 2. Загрузка в консоли. В самой консоли запросов (которую мы можем доработать или создать как внешнюю обработку) добавим команду загрузки. Проанализируем алгоритм:
ЗначениеИзФайла.Одной из главных сложностей является передача состояния временных таблиц. Временные таблицы «живут» внутри объекта МенеджерВременныхТаблиц. Чтобы проанализировать запрос, который опирается на созданные ранее в коде таблицы, консоль должна уметь восстанавливать этот контекст. Профессиональные инструменты делают это путем копирования данных из таблиц менеджера в новые временные таблицы уже внутри сеанса консоли. Рассмотрим, как это работает: инструмент перехватывает менеджер, выгружает содержимое каждой таблицы в ТаблицаЗначений и при запуске в консоли сначала создает эти таблицы заново (командами ВЫБРАТЬ ... ПОМЕСТИТЬ).
Выясним, как автоматизировать этот процесс, чтобы не вызывать функции вручную. Современная платформа позволяет использовать механизм расширений. Мы можем создать расширение, которое «вклинивается» (используя аннотацию &После) в типовые методы выполнения запросов.
Проанализируем преимущества такого подхода:
Посмотрим на ситуацию шире. Когда запрос содержит десятки соединений, даже в консоли его бывает трудно понять. Продвинутые консоли предоставляют функционал визуализации графа запроса. Проанализировав такой граф, мы можем визуально увидеть, какие таблицы являются ключевыми («узловыми»), а какие — вспомогательными, и по каким полям они связаны.
Еще одна полезная функция — генерация обратного кода. Если вы в консоли оптимизировали запрос или исправили в нем ошибку, профессиональная консоль позволит вам одним нажатием кнопки сгенерировать готовый фрагмент кода на языке 1С. Рассмотрим пример такого генерируемого кода:
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ * ИЗ Справочник.Номенклатура ГДЕ Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ВыбраннаяСсылка);
РезультатЗапроса = Запрос.Выполнить();
Вам останется только скопировать этот блок и вставить его в конфигуратор на место старого кода.
При ручном сохранении параметров мы часто сталкиваемся с проблемой типов, которые нельзя просто так сохранить в XML или JSON (например, ссылки на удаленные объекты, уникальные идентификаторы или специфические системные перечисления). В таких случаях рекомендуется использовать методы ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр. Это гарантирует стопроцентное восстановление параметров при загрузке в консоль, так как сохраняется внутреннее представление объекта платформой.
Для «узловых» запросов критически важна производительность. Некоторые консоли позволяют, не выходя из интерфейса 1С, получить План выполнения запроса со стороны SQL-сервера. Проанализируем этот план: он покажет, используются ли индексы, происходит ли сканирование всей таблицы (Table Scan) или поиск по индексу (Index Seek). Это позволяет выявить причины тормозов в коде, которые не очевидны при простом чтении текста запроса.
Подводя итог, можно сказать, что для эффективного разбора чужого кода программисту 1С необходимо иметь в арсенале настроенную консоль запросов с возможностью импорта контекста отладки. Будь то мощный внешний инструмент или самописная процедура сериализации — это в разы ускоряет диагностику и оптимизацию сложных аналитических механизмов системы.