Функция просмотра временных таблиц запроса в отладчике

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

Для просмотра временных таблиц запроса в отладчике удобно использовать специальную функцию. Данная функция парсит текст запроса, вычленяет все временные таблицы, вычисляет их и результат складывает в структуру.

 

 

Как уже было сказано, данная функция парсит текст запроса, вычленяет все временные таблицы, вычисляет их и результат складывает в структуру.

Для удобства использования удобно поместить процедуру в один из глобальных модулей конфигурации.

funkciya-prosmotra-vremennyx-tablic-zaprosa-v-otladchike_03

funkciya-prosmotra-vremennyx-tablic-zaprosa-v-otladchike_04

Функция предназначена для использования в окне «Вычислить выражение» отладчика — возвращает значение, удобное для просмотра в этом окне. Функция максимально автоматизирована и может работать с входными данными разных типов. Назначение аргументов функции понятно из их имён.

funkciya-prosmotra-vremennyx-tablic-zaprosa-v-otladchike_01

По кнопке «Показать значения в отдельном окне (F2)» можно просмотреть сами таблицы:

funkciya-prosmotra-vremennyx-tablic-zaprosa-v-otladchike_02

Текст процедур:

////////////////////////////////////////////////////////////
// Глобальные процедуры и функции, выполняемые на сервере

#Область ОтладкаВременныхТаблиц

//***********************************************************
// Функция показывает все поля всех временных таблиц из менеджера временных таблиц или из самого запроса.
// Используется для просмотра временных таблиц в отладчике.
// Запрос - запрос (для вычленения текста запроса) или менеджер временных таблиц (имена временных таблиц в этом случае надо передавать явно)
// ИменаВТ - строка с именами интересующих временных таблиц (обязательный параметр при передаче менеджера ВТ вместо запроса в первом параметре)
// Пример вызова функции:
//      ПросмотрВременныхТаблиц(Запрос, "")
Функция ВТ(ЗапросИлиМенеджер, ИменаВТ="") Экспорт

    // предварительная обработка параметров:

    Если ТипЗнч(ЗапросИлиМенеджер) = Тип("МенеджерВременныхТаблиц") Тогда
        Если ИменаВТ = "" Тогда
            Возврат "Укажите имена временных таблиц через запятую";
        Иначе
            Запрос = новый Запрос;
            Запрос.МенеджерВременныхТаблиц = ЗапросИлиМенеджер;
        КонецЕсли;
    Иначе
        Запрос = ЗапросИлиМенеджер;
    КонецЕсли;

    ТекстЗапроса = ВРег(Запрос.Текст);
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, Символы.Таб, " ");
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, Символы.ВТаб, " ");
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, Символы.НПП, " ");
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ")", ") ");
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "(", " (");

    ОчищенныйТекстЗапроса = "";
    Для НомерСтроки = 1 По СтрЧислоСтрок(ТекстЗапроса) Цикл
        ОчереднаяСтрока = СтрПолучитьСтроку(ТекстЗапроса, НомерСтроки);
        ПозицияКомментария = Найти(ОчереднаяСтрока, "//");
        Если ПозицияКомментария > 0 Тогда
            ОчереднаяСтрока = Лев(ОчереднаяСтрока,ПозицияКомментария-1);
        КонецЕсли;
        ОчищенныйТекстЗапроса = ОчищенныйТекстЗапроса + " " + ОчереднаяСтрока;
    КонецЦикла;
    ТекстЗапроса = ОчищенныйТекстЗапроса;

    // парсинг текста запроса и получение из него имен временных таблиц

    ВременныеТаблицыЗапроса = новый Массив;

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

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

    стрВременныеТаблицы = НайтиИменаТаблицПоРасположениюСлов(ТекстЗапроса, "ИЗ", "КАК");
    Для Каждого КлючЗначение Из стрВременныеТаблицы Цикл
        ВременныеТаблицыЗапроса.Добавить(КлючЗначение.Ключ);
    КонецЦикла;

    стрВременныеТаблицы = НайтиИменаТаблицПоРасположениюСлов(ТекстЗапроса, "СОЕДИНЕНИЕ", "КАК");
    Для Каждого КлючЗначение Из стрВременныеТаблицы Цикл
        ВременныеТаблицыЗапроса.Добавить(КлючЗначение.Ключ);
    КонецЦикла;

    УничтожаемыеВременныеТаблицы = НайтиИменаТаблицПоРасположениюСлов(ТекстЗапроса, "УНИЧТОЖИТЬ");
    Для Каждого КлючЗначение Из УничтожаемыеВременныеТаблицы Цикл
        ВременныеТаблицыЗапроса.Добавить(КлючЗначение.Ключ);
    КонецЦикла;

    Ответ = новый Структура;

    Если Запрос.МенеджерВременныхТаблиц = Неопределено тогда

        // на случай, если ВТ удаляются в тексте запроса, сложнейший алгоритм предварительно скопирует их
        Смещение =0;
        Если УничтожаемыеВременныеТаблицы.Количество() >0 Тогда
            Для Каждого КлючИЗначение Из УничтожаемыеВременныеТаблицы Цикл
                ПозицияУничтожения = КлючИЗначение.Значение + Смещение;
                ИмяВТ = КлючИЗначение.Ключ ;
                НовыйПодзапросКопирования   = "ВЫБРАТЬ * ПОМЕСТИТЬ КОПИЯ"+ИмяВТ+" ИЗ "+ИмяВТ+";";
                ТекстЗапроса = ЛЕВ(ТекстЗапроса, ПозицияУничтожения-1) + НовыйПодзапросКопирования + Прав(ТекстЗапроса, СтрДлина(ТекстЗапроса)-(ПозицияУничтожения-1));
                Смещение = Смещение + НовыйПодзапросКопирования;
            КонецЦикла;
        КонецЕсли;

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

        ЗапросТМП.Текст = ТекстЗапроса;
        ЗапросТМП.Выполнить();

        ЗаполнитьТаблицыПоСпискуИмен(Ответ, ВременныеТаблицыЗапроса, ЗапросТМП.МенеджерВременныхТаблиц);

        ЗапросТМП.МенеджерВременныхТаблиц.Закрыть();

    Иначе
        // это надо запускать после выполнения запроса, чтобы временные таблицы уже были созданы

        ОтсутствующиеИменаТаблиц = ЗаполнитьТаблицыПоСпискуИмен(Ответ, ВременныеТаблицыЗапроса, Запрос.МенеджерВременныхТаблиц);

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

    КонецЕсли;

    Возврат Ответ;

КонецФункции

//***********************************************************
Функция ЗаполнитьТаблицыПоСпискуИмен(СтруктураОтвета, МассивИменТаблиц, Менеджер)

    ОтсутствующиеИменаТаблиц = Новый Массив;

    ЗапросТМП = новый запрос;
    ЗапросТМП.МенеджерВременныхТаблиц = Менеджер;

    Для Каждого ИмяТаблицы Из МассивИменТаблиц Цикл
        Если НЕ СтруктураОтвета.Свойство(ИмяТаблицы) Тогда
            ЗапросТМП.Текст = "ВЫБРАТЬ * ИЗ "+ИмяТаблицы+" КАК "+ИмяТаблицы;
            Попытка
                СтруктураОтвета.Вставить(ИмяТаблицы, ЗапросТМП.Выполнить().Выгрузить());
            Исключение
                СтруктураОтвета.Вставить(ИмяТаблицы, ОписаниеОшибки());
                ОтсутствующиеИменаТаблиц.Добавить(ИмяТаблицы);
            КонецПопытки;
        КонецЕсли;
    КонецЦикла;

    Возврат ОтсутствующиеИменаТаблиц;

КонецФункции 

//***********************************************************
Функция НайтиИменаТаблицПоРасположениюСлов(Знач Текст, ПервоеИскомоеСлово, ВтороеИскомоеСлово="")

    СписокИгнорируемыхСимволов = новый СписокЗначений;
    СписокИгнорируемыхСимволов.Добавить(Символы.ПС);
    СписокИгнорируемыхСимволов.Добавить(Символы.ВК);
    СписокИгнорируемыхСимволов.Добавить(Символы.НПП);
    СписокИгнорируемыхСимволов.Добавить(Символы.Таб);
    СписокИгнорируемыхСимволов.Добавить(" ");

    СписокРазделителей = новый СписокЗначений;
    СписокРазделителей.Добавить("(");
    СписокРазделителей.Добавить(")");
    СписокРазделителей.Добавить(".");
    СписокРазделителей.Добавить(",");
    СписокРазделителей.Добавить(";");
    СписокРазделителей.Добавить("&");

    НайденныеИмена = Новый Структура;
    ПервоеИскомоеСлово = ВРег(ПервоеИскомоеСлово);
    ВтороеИскомоеСлово = ВРег(ВтороеИскомоеСлово);

    Пока Истина Цикл
        Найдено = найти(Текст, " " + ВРег(ПервоеИскомоеСлово) + " ");
        Длина = СтрДлина(Текст);
        Если Найдено > 0 тогда
            Текст = СОКРЛП(Прав(Текст, Длина-Найдено-СтрДлина(ПервоеИскомоеСлово)-1));
            СтрДлина = СтрДлина(Текст);
            СоставляемоеСлово = "";
            НайденноеСлово = "";
            Для ном = 1 по СтрДлина цикл
                ОчереднойСимвол = Сред(Текст, ном, 1) ;
                Если не СписокРазделителей.НайтиПоЗначению(ОчереднойСимвол) = Неопределено тогда
                    СоставляемоеСлово = "";
                    НайденноеСлово = "";
                    Прервать;
                ИначеЕсли не СписокИгнорируемыхСимволов.НайтиПоЗначению(ОчереднойСимвол) = Неопределено тогда
                    Если СоставляемоеСлово = "" Тогда
                        Продолжить;
                    Иначе
                        Если НайденноеСлово = "" Тогда
                            НайденноеСлово = СоставляемоеСлово;
                            СоставляемоеСлово = "";
                            Если ВтороеИскомоеСлово="" Тогда
                                Прервать;
                            КонецЕсли;
                        Иначе
                            Если не СоставляемоеСлово = ВтороеИскомоеСлово Тогда
                                НайденноеСлово = "";
                            КонецЕсли;
                            Прервать;
                        КонецЕсли;
                    КонецЕсли;
                иначе
                    СоставляемоеСлово = СоставляемоеСлово + ОчереднойСимвол;
                КонецЕсли;
            КонецЦикла;
            Если НЕ НайденноеСлово = "" Тогда
                НайденныеИмена.Вставить(НайденноеСлово, Найдено);
            КонецЕсли;
        иначе
            Прервать;
        КонецЕсли;
    КонецЦикла;

    Возврат НайденныеИмена;

КонецФункции 

#КонецОбласти
Помогла ли вам данная статья?
Да, спасибо, все получилось.
Немного помогла.
Совсем не помогла.
Не то, что я искал(а).
Смотреть результаты
Запись опубликована в рубрике Разработка в 1С с метками . Добавьте в закладки постоянную ссылку.


4 Responses to Функция просмотра временных таблиц запроса в отладчике

  1. Иван говорит:

    Добрый день.
    Хорошая функция.

    Нужно только подправить:

    Смещение = ПозицияУничтожения+СтрДлина(» УНИЧТОЖИТЬ»)+СтрДлина(НовыйПодзапросКопирования);

  2. Иван говорит:

    И еще вот здесь

    УничтожаемыеВременныеТаблицы = НайтиИменаТаблицПоРасположениюСлов(ТекстЗапроса, «УНИЧТОЖИТЬ»);
    Для Каждого КлючЗначение Из УничтожаемыеВременныеТаблицы Цикл
    ВременныеТаблицыЗапроса.Добавить(«КОПИЯ»+КлючЗначение.Ключ);
    КонецЦикла;

  3. Иван говорит:

    И еще вот так доработать.

    Если ТипЗнч(ЗапросИлиМенеджер) = Тип(«МенеджерВременныхТаблиц») Тогда
    Если ИменаВТ = «» Тогда
    Для СчетВТ = 0 По ЗапросИлиМенеджер.Таблицы.Количество()-1 Цикл
    Если ИменаВТ = «» Тогда
    ИменаВТ = ЗапросИлиМенеджер.Таблицы[СчетВТ].ПолноеИмя;
    Иначе
    ИменаВТ = ИменаВТ+»,»+ЗапросИлиМенеджер.Таблицы[СчетВТ].ПолноеИмя;
    КонецЕсли;
    КонецЦикла;
    Если ИменаВТ = «» Тогда
    Возврат «Укажите имена временных таблиц через запятую»;
    Иначе
    Запрос = новый Запрос;
    Запрос.МенеджерВременныхТаблиц = ЗапросИлиМенеджер;
    КонецЕсли;
    Иначе
    Запрос = новый Запрос;
    Запрос.МенеджерВременныхТаблиц = ЗапросИлиМенеджер;
    КонецЕсли;
    Иначе
    Запрос = ЗапросИлиМенеджер;
    КонецЕсли;

  4. oleksandrhomyak@gmail.com говорит:

Добавить комментарий для Иван Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *