Для отладки запросов 1С вложенные запросы очень неудобны. Разработанный набор функций позволяет перенести вложенные запросы в пакеты. Результаты пакетов можно просматривать отдельно с помощью доработанных консолей запросов, которых множество.
Пример использования:
ТекстЗапросаНовый = ВынестиВложенныеТаблицы(ТекстЗапроса);
Пример того, что было:
ВЫБРАТЬ
ВложенныйЗапрос.Ссылка
ИЗ
(ВЫБРАТЬ
Банки.Ссылка КАК Ссылка
ИЗ
Справочник.Банки КАК Банки) КАК ВложенныйЗапрос
Стало:
ВЫБРАТЬ
Банки.Ссылка КАК Ссылка
ПОМЕСТИТЬ Банки
ИЗ
Справочник.Банки КАК Банки
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВложенныйЗапрос.Ссылка
ИЗ
Банки КАК ВложенныйЗапрос
Для примера использования встроил функции в типовую обработку КонсольОтчетов из 1С УПП 1.3, см. приложенный файл:
Также набор функций приложил в отдельном файле txt.
Или можно скачать здесь:
// --
// Функции редактирования запроса
// Функция выноса вложенных таблиц
Функция ВынестиВложенныеТаблицы(Знач ГлобальныйТекстЗапроса)
МассивПакетовЗапросов = Новый Массив;
// Получаем все подзапросы, разделенные ";"
МассивИсключенийСимоволов = Новый Массив;
МассивИсключенийСимоволов.Добавить("""");
ПакетыЗапросов = ПолучитьМассивСловРазделенныхСимволом(ГлобальныйТекстЗапроса, ";", , , МассивИсключенийСимоволов);
// --
// Из ПакетыЗапросов сформируем МассивПакетовЗапросов
// При формировании пакетов имена должны быть уникальны. Вложенные запросы могут иметь неуникальные наименования.
// Для этого ведём массив созданных пакетов, в случае неуникального наименования добавляем порядковый номер
МассивИменПакетов = Новый Массив;
// Заполним массив пакетов имена существующих пакетов
ГлобальныйТекстЗапросаПоискПакетов = ГлобальныйТекстЗапроса;
МассивСпециальныхСимволов = ПолучитьМассивСпециальныхСимволов();
Пока Истина Цикл
ПозицияПоместить = Найти(ГлобальныйТекстЗапросаПоискПакетов, "ПОМЕСТИТЬ ");
Если ПозицияПоместить = 0 Тогда
Прервать;
КонецЕсли;
НачальнаяПозиция = ПозицияПоместить + 10;
ИмяПакета = ПолучитьСлово(ГлобальныйТекстЗапросаПоискПакетов, НачальнаяПозиция, Ложь, Истина, МассивСпециальныхСимволов);
МассивИменПакетов.Добавить(ИмяПакета);
ГлобальныйТекстЗапросаПоискПакетов = Сред(ГлобальныйТекстЗапросаПоискПакетов, НачальнаяПозиция, СтрДлина(ГлобальныйТекстЗапросаПоискПакетов));
КонецЦикла;
ПозицияНачала = 1;
ПозицияОкончания = 0;
Для Каждого ПакетЗапроса Из ПакетыЗапросов Цикл
ПозицияОкончания = ПозицияНачала + СтрДлина(ПакетЗапроса);
СтруктураПодзапросовПакета = ПолучитьСтруктуруПодзапросов(ПакетЗапроса, ПозицияНачала, ГлобальныйТекстЗапроса, МассивИменПакетов);
МассивПакетовЗапросов.Добавить(Новый Структура("ТекстЗапроса, Подзапросы, ПозицияНачала, ПозицияОкончания", ПакетЗапроса, СтруктураПодзапросовПакета, ПозицияНачала, ПозицияОкончания));
ПозицияНачала = ПозицияОкончания + 1;
КонецЦикла;
// Из ПакетыЗапросов сформируем МассивПакетовЗапросов
// --
// Сформируем запрос из МассивПакетовЗапросов
ГлобальныйТекстЗапросаНовый = "";
Для Каждого ПакетЗапроса Из МассивПакетовЗапросов Цикл
МассивВырезок = Новый Массив;
ТекстПодзапросов = ПолучитьТекстПодзапросов(ГлобальныйТекстЗапроса, ПакетЗапроса.Подзапросы, МассивВырезок);
ГлобальныйТекстЗапросаНовый = ГлобальныйТекстЗапросаНовый + ?(ГлобальныйТекстЗапросаНовый = "" Или ТекстПодзапросов = "", "", ";") + ТекстПодзапросов;
ТекстПакета = ПолучитьВырезкуТекста(ГлобальныйТекстЗапроса, ПакетЗапроса.ПозицияНачала, ПакетЗапроса.ПозицияОкончания, МассивВырезок);
ГлобальныйТекстЗапросаНовый = ГлобальныйТекстЗапросаНовый + ?(ГлобальныйТекстЗапросаНовый = "" Или ТекстПакета = "", "", ";") + ТекстПакета;
КонецЦикла;
Возврат ГлобальныйТекстЗапросаНовый;
КонецФункции
// ПозицияВГлобальномТексте - позиция переданного текста в тексте глобального запроса
Функция ПолучитьСтруктуруПодзапросов(Знач ТекстПакетаЗапроса, Знач ПозицияВГлобальномТексте = 0, Знач ГлобальныйТекстЗапроса, МассивИменПакетов)
ТекстДлина = СтрДлина(ТекстПакетаЗапроса);
Структура = Новый Структура;
МассивСпециальныхСимволов = ПолучитьМассивСпециальныхСимволов();
МассивСпециальныхСимволовКромеСкобок = ПолучитьМассивСпециальныхСимволов("()");
// --
// Перебираем текст по символьно
Для НомерБуквы = 1 По ТекстДлина Цикл
// --
// Определяем, что это начало нового запроса
// В целях оптимизации не используем ПолучитьСлово, но могут быть ошибки, поэтому перепроверим через ПолучитьСлово ещё раз внизу
Если Сред(ТекстПакетаЗапроса, НомерБуквы, 8) = "(ВЫБРАТЬ" Тогда
ПрошлоеСлово = ПолучитьСлово(ТекстПакетаЗапроса, НомерБуквы, Истина, Ложь, МассивСпециальныхСимволов);
Если
ПолучитьСлово(ТекстПакетаЗапроса, НомерБуквы, Ложь, Истина, МассивСпециальныхСимволовКромеСкобок) = "(ВЫБРАТЬ"
И
ПрошлоеСлово <> "ВСЕ" И ПрошлоеСлово <> "ОБЪЕДИНИТЬ" И ПрошлоеСлово <> "В" И ПрошлоеСлово <> "ИЕРАРХИИ" Тогда
ПозицияИз = Неопределено;
Для НомерПодбуквы = НомерБуквы + 1 По ТекстДлина Цикл
ТекстПодзапроса = Сред(ТекстПакетаЗапроса, НомерБуквы, НомерПодбуквы - НомерБуквы);
// Определяем позицию ИЗ в запросе
Если ПозицияИз = Неопределено Тогда
Если Сред(ТекстПакетаЗапроса, НомерПодбуквы, 2) = "ИЗ" И СтрЧислоВхождений(ТекстПодзапроса, "(") - СтрЧислоВхождений(ТекстПодзапроса, ")") = 1 Тогда
ПозицияИз = ПозицияВГлобальномТексте + НомерПодбуквы - 1;
ИначеЕсли Сред(ТекстПакетаЗапроса, НомерПодбуквы + 1, 10) = "ОБЪЕДИНИТЬ" Тогда
ПозицияИз = ПозицияВГлобальномТексте + НомерПодбуквы - 1;
КонецЕсли;
КонецЕсли;
// --
// Проверим, что скобки закрылись, значит подзапрос закрывается
Если СтрЧислоВхождений(ТекстПодзапроса, "(") = СтрЧислоВхождений(ТекстПодзапроса, ")") Тогда
// Если ПозицияИз не определена, значит ставим её в конце
Если ПозицияИз = Неопределено Тогда
ПозицияИз = НомерПодбуквы;
КонецЕсли;
// Урезаем скобки по краяем
ТекстПодзапросаБезСкобок = Сред(ТекстПодзапроса, 2, СтрДлина(ТекстПодзапроса) - 2);
Ключ = "Запрос" + Строка(Структура.Количество());
// Получаем имя пакета как слово после КАК во вложенном запросе
НачальнаяПозиция = ПозицияВГлобальномТексте + НомерПодбуквы;
СловоКАК = ПолучитьСлово(ГлобальныйТекстЗапроса, НачальнаяПозиция, , Истина, МассивСпециальныхСимволов, НачальнаяПозиция);
Если СловоКАК = "КАК" Тогда
ИмяПакета = ПолучитьСлово(ГлобальныйТекстЗапроса, НачальнаяПозиция + 4, , Истина, МассивСпециальныхСимволов);
Если ИмяПакета = "" Тогда
ВызватьИсключение("СП. Не смогли определить имя пакета!");
КонецЕсли;
Иначе
ВызватьИсключение("СП. Не смогли определить имя пакета!");
КонецЕсли;
// Проверка на уникальность будущего пакета
Если МассивИменПакетов.Найти(ИмяПакета) = Неопределено Тогда
МассивИменПакетов.Добавить(ИмяПакета);
Иначе
Индекс = 0;
Пока Истина Цикл
Индекс = Индекс + 1;
ИмяНовое = ИмяПакета + "_ИзВложенногоЗапроса" + Строка(Индекс);
Если МассивИменПакетов.Найти(ИмяНовое) = Неопределено Тогда
ИмяПакета = ИмяНовое;
МассивИменПакетов.Добавить(ИмяПакета);
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Структура.Вставить(Ключ, Новый Структура("ТекстЗапроса, ИмяПакета, ПозицияНачалаСоСкобкой, ПозицияОкончанияСоСкобкой, ПозицияИз, Подзапросы", ТекстПодзапросаБезСкобок, ИмяПакета, ПозицияВГлобальномТексте - 1 + НомерБуквы, ПозицияВГлобальномТексте - 1 + НомерПодбуквы, ПозицияИз));
Структура[Ключ].Подзапросы = ПолучитьСтруктуруПодзапросов(ТекстПодзапросаБезСкобок, ПозицияВГлобальномТексте + НомерБуквы, ГлобальныйТекстЗапроса, МассивИменПакетов);
НомерБуквы = НомерПодбуквы + 1;
Прервать;
КонецЕсли;
// Проверим, что скобки закрылись, значит подзапрос закрывается
// --
КонецЦикла;
КонецЕсли;
КонецЕсли;
// Определяем, что это начало нового запроса
// --
КонецЦикла;
// Перебираем текст по символьно
// --
Возврат Структура;
КонецФункции
// Функция получает тексты подзапросов из структуры подзапросов
// МассивВырезок - нужен для накопления информации о подзапросах
Функция ПолучитьТекстПодзапросов(Знач ГлобальныйТекстЗапроса, Подзапросы, МассивВырезок)
ТекстЗапроса = "";
Для Каждого Подзапрос Из Подзапросы Цикл
// Добавляем вырезку текушего подзапроса
МассивВырезок.Добавить(Новый Структура("ПозицияНачала, ПозицияОкончания, ТекстЗапроса", Подзапрос.Значение.ПозицияНачалаСоСкобкой, Подзапрос.Значение.ПозицияОкончанияСоСкобкой, Подзапрос.Значение.ИмяПакета));
// Получаем подзапросы подзапроса, потом получаем текст подзапроса
МассивПодвырезок = Новый Массив;
ТекстПодзапросов = ПолучитьТекстПодзапросов(ГлобальныйТекстЗапроса, Подзапрос.Значение.Подзапросы, МассивПодвырезок);
ТекстЗапроса = ТекстЗапроса + ?(ТекстЗапроса = "" Или ТекстПодзапросов = "", "", ";") + ТекстПодзапросов;
ТекстПодзапроса =
Сред(ГлобальныйТекстЗапроса, Подзапрос.Значение.ПозицияНачалаСоСкобкой + 1, Подзапрос.Значение.ПозицияИз - Подзапрос.Значение.ПозицияНачалаСоСкобкой - 1)
+
" ПОМЕСТИТЬ " + Подзапрос.Значение.ИмяПакета + " "
+
ПолучитьВырезкуТекста(ГлобальныйТекстЗапроса, Подзапрос.Значение.ПозицияИз, Подзапрос.Значение.ПозицияОкончанияСоСкобкой - 1, МассивПодвырезок);
ТекстЗапроса = ТекстЗапроса + ?(ТекстЗапроса = "" Или ТекстПодзапроса = "", "", ";") + ТекстПодзапроса;
//// Объединим массив подвырезок с массивом вырезок
//Для Каждого Элемент Из МассивПодвырезок Цикл
// МассивВырезок.Добавить(Элемент);
//КонецЦикла;
КонецЦикла;
Возврат ТекстЗапроса;
КонецФункции
// Функция получает вырезку из текста с учётом всех фрагментов, которые должны быть вырезаны внутри неё
// МассивВырезок - сожержит элементы - структуры (ПозицияНачала, ПозицияОкончания, ТекстЗапроса = ""), где ТекстЗапроса - будет вставлено вместо вырезаемого текста
Функция ПолучитьВырезкуТекста(ГлобальныйТекстЗапроса, ПозицияНачала, ПозицияОкончания, Знач МассивВырезок)
// --
// Строим МассивТочекТекста
// Массив, элементами которого будет структура(Позиция, ТекстЗапроса = "")
// Если ТекстЗапроса заполнено, то вместо текста между позициями, берём этот текст
МассивТочекТекста = Новый Массив;
МассивТочекТекста.Добавить(Новый Структура("Позиция, ТекстЗапроса", ПозицияНачала, ""));
Для Каждого Вырезка Из МассивВырезок Цикл
Если ПозицияНачала <> Вырезка.ПозицияНачала Тогда
МассивТочекТекста.Добавить(Новый Структура("Позиция, ТекстЗапроса", Вырезка.ПозицияНачала, Вырезка.ТекстЗапроса));
КонецЕсли;
Если ПозицияОкончания <> Вырезка.ПозицияОкончания Тогда
МассивТочекТекста.Добавить(Новый Структура("Позиция, ТекстЗапроса", Вырезка.ПозицияОкончания, ""));
КонецЕсли;
КонецЦикла;
МассивТочекТекста.Добавить(Новый Структура("Позиция, ТекстЗапроса", ПозицияОкончания, ""));
// Строим МассивТочекТекста
// --
// --
// Формируем текст
ТекстЗапроса = "";
ПозицияПрошлая = Неопределено;
ТекстПрошлый = "";
Для Каждого ТочкаТекста Из МассивТочекТекста Цикл
Если ПозицияПрошлая <> Неопределено Тогда
Если ТекстПрошлый <> "" Тогда
ТекстЗапроса = ТекстЗапроса + ТекстПрошлый;
Иначе
ТекстЗапроса = ТекстЗапроса + Сред(ГлобальныйТекстЗапроса, ПозицияПрошлая, ТочкаТекста.Позиция - ПозицияПрошлая);
КонецЕсли;
КонецЕсли;
ПозицияПрошлая = ТочкаТекста.Позиция;
ТекстПрошлый = ТочкаТекста.ТекстЗапроса;
КонецЦикла;
// Формируем текст
// --
Возврат ТекстЗапроса;
КонецФункции
// СловоИсключение - содержит символы, которые не являются специальными символами
Функция ПолучитьМассивСпециальныхСимволов(СловоИсключение = "")
МассивДляВозврата = Новый Массив;
Массив = Новый Массив;
Массив.Добавить(Символы.ВК);
Массив.Добавить(Символы.ВТаб);
Массив.Добавить(Символы.НПП);
Массив.Добавить(Символы.ПС);
Массив.Добавить(Символы.ПФ);
Массив.Добавить(Символы.Таб);
Массив.Добавить(")");
Массив.Добавить("(");
Массив.Добавить("{");
Массив.Добавить(".");
Массив.Добавить(",");
Массив.Добавить(";");
Массив.Добавить(" ");
Для Каждого Символ Из Массив Цикл
Если Найти(СловоИсключение, Символ) = 0 Тогда
МассивДляВозврата.Добавить(Символ);
КонецЕсли;
КонецЦикла;
Возврат МассивДляВозврата;
КонецФункции
// Функции редактирования запроса
// --
// --
// Дополнительные строковые функции
// Функция разбивает текст на слова и возвращает массив.
// Если нужно получить конкретное количество слов, то
// надо задать параметр НужноСлов.
// В случае если найденных слов меньше показателя НужноСлов, то
// оставшиеся элементы массива будут заданы значением ТекстЗаменыНенайденных.
//
// Параметры
// - ТекстЗапроса:Строка - текст, в котором ищем слова, разделенные символом
// - Символ:Строка - символ разделения
// - НужноСлов:Число - нужно элементов в возвращаемом массиве
// - ТекстЗаменыНенайденных:Строка - текст, в котором ищем слова, разделенные символом
// - СимволыКоторыеДолжныЗакрываться:Массив - массив символов, которые в нутри слова должны иметь четное количество или 0. Например в слове не может быть одной открывающей кавычки
//
// Возвращаемое значение:
// МассивСлов:Массив – массив, элементами которого являются части переданного в функцию текст
//
Функция ПолучитьМассивСловРазделенныхСимволом(Знач ТекстЗапроса, Символ, НужноСлов = 0, ТекстЗаменыНенайденных = "", СимволыКоторыеДолжныЗакрываться = Неопределено) Экспорт
// --
// Массив слов для возврата
МассивСлов = Новый Массив();
// --
// --
// Предварительно удалаем повтор заданного символа в слове
ТекстЗапроса = УдалитьДублирующиеСимволы(ТекстЗапроса, Символ);
// --
// --
// Находим позицию первого Символа
ПозицияСимвола = Найти(ТекстЗапроса, Символ);
// --
// --
// Перебираем все позиции Символа
Пока ПозицияСимвола <> 0 Цикл
// Получаем слово и заносим его в массив
Слово = Лев(ТекстЗапроса, ПозицияСимвола - 1);
// --
// Проверка на СимволыДолжныЗакрываться
Если СимволыКоторыеДолжныЗакрываться <> Неопределено Тогда
ВыйтиИзВерхнегоЦикла = Ложь;
// --
// Перебираем символы, которые должны закрываться
Для Каждого СимволКоторыйДолженЗакрываться Из СимволыКоторыеДолжныЗакрываться Цикл
ЧислоВхождений = СтрЧислоВхождений(Слово, СимволКоторыйДолженЗакрываться);
Если ЧислоВхождений <> 0 Тогда
РезультатДеления = ЧислоВхождений / 2;
Если РезультатДеления <> Окр(РезультатДеления, 0) Тогда
ТекстПослеВхожденияСимвола = Сред(ТекстЗапроса, ПозицияСимвола + 1, СтрДлина(ТекстЗапроса));
НоваяПозиция = Найти(ТекстПослеВхожденияСимвола, Символ);
Если НоваяПозиция = 0 Тогда
ПозицияСимвола = 0;
Иначе
ПозицияСимвола = ПозицияСимвола + НоваяПозиция;
КонецЕсли;
// Если находим случай незакрытого символа, то входим в цикл по новому
ВыйтиИзВерхнегоЦикла = Истина;
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Перебираем символы, которые должны закрываться
// --
Если ВыйтиИзВерхнегоЦикла = Истина Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
// Проверка на СимволыДолжныЗакрываться
// --
МассивСлов.Добавить(Слово);
// Уменьшаем количество НужноСлов
НужноСлов = НужноСлов - 1;
// Обрезаем текст
ТекстЗапроса = Прав(ТекстЗапроса, СтрДлина(ТекстЗапроса) - ПозицияСимвола);
// Находим позицию следующего Символа
ПозицияСимвола = Найти(ТекстЗапроса, Символ);
КонецЦикла;
// --
// --
// Добавляем последнее слово
МассивСлов.Добавить(ТекстЗапроса);
// --
// --
// Дополняем при необходимости массив пустыми значениями
Для Нумератор = 1 По НужноСлов Цикл
МассивСлов.Добавить(ТекстЗаменыНенайденных);
КонецЦикла;
// --
// --
// Возвращаем массив
Возврат МассивСлов;
// --
КонецФункции
// Функция удаления дублирующих символов в строке
//
// Параметры
// - ТекстЗапроса:Строка - строка, из которой удаляем дублирующие символы
// - ТекстЗапроса:Символ - строка, которая является разделительным символом в строку замены
// - НужноСлов:Число - нужно слов, разделенных в данной строке заданным символом
// - ТекстЗаменыНенайденных:Строка - строки, которые добавляются для достижения нужного количества слов
//
// Возвращаемое значение:
// ТекстЗапроса:Строка – отредактированная строка ТекстЗапроса
//
//&НаСервере
Функция УдалитьДублирующиеСимволы(Знач ТекстЗапроса, ТекстУдаления) Экспорт
// --
// Определяем длину текста удаления
ДлинаТекстаУдаленияТекст = СтрДлина(ТекстУдаления);
// --
// --
// Удаляем дублирующие символы
Пока Найти(ТекстЗапроса, ТекстУдаления + ТекстУдаления) <> 0 Цикл
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ТекстУдаления + ТекстУдаления, ТекстУдаления);
КонецЦикла;
// --
// --
// Обрезаем пробелы
ТекстЗапроса = СокрЛП(ТекстЗапроса);
// --
// --
// Удалям заданный символ из начала и конца строки: слева и справа
// Слева
Если Лев(ТекстЗапроса, ДлинаТекстаУдаленияТекст) = ТекстУдаления Тогда
ТекстЗапроса = Прав(ТекстЗапроса, СтрДлина(ТекстЗапроса) - ДлинаТекстаУдаленияТекст);
КонецЕсли;
// Справа
Если Прав(ТекстЗапроса, ДлинаТекстаУдаленияТекст) = ТекстУдаления Тогда
ТекстЗапроса = Лев(ТекстЗапроса, СтрДлина(ТекстЗапроса) - ДлинаТекстаУдаленияТекст);
КонецЕсли;
// --
// --
// Возвращаем отредактированный текст
Возврат ТекстЗапроса;
// --
КонецФункции
// Разбивает строку вида ключ=значение;ключ2=значение;
// где СимволМеждуКлючомИЗначением - =, СимволМеждуЗначениемИКлючом - ;
Функция ПолучитьСтрктуруЗначенийИзСтроки(Знач ТекстЗапроса, СимволМеждуКлючомИЗначением, СимволМеждуЗначениемИКлючом, СимволыКоторыеДолжныЗакрываться)
Структура = Новый Структура;
МассивКлючЗначение = ПолучитьМассивСловРазделенныхСимволом(ТекстЗапроса, СимволМеждуЗначениемИКлючом, , , СимволыКоторыеДолжныЗакрываться);
Для Каждого КлючЗначение Из МассивКлючЗначение Цикл
Массив = ПолучитьМассивСловРазделенныхСимволом(КлючЗначение, СимволМеждуКлючомИЗначением, , , СимволыКоторыеДолжныЗакрываться);
Если Массив.Количество() = 2 Тогда
Структура.Вставить(Массив[0], Массив[1]);
Иначе
// Что-то распарсили не так, возможно надо вызвать ошибку
КонецЕсли;
КонецЦикла;
Возврат Структура;
КонецФункции
// Получает следующее слово в тексте
// ОбходВперед - Слово должно быть за начальной позицией или до начальной позиции
// НачальнаяПозицияСкорректированная - служит для возврата скорректированной начальной позиции
Функция ПолучитьСлово(ТекстЗапроса, Знач НачальнаяПозиция, КорриктороватьНачальнуюПозицию = Ложь, ОбходВперед = Истина, МассивСпециальныхСимволов, НачальнаяПозицияСкорректированная = Неопределено)
ДлинаТекста = СтрДлина(ТекстЗапроса);
// --
// Подредактировать начальную позицию.
// Например, если начальная позиия не верна, равна пробелу, то нужно увеличить вправо начальную позицию, чтобы добравться до первой буквы
// и потом получить начиная с неё слово
Если КорриктороватьНачальнуюПозицию = Истина Тогда
Если ОбходВперед = Истина Тогда
Для НомерБуквы = НачальнаяПозиция По ДлинаТекста Цикл
Если МассивСпециальныхСимволов.Найти(Сред(ТекстЗапроса, НомерБуквы, 1)) = Неопределено Тогда
НачальнаяПозиция = НачальнаяПозиция + 1;
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
Иначе
Пока НачальнаяПозиция <> 0 Цикл
Если МассивСпециальныхСимволов.Найти(Сред(ТекстЗапроса, НачальнаяПозиция, 1)) <> Неопределено Тогда
НачальнаяПозиция = НачальнаяПозиция - 1;
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
НачальнаяПозицияСкорректированная = НачальнаяПозиция;
// Подредактировать начальную позицию.
// Например, если начальная позиия не верна, равна пробелу, то нужно увеличить вправо начальную позицию, чтобы добравться до первой буквы
// и потом получить начиная с неё слово
// --
// --
// Ищем конец слова
Если ОбходВперед = Истина Тогда
Для НомерБуквы = НачальнаяПозиция По ДлинаТекста Цикл
Если МассивСпециальныхСимволов.Найти(Сред(ТекстЗапроса, НомерБуквы, 1)) <> Неопределено
Или
НомерБуквы = ДлинаТекста
Тогда
// --
// Возвращаем найденное слово
// Если слово последнее в тексте (НомерБуквы = ДлинаТекста), то возвращаем с последним символом
НайденноеСлово = Сред(
ТекстЗапроса,
НачальнаяПозиция,
НомерБуквы - НачальнаяПозиция + ?(НомерБуквы = ДлинаТекста, 1, 0)
);
Возврат НайденноеСлово;
// --
КонецЕсли;
КонецЦикла;
Иначе
НомерБуквы = НачальнаяПозиция;
Пока НомерБуквы <> 0 Цикл
Если МассивСпециальныхСимволов.Найти(Сред(ТекстЗапроса, НомерБуквы, 1)) <> Неопределено
Или
НомерБуквы = 0
Тогда
// --
// Возвращаем найденное слово
// Если слово последнее в тексте (НомерБуквы = ДлинаТекста), то возвращаем с последним символом
НайденноеСлово = Сред(
ТекстЗапроса,
НомерБуквы + ?(НомерБуквы = 0, 0, 1),
НачальнаяПозиция - НомерБуквы
);
Возврат НайденноеСлово;
// --
КонецЕсли;
НомерБуквы = НомерБуквы - 1;
КонецЦикла;
КонецЕсли;
Возврат Неопределено;
КонецФункции
// Дополнительные строковые функции
// --
Интересно, нашел маленький баг, нужно добавить проверку СтрДлина(ИмяПакета) > 0:
(1) Bazin, Здравствуйте, а как может ИмяПакета быть пустой строкой? Имя пакета берётся из вложенного запроса после слова КАК. Т.е. в запросе
Показать
ВложенныйЗапрос — это ИмяПакета. Разве есть вложенные запросы без КАК … ?
Вот пример:
Показать
А вот вообще без «КАК»
Показать
И вот такой, «Временная таблица уже существует»:
Показать
(5) Bazin, Спасибо! Все замечания исправил.
У меня в отладчике запросов — это реализовано, года так три назад…
http://infostart.ru/public/190493/#UnwrapQueryToBatch
(7) DrAku1a, тонкий есть?
(7)Мощная вещь, но к сожалению там обычные формы, на современных конфигурациях(управляемые) не открываются даже если выбрать толстый клиент управляемое приложение. Так что автору плюс за алгоритм, но просьба для в запросник для управляемых добавить
(7) DrAku1a, Но при этом сам обработчик толком не работает. Уж извините за пост в защиту автора.
А если добавить что есть комментарий к Вашему обработчику:
Функция «Разложить вложенный запрос в пакетный» (ноухау)
…
Это довольно интересная функция — нигде такого не встречал.
Кто не хочет видеть, тот не видит =) В консоли запросов из подсистемы «Инструменты разработчика» это уже давно есть. В описании есть такая функция «Вынести в новый запрос» и даже на картинке видноhttp://devtool1c.ucoz.ru/index/konsol_zaprosov/0-18
То совсем весело.
Эх-х-х если бы Вы его довели до ума, цены бы не было.
Если данный алгоритм не работает на каких-либо примерах, присылайте, буду править.
(9) kiruha, на управляемых формах должно работать, все функции выполняются на сервере
Бездумно выносить все вложенные запросы в отдельные запросы пакета вредно. Временные таблицы имеют свои накладные расходы. Поэтому выносить оправдано те подзапросы, для которых эти расходы будут меньше «сложности» для построения плана запроса, вносимой подзапросом. Поэтому то и была сделана команда для выборочного вынесения (10)
(9)
надо выбирать Толстый клиент обычное приложение, а не управляемое.
А еще добавлять обработки на УФ в конфигурацию. чтобы они открывались.
Этот вариант не для того, чтобы к конфе на УФ добавить обычную обработку, а как раз наоборот
К обычной конфе добавить обработку на УФ.
Т.е не реально использовать эту обработку на УФ конфе, чтобы при этом конфа еще и работала.
ОФФ наверное. Маленькое замечание. В режиме отладки, если не применять специальные инструменты можно использовать метод Запрос.ВыполнитьПакетСПромежуточнымиРезультатами()
После отладки можно вернуть метод ВыполнитьПакет() на место
(13) tormozit, Публикация начинается со слов «Запросы неудобно отлаживать…», а не использовать
(17) Согласен, чисто для отладки такое может быть полезно быть полезно с учетом того, что нет возможности использовать дерево запроса. Однако связь частей полученного пакетного запроса с частями оригинального запроса может быть довольно ненаглядной после переноса всех подзапросов во временные таблицы.
(10) uri1978, Как обычно, руки не доходят сделать. Да и смысл? Есть же хорошая консоль от ИР (в т.ч. мобильных ИР).
Сам — пользуюсь отладчиком, мне удобно — то, что разделил всё по вкладкам. В итоге — большое окно для редактирования текста запроса, большое окно для просмотра результата, и ничего лишнего.
Исправил
ПрошлоеСлово <> «ВСЕ» И ПрошлоеСлово <> «ОБЪЕДИНИТЬ» И ПрошлоеСлово <> «В» Тогда
на
ПрошлоеСлово <> «ВСЕ» И ПрошлоеСлово <> «ОБЪЕДИНИТЬ» И ПрошлоеСлово <> «В» И ПрошлоеСлово <> «ИЕРАРХИИ» Тогда