//ирПортативный Перем ирПортативный Экспорт; //ирПортативный Перем ирОбщий Экспорт; //ирПортативный Перем ирСервер Экспорт; //ирПортативный Перем ирКэш Экспорт; //ирПортативный Перем ирПривилегированный Экспорт; Перем мТаблицаКолонок Экспорт; Перем мСписокКолонок Экспорт; Перем КлючиЗагруженныхСтрок; Перем мСвойстваСИменамиБД Экспорт; Перем RegExpПараметры; Перем RegExpМета; Перем шБуква; Перем шГраничныйСимволИмени; //Перем МинимальнаяДатаЗагрузки Экспорт; Перем мЧисловыеСвойства; Перем мТипСУБД Экспорт; Перем мСерверныеТипыПроцессов Экспорт; Перем мКартыФайлов Экспорт; Перем мПлатформа Экспорт; //Перем мСоставСвойствСобытий Экспорт; Перем мСвойстваСобытий Экспорт; Перем мАдресЧужойСхемыБД Экспорт; //Трассировка Перем КонецПериодаКлиента Экспорт; Перем НачалоПериодаКлиента Экспорт; Перем КонецПериодаСервера Экспорт; Перем НачалоПериодаСервера Экспорт; Перем мИдентификаторТрассы Экспорт; Перем мНепустыеКолонкиЖурнала Экспорт; Перем мСоответствиеКолонок; Перем мАнализТрассыЗапроса; // СдвигВремени - Число - в секундах задается, нужно для компенсации разницы времени между компьютерами // ОтборПоПроцессу и ОтборПоСеансу частично игнорируются когда ЗагружатьТолькоТекущийСеанс = Истина Функция ПрочитатьПроизвольныйЖурнал(СообщитьРазмер = Неопределено, СдвигВремени = 0, ОтборПоПроцессу = Неопределено, ОтборПоСеансу = Неопределено, НаСервере = Неопределено) #Если Сервер И Не Сервер Тогда мПлатформа = Обработки.ирПлатформа.Создать(); #КонецЕсли НеизвестныеСвойства = Новый Соответствие(); Если Ложь Или (НаСервере <> Неопределено И мАнализТрассыЗапроса <> Истина) Или Не ЗначениеЗаполнено(КаталогЖурнала) Тогда КаталогЖурнала = ПолучитьКаталогТекущегоЖурнала(НаСервере = Истина); Если Не ЗначениеЗаполнено(КаталогЖурнала) Тогда Возврат Ложь; КонецЕсли; КонецЕсли; Если Не ирОбщий.ЛиКаталогДоступенЛкс(КаталогЖурнала) Тогда Возврат Ложь; КонецЕсли; Если ЗагружатьТолькоТекущийСеанс Тогда Если Ложь Или ирКэш.ЭтоФайловаяБазаЛкс() Или Не НаСервере = Истина Тогда ОтборПоПроцессу = ирКэш.Получить().ПолучитьИдентификаторПроцессаОС(); КонецЕсли; Если НаСервере = Истина Тогда ОтборПоСеансу = НомерСеансаИнформационнойБазы(); КонецЕсли; КонецЕсли; лПоследнееВремяНачалаЗагрузки = ТекущаяДата(); Если ПериодПоследниеМинуты > 0 Тогда НачалоПериода = лПоследнееВремяНачалаЗагрузки - 60 * ПериодПоследниеМинуты; КонецПериода = Неопределено; КонецЕсли; //Если ТаблицаЖурнала.Количество() = 0 Тогда // МинимальнаяДатаЗагрузки = ТекущаяДата() + 100000; //КонецЕсли; //Если МинимальнаяДатаЗагрузки > НачалоПериода Тогда // ТаблицаЖурнала.Очистить(); //КонецЕсли; //РежимДозагрузки = Истина // И ТаблицаЖурнала.Количество() > 0 // И МинимальнаяДатаЗагрузки <= НачалоПериода; Если СообщитьРазмер = Неопределено Тогда СообщитьРазмер = (ТаблицаЖурнала.Количество() = 0) Или КомментироватьЗагрузку; КонецЕсли; Если ТаблицаЖурнала.Количество() = 0 Тогда мКартыФайлов.Очистить(); КонецЕсли; ирОбщий.ЛиКаталогТехножурналаНедоступенЛкс(КаталогЖурнала); ФайлыЖурнала = НайтиФайлы(КаталогЖурнала, "*.log", Истина); ОбщийРазмер = 0; Для Каждого ФайлЖурнала Из ФайлыЖурнала Цикл ОбщийРазмер = ОбщийРазмер + ФайлЖурнала.Размер(); КонецЦикла; Если СообщитьРазмер Тогда Сообщить("В каталоге """ + КаталогЖурнала + """ обнаружено для обработки " + Формат(Цел(ОбщийРазмер / 1024), "ЧН=") + "КБ логов"); ПредставлениеОтбора = ""; Если СписокЗагружаемыхТиповСобытий.Количество() > 0 Тогда ПредставлениеОтбора = ПредставлениеОтбора + " события " + СписокЗагружаемыхТиповСобытий; КонецЕсли; Если ЗначениеЗаполнено(НачалоПериода) Тогда ПредставлениеОтбора = ПредставлениеОтбора + " с " + НачалоПериода; КонецЕсли; Если ЗначениеЗаполнено(КонецПериода) Тогда ПредставлениеОтбора = ПредставлениеОтбора + " по " + КонецПериода; КонецЕсли; Если ЗначениеЗаполнено("" + ФильтрЗагрузки) Тогда Если ЗначениеЗаполнено(ПредставлениеОтбора) Тогда ПредставлениеОтбора = ПредставлениеОтбора + " И"; КонецЕсли; ПредставлениеОтбора = ПредставлениеОтбора + " " + ФильтрЗагрузки; КонецЕсли; Если ЗначениеЗаполнено(ПредставлениеОтбора) Тогда Сообщить("Отбор загрузки:" + ПредставлениеОтбора); КонецЕсли; Если мПлатформа.ПолучитьИдентификаторПроцессаОтладчика() <> Неопределено Тогда Сообщить("Отладчик подключен и замедляет загрузку логов. Отключите отладчик для ускорения загрузки."); КонецЕсли; КонецЕсли; //БезопасныйРазмерЖурнала = 10*1000*1000; // 10МБ //Если ОбщийРазмер > БезопасныйРазмерЖурнала Тогда // Ответ = Вопрос("Размер журнала составляет " + Формат(Цел(ОбщийРазмер / 1000000)) + " МБ. // |Чтение журнала может продолжаться длительное время, продолжить?", РежимДиалогаВопрос.ДаНет); //Иначе // Ответ = КодВозвратаДиалога.Да; //КонецЕсли; //Если Ответ = КодВозвратаДиалога.Нет Тогда // Возврат Ложь; //КонецЕсли; НеОбрабатывать = Ложь; СтрокаСобытия = ""; СтруктураЗаписиТЖ = Новый Структура(); РеквизитыТЧ = Метаданные().ТабличныеЧасти.ТаблицаЖурнала.Реквизиты; шСимвол = "[" + шБуква + "\d\._#{}-]"; ////ШаблонСвойствоЗначение = ",([\w\:]+)=(?:'\s*([^']*)'|""\s*([^""]*)""|([^'""\n\r,]*))"; ////Шаблон = "(\d\d:\d\d)\.(\d+)-(\d+),(" + шСимвол + "+),\d+" ////+ "((?:" + ШаблонСвойствоЗначение + ")*)"; //ШаблонСвойствоЗначение = "([\w\:]+)=(?:'\s*((?:.|\n|\r)*?)'|""\s*([^""]*)""|([^'""\n\r,]*))(?:,|\r|$)"; // Так были очень большие трассы вычисления RegExp ШаблонСвойствоЗначение = "([\w\:]+)=(?:'\s*([\s\S]*?)'|""\s*((?:""""|[^""])*)""|([^'""\n\r,]*))(?:,|\r|\n|$)+"; Шаблон = "(\d\d:\d\d)\.(\d+)-(\d+),(" + шСимвол + "+),\d+" + ",((?:" + ШаблонСвойствоЗначение + ")*)"; мПлатформа = ирКэш.Получить(); RegExp = мПлатформа.RegExp; RegExp2 = мПлатформа.RegExp2; //: RegExp = Новый COMОбъект("VBScript.RegExp"); RegExp.Pattern = Шаблон; //RegExp.Multiline = Истина; RegExp.Global = Истина; RegExp2.Pattern = ШаблонСвойствоЗначение; RegExp2.Global = Истина; Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ОбщийРазмер, "Загрузка файлов"); ПустаяДата = Дата("00010101"); РазмерОбработанныхДанных = 0; //лНачалоПериода = НачалоПериода; //Если Не РежимДозагрузки Тогда // //ТаблицаЖурнала.Очистить(); // КлючиЗагруженныхСтрок = Новый Соответствие; //Иначе // Если НаСервере = Истина Тогда // лДатаЗагрузки = ПоследнееВремяНачалаЗагрузкиСервера; // Иначе // лДатаЗагрузки = ПоследнееВремяНачалаЗагрузки; // КонецЕсли; // Если ЗначениеЗаполнено(лДатаЗагрузки) Тогда // лНачалоПериода = лДатаЗагрузки - НаложениеПриДозагрузкеСекунд; // КонецЕсли; //КонецЕсли; Если УдалятьДанныеВнеПериода Тогда ТаблицаЖурнала.Сортировать("МоментВремени"); КоличествоСтрок = ТаблицаЖурнала.Количество(); Пока Истина И КоличествоСтрок > 0 И ТаблицаЖурнала[0].Дата < НачалоПериода Цикл ТаблицаЖурнала.Удалить(0); КоличествоСтрок = КоличествоСтрок - 1; КонецЦикла; Если ЗначениеЗаполнено(КонецПериода) Тогда ИндексСтроки = КоличествоСтрок - 1; Пока Истина И КоличествоСтрок > 0 И ТаблицаЖурнала[ИндексСтроки].Дата > КонецПериода Цикл ТаблицаЖурнала.Удалить(ИндексСтроки); ИндексСтроки = ИндексСтроки - 1; КонецЦикла; КонецЕсли; КонецЕсли; ДостигнутоПредельноеКоличество = Ложь; //НовыеКлючиЗагруженныхСтрок = Новый Соответствие(); Для Каждого ФайлЖурнала Из ФайлыЖурнала Цикл #Если Сервер И Не Сервер Тогда ФайлЖурнала = Новый файл; #КонецЕсли Попытка РазмерФайла = ФайлЖурнала.Размер(); Исключение РазмерФайла = "?"; КонецПопытки; Если ТипЗнч(РазмерФайла) = Тип("Число") Тогда РазмерОбработанныхДанных = РазмерОбработанныхДанных + РазмерФайла; КонецЕсли; #Если Клиент Тогда ирОбщий.ОбработатьИндикаторЛкс(Индикатор, РазмерОбработанныхДанных); #КонецЕсли Если КомментироватьЗагрузку Тогда Сообщить("Читаем " + ФайлЖурнала.ПолноеИмя + ", размер - " + РазмерФайла); КонецЕсли; ПолноеИмяКаталогаПроцесса = Лев(ФайлЖурнала.Путь, СтрДлина(ФайлЖурнала.Путь) - 1); Длина1 = СтрДлина(ПолноеИмяКаталогаПроцесса); СтрокаЧасаЗаписи = "20" + Сред(ФайлЖурнала.ПолноеИмя, Длина1 + 2, 8); ДатаЧасЗаписи = Дата(СтрокаЧасаЗаписи + "0000"); ИдентификаторПроцессаСтрока = ирОбщий.ПолучитьСтрокуБезКонцаЛкс(ирОбщий.ПоследнийФрагментЛкс(ФайлЖурнала.Путь, "_"), 1); Попытка ИдентификаторПроцесса = Число(ИдентификаторПроцессаСтрока); Исключение Сообщить("Неверная структура каталогов техножурнала", СтатусСообщения.Внимание); Возврат Ложь; КонецПопытки; //ЛиФайлВИнтервалеПолностью = ирОбщий.ЛиДатаВИнтервалеБезГраницЛкс(ДатаЧасЗаписи, НачалоЧаса(лНачалоПериода), НачалоЧаса(КонецПериода)); //ЛиДатаВИнтервале = ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(ДатаЧасЗаписи, НачалоЧаса(лНачалоПериода), НачалоЧаса(КонецПериода)); ЛиФайлВИнтервалеПолностью = ирОбщий.ЛиДатаВИнтервалеБезГраницЛкс(ДатаЧасЗаписи, НачалоЧаса(НачалоПериода), НачалоЧаса(КонецПериода)); ЛиДатаВИнтервале = ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(ДатаЧасЗаписи, НачалоЧаса(НачалоПериода), НачалоЧаса(КонецПериода)); Если Не ЛиДатаВИнтервале Тогда Продолжить; КонецЕсли; Если Истина И ОтборПоПроцессу <> Неопределено И ИдентификаторПроцесса <> ОтборПоПроцессу Тогда Продолжить; КонецЕсли; ПоследняяСтрокаТаблицыФайла = Неопределено; ТекстФайла = ""; // Уничтожаем старый текст, т.к. он может быть очень большим Попытка ЧтениеТекста = Новый ЧтениеТекста(ФайлЖурнала.ПолноеИмя, КодировкаТекста.UTF8, ,,Ложь); //ТекстовыйДокумент.Прочитать(ФайлЖурнала.ПолноеИмя, КодировкаТекста.UTF8); Исключение Сообщить("Не удалось прочитать данные из файла " + ФайлЖурнала.ПолноеИмя, СтатусСообщения.Внимание); Продолжить; КонецПопытки; СигнатураФайла = ЧтениеТекста.Прочитать(20); // Для идентификации файла Если ПустаяСтрока(СигнатураФайла) Тогда Продолжить; КонецЕсли; РазмерПорции = 2 * 1000 * 1000; // Подобрано экспериментально КраткоеИмяКаталогаПроцесса = ирОбщий.ПоследнийФрагментЛкс(ПолноеИмяКаталогаПроцесса, "\"); ЧислоПорций = Цел(РазмерФайла / РазмерПорции) + 1; ЧтениеТекста = Новый ЧтениеТекста(ФайлЖурнала.ПолноеИмя, КодировкаТекста.UTF8, ,,Ложь); АбсолютнаяПозицияВФайле = 0; КлючКарты = Новый Структура("ИмяКаталогаПроцесса, ИмяТекущегоФайла, СигнатураТекущегоФайла, ОтборПоСеансу", КраткоеИмяКаталогаПроцесса, ФайлЖурнала.Имя, СигнатураФайла, ОтборПоСеансу); СтрокиКарт = мКартыФайлов.НайтиСтроки(КлючКарты); Если СтрокиКарт.Количество() > 0 Тогда КартаФайла = СтрокиКарт[0]; Иначе КартаФайла = мКартыФайлов.Добавить(); ЗаполнитьЗначенияСвойств(КартаФайла, КлючКарты); КартаФайла.КонецПериода = Дата(1000, 1, 1); КонецЕсли; Если ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(НачалоПериода, КартаФайла.НачалоПериода, КартаФайла.КонецПериода) Тогда АбсолютнаяПозицияВФайле = КартаФайла.ПозицияКонца; ИначеЕсли Ложь Или НачалоПериода > КартаФайла.НачалоПериода Или КонецПериода < КартаФайла.КонецПериода Тогда // Периоды не сшиваются. Очищаем карту. КартаФайла.ПозицияНачала = -1; КартаФайла.ПозицияКонца = -1; КартаФайла.НачалоПериода = НачалоПериода; КартаФайла.КонецПериода = КонецПериода; КартаФайла.ДатаИзмененияФайла = Неопределено; КонецЕсли; Если АбсолютнаяПозицияВФайле > 0 Тогда Если ЗначениеЗаполнено(КартаФайла.ДатаИзмененияФайла) Тогда Если КартаФайла.ДатаИзмененияФайла = ФайлЖурнала.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс() Тогда Продолжить; КонецЕсли; КонецЕсли; ЧтениеТекста.Прочитать(АбсолютнаяПозицияВФайле); КонецЕсли; ПозицияНачалаСчитанныхДанных = -1; Если ЧислоПорций > 1 Тогда ИндикаторФайла = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ЧислоПорций, "" + КраткоеИмяКаталогаПроцесса + "\" + ФайлЖурнала.Имя); Иначе ИндикаторФайла = Неопределено; КонецЕсли; РазрешенныеТипыСобытий = Неопределено; Если СписокЗагружаемыхТиповСобытий.Количество() > 0 Тогда РазрешенныеТипыСобытий = Новый Структура; Для Каждого ТипСобытия Из СписокЗагружаемыхТиповСобытий.ВыгрузитьЗначения() Цикл РазрешенныеТипыСобытий.Вставить(ТипСобытия); КонецЦикла; КонецЕсли; СтрокаТЧ = Неопределено; РазмерТекущейПорции = 0; Пока Истина Цикл КартаФайла.ДатаИзмененияФайла = ФайлЖурнала.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс(); ПорцияТекстаФайла = ЧтениеТекста.Прочитать(РазмерПорции); Если Ложь Или ПорцияТекстаФайла = Неопределено Или ПустаяСтрока(ПорцияТекстаФайла) Тогда Прервать; КонецЕсли; #Если Клиент Тогда Если ИндикаторФайла <> Неопределено Тогда ирОбщий.ОбработатьИндикаторЛкс(ИндикаторФайла); КонецЕсли; #КонецЕсли Если Истина И АбсолютнаяПозицияВФайле >= КартаФайла.ПозицияНачала И АбсолютнаяПозицияВФайле + СтрДлина(ПорцияТекстаФайла) + СтрДлина(ТекстФайла) < КартаФайла.ПозицияКонца Тогда АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + СтрДлина(ПорцияТекстаФайла) + СтрДлина(ТекстФайла); Продолжить; КонецЕсли; ТекстФайла = ТекстФайла + ПорцияТекстаФайла; РазборТекстаРазрешен = Истина; ОписаниеОшибки = ""; МаксимальныйРазмерТекстДляАнализа = 20000000; // Экспериментально подобрано http://devtool1c.ucoz.ru/forum/2-270-1#1145 Если СтрДлина(ТекстФайла) > МаксимальныйРазмерТекстДляАнализа Тогда Если Истина И РазмерТекущейПорции = РазмерПорции И СтрокаТЧ <> Неопределено Тогда СтрокаТЧ.ТекстSDBL = ""; СтрокаТЧ.ТекстСУБД = ""; Сообщить("При анализе файла """ + ФайлЖурнала.ПолноеИмя + """ некоторые свойства события пропущены, т.к. оно превышает допустимый размер " + XMLСтрока(Цел(МаксимальныйРазмерТекстДляАнализа/1024/1024)) + "МБ: " + Лев(СокрЛ(СтрЗаменить(ТекстФайла, Символы.ПС, "")), 80) + "..."); Иначе ОписаниеОшибки = "Событие превышает допустимый размер 20МБ"; КонецЕсли; РазборТекстаРазрешен = Ложь; Иначе Если Истина И РазмерТекущейПорции = РазмерПорции И СтрокаТЧ <> Неопределено Тогда ТаблицаЖурнала.Удалить(ТаблицаЖурнала.Количество() - 1); КонецЕсли; КонецЕсли; Вхождения = RegExp.Execute(""); Если РазборТекстаРазрешен Тогда Попытка Вхождения = RegExp.Execute(ТекстФайла); Исключение ОписаниеОшибки = ОписаниеОшибки(); КонецПопытки; КонецЕсли; Если ОписаниеОшибки <> "" Тогда Сообщить("При анализе файла """ + ФайлЖурнала.ПолноеИмя + """ пропущена порция """ + Лев(СокрЛ(СтрЗаменить(ТекстФайла, Символы.ПС, "")), 80) + "..."": | " + ОписаниеОшибки); Иначе Если КомментироватьЗагрузку Тогда Сообщить("Анализ порции " + СтрДлина(ТекстФайла) + " символов обнаружил " + Вхождения.Count + " событий"); КонецЕсли; КонецЕсли; СтрокаТекущегоКонтекста = Неопределено; СтрокаТЧ = Неопределено; Вхождение = Неопределено; Для Каждого Вхождение Из Вхождения Цикл #Если Клиент Тогда ОбработкаПрерыванияПользователя(); #КонецЕсли СтрокаТЧ = Неопределено; АбсолютнаяПозицияВхождения = АбсолютнаяПозицияВФайле + Вхождение.FirstIndex; Если Истина И КартаФайла.ПозицияНачала > -1 И АбсолютнаяПозицияВхождения >= КартаФайла.ПозицияНачала И АбсолютнаяПозицияВхождения < КартаФайла.ПозицияКонца Тогда Продолжить; КонецЕсли; СтрокаВремениЗаписи = СтрокаЧасаЗаписи + СтрЗаменить(Вхождение.SubMatches(0), ":", ""); ДатаТекущегоСобытия = Дата(СтрокаВремениЗаписи); Если Не ЛиФайлВИнтервалеПолностью Тогда //ЛиДатаВИнтервале = ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(ДатаТекущегоСобытия, лНачалоПериода, КонецПериода); //Если Не ЛиДатаВИнтервале Тогда // Продолжить; //КонецЕсли; Если Истина И ЗначениеЗаполнено(НачалоПериода) И ДатаТекущегоСобытия < НачалоПериода Тогда Продолжить; КонецЕсли; Если Истина И ЗначениеЗаполнено(КонецПериода) И ДатаТекущегоСобытия > КонецПериода Тогда Вхождение = Неопределено; Прервать; КонецЕсли; КонецЕсли; ТипСобытия = ВРег(Вхождение.SubMatches(3)); Если Истина И РазрешенныеТипыСобытий <> Неопределено И Не РазрешенныеТипыСобытий.Свойство(ТипСобытия) Тогда Продолжить; КонецЕсли; Если ПозицияНачалаСчитанныхДанных = -1 Тогда ПозицияНачалаСчитанныхДанных = АбсолютнаяПозицияВхождения; КонецЕсли; КонецМикросекунды = Вхождение.SubMatches(1); //КлючСтроки = МоментВремени + ";" + ФайлЖурнала.ПолноеИмя; //Если РежимДозагрузки Тогда // Если КлючиЗагруженныхСтрок[КлючСтроки] = 1 Тогда // Продолжить; // КонецЕсли; //КонецЕсли; Если СтрДлина(КонецМикросекунды) = 6 Тогда //Это 8.3 ЧислоМикросекунд = Число(КонецМикросекунды); ПродолжительностьВМикросекундах = Число(Вхождение.SubMatches(2)); Иначе //Это 8.2 ЧислоМикросекунд = Число(КонецМикросекунды) * 100; ПродолжительностьВМикросекундах = Число(Вхождение.SubMatches(2)) * 100; КонецЕсли; Если ТаблицаЖурнала.Количество() = МаксТысячСобытий * 1000 Тогда УдалитьСтрокиВнеФильтра(); Если ТаблицаЖурнала.Количество() = МаксТысячСобытий * 1000 Тогда ДостигнутоПредельноеКоличество = Истина; Прервать; КонецЕсли; КонецЕсли; СтрокаТЧ = ТаблицаЖурнала.Добавить(); СтрокаТЧ.Дата = ДатаТекущегоСобытия - СдвигВремени; СтрокаТЧ.МоментВремени = ПолучитьМоментВремени(СтрокаТЧ.Дата, КонецМикросекунды); СтрокаТЧ.ИмяФайлаЛога = ФайлЖурнала.ПолноеИмя; СтрокаТЧ.ПроцессОС = ИдентификаторПроцесса; //СтрокаТЧ.ТекстЖурнала = Вхождение.Value; // Теперь это только для отладки будем включать СтрокаТЧ.Длительность = ПродолжительностьВМикросекундах / 1000; // Переводим длительность в миллисекунды Длительность1Секунды = Цел(ПродолжительностьВМикросекундах / 1000000); Длительность1Микросекунды = ПродолжительностьВМикросекундах - Длительность1Секунды * 1000000; ДатаНачала = СтрокаТЧ.Дата - Длительность1Секунды; НачалоМикросекунды = КонецМикросекунды - Длительность1Микросекунды; Если НачалоМикросекунды < 0 Тогда ДатаНачала = ДатаНачала - 1; НачалоМикросекунды = 1000000 + НачалоМикросекунды; КонецЕсли; СтрокаТЧ.ДатаНачала = ДатаНачала; СтрокаТЧ.МоментВремениНачала = ПолучитьМоментВремени(ДатаНачала, НачалоМикросекунды); СтрокаТЧ.Событие = ТипСобытия; ВхожденияСвойств = RegExp2.Execute(Вхождение.SubMatches(4)); // Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах. #Если Сервер И Не Сервер Тогда Для Каждого ВхождениеСвойства Из ВхожденияСвойств Цикл //Для Индекс = 0 По мТаблицаКолонок.Количество() - 1 Цикл //Индекс + СмещениеПервойКолонки ИмяСвойства = ВхождениеСвойства.SubMatches(0); ЗначениеСвойства = ВхождениеСвойства.SubMatches(3); //Если ирОбщий.ЛиПустаяПодгруппаRegExpЛкс(ЗначениеСвойства) Тогда Если ЗначениеСвойства = Неопределено Тогда // Скорость критична ЗначениеСвойства = ВхождениеСвойства.SubMatches(2); КонецЕсли; //Если ирОбщий.ЛиПустаяПодгруппаRegExpЛкс(ЗначениеСвойства) Тогда Если ЗначениеСвойства = Неопределено Тогда // Скорость критична ЗначениеСвойства = ВхождениеСвойства.SubMatches(1); КонецЕсли; //Если ирОбщий.ЛиПустаяПодгруппаRegExpЛкс(ЗначениеСвойства) Тогда Если ЗначениеСвойства = Неопределено Тогда // Скорость критична Продолжить; КонецЕсли; ИмяКолонкиТЧ = мСоответствиеКолонок[НРег(ИмяСвойства)]; Если ИмяКолонкиТЧ = Неопределено Тогда //Если НеизвестныеСвойства[ИмяСвойства] = Неопределено Тогда // НеизвестныеСвойства[ИмяСвойства] = 1; // Сообщить("Обнаружено неизвестное свойство """ + ИмяСвойства + """ события " + ТипСобытия, СтатусСообщения.Информация); //КонецЕсли; СтрокаТЧ.НеизвестныеСвойства = СтрокаТЧ.НеизвестныеСвойства + ИмяСвойства + "=" + ЗначениеСвойства + ", "; Иначе //Если мЧисловыеСвойства.Свойство(ИмяКолонкиТЧ) Тогда // Если Не ЗначениеЗаполнено(ЗначениеСвойства) Тогда // ЗначениеСвойства = 0; // Иначе // Попытка // ЗначениеСвойства = Число(ЗначениеСвойства); // Исключение // ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения числового свойства """ + ИмяКолонкиТЧ + """"; // КонецПопытки; // КонецЕсли; //КонецЕсли; Если ТипЗнч(СтрокаТЧ[ИмяКолонкиТЧ]) = Тип("Булево") Тогда ЗначениеСвойства = ?(ЗначениеСвойства = "1" Или Нрег(ЗначениеСвойства) = "true", Истина, Ложь); КонецЕсли; Если Не мНепустыеКолонкиЖурнала.Свойство(ИмяКолонкиТЧ) Тогда Если ЗначениеЗаполнено(ЗначениеСвойства) Тогда мНепустыеКолонкиЖурнала.Вставить(ИмяКолонкиТЧ); КонецЕсли; КонецЕсли; Попытка СтрокаТЧ[ИмяКолонкиТЧ] = ЗначениеСвойства; Исключение ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения свойства """ + ИмяКолонкиТЧ + """"; КонецПопытки; КонецЕсли; КонецЦикла; #КонецЕсли // Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru) Для Каждого ВхождениеСвойства Из ВхожденияСвойств Цикл       ИмяСвойства = ВхождениеСвойства.SubMatches(0);   ЗначениеСвойства = ВхождениеСвойства.SubMatches(3);     Если ЗначениеСвойства = Неопределено Тогда   ЗначениеСвойства = ВхождениеСвойства.SubMatches(2);   КонецЕсли;     Если ЗначениеСвойства = Неопределено Тогда   ЗначениеСвойства = ВхождениеСвойства.SubMatches(1);   КонецЕсли;     Если ЗначениеСвойства = Неопределено Тогда   Продолжить;   КонецЕсли;   ИмяКолонкиТЧ = мСоответствиеКолонок[НРег(ИмяСвойства)];   Если ИмяКолонкиТЧ = Неопределено Тогда           СтрокаТЧ.НеизвестныеСвойства = СтрокаТЧ.НеизвестныеСвойства + ИмяСвойства + "=" + ЗначениеСвойства + ", ";   Иначе                         Если ТипЗнч(СтрокаТЧ[ИмяКолонкиТЧ]) = Тип("Булево") Тогда   ЗначениеСвойства = ?(ЗначениеСвойства = "1" Или Нрег(ЗначениеСвойства) = "true", Истина, Ложь);   КонецЕсли;   Если Не мНепустыеКолонкиЖурнала.Свойство(ИмяКолонкиТЧ) Тогда   Если ЗначениеЗаполнено(ЗначениеСвойства) Тогда   мНепустыеКолонкиЖурнала.Вставить(ИмяКолонкиТЧ);   КонецЕсли;   КонецЕсли;   Попытка   СтрокаТЧ[ИмяКолонкиТЧ] = ЗначениеСвойства;   Исключение   ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения свойства """ + ИмяКолонкиТЧ + """";   КонецПопытки;   КонецЕсли;   КонецЦикла;   //АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + Вхождение.Length; Если Истина И ОтборПоСеансу <> Неопределено И СтрокаТЧ.Сеанс <> ОтборПоСеансу Тогда ТаблицаЖурнала.Удалить(СтрокаТЧ); СтрокаТЧ = Неопределено; #Если Сервер И Не Сервер Тогда СтрокаТЧ = ТаблицаЖурнала.Добавить(); #КонецЕсли Продолжить; КонецЕсли; //Если НаСервере <> Неопределено Тогда // СтрокаТЧ.НаСервере = НаСервере; //Иначе Если Ложь Или ТипСобытия = "SCOM" Тогда СтрокаТЧ.НаСервере = Истина; Иначе ИмяТипаПроцесса = "_" + СтрЗаменить(СтрокаТЧ.ТипПроцессаОС, "#", ""); Попытка СтрокаТЧ.НаСервере = мСерверныеТипыПроцессов.Свойство(ИмяТипаПроцесса); Исключение // Бывают типы процессов с UID, к сожалению тогда невозможно определить КонецПопытки; КонецЕсли; //КонецЕсли; Если СтрокаТЧ.Контекст <> "" Тогда КонтекстТД = Новый ТекстовыйДокумент; КонтекстТД.УстановитьТекст(СтрокаТЧ.Контекст); СтрокаТЧ.СтрокаМодуля = СокрЛП(КонтекстТД.ПолучитьСтроку(КонтекстТД.КоличествоСтрок())); Если БазовыйУровеньСтека > 0 Тогда ЗаполнитьСтрокуБазовогоУровня(СтрокаТЧ); КонецЕсли; КонецЕсли; //Если ДатаТекущегоСобытия > лПоследнееВремяНачалаЗагрузки - НаложениеПриДозагрузкеСекунд Тогда // НовыеКлючиЗагруженныхСтрок[КлючСтроки] = 1; //КонецЕсли; Если ирОбщий.СтрокиРавныЛкс(ТипСобытия, "Context") Тогда // Встроим контекст в предыдущие события Индекс = ТаблицаЖурнала.Количество() - 2; Пока Индекс >= 0 Цикл СтрокаБезКонтекста = ТаблицаЖурнала[Индекс]; Индекс = Индекс - 1; Если Ложь Или СтрокаБезКонтекста.Сеанс <> СтрокаТЧ.Сеанс Или СтрокаБезКонтекста.Инфобаза <> СтрокаТЧ.Инфобаза Тогда Прервать; КонецЕсли; Если Не СтрокаБезКонтекста.СтрокаМодуля = "" Тогда Прервать; КонецЕсли; ЗаполнитьЗначенияСвойств(СтрокаБезКонтекста, СтрокаТЧ, "СтрокаМодуля, Контекст"); КонецЦикла; КонецЕсли; КонецЦикла; Если ДостигнутоПредельноеКоличество Тогда Прервать; КонецЕсли; // Для отката к началу последнего события РазмерТекущейПорции = СтрДлина(ПорцияТекстаФайла); АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + СтрДлина(ТекстФайла); Если РазмерТекущейПорции = РазмерПорции Тогда //Если СтрокаТЧ <> Неопределено Тогда // ТаблицаЖурнала.Удалить(ТаблицаЖурнала.Количество() - 1); //КонецЕсли; Если Вхождение <> Неопределено Тогда ТекстФайла = Сред(ТекстФайла, Вхождение.FirstIndex); Иначе ТекстФайла = Прав(ТекстФайла, 1000); // Страховка КонецЕсли; АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле - СтрДлина(ТекстФайла); Иначе ТекстФайла = ""; КонецЕсли; КонецЦикла; Если ИндикаторФайла <> Неопределено Тогда ирОбщий.ОсвободитьИндикаторПроцессаЛкс(); КонецЕсли; Если ДостигнутоПредельноеКоличество Тогда ТекстСообщения = "Загрузка остановлена по достижению максимального количества событий в таблице"; Если Не ЗначениеЗаполнено("" + ФильтрЗагрузки) Тогда ТекстСообщения = ТекстСообщения + ". Если задать фильтр отображения таблицы, то будет предложено применить его при загрузке нового журнала."; КонецЕсли; Сообщить(ТекстСообщения); Прервать; КонецЕсли; КартаФайла.ПозицияКонца = АбсолютнаяПозицияВФайле; Если Истина И ПозицияНачалаСчитанныхДанных <> -1 И (Ложь Или КартаФайла.ПозицияНачала = -1 Или КартаФайла.ПозицияНачала > ПозицияНачалаСчитанныхДанных) Тогда КартаФайла.ПозицияНачала = ПозицияНачалаСчитанныхДанных; КонецЕсли; Если Ложь Или Не ЗначениеЗаполнено(КонецПериода) Или КонецПериода > КартаФайла.КонецПериода Тогда КартаФайла.КонецПериода = КонецПериода; КонецЕсли; Если Ложь Или Не ЗначениеЗаполнено(НачалоПериода) Или НачалоПериода < КартаФайла.НачалоПериода Тогда КартаФайла.НачалоПериода = НачалоПериода; КонецЕсли; КонецЦикла; ирОбщий.ОсвободитьИндикаторПроцессаЛкс(); УдалитьСтрокиВнеФильтра(); //КлючиЗагруженныхСтрок = НовыеКлючиЗагруженныхСтрок; //Если НаСервере = Истина Тогда // ЭтотОбъект.ПоследнееВремяНачалаЗагрузкиСервера = лПоследнееВремяНачалаЗагрузки; //Иначе // ЭтотОбъект.ПоследнееВремяНачалаЗагрузки = лПоследнееВремяНачалаЗагрузки; //КонецЕсли; //МинимальнаяДатаЗагрузки = Мин(НачалоПериода, МинимальнаяДатаЗагрузки); ТаблицаЖурнала.Сортировать("МоментВремени"); //ТаблицаЖурнала.Сортировать("МоментВремениНачала"); ОпределитьНепустыеКолонки(); Возврат Истина; КонецФункции Процедура УдалитьСтрокиВнеФильтра() Если ЗначениеЗаполнено("" + ФильтрЗагрузки) Тогда Построитель = Новый ПостроительЗапроса; Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаЖурнала); ирОбщий.СкопироватьОтборПостроителяЛкс(Построитель.Отбор, ФильтрЗагрузки); ТаблицаЖурнала.Загрузить(Построитель.Результат.Выгрузить()); КонецЕсли; КонецПроцедуры Процедура ОпределитьНепустыеКолонки() Экспорт Если мНепустыеКолонкиЖурнала.Количество() = 0 Тогда Для Каждого Реквизит Из Метаданные().ТабличныеЧасти.ТаблицаЖурнала.Реквизиты Цикл Если ТаблицаЖурнала.НайтиСтроки(Новый Структура(Реквизит.Имя, Реквизит.Тип.ПривестиЗначение())).Количество() < ТаблицаЖурнала.Количество() Тогда мНепустыеКолонкиЖурнала.Вставить(Реквизит.Имя); КонецЕсли; КонецЦикла; КонецЕсли; //Пустота производных колонок мНепустыеКолонкиЖурнала.Вставить("Длительность"); мНепустыеКолонкиЖурнала.Вставить("Дата"); мНепустыеКолонкиЖурнала.Вставить("ДатаНачала"); //мНепустыеКолонкиЖурнала.Вставить("Картинка"); Если мНепустыеКолонкиЖурнала.Свойство("Контекст") Тогда мНепустыеКолонкиЖурнала.Вставить("СтрокаМодуля"); мНепустыеКолонкиЖурнала.Вставить("СтрокаБазовогоМодуля"); КонецЕсли; КонецПроцедуры Функция ПолучитьМоментВремени(Дата, Микросекунды) Экспорт Результат = Формат(Дата, "ДФ=yyyyMMddHHmmss") + Формат(Микросекунды, "ЧЦ=6; ЧВН=; ЧГ="); Возврат Результат; КонецФункции Функция РазностьМоментовВремени(МоментВремениУменьшаемый, МоментВремениВычитаемый) Экспорт Если СтрДлина(МоментВремениВычитаемый) <> СтрДлина(МоментВремениВычитаемый) Тогда ВызватьИсключение "Размерность моментов времени не совпадает"; КонецЕсли; ДлинаЧастиДаты = 14; ДатаУменьшаемая = Дата(Лев(МоментВремениУменьшаемый, ДлинаЧастиДаты)); ДатаВычитаемая = Дата(Лев(МоментВремениВычитаемый, ДлинаЧастиДаты)); РазрядностьДолейСекунд = СтрДлина(МоментВремениУменьшаемый) - ДлинаЧастиДаты; РазностьСекунд = ДатаУменьшаемая - ДатаВычитаемая; Результат = РазностьСекунд; Для Счетчик = 1 По РазрядностьДолейСекунд Цикл Результат = Результат * 10; КонецЦикла; Результат = Результат + Число(Сред(МоментВремениУменьшаемый, ДлинаЧастиДаты + 1)) - Число(Сред(МоментВремениВычитаемый, ДлинаЧастиДаты + 1)); Возврат Результат; КонецФункции // РазностьМоментовВремени() Функция ЗаполнитьСтрокуБазовогоУровня(СтрокаТЧ) Если БазовыйУровеньСтека > 0 Тогда //МаркерБазовогоМодуля = Символы.Таб + мИмяБазовогоМодуля + " : "; //ПозицияМаркераМодуля = Найти(СтрокаТЧ.Контекст, МаркерБазовогоМодуля); //КонецСтроки = Сред(СтрокаТЧ.Контекст, ПозицияМаркераМодуля + СтрДлина(МаркерБазовогоМодуля)); НовоеЗначение = СокрЛ(СтрПолучитьСтроку(СтрокаТЧ.Контекст, БазовыйУровеньСтека)); Иначе НовоеЗначение = ""; КонецЕсли; ирОбщий.ПрисвоитьЕслиНеРавноЛкс(СтрокаТЧ.СтрокаМодуляБазовогоУровня, НовоеЗначение); Возврат Неопределено; КонецФункции // ПопытокЧтения - Число, используется только при РежимТрассы = Истина Функция ПрочитатьСобственныйЖурналДвухСторон(УдалитьДополнительныеСобытия = Истина, ИменаНеполезныхКолонок = "", РежимТрассы = Истина, ПопытокЧтения = 10, СмещениеБазовогоУровня = Неопределено) Если РежимТрассы Тогда Если мИдентификаторТрассы = Неопределено Тогда Если Не ирКэш.ЭтоФайловаяБазаЛкс() Тогда ирОбщий.ЛиТехножурналВключенЛкс(Истина, Истина, Истина); КонецЕсли; ирОбщий.ЛиТехножурналВключенЛкс(, Истина, Истина); Возврат Ложь; КонецЕсли; КонецЕсли; Если РежимТрассы Тогда ЭтотОбъект.ЗагружатьЖурналКлиента = Истина; ЭтотОбъект.ЗагружатьЖурналСервера = Не ирКэш.ЭтоФайловаяБазаЛкс(); ЭтотОбъект.ЗагружатьТолькоТекущийСеанс = Истина; КонецЕсли; ВыраниватьДатуПоСерверу = Ложь; #Если Клиент Тогда ВыраниватьДатуПоСерверу = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.ВыраниватьДатуПоСерверу") = Истина; #КонецЕсли Если РежимТрассы Тогда РазницаВремениКлиентСервер = НачалоПериодаКлиента - НачалоПериодаСервера; Иначе РазницаВремениКлиентСервер = ирОбщий.ПолучитьТекущуюДатуЛкс() - ирОбщий.ПолучитьТекущуюДатуЛкс(Истина); КонецЕсли; Если Истина И Не ирКэш.Получить().ЭтоФайловаяБаза И ЗагружатьЖурналСервера Тогда ЭтотОбъект.КаталогЖурнала = ""; Если ВыраниватьДатуПоСерверу Тогда СдвигВремени = 0; Иначе СдвигВремени = -РазницаВремениКлиентСервер; КонецЕсли; РезультатСервера = ПрочитатьСобственныйЖурналОднойСтороны(НачалоПериодаСервера, КонецПериодаСервера, Истина, СдвигВремени, РежимТрассы, ПопытокЧтения, СмещениеБазовогоУровня); КонецЕсли; Если ЗагружатьЖурналКлиента Тогда ЭтотОбъект.КаталогЖурнала = ""; Если ВыраниватьДатуПоСерверу Тогда СдвигВремени = РазницаВремениКлиентСервер; Иначе СдвигВремени = 0; КонецЕсли; РезультатКлиента = ПрочитатьСобственныйЖурналОднойСтороны(НачалоПериодаКлиента, КонецПериодаКлиента, Ложь, СдвигВремени, РежимТрассы, ПопытокЧтения, СмещениеБазовогоУровня); КонецЕсли; Если Истина И РезультатКлиента = Неопределено И РезультатСервера = Неопределено Тогда Возврат Ложь; КонецЕсли; Если УдалитьДополнительныеСобытия Тогда УдалитьСтрокиПоОтбору(Новый Структура("Действие", "getExecSQLStatistics")); УдалитьСтрокиПоОтбору(Новый Структура("Событие", "CONTEXT")); КонецЕсли; Если РежимТрассы Тогда ЭтотОбъект.ВключитьСвойстваСИменамиМетаданных = Истина; КонецЕсли; Если ВключитьСвойстваСИменамиМетаданных Тогда ОбновитьСвойстваВТерминахМетаданных(); КонецЕсли; //ОбновитьСтрокиБазовогоУровня(); Возврат Истина; КонецФункции Функция ПрочитатьСобственныйЖурналОднойСтороны(НачалоПериода = Неопределено, КонецПериода = Неопределено, НаСервере = Истина, СдвигВремени = 0, РежимТрассы = Истина, ПопытокЧтения = 10, СмещениеБазовогоУровня = Неопределено) Если НачалоПериода <> Неопределено Тогда ЭтотОбъект.НачалоПериода = НачалоПериода; КонецЕсли; Если КонецПериода <> Неопределено Тогда ЭтотОбъект.КонецПериода = КонецПериода; КонецЕсли; ТехножурналВключен = ирОбщий.ЛиТехножурналВключенЛкс(НаСервере,, Истина); Если Истина И Не ТехножурналВключен И РежимТрассы Тогда Возврат Неопределено; КонецЕсли; МассивТиповСУБД = Новый Массив(); Если ирКэш.ЭтоФайловаяБазаЛкс() Тогда МассивТиповСУБД.Добавить("DBV8DBENG"); //ОтборТЧ = Новый Структура("Событие", "SDBL"); Иначе МассивТиповСУБД.Добавить("DBMSSQL"); МассивТиповСУБД.Добавить("DBPOSTGRS"); МассивТиповСУБД.Добавить("DBORACLE"); МассивТиповСУБД.Добавить("DB2"); //ОтборТЧ = Новый Структура("Событие", "CONTEXT"); КонецЕсли; СообщитьРазмер = Неопределено; МаркерНачалаНайден = Ложь; Для Счетчик = 1 По ПопытокЧтения Цикл #Если Клиент Тогда ОбработкаПрерыванияПользователя(); #КонецЕсли Если Счетчик > 1 Тогда #Если Клиент Тогда Состояние("Ожидание техножурнала"); #КонецЕсли мПлатформа.Sleep(0.5); СообщитьРазмер = Ложь; КонецЕсли; ЖурналСчитан = ПрочитатьПроизвольныйЖурнал(СообщитьРазмер, СдвигВремени, , , НаСервере); Если Не ЖурналСчитан Тогда Возврат Неопределено; КонецЕсли; //ТехножурналВключен = ирОбщий.ЛиТехножурналВключенЛкс(Истина,, Истина); //Если ТехножурналВключен Тогда // Если АвтоочисткаТехножурнала Тогда // КаталогТекущегоЖурнала = ПолучитьКаталогТекущегоЖурнала(); // Если ЗначениеЗаполнено(КаталогТекущегоЖурнала) Тогда // ирОбщий.ОчиститьКаталогТехножурналаЛкс(КаталогТекущегоЖурнала, Истина, Ложь); // КонецЕсли; // КонецЕсли; //КонецЕсли; Если РежимТрассы Тогда Если Ложь Или Не ирКэш.ЛиПортативныйРежимЛкс() Или Не НаСервере Тогда МаркерНачала = Новый Структура("Описание", "{(1, 1)}: Ожидается выражение ""ВЫБРАТЬ"" |<>НачалоТрассы_" + мИдентификаторТрассы); МаркерКонца = Новый Структура("Описание", "{(1, 1)}: Ожидается выражение ""ВЫБРАТЬ"" |<>КонецТрассы_" + мИдентификаторТрассы); Иначе МаркерНачала = Новый Структура("ТекстSDBL", "SELECT |""НачалоТрассы_" + мИдентификаторТрассы + """ |"); МаркерКонца = Новый Структура("ТекстSDBL", "SELECT |""КонецТрассы_" + мИдентификаторТрассы + """ |"); КонецЕсли; // Удаляем лишние строки до маркера начала и после маркера конца Если Не МаркерНачалаНайден Тогда НайденныеСтроки = ТаблицаЖурнала.НайтиСтроки(МаркерНачала); Если НайденныеСтроки.Количество() = 0 Тогда Продолжить; КонецЕсли; НачальнаяСтрока = НайденныеСтроки[0]; #Если Сервер И Не Сервер Тогда НачальнаяСтрока = ТаблицаЖурнала.Добавить(); #КонецЕсли Если СмещениеБазовогоУровня <> Неопределено Тогда ЭтотОбъект.БазовыйУровеньСтека = СтрЧислоСтрок(НачальнаяСтрока.Контекст) + СмещениеБазовогоУровня; КонецЕсли; КонечныйИндекс = ТаблицаЖурнала.Индекс(НачальнаяСтрока); Для Индекс = 0 По КонечныйИндекс Цикл Если ТаблицаЖурнала[0].НаСервере = НаСервере Тогда ТаблицаЖурнала.Удалить(0); КонецЕсли; КонецЦикла; МаркерНачалаНайден = Истина; КонецЕсли; НайденныеСтроки = ТаблицаЖурнала.НайтиСтроки(МаркерКонца); Если НайденныеСтроки.Количество() = 0 Тогда Продолжить; КонецЕсли; КонечнаяСтрока = НайденныеСтроки[0]; НачальныйИндекс = ТаблицаЖурнала.Индекс(КонечнаяСтрока); Если Ложь Или НаСервере Или ирКэш.ЭтоФайловаяБазаЛкс() Тогда КонечнаяСтрока1 = ТаблицаЖурнала[НачальныйИндекс]; Если МассивТиповСУБД.Найти(КонечнаяСтрока1.Событие) <> Неопределено Тогда // Опасно. Учитывается регистр букв мТипСУБД = КонечнаяСтрока1.Событие; НачальныйИндекс = НачальныйИндекс - 1; КонецЕсли; КонецЕсли; НачальноеКоличество = ТаблицаЖурнала.Количество(); Для Индекс = 1 По НачальноеКоличество - НачальныйИндекс Цикл СтрокаЖурнала = ТаблицаЖурнала[НачальноеКоличество - Индекс]; Если СтрокаЖурнала.НаСервере = НаСервере Тогда ТаблицаЖурнала.Удалить(СтрокаЖурнала); КонецЕсли; КонецЦикла; Пока Истина И ТаблицаЖурнала.Количество() > 0 И ТаблицаЖурнала[0].НаСервере = НаСервере И Найти(ТаблицаЖурнала[0].Контекст, "Обработка.ирАнализТехножурнала.МодульОбъекта") > 0 Цикл ТаблицаЖурнала.Удалить(0); КонецЦикла; Пока Истина И ТаблицаЖурнала.Количество() > 0 И ТаблицаЖурнала[ТаблицаЖурнала.Количество() - 1].НаСервере = НаСервере И Найти(ТаблицаЖурнала[ТаблицаЖурнала.Количество() - 1].Контекст, "Обработка.ирАнализТехножурнала.МодульОбъекта") > 0 Цикл ТаблицаЖурнала.Удалить(ТаблицаЖурнала.Количество() - 1); КонецЦикла; КонецЕсли; Прервать; КонецЦикла; Если РежимТрассы Тогда Если КонечнаяСтрока = Неопределено Тогда Возврат Неопределено; КонецЕсли; // ФрагментыНачальнойСтрокиМодуля = ирОбщий.СтрРазделитьЛкс(ТаблицаЖурнала[0].СтрокаМодуля, ":", Истина); // ФрагментыКонечнойСтрокиМодуля = ирОбщий.СтрРазделитьЛкс(ТаблицаЖурнала[ТаблицаЖурнала.Количество() - 1].СтрокаМодуля, ":", Истина); // ИмяМодуляНачальнойСтроки = ФрагментыНачальнойСтрокиМодуля[0]; // ИмяМодуляКонечнойСтроки = ФрагментыКонечнойСтрокиМодуля[0]; // НомерНачальнойСтроки = Число(ФрагментыНачальнойСтрокиМодуля[1]); // НомерКонечнойСтроки = Число(ФрагментыКонечнойСтрокиМодуля[1]); // ЕстьВызовыМетодовМодулей = Ложь // Или ИмяМодуляНачальнойСтроки <> ИмяМодуляНачальнойСтроки // Или НомерНачальнойСтроки > НомерКонечнойСтроки; // СтрокиВызововМетодов = НайтиВызовыМетодовМодулей(ИмяМодуляНачальнойСтроки, НомерНачальнойСтроки, НомерКонечнойСтроки, Истина); // Если СтрокиВызововМетодов.Количество() > 0 Тогда // Ответ = Вопрос("В трассе обнаружены вызовы методов модулей. Хотите удалить их из трассы?", РежимДиалогаВопрос.ДаНет); // Если Ответ = КодВозвратаДиалога.Да Тогда // СтрокиВызововМетодов = НайтиВызовыМетодовМодулей(ИмяМодуляНачальнойСтроки, НомерНачальнойСтроки, НомерКонечнойСтроки, Ложь); // Для Каждого СтрокаВызоваМетода Из СтрокиВызововМетодов Цикл // ТаблицаЖурнала.Удалить(СтрокаВызоваМетода); // КонецЦикла; // КонецЕсли; // КонецЕсли; КонецЕсли; Возврат Истина; КонецФункции Функция ПрочитатьЖурнал(Фильтр = Неопределено) Экспорт БазовыйУровеньКонтекста = 0; ЭтотОбъект.КонецПериодаСервера = Неопределено; ЭтотОбъект.КонецПериодаКлиента = Неопределено; ЭтотОбъект.НачалоПериодаСервера = Неопределено; ЭтотОбъект.НачалоПериодаКлиента = Неопределено; ЭтотОбъект.ФильтрЗагрузки = Фильтр; Если Ложь Или ЗагружатьЖурналКлиента Или ЗагружатьЖурналСервера Тогда ЖурналПрочитан = ПрочитатьСобственныйЖурналДвухСторон(,, Ложь); Иначе ЖурналПрочитан = ПрочитатьПроизвольныйЖурнал(); Если ВключитьСвойстваСИменамиМетаданных Тогда ОбновитьСвойстваВТерминахМетаданных(); КонецЕсли; КонецЕсли; Возврат ЖурналПрочитан; КонецФункции // ТолькоПустые - заполнять только ранее не заполненные свойства Процедура ЗаполнитьСвойстваСИменамиМетаданных(ВыбраннаяСтрока, Принудительно = Ложь) Экспорт Если Не Принудительно И ВыбраннаяСтрока.СвойстваСИменамиМетаданныхАктуальны Тогда Возврат; КонецЕсли; Попытка Инфобаза = ВыбраннаяСтрока.Инфобаза; Исключение Инфобаза = ""; КонецПопытки; ЧужаяСхемаБД = ирОбщий.ПолучитьЧужуюСхемуБДЛкс(мАдресЧужойСхемыБД); ЭтоГарантированоСобытиеВыбраннойЧужойБазы = Истина И ЗначениеЗаполнено(Инфобаза) И ЧужаяСхемаБД <> Неопределено И ирОбщий.СтрокиРавныЛкс(Инфобаза, НСтр(ЧужаяСхемаБД.СтрокаСоединения, "Ref")); ЭтоГарантированоСобытиеСобственнойБазы = Истина И ЗначениеЗаполнено(Инфобаза) И Не ЭтоГарантированоСобытиеВыбраннойЧужойБазы И ирОбщий.СтрокиРавныЛкс(Инфобаза, НСтр(СтрокаСоединенияИнформационнойБазы(), "Ref")); НайденныеТаблицы = Новый ТаблицаЗначений; Для Каждого КлючИЗначение Из мСвойстваСИменамиБД Цикл ИмяСвойства = КлючИЗначение.Ключ; Если Найти(ИмяСвойства, "Шаблон") > 0 Тогда Продолжить; КонецЕсли; Попытка Пустышка = ТипЗнч(ВыбраннаяСтрока[ИмяСвойства]); // т.к. строки длинные, то их копирование в новую переменную накладно Исключение // Такого свойства нет - пропускаем Продолжить; КонецПопытки; ЗначениеСвойства = ВыбраннаяСтрока[ИмяСвойства]; // Берем только имя базы, т.к. кластер может быть по-разному написан Если Истина И ЗначениеЗаполнено(ЗначениеСвойства) И (Ложь Или Инфобаза = "" Или ЭтоГарантированоСобытиеСобственнойБазы Или ЭтоГарантированоСобытиеВыбраннойЧужойБазы) Тогда ЛиМенаБД = КлючИЗначение.Значение; Если Не ЛиМенаБД Тогда ТипСУБД = ""; Иначе Попытка ТипСУБД = ВыбраннаяСтрока.Событие; Исключение ТипСУБД = Сред(ИмяСвойства, СтрДлина("Текст") + 1); // Опасно КонецПопытки; КонецЕсли; //Попытка ТекстМета = ПеревестиТекстБДВТерминыМетаданных(ЗначениеСвойства, , , ТипСУБД, НайденныеТаблицы,, Ложь,, ЭтоГарантированоСобытиеСобственнойБазы); //Исключение // ТекстМета = ""; //КонецПопытки; //Если ТекстМета <> "" Тогда ВыбраннаяСтрока[ИмяСвойства + "Мета"] = ТекстМета; //КонецЕсли; Иначе // База чужая. Не делаем преобразования //ВыбраннаяСтрока[ИмяСвойства + "Мета"] = ЗначениеСвойства; КонецЕсли; КонецЦикла; Если НайденныеТаблицы.Количество() > 0 Тогда НайденныеТаблицы.Свернуть("ИмяМета"); НайденныеТаблицы.Сортировать("ИмяМета"); ВыбраннаяСтрока.ТаблицыМетаданных = ирОбщий.СтрСоединитьЛкс(НайденныеТаблицы.ВыгрузитьКолонку("ИмяМета")); мНепустыеКолонкиЖурнала.Вставить("ТаблицыМетаданных"); КонецЕсли; Попытка ТекстSDBLШаблонМета = ВыбраннаяСтрока.ТекстSDBLШаблонМета; Исключение ТекстSDBLШаблонМета = Неопределено; КонецПопытки; Если ТекстSDBLШаблонМета <> Неопределено Тогда Инфобаза = ""; ТекстSDBLМета = ""; Попытка Инфобаза = ВыбраннаяСтрока.Инфобаза; ТекстSDBLМета = ВыбраннаяСтрока.ТекстSDBLМета; Исключение КонецПопытки; Если Ложь Или Инфобаза = "" Или ЭтоГарантированоСобытиеСобственнойБазы Или ЭтоГарантированоСобытиеВыбраннойЧужойБазы Тогда Если Истина И ТекстSDBLМета <> "" Тогда ВыбраннаяСтрока.ТекстSDBLШаблонМета = ПолучитьШаблонТекстаБД(ТекстSDBLМета); Иначе ВыбраннаяСтрока.ТекстSDBLШаблонМета = ПеревестиТекстБДВТерминыМетаданных(ВыбраннаяСтрока.ТекстSDBLШаблон,,,,,, Ложь,, ЭтоГарантированоСобытиеСобственнойБазы); КонецЕсли; КонецЕсли; КонецЕсли; Попытка ТекстСУБДШаблонМета = ВыбраннаяСтрока.ТекстСУБДШаблонМета; Исключение ТекстСУБДШаблонМета = Неопределено; КонецПопытки; Если ТекстСУБДШаблонМета <> Неопределено Тогда Инфобаза = ""; ТекстСУБДМета = ""; Попытка Инфобаза = ВыбраннаяСтрока.Инфобаза; ТекстСУБДМета = ВыбраннаяСтрока.ТекстСУБДМета; Исключение КонецПопытки; Если Ложь Или Инфобаза = "" Или ЭтоГарантированоСобытиеСобственнойБазы Или ЭтоГарантированоСобытиеВыбраннойЧужойБазы Тогда Если Истина И ТекстСУБДМета <> "" Тогда ВыбраннаяСтрока.ТекстСУБДШаблонМета = ПолучитьШаблонТекстаБД(ТекстСУБДМета); Иначе ВыбраннаяСтрока.ТекстСУБДШаблонМета = ПеревестиТекстБДВТерминыМетаданных(ВыбраннаяСтрока.ТекстСУБДШаблон,,, мТипСУБД,,, Ложь,, ЭтоГарантированоСобытиеСобственнойБазы); КонецЕсли; КонецЕсли; КонецЕсли; ВыбраннаяСтрока.СвойстваСИменамиМетаданныхАктуальны = Истина; КонецПроцедуры Функция ПолучитьКаталогТекущегоЖурнала(НаСервере) Экспорт Результат = Неопределено; Если НаСервере Тогда #Если Клиент Тогда Если мАнализТрассыЗапроса = Истина Тогда Результат = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.КаталогТрассировкиЗапросов"); Иначе Результат = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.КаталогЖурналаСервера"); КонецЕсли; #КонецЕсли КонецЕсли; Если Не ЗначениеЗаполнено(Результат) Тогда Если мАнализТрассыЗапроса = Истина Тогда Результат = ирСервер.КаталогТрассировкиЗапросовЛкс(); Иначе Результат = ирОбщий.КаталогТехножурналаЛкс(НаСервере); КонецЕсли; Если Не ЗначениеЗаполнено(Результат) Тогда Если НаСервере Тогда ТекстКлиентСервер = "сервера"; Иначе ТекстКлиентСервер = "клиента"; КонецЕсли; Сообщить("Технологический журнал " + ТекстКлиентСервер + " выключен. Невозможно определить каталог журнала по умолчанию."); Возврат Неопределено; КонецЕсли; Если НаСервере Тогда КлиентЗапущенНаКомпьютереСервера = ирОбщий.ЛиКлиентЗапущенНаКомпьютереСервераЛкс(); Если Не КлиентЗапущенНаКомпьютереСервера Тогда Если ЭтоЛокальныйПутьЛкс(Результат) Тогда Сообщить("Клиент запущен не на компьютере сервера (" + ирСервер.ПолучитьИмяКомпьютераЛкс() + "), а в серверной настройке техножурнала указан локальный каталог. Необходимо указать сетевой путь к техножурналу сервера"); #Если Клиент Тогда ФормаНастройки = ПолучитьФорму("НастройкаЧтения"); РезультатНастройки = ФормаНастройки.ОткрытьМодально(); Если РезультатНастройки = Истина Тогда Если мАнализТрассыЗапроса = Истина Тогда Результат = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.КаталогТрассировкиЗапросов"); Иначе Результат = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.КаталогЖурналаСервера"); КонецЕсли; Иначе Результат = Неопределено; КонецЕсли; #КонецЕсли КонецЕсли; КонецЕсли; КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Функция ЭтоЛокальныйПутьЛкс(Путь) Экспорт ЭтоЛокальныйРесурс = Ложь Или Найти(НРег(Путь), "\\localhost") = 1 Или Найти(НРег(Путь), "\\127.0.0.1") = 1 Или Лев(Путь, 2) <> "\\"; Возврат ЭтоЛокальныйРесурс; КонецФункции // ЭтоЛокальныйПуть() Функция ОткрытьСПараметрами(пКаталогЖурнала) Экспорт Форма = ПолучитьФорму(); Форма.Открыть(); ЭтотОбъект.ЗагружатьТолькоТекущийСеанс = Ложь; ЭтотОбъект.ЗагружатьЖурналСервера = Ложь; ЭтотОбъект.ЗагружатьЖурналКлиента = Ложь; Форма.ОбновитьДоступность(); Форма.КаталогЖурнала = пКаталогЖурнала; Возврат Форма; КонецФункции Функция ОткрытьСОтбором(НачалоПериода = Неопределено, КонецПериода = Неопределено, СтруктураОтбора = Неопределено) Экспорт Форма = ПолучитьФорму(,,); Форма.Открыть(); Отбор = Форма.ЭлементыФормы.ТаблицаЖурнала.ОтборСтрок; Отбор.Сбросить(); Если НачалоПериода <> Неопределено Тогда Форма.НачалоПериода = НачалоПериода; КонецЕсли; Если КонецПериода <> Неопределено Тогда Форма.КонецПериода = КонецПериода; КонецЕсли; Если СтруктураОтбора <> Неопределено Тогда Для Каждого КлючИЗначение Из СтруктураОтбора Цикл Отбор[КлючИЗначение.Ключ].Установить(КлючИЗначение.Значение); КонецЦикла; КонецЕсли; Возврат Форма; КонецФункции Функция ПолучитьИмяСвойстваБезМета(Знач МестноеИмя) Экспорт Если ирОбщий.СтрокиРавныЛкс(Прав(МестноеИмя, 4), "мета") Тогда МестноеИмя = Лев(МестноеИмя, СтрДлина(МестноеИмя) - 4); КонецЕсли; Возврат МестноеИмя; КонецФункции Процедура ОбновитьСвойстваВТерминахМетаданных() Экспорт ВыбранныеСтроки = ТаблицаЖурнала.НайтиСтроки(Новый Структура("СвойстваСИменамиМетаданныхАктуальны", Ложь)); Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ВыбранныеСтроки.Количество(), "Перевод в термины метаданных"); Для Каждого СтрокаТаблицыЖурнала Из ВыбранныеСтроки Цикл ирОбщий.ОбработатьИндикаторЛкс(Индикатор); ЗаполнитьСвойстваСИменамиМетаданных(СтрокаТаблицыЖурнала); КонецЦикла; ирОбщий.ОсвободитьИндикаторПроцессаЛкс(); КонецПроцедуры Процедура ОбновитьСтрокиБазовогоУровня() Экспорт //Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ТаблицаЖурнала.Количество()); Для Каждого СтрокаТаблицыЖурнала Из ТаблицаЖурнала Цикл //ирОбщий.ОбработатьИндикаторЛкс(Индикатор); ЗаполнитьСтрокуБазовогоУровня(СтрокаТаблицыЖурнала); КонецЦикла; //Для Каждого СтрокаКонтекста Из Контексты Цикл // ЗаполнитьСтрокуБазовогоУровня(СтрокаКонтекста); //КонецЦикла; КонецПроцедуры Функция ПолучитьШаблонТекстаБД(ТекстБД, ЗаменаПеременныхФрагментов = "7") Экспорт ШаблонТекстаБД = RegExpПараметры.Replace(ТекстБД, "$1$2" + ЗаменаПеременныхФрагментов); Возврат ШаблонТекстаБД; КонецФункции Процедура ЗаполнитьСвойстваШаблоны() Экспорт Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ТаблицаЖурнала.Количество()); Для Каждого СтрокаТаблицыЖурнала Из ТаблицаЖурнала Цикл ирОбщий.ОбработатьИндикаторЛкс(Индикатор); Если Истина И СтрокаТаблицыЖурнала.ТекстSDBL <> "" И СтрокаТаблицыЖурнала.ТекстSDBLШаблон = "" Тогда СтрокаТаблицыЖурнала.ТекстSDBLШаблон = ПолучитьШаблонТекстаБД(СтрокаТаблицыЖурнала.ТекстSDBL); КонецЕсли; Если Истина И СтрокаТаблицыЖурнала.ТекстСУБД <> "" И СтрокаТаблицыЖурнала.ТекстСУБДШаблон = "" Тогда СтрокаТаблицыЖурнала.ТекстСУБДШаблон = ПолучитьШаблонТекстаБД(СтрокаТаблицыЖурнала.ТекстСУБД); КонецЕсли; Если Истина И СтрокаТаблицыЖурнала.Описание <> "" И СтрокаТаблицыЖурнала.ОписаниеШаблон = "" Тогда СтрокаТаблицыЖурнала.ОписаниеШаблон = ПолучитьШаблонТекстаБД(СтрокаТаблицыЖурнала.Описание); КонецЕсли; КонецЦикла; КонецПроцедуры Процедура ОставитьТолькоСтрокиПоОтбору(СтруктураОтбора) Экспорт НужныеСтроки = ТаблицаЖурнала.НайтиСтроки(СтруктураОтбора); КоличествоСтрок = ТаблицаЖурнала.Количество(); Для Счетчик = 1 По КоличествоСтрок Цикл Индекс = КоличествоСтрок - Счетчик; СтрокаЖурнала = ТаблицаЖурнала[Индекс]; Если НужныеСтроки.Найти(СтрокаЖурнала) = Неопределено Тогда ТаблицаЖурнала.Удалить(СтрокаЖурнала); КонецЕсли; КонецЦикла; КонецПроцедуры Процедура УдалитьСтрокиПоОтбору(СтруктураОтбора) Экспорт НенужныеСтроки = ТаблицаЖурнала.НайтиСтроки(СтруктураОтбора); Для Каждого НенужнаяСтрока Из НенужныеСтроки Цикл ТаблицаЖурнала.Удалить(НенужнаяСтрока); КонецЦикла; КонецПроцедуры Процедура ЗаписатьМаркерВТехножурнал(Маркер, ДляКлиента = Истина, ДляСервера = Истина) Экспорт ЗапросМаркер = Новый Запрос(); Если ДляКлиента Тогда ЗапросМаркер.Текст = Маркер; Попытка ЗапросМаркер.Выполнить(); // Генерируем для клиента маркер-событие QERR Исключение КонецПопытки; КонецЕсли; Если Истина И ДляСервера И Не ирКэш.ЭтоФайловаяБазаЛкс() Тогда Если Не ирКэш.ЛиПортативныйРежимЛкс() Тогда Попытка ирСервер.ВыполнитьЗапросЛкс(Маркер); // Генерируем для сервера маркер-событие QERR Исключение КонецПопытки; Иначе ЗапросМаркер.Текст = "ВЫБРАТЬ """ + Маркер + """"; Попытка ЗапросМаркер.Выполнить(); // Генерируем для клиента маркер-событие SDBL Исключение // Может возникнуть ошибка "В данной транзакции уже происходили ошибки!" КонецПопытки; КонецЕсли; КонецЕсли; КонецПроцедуры Функция НачатьТрассу(ПрефиксТрассы = "", ВыводитьСообщения = Ложь) Экспорт Если ВыводитьСообщения Тогда // Попробовать сделать проверку регистрации событий QERR в настройке техножурнала на сервере // Вызовы ЛиТехножурналВключенЛкс могут быть очень долгими, если в анализе техножурнала пользователь сохранил сетевой путь к логам на сервере и он недоступен Если Не ирКэш.ЭтоФайловаяБазаЛкс() Тогда ТехножурналСервераВключен = ирОбщий.ЛиТехножурналВключенЛкс(Истина, ВыводитьСообщения); КонецЕсли; ТехножурналКлиентаВключен = ирОбщий.ЛиТехножурналВключенЛкс(, ВыводитьСообщения); Если Истина И ТехножурналСервераВключен <> Истина И Не ТехножурналКлиентаВключен Тогда Возврат Ложь; КонецЕсли; КонецЕсли; ЭтотОбъект.КонецПериодаСервера = Неопределено; ЭтотОбъект.КонецПериодаКлиента = Неопределено; ЭтотОбъект.НачалоПериодаСервера = ирОбщий.ПолучитьТекущуюДатуЛкс(Истина); ЭтотОбъект.НачалоПериодаКлиента = ирОбщий.ПолучитьТекущуюДатуЛкс(Ложь); мИдентификаторТрассы = ПрефиксТрассы + "_" + СтрЗаменить(Новый УникальныйИдентификатор(), "-", ""); ЗаписатьМаркерВТехножурнал("НачалоТрассы_" + мИдентификаторТрассы); Возврат Истина; КонецФункции Функция КончитьТрассу() Экспорт Если ЗначениеЗаполнено(ЭтотОбъект.КонецПериодаКлиента) Тогда Возврат Ложь; КонецЕсли; ЗаписатьМаркерВТехножурнал("КонецТрассы_" + мИдентификаторТрассы); ЭтотОбъект.КонецПериодаСервера = ирОбщий.ПолучитьТекущуюДатуЛкс(Истина); ЭтотОбъект.КонецПериодаКлиента = ирОбщий.ПолучитьТекущуюДатуЛкс(Ложь); Возврат Истина; КонецФункции Функция ПолучитьТекстSQLДляПоискаВТехножурнале(Текст) Экспорт RegExpМета.Pattern = "([^A-ZА-ЯЁ_0-9]|^)(?:@P\d+)"; Результат = RegExpМета.Replace(Текст, "$1?"); Возврат Результат; КонецФункции #Если Клиент Тогда Функция ПоказатьТрассу(УдалитьДополнительныеСобытия = Истина, ИменаНеполезныхКолонок = "", ПопытокЧтения = 10, СмещениеБазовогоУровня = Неопределено) Экспорт Если ЭтотОбъект.КонецПериодаСервера = Неопределено Тогда Предупреждение("Сформируйте трассу заново"); Возврат Неопределено; КонецЕсли; ОчиститьТаблицуЖурнала(); ЖурналПрочитан = ПрочитатьСобственныйЖурналДвухСторон(УдалитьДополнительныеСобытия, ИменаНеполезныхКолонок, Истина, ПопытокЧтения, СмещениеБазовогоУровня); Если Не ЖурналПрочитан Тогда Сообщить("Не удалось найти маркеры трассы в логах. Проверьте включенность регистрации события QERR в настройке техножурнала"); Возврат Неопределено; КонецЕсли; ВыраниватьДатуПоСерверу = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.ВыраниватьДатуПоСерверу") = Истина; лКаталогЖурнала = КаталогЖурнала; ФормаАнализа = ПолучитьФорму(); ФормаАнализа.ЭтоТрасса = Истина; ФормаАнализа.Открыть(); ФормаАнализа.ЗагружатьТолькоТекущийСеанс = Истина; ФормаАнализа.ЗагружатьЖурналКлиента = Истина; ФормаАнализа.ЗагружатьЖурналСервера = Не ирКэш.ЭтоФайловаяБазаЛкс(); Если ВыраниватьДатуПоСерверу Тогда ФормаАнализа.КонецПериода = КонецПериодаСервера; ФормаАнализа.НачалоПериода = НачалоПериодаСервера; Иначе ФормаАнализа.КонецПериода = КонецПериодаКлиента; ФормаАнализа.НачалоПериода = НачалоПериодаКлиента; КонецЕсли; ФормаАнализа.КаталогЖурнала = лКаталогЖурнала; ФормаАнализа.УстановитьРежимИтогов(ТаблицаЖурнала.Количество() > 20); ФормаАнализа.ПериодПоследниеМинуты = 0; ФормаАнализа.ОбновитьДоступность(); ФормаАнализа.ЭлементыФормы.ПанельНастройки.ТекущаяСтраница = ФормаАнализа.ЭлементыФормы.ПанельНастройки.Страницы.Анализ; ФормаАнализа.УстановитьБесполезныеКолонки(ИменаНеполезныхКолонок); Если мАнализТрассыЗапроса = Истина Тогда ТаблицаЖурнала.Сортировать("МоментВремениНачала"); КонецЕсли; Возврат ФормаАнализа; КонецФункции Функция ПоказатьТрассуЗапроса() Экспорт мАнализТрассыЗапроса = Истина; ФормаАнализа = ПоказатьТрассу(, "СтрокаМодуля",, 0); мАнализТрассыЗапроса = Ложь; Возврат ФормаАнализа; КонецФункции Функция ОчиститьТаблицуЖурнала() Экспорт мНепустыеКолонкиЖурнала = Новый Структура(); ТаблицаЖурнала.Очистить(); Возврат Неопределено; КонецФункции Функция ОткрытьТекстБДВКонверторе(ТекстБД, СразуПеревестиВМета = Истина, КлючУникальности = Неопределено, ЭтоТекстSDBL = Истина) Экспорт ФормаЗапроса = ПолучитьФорму("КонверторТекстаСУБД", , КлючУникальности); ФормаЗапроса.ЭтоТекстSDBL = ЭтоТекстSDBL; ФормаЗапроса.ЭлементыФормы.ТекстБД.УстановитьТекст(ТекстБД); ФормаЗапроса.ПереводитьВМета = СразуПеревестиВМета; ФормаЗапроса.Открыть(); Возврат Неопределено; КонецФункции Процедура ОткрытьНастройкуТехножурналаДляРегистрацииВыполненияЗапроса(Знач ТекстБД, пЭтоТекстSDBL = Ложь, ТипСУБД = Неопределено, ИмяБазы = "") Экспорт Если Не пЭтоТекстSDBL Тогда ТекстБД = ПолучитьТекстSQLДляПоискаВТехножурнале(ТекстБД); КонецЕсли; ШаблонЗапроса = ПолучитьШаблонТекстаБД(Лев(ТекстБД, 1000), "%"); ФормаНастройки = ирОбщий.ПолучитьФормуЛкс("Обработка.ирНастройкаТехножурнала.Форма"); ФормаНастройки.Открыть(); ФормаНастройки.НаСервере = Не ирКэш.Получить().ЭтоФайловаяБаза; ФормаНастройки.ПриИзмененииПравилаПолученияФайлаНастройки(); Ответ = Вопрос("Хотите создать новую настройку?", РежимДиалогаВопрос.ДаНет); Если Ответ = КодВозвратаДиалога.Да Тогда ФормаНастройки.ЗагрузитьФайлНастройки("ШаблонЗаписьИсключительныхСитуаций", Истина, Истина, Ложь); КонецЕсли; СтрокаКаталога = ФормаНастройки.ТабличноеПолеЖурналы[0]; ФормаНастройки.ЭлементыФормы.ТабличноеПолеЖурналы.ТекущаяСтрока = СтрокаКаталога; ФормаЖурнала = ФормаНастройки.ОткрытьФормуРедактированияЖурнала(); Если пЭтоТекстSDBL Тогда УстановитьОтборПоСвойствуСобытияВФормеЖурнала(ФормаЖурнала, "SDBL", "sdbl", ШаблонЗапроса, , ИмяБазы); Иначе Если Не ЗначениеЗаполнено(ТипСУБД) Тогда ВызватьИсключение "Для текста СУБД необходимо указать тип СУБД"; КонецЕсли; УстановитьОтборПоСвойствуСобытияВФормеЖурнала(ФормаЖурнала, ТипСУБД, "sql", ШаблонЗапроса, , ИмяБазы); КонецЕсли; КонецПроцедуры // Сравнение - Строка - как оно задается в настройке техножурнала (eq, ne, like и т.д.) Процедура УстановитьОтборПоСвойствуСобытияВФормеЖурнала(ФормаЖурнала, ИмяСобытия, Знач ИмяСвойства, Знач ШаблонЗапроса, Сравнение = "like", Знач ИмяБазы = "") Экспорт ТабличноеПолеСписокСобытий = ФормаЖурнала.ЭлементыФормы.ТабличноеПолеСписокСобытий; ТабличноеПолеСписокСобытий.ВыделенныеСтроки.Очистить(); СтрокаСобытия = ФормаЖурнала.УстановитьРегистрациюСобытия(ИмяСобытия, Истина); ТабличноеПолеСписокСобытий.ТекущаяСтрока = СтрокаСобытия; ФормаЖурнала.УстановитьЭлементОтбораВВыделенныхГруппахИ(ИмяСвойства, ШаблонЗапроса, Сравнение); Если Истина И ЗначениеЗаполнено(ИмяБазы) И Не ирКэш.ЭтоФайловаяБазаЛкс() Тогда // К сожалению в файловой СУБД это свойство не заполняется //ФормаЖурнала.КП_ДетальныйФильтрСобытийТекущаяБаза(); ФормаЖурнала.УстановитьЭлементОтбораВВыделенныхГруппахИ("p:processname", ИмяБазы); КонецЕсли; КонецПроцедуры #КонецЕсли Функция ПолучитьВариантПросмотраТекстПоИмениРеквизита(ИмяРеквизита) Экспорт Если Ложь Или мСвойстваСИменамиБД.Свойство(ПолучитьИмяСвойстваБезМета(ИмяРеквизита)) Или ирОбщий.СтрокиРавныЛкс(ИмяРеквизита, "ТекстЗапроса1С") Тогда ВариантПросмотра = "ЯзыкЗапросов"; ИначеЕсли ирОбщий.СтрокиРавныЛкс(ИмяРеквизита, "Контекст") <> Неопределено Тогда ВариантПросмотра = "ВстроенныйЯзык"; Иначе ВариантПросмотра = "Компактный"; КонецЕсли; Возврат ВариантПросмотра; КонецФункции Функция ПреобразоватьЗначениеВSDBL(Ссылка) Экспорт СтруктураБД = ирКэш.ПолучитьСтруктуруХраненияБДЛкс(,, мАдресЧужойСхемыБД); Если ТипЗнч(Ссылка) = Тип("Строка") Тогда Текст = ""; Иначе СтруктураПоиска = Новый Структура("Метаданные, Назначение", Ссылка.Метаданные().ПолноеИмя(), "Основная"); СтрокаТаблицы = СтруктураБД.НайтиСтроки(СтруктураПоиска)[0]; RegExp = ирКэш.Получить().RegExp; RegExp.Pattern = "\d+"; РезультатПоиска = RegExp.Execute(СтрокаТаблицы.ИмяТаблицыХранения); Текст = РезультатПоиска.Item(0).Value + ":" + ирОбщий.ПолучитьГУИДИнверсныйИзПрямогоЛкс("" + Ссылка.УникальныйИдентификатор()); КонецЕсли; Возврат Текст; КонецФункции Функция ПолучитьСтруктуруЗапросаИзТекстаБД(ТекстБД, ТипСУБД = "", ПересобратьТекст = Ложь, ПеревестиИндексы = Истина, ПереводитьВМета = Истина, ЗаменитьHexЛитералы = Ложь, ВстраиватьПараметры = Истина) Экспорт Текст = ТекстБД; //ТаблицаПараметров = Новый ТаблицаЗначений; //ТаблицаПараметров.Колонки.Добавить("ЗначениеSDBL", Новый ОписаниеТипов("Строка")); //ТаблицаПараметров.Колонки.Добавить("Значение"); //ТаблицаПараметров.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка")); ТаблицаПараметров = ПараметрыЗапроса.ВыгрузитьКолонки(); ТаблицаПараметров.Индексы.Добавить("ЗначениеSDBL"); ТаблицаПараметров.Индексы.Добавить("Имя"); RegExp = мПлатформа.RegExp; RegExp.Global = Истина; RegExp.Multiline = Истина; Если ЗначениеЗаполнено(ТипСУБД) Тогда Если ПереводитьВМета Тогда RegExp.Pattern = "TRef\s*=\s*(0x[\da-z]+)"; // замена обращений к типам Вхождения = RegExp.Execute(Текст); ОбработанныеОбращения = Новый Соответствие; Для Каждого Вхождение Из Вхождения Цикл ЗначениеСУБД = Вхождение.Value; Если ОбработанныеОбращения[ЗначениеСУБД] = Неопределено Тогда ПолноеИмяМД = ирОбщий.ПолучитьМетаданныеПоНомеруСсылочнойТаблицыЛкс(ирОбщий.СтрокаHEXtoINTЛкс(Вхождение.SubMatches(0)), мАдресЧужойСхемыБД); Если ПолноеИмяМД <> Неопределено Тогда ЗаменаСтроки = "TRef = " + ПолноеИмяМД; ОбработанныеОбращения[ЗначениеСУБД] = ЗаменаСтроки; Текст = СтрЗаменить(Текст, ЗначениеСУБД, ЗаменаСтроки); Иначе ОбработанныеОбращения[ЗначениеСУБД] = 1; КонецЕсли; КонецЕсли; КонецЦикла; RegExp.Pattern = "^\s*\(@P\d+\s+\w+(?:\(\d+(?:,\d+)?\))?(,@P\d+\s+\w+(?:\(\d+(?:,\d+)?\))?)*\)"; // для удаления типов параметров MSSQL Текст = RegExp.Replace(Текст, ""); КонецЕсли; Иначе RegExp.Pattern = "([A-F0-9]+):([A-F0-9]+|0x[A-F0-9]+)"; // замена ссылочных констант Вхождения = RegExp.Execute(Текст); Для Каждого Вхождение Из Вхождения Цикл ЗначениеSDBL = Вхождение.Value; Если СтрДлина(ЗначениеSDBL) < 32 Тогда // Защита от частей литерала Дата Продолжить; КонецЕсли; Если ТаблицаПараметров.Найти(ЗначениеSDBL, "ЗначениеSDBL") = Неопределено Тогда ЗначениеПараметра = ирОбщий.ПреобразоватьЗначениеИзSDBLЛкс(ЗначениеSDBL, мАдресЧужойСхемыБД); СтрокаПараметра = ирОбщий.НайтиДобавитьПараметрСсылкуВТаблицуЛкс(ТаблицаПараметров,,, ЗначениеПараметра); СтрокаПараметра.ЗначениеSDBL = ЗначениеSDBL; ОбъектМД = ирОбщий.ПолучитьМетаданныеЛкс(ЗначениеПараметра); Если ОбъектМД <> Неопределено Тогда СтрокаПараметра.Метаданные = ОбъектМД.ПолноеИмя(); КонецЕсли; Если ПереводитьВМета Тогда Текст = СтрЗаменить(Текст, ЗначениеSDBL, "&" + СтрокаПараметра.Имя); КонецЕсли; КонецЕсли; КонецЦикла; КонецЕсли; Если ЗаменитьHexЛитералы Тогда RegExp.Pattern = "0x[\da-z]+"; // замена значений констант Вхождения = RegExp.Execute(Текст); СоответствиеКонстант = Новый Соответствие; Для Каждого Вхождение Из Вхождения Цикл ЗначениеСУБД = Вхождение.Value; Если СоответствиеКонстант[ЗначениеСУБД] = Неопределено Тогда ЗаменаСтроки = "_" + ЗначениеСУБД; СоответствиеКонстант[ЗначениеСУБД] = ЗаменаСтроки; Текст = СтрЗаменить(Текст, ЗначениеСУБД, ЗаменаСтроки); КонецЕсли; КонецЦикла; КонецЕсли; //RegExp.Pattern = "#(T[\d_A-Z]+)"; // имена временных таблиц //Текст = RegExp.Replace(Текст, "_$1"); RegExp.Pattern = "\{ts '(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)'\}"; // литералы Дата DBV8DBEng Текст = RegExp.Replace(Текст, "DATETIME($1,$2,$3,$4,$5,$6)"); ТаблицаТаблиц = Новый ТаблицаЗначений; Если ПереводитьВМета Тогда RegExp.Pattern = "N'([^']*)'"; // для замены юникодных литералов типа Строка MSSQL Текст = RegExp.Replace(Текст, """$1"""); КонецЕсли; ТекстМета = ПеревестиТекстБДВТерминыМетаданных(Текст,,, ТипСУБД, ТаблицаТаблиц, 999999, ПеревестиИндексы, ПереводитьВМета); Если Не ПереводитьВМета Тогда ТекстМета = Текст; КонецЕсли; ТаблицаТаблиц.Сортировать("ИмяМета"); ЧастьПараметров = ""; Если ЗначениеЗаполнено(ТипСУБД) Тогда ДиалектSQL = "MSSQL"; ПозицияНачалаПараметров = Найти(ТекстМета, "p_0:"); Если ПозицияНачалаПараметров > 0 Тогда ЧастьПараметров = Сред(ТекстМета, ПозицияНачалаПараметров); ТекстМета = Лев(ТекстМета, ПозицияНачалаПараметров - 1); КонецЕсли; Иначе ДиалектSQL = "1С"; КонецЕсли; ШаблонИмениПараметра = "Parameter"; Если ЗначениеЗаполнено(ЧастьПараметров) Тогда ТекстовыйДокумент = Новый ТекстовыйДокумент; ТекстовыйДокумент.УстановитьТекст(ЧастьПараметров); Для Счетчик = 1 По ТекстовыйДокумент.КоличествоСтрок() Цикл СтрокаПараметра = ТаблицаПараметров.Добавить(); Фрагменты = ирОбщий.СтрРазделитьЛкс(ТекстовыйДокумент.ПолучитьСтроку(Счетчик), ":"); СтрокаПараметра.Имя = СокрЛП(Фрагменты[0]); СтрокаПараметра.Значение = СокрЛП(Фрагменты[1]); КонецЦикла; КонецЕсли; // Встроим имена парамаетров вместо знаков "?" ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.УстановитьСтроку(""); ИндексПараметра = 0; СтрокаПоиска = "?"; Пока ТекстМета <> "" Цикл ПозицияПараметра = Найти(ТекстМета, СтрокаПоиска); Если ПозицияПараметра > 0 Тогда Если ИндексПараметра < ТаблицаПараметров.Количество() Тогда СтрокаПараметра = ТаблицаПараметров[ИндексПараметра]; Иначе СтрокаПараметра = ТаблицаПараметров.Добавить(); СтрокаПараметра.Имя = ШаблонИмениПараметра + XMLСтрока(ТаблицаПараметров.Количество() - 1); КонецЕсли; ЗаписьXML.ЗаписатьБезОбработки(Лев(ТекстМета, ПозицияПараметра - 1) + СтрокаПоиска + СтрокаПараметра.Имя); ТекстМета = Сред(ТекстМета, ПозицияПараметра + СтрДлина(СтрокаПоиска)); ИндексПараметра = ИндексПараметра + 1; Иначе ЗаписьXML.ЗаписатьБезОбработки(ТекстМета); ТекстМета = ""; КонецЕсли; КонецЦикла; ТекстМета = ЗаписьXML.Закрыть(); Если Истина И ПересобратьТекст И ЗначениеЗаполнено(ТекстМета) Тогда ПолеТекста = ирОбщий.ПолучитьОбъектПоПолномуИмениМетаданныхЛкс("Обработка.ирКлсПолеТекстовогоДокументаСКонтекстнойПодсказкой"); ПолеТекста.ИнициализироватьНеинтерактивно(1); //ПолеТекста.ПолеТекстовогоДокумента = ПолеТекстаЗапроса; КонструкторЗапроса = ПолеТекста.ПолучитьФорму("КонструкторЗапроса"); КонструкторЗапроса.Английский1С = Не ПереводитьВМета; ИменованныеПараметры = Истина; Если ПолеТекста.ЗагрузитьТекстВКонструктор(ТекстМета, КонструкторЗапроса,, ДиалектSQL, ИменованныеПараметры) Тогда ТекстМета = КонструкторЗапроса.СобратьПолныйТекст(, Истина); КонецЕсли; КонецЕсли; Если ВстраиватьПараметры Тогда ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.УстановитьСтроку(""); ИндексПараметра = 0; Пока ТекстМета <> "" Цикл ПозицияПараметра = 0; Если ИндексПараметра < ТаблицаПараметров.Количество() Тогда СтрокаПоиска = "?" + ТаблицаПараметров[ИндексПараметра].Имя; ПозицияПараметра = Найти(ТекстМета, СтрокаПоиска); КонецЕсли; Если Истина И ПозицияПараметра > 0 Тогда ЗаписьXML.ЗаписатьБезОбработки(Лев(ТекстМета, ПозицияПараметра - 1) + ТаблицаПараметров[ИндексПараметра].Значение); ИндексПараметра = ИндексПараметра + 1; ТекстМета = Сред(ТекстМета, ПозицияПараметра + СтрДлина(СтрокаПоиска)); Иначе ЗаписьXML.ЗаписатьБезОбработки(ТекстМета); ТекстМета = ""; КонецЕсли; КонецЦикла; ТекстМета = ЗаписьXML.Закрыть(); КонецЕсли; Результат = Новый Структура(); Результат.Вставить("Текст", ТекстМета); Результат.Вставить("Параметры", ТаблицаПараметров); Результат.Вставить("Таблицы", ТаблицаТаблиц); Возврат Результат; КонецФункции Функция НайтиВызовыМетодовМодулей(ИмяМодуля, НомерНачальнойСтроки, НомерКонечнойСтроки, ТолькоОдну = Истина) Результат = Новый Массив(); Для Каждого СтрокаТаблицы Из ТаблицаЖурнала Цикл ФрагментыНачальнойСтрокиМодуля = ирОбщий.СтрРазделитьЛкс(СтрокаТаблицы.СтрокаМодуля, ":", Истина); Если ФрагментыНачальнойСтрокиМодуля[0] <> ИмяМодуля Тогда Результат.Вставить(0, СтрокаТаблицы); Если ТолькоОдну Тогда Прервать; КонецЕсли; КонецЕсли; НомерСтрокиМодуля = Число(ФрагментыНачальнойСтрокиМодуля[1]); Если Ложь Или НомерСтрокиМодуля < НомерНачальнойСтроки Или НомерСтрокиМодуля > НомерКонечнойСтроки Тогда Результат.Вставить(0, СтрокаТаблицы); Если ТолькоОдну Тогда Прервать; КонецЕсли; КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции // Получить словарь имен таблиц входящих в запрос и соответствующих // шаблонам словаря метаданных // // Параметры: // ТекстЗапроса - Строка, текст запроса для которого строится словарь // СловарьШаблоновМетаданных - Соответствие, словарь шаблонов метаданных // ТипСУБД - Строка (Перечисление.ТипСУБД) // // Возвращаемое значение: // Соответствие - Словарь имен таблиц запроса // Функция ИменаМетаданныхЗапросаСУБД(Знач ТекстЗапроса, СловарьШаблоновМетаданных, ТипСУБД = "") Экспорт Результат = Новый ТаблицаЗначений; Результат.Колонки.Добавить("Имя"); Результат.Колонки.Добавить("Длина"); ТекстЗапроса = НРег(ТекстЗапроса); //Если НРег(ТипСУБД) = НРег("DB2") Тогда // ТекстЗапроса = ВРег(ТекстЗапроса); //КонецЕсли; Для Каждого СтрокаСловаряМетаданных Из СловарьШаблоновМетаданных Цикл ТаблицаВхождений = ирОбщий.НайтиРегулярноеВыражениеЛкс(ТекстЗапроса, СтрокаСловаряМетаданных.РегулярныйШаблон,,,,,, Истина); #Если Сервер И Не Сервер Тогда ТаблицаВхождений = Обработки.ирПлатформа.Создать().ВхожденияРегулярногоВыражения; #КонецЕсли Для Каждого СтрокаВхождения Из ТаблицаВхождений Цикл НоваяСтрока = Результат.Добавить(); НоваяСтрока.Имя = СтрокаВхождения.ТекстВхождения; НоваяСтрока.Длина = СтрДлина(НоваяСтрока.Имя); КонецЦикла; КонецЦикла; Результат.Сортировать("Длина Убыв"); Результат.Свернуть("Имя"); Возврат Результат; КонецФункции // ПолучитьСловарьЗапроса() // Получить число из строки в которой число находится в начале строки // // Праметры: // ИсходнаяСтрока - Строка, строка в которой находится число // // Возвращаемое значение: // Число - если оно есть, неопределено, если числа нет // Функция ПолучитьЧислоСтрокой(ИсходнаяСтрока, КоличествоСимволов) КоличествоСимволов = 0; ДлинаСтроки = СтрДлина(ИсходнаяСтрока); Для Сч = 1 По ДлинаСтроки Цикл ТекущийСимвол = КодСимвола(Сред(ИсходнаяСтрока, Сч, 1)); Если 48 <= ТекущийСимвол И ТекущийСимвол <= 57 Тогда КоличествоСимволов = КоличествоСимволов + 1; Иначе Прервать; КонецЕсли; КонецЦикла; Если КоличествоСимволов > 0 Тогда Возврат Лев(ИсходнаяСтрока, КоличествоСимволов); Иначе Возврат Неопределено; КонецЕсли; КонецФункции // ПолучитьЧислоСтрокой() // Перевести часть запроса из терминов СУБД в термины метаданных // // Параметры: // Запрос - Строка, сапрос в терминах СУБД // СтруктураХраненияБазыДанных - ТаблицаЗначений // СловарьШаблоновМетаданных - Соответствие, подробности в функции // ПолучитьСловарьШаблоновМетаданных() // ТипСУБД - Строка, (Перечисление.ТипСУБД) // выхТаблицы - ТаблицаЗначений, *Неопределено - описание использованных в тексте таблиц, заполняется только если таблица передана (без колонок) // // Возвращаемое значение: // Строка, запрос в терминах метаданных // Функция ПеревестиТекстБДВТерминыМетаданных(Знач Текст, СтруктураХраненияБазыДанных = Неопределено, СловарьШаблоновМетаданных = Неопределено, Знач ТипСУБД = "", выхТаблицы = Неопределено, ДопустимыйРазмер = 20000, ПереводитьИндексы = Истина, ПереводитьВМета = Истина, ЭтоГарантированоТекстСобственнойБазы = Ложь) Экспорт Если выхТаблицы <> Неопределено Тогда #Если Сервер И Не Сервер Тогда выхТаблицы = Новый ТаблицаЗначений; #КонецЕсли //выхТаблицы.Колонки.Очистить(); Если выхТаблицы.Колонки.Найти("ИмяБД") = Неопределено Тогда выхТаблицы.Колонки.Добавить("ИмяБД", Новый ОписаниеТипов("Строка")); КонецЕсли; Если выхТаблицы.Колонки.Найти("ИмяМета") = Неопределено Тогда выхТаблицы.Колонки.Добавить("ИмяМета", Новый ОписаниеТипов("Строка")); КонецЕсли; КонецЕсли; Если Ложь Или Не ЗначениеЗаполнено(Текст) Тогда Возврат ""; КонецЕсли; Если Истина И ДопустимыйРазмер > 0 И СтрДлина(Текст) > ДопустимыйРазмер И ПереводитьВМета Тогда Возврат РезультатПереводаСлишкомБольшогоТекста(); КонецЕсли; Если ирОбщий.СтрокиРавныЛкс(ТипСУБД, "sdbl") Тогда ТипСУБД = ""; КонецЕсли; АдресЧужойСхемыБД = ""; Если Не ЭтоГарантированоТекстСобственнойБазы Тогда АдресЧужойСхемыБД = мАдресЧужойСхемыБД; КонецЕсли; Если СтруктураХраненияБазыДанных = Неопределено Тогда СтруктураХраненияБазыДанных = ирКэш.ПолучитьСтруктуруХраненияБДЛкс(ЗначениеЗаполнено(ТипСУБД),, АдресЧужойСхемыБД); КонецЕсли; Если СловарьШаблоновМетаданных = Неопределено Тогда СловарьШаблоновМетаданных = ирКэш.ПолучитьСловарьШаблоновМетаданныхЛкс(ЗначениеЗаполнено(ТипСУБД), АдресЧужойСхемыБД); КонецЕсли; Текст = Текст + Символы.ПС; ИменаМетаданныхЗапроса = ИменаМетаданныхЗапросаСУБД(Текст, СловарьШаблоновМетаданных, ТипСУБД); Если НРег(ТипСУБД) = НРег("DB2") Тогда Текст = ВРег(Текст); КонецЕсли; // Поиск имен таблиц в строке запроса Если ИменаМетаданныхЗапроса.Количество() > 10 Тогда Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ИменаМетаданныхЗапроса.Количество(), "Преобразование в имена метаданных"); КонецЕсли; Для Каждого ИмяМетаданного Из ИменаМетаданныхЗапроса Цикл Если Индикатор <> Неопределено Тогда ирОбщий.ОбработатьИндикаторЛкс(Индикатор); КонецЕсли; ОписаниеТаблицы = Неопределено; Если выхТаблицы <> Неопределено Тогда Если Найти(ИмяМетаданного.Имя, ".") = 0 Тогда ОписаниеТаблицы = выхТаблицы.Добавить(); ОписаниеТаблицы.ИмяБД = ИмяМетаданного.Имя; КонецЕсли; КонецЕсли; // Получить имя таблицы СтрокаСтруктуры = СтруктураХраненияБазыДанных.Найти(ирОбщий.ПоследнийФрагментЛкс(ИмяМетаданного.Имя), "КраткоеИмяТаблицыХранения"); Если СтрокаСтруктуры = Неопределено Тогда // Видимо чужие метаданные Продолжить; КонецЕсли; ИмяТаблицы = СтрокаСтруктуры.КраткоеИмяТаблицыХранения; МетаПолноеИмяТаблицы = СтрокаСтруктуры.ИмяТаблицы; Если ОписаниеТаблицы <> Неопределено Тогда ОписаниеТаблицы.ИмяМета = МетаПолноеИмяТаблицы; КонецЕсли; Если Не ПереводитьВМета Тогда Продолжить; КонецЕсли; Синонимы = ПолучитьСинонимы(Текст, ИмяТаблицы, МетаПолноеИмяТаблицы, ТипСУБД); //Синонимы.Вставить(ИмяТаблицы, МетаИмяТаблицы); ЭтоТабличнаяЧасть = СтрокаСтруктуры.Назначение = "ТабличнаяЧасть"; Для Каждого СтрокаПоля Из СтрокаСтруктуры.Поля Цикл Если Найти(Текст, СтрокаПоля.ИмяПоляХранения) = 0 Тогда Продолжить; КонецЕсли; ПредставлениеПоля = ирОбщий.ПолучитьПредставлениеПоляБДЛкс(СтрокаПоля, ТипСУБД <> "", ЭтоТабличнаяЧасть); Если Не ЗначениеЗаполнено(ПредставлениеПоля) Тогда Продолжить; КонецЕсли; RegExpМета.Pattern = шГраничныйСимволИмени + СтрокаПоля.ИмяПоляХранения + "([^&" + шБуква + "\d]|Balance|Turnover|Receipt|Expense|^|$)"; // Можно оптимизировать путем создания шаблона мультизамены Текст = RegExpМета.Replace(Текст, "$1" + ПредставлениеПоля + "$2"); КонецЦикла; Если ПереводитьИндексы Тогда Для Каждого СтрокаИндекса Из СтрокаСтруктуры.Индексы Цикл ПредставлениеИндекса = СтрокаИндекса.ИмяИндекса; СтрокаДляЗамены = СтрокаИндекса.ИмяИндексаХранения; Если ирОбщий.СтрокиРавныЛкс(ТипСУБД, "DBPOSTGRS") Тогда СтрокаДляЗамены = ВРег(СтрокаИндекса.ИмяИндексаХранения); ИначеЕсли ирОбщий.СтрокиРавныЛкс(ТипСУБД, "DBV8DBEng") Тогда СтрокаДляЗамены = ВРег(СтрокаИндекса.ИмяИндексаХранения); КонецЕсли; // Имена индексов достаточно уникальны, чтобы использовать СтрЗаменить Текст = СтрЗаменить(Текст, СтрокаДляЗамены, ПредставлениеИндекса); КонецЦикла; КонецЕсли; Для Каждого Синоним Из Синонимы Цикл // Заменить псевдоним таблицы RegExpМета.Pattern = шГраничныйСимволИмени + Синоним.Ключ + шГраничныйСимволИмени; Текст = RegExpМета.Replace(Текст, "$1" + Синоним.Значение + "$2"); //RegExpМета.Pattern = ИмяТаблицы + " " + Синоним.Ключ + шГраничныйСимволИмени; //Запрос = RegExpМета.Replace(Текст, ИмяТаблицы + " AS " + Синоним.Значение + "$1"); КонецЦикла; // Заменить имя таблицы RegExpМета.Pattern = шГраничныйСимволИмени + СтрокаСтруктуры.ИмяТаблицыХранения + шГраничныйСимволИмени; Текст = RegExpМета.Replace(Текст, "$1" + МетаПолноеИмяТаблицы + "$2"); Если НРег(СтрокаСтруктуры.ИмяТаблицыХранения) <> СтрокаСтруктуры.КраткоеИмяТаблицыХранения Тогда RegExpМета.Pattern = шГраничныйСимволИмени + СтрокаСтруктуры.КраткоеИмяТаблицыХранения + шГраничныйСимволИмени; Текст = RegExpМета.Replace(Текст, "$1" + ирОбщий.ПоследнийФрагментЛкс(МетаПолноеИмяТаблицы) + "$2"); КонецЕсли; КонецЦикла; Если Индикатор <> Неопределено Тогда ирОбщий.ОсвободитьИндикаторПроцессаЛкс(Индикатор); КонецЕсли; // Заменим приведение к ссылочному типу Если Не ЗначениеЗаполнено(ТипСУБД) Тогда Текст = СтрЗаменить(Текст, "AS REF(", "AS ("); КонецЕсли; Текст = СокрП(Текст); Возврат Текст; КонецФункции Функция РезультатПереводаСлишкомБольшогоТекста() Экспорт Возврат "<Текст слишком большой для быстрого перевода>" КонецФункции // Получить синонимы имени таблицы в запросе // // Параметры: // Запрос - Строка, текст запроса // ИмяТаблицы - Строка, имя таблицы для которой ищутся синонимы // МетаИмяТаблицы - Строка, имя таблицы в терминах метаданных // // Возвращаемое занчение: // Соответствие, имена синонимов и их мета имена // Функция ПолучитьСинонимы(Запрос, ИмяТаблицы, МетаИмяТаблицы, ТипСУБД = "") Экспорт // Построить список синонимом ими таблицы Синонимы = Новый Соответствие; RegExpМета.Pattern = ИмяТаблицы + " " + "(?:([" + шБуква + "\d]+)|\(([" + шБуква + "\d]+)\))" + шГраничныйСимволИмени; Вхождения = RegExpМета.Execute(Запрос); ПсевдонимТаблицы = ирОбщий.ПоследнийФрагментЛкс(МетаИмяТаблицы, "."); Для Каждого Вхождение Из Вхождения Цикл Синоним = Вхождение.SubMatches(0); Если ирОбщий.ЛиПустаяПодгруппаRegExpЛкс(Синоним) Тогда Синоним = Вхождение.SubMatches(1); КонецЕсли; Если Ложь Или (Истина И ирОбщий.СтрокиРавныЛкс(ТипСУБД, "DBMSSQL") И ирОбщий.СтрокиРавныЛкс(Синоним, "WITH")) Или ирОбщий.СтрокиРавныЛкс(Синоним, "WHERE") Или ирОбщий.СтрокиРавныЛкс(Синоним, "GROUP") Или ирОбщий.СтрокиРавныЛкс(Синоним, "HAVING") Или ирОбщий.СтрокиРавныЛкс(Синоним, "SET") Или ирОбщий.СтрокиРавныЛкс(Синоним, "ORDER") Или ирОбщий.СтрокиРавныЛкс(Синоним, "THEN") Тогда Продолжить; КонецЕсли; Синонимы.Вставить(Синоним, ПсевдонимТаблицы + "_" + Синоним); КонецЦикла; Возврат Синонимы; КонецФункции // ПолучитьСинонимы() //ирПортативный лФайл = Новый Файл(ИспользуемоеИмяФайла); //ирПортативный ПолноеИмяФайлаБазовогоМодуля = Лев(лФайл.Путь, СтрДлина(лФайл.Путь) - СтрДлина("Модули\")) + "ирПортативный.epf"; //ирПортативный #Если Клиент Тогда //ирПортативный Контейнер = Новый Структура(); //ирПортативный Оповестить("ирПолучитьБазовуюФорму", Контейнер); //ирПортативный Если Не Контейнер.Свойство("ирПортативный", ирПортативный) Тогда //ирПортативный ирПортативный = ВнешниеОбработки.ПолучитьФорму(ПолноеИмяФайлаБазовогоМодуля); //ирПортативный ирПортативный.Открыть(); //ирПортативный КонецЕсли; //ирПортативный #Иначе //ирПортативный ирПортативный = ВнешниеОбработки.Создать(ПолноеИмяФайлаБазовогоМодуля, Ложь); // Это будет второй экземпляр объекта //ирПортативный #КонецЕсли //ирПортативный ирОбщий = ирПортативный.ПолучитьОбщийМодульЛкс("ирОбщий"); //ирПортативный ирКэш = ирПортативный.ПолучитьОбщийМодульЛкс("ирКэш"); //ирПортативный ирСервер = ирПортативный.ПолучитьОбщийМодульЛкс("ирСервер"); //ирПортативный ирПривилегированный = ирПортативный.ПолучитьОбщийМодульЛкс("ирПривилегированный"); мПлатформа = ирКэш.Получить(); мНепустыеКолонкиЖурнала = Новый Структура(); //ЭтотОбъект.НаложениеПриДозагрузкеСекунд = 30; RegExpПараметры = мПлатформа.ПолучитьНовыйВычислительРегулярныхВыражений(); RegExpПараметры.IgnoreCase = Истина; RegExpПараметры.Global = Истина; RegExpПараметры.Pattern = "([^A-ZА-ЯЁ_0-9]|^)(?:[A-F0-9]+:[A-F0-9]+|0x[A-F0-9]+|[A-F0-9]+(?:-[A-F0-9]+)+-[A-F0-9]+|(#TT?)[_A-F0-9]+|[0-9]+)"; // для стирания констант и имен временных таблиц RegExpМета = мПлатформа.ПолучитьНовыйВычислительРегулярныхВыражений(); RegExpМета.IgnoreCase = Истина; RegExpМета.Global = Истина; мСписокКолонок = Новый СписокЗначений; //мСписокКолонок.Добавить("Name", "Событие"); // В некоторых случаях нужно мСписокКолонок.Добавить("SrcName", "Источник"); мСписокКолонок.Добавить("OSThread", "ПотокОС"); мСписокКолонок.Добавить("process", "ТипПроцессаОС"); мСписокКолонок.Добавить("p:processName", "Инфобаза"); мСписокКолонок.Добавить("t:clientID", "Соединение_"); мСписокКолонок.Добавить("t:applicationName", "Приложение"); мСписокКолонок.Добавить("t:computerName", "Компьютер"); мСписокКолонок.Добавить("t:connectID", "TCPСоединение"); мСписокКолонок.Добавить("SessionID", "Сеанс"); мСписокКолонок.Добавить("Usr", "Пользователь"); мСписокКолонок.Добавить("OSException", "ИсключениеОС"); мСписокКолонок.Добавить("Interface", "Интерфейс"); мСписокКолонок.Добавить("Method", "Метод"); мСписокКолонок.Добавить("Exception", "ТипИсключения"); мСписокКолонок.Добавить("Descr", "Описание"); мСписокКолонок.Добавить("ClientComputerName", "КомпьютерКлиента"); мСписокКолонок.Добавить("ServerComputerName", "КомпьютерСервера"); мСписокКолонок.Добавить("UserName", "Пользователь"); мСписокКолонок.Добавить("ConnectString", "СтрокаСоединения"); мСписокКолонок.Добавить("ProcessName", "ТипПроцессаОС"); мСписокКолонок.Добавить("SrcProcessName", "Инфобаза"); //мСписокКолонок.Добавить("Trans", "Транзакция"); мСписокКолонок.Добавить("Func", "Действие"); мСписокКолонок.Добавить("Sdbl", "ТекстSDBL"); мСписокКолонок.Добавить("dbpid", "ПроцессСУБД"); мСписокКолонок.Добавить("Sql", "ТекстСУБД"); мСписокКолонок.Добавить("NParams", "КоличествоПараметров"); мСписокКолонок.Добавить("Rows", "ЧислоСтрок"); мСписокКолонок.Добавить("RowsAffected", "ЧислоИзменныхСтрок"); мСписокКолонок.Добавить("planSQLText", "ПланСУБД"); мСписокКолонок.Добавить("Context", "Контекст"); мСписокКолонок.Добавить("CatName", "КаталогСУБД"); мСписокКолонок.Добавить("WaitConnections", "Блокираторы"); мСписокКолонок.Добавить("FileName", "ФайлСУБД"); мСписокКолонок.Добавить("DeadlockConnectionIntersections", "Взаимоблокировка"); мСписокКолонок.Добавить("Finish", "ПричинаЗавершения"); мСписокКолонок.Добавить("Err", "ТипСообщения"); мСписокКолонок.Добавить("Txt", "ТекстСообщения"); мСписокКолонок.Добавить("URI", "Ресурс"); мСписокКолонок.Добавить("Administrator", "Администратор"); мСписокКолонок.Добавить("Body", "РазмерЗапроса"); мСписокКолонок.Добавить("Cluster", "НомерПорта"); мСписокКолонок.Добавить("Val", "ЗначениеПараметра"); // Свойства найденные экспериментально. Они не документированы. мСписокКолонок.Добавить("Query", "ТекстЗапроса1С"); // События: QERR мСписокКолонок.Добавить("From", "From_"); // События: DBV8DBENG //мСписокКолонок.Добавить("AppID", "AppID"); // События: QERR, DBMSSQL (дублируется t:applicationName), SDBL (дублирует t:applicationName) мСписокКолонок.Добавить("Index", "Index_"); //мСписокКолонок.Добавить("setUnhandledExceptionFilter", "setUnhandledExceptionFilter"); мСписокКолонок.Добавить("Module", "МодульКонфигурации"); // События: EXCPCNTX мСписокКолонок.Добавить("ClientID", "Клиент"); // События: EXCPCNTX, SCALL, EXCP (дублируется t:clientID ?) мТаблицаКолонок = Новый ТаблицаЗначений; мТаблицаКолонок.Колонки.Добавить("ВнутреннееИмя", Новый ОписаниеТипов("Строка")); мТаблицаКолонок.Колонки.Добавить("ИмяВТаблице", Новый ОписаниеТипов("Строка")); мТаблицаКолонок.Индексы.Добавить("ВнутреннееИмя"); мТаблицаКолонок.Индексы.Добавить("ИмяВТаблице"); мЧисловыеСвойства = Новый Структура; мСоответствиеКолонок = Новый Соответствие; МетаРеквизиты = Метаданные().ТабличныеЧасти.ТаблицаЖурнала.Реквизиты; Для Каждого ЭлементСписка Из мСписокКолонок Цикл мСоответствиеКолонок.Вставить(НРег(ЭлементСписка.Значение), ЭлементСписка.Представление); СтрокаСоответствия = мТаблицаКолонок.Добавить(); СтрокаСоответствия.ВнутреннееИмя = ЭлементСписка.Значение; СтрокаСоответствия.ИмяВТаблице = ЭлементСписка.Представление; Если МетаРеквизиты[ЭлементСписка.Представление].Тип.СодержитТип(Тип("Число")) Тогда мЧисловыеСвойства.Вставить(ЭлементСписка.Представление); КонецЕсли; КонецЦикла; Для Каждого МетаРеквизит Из МетаРеквизиты Цикл Если мСоответствиеКолонок[МетаРеквизит.Имя] = Неопределено Тогда мСоответствиеКолонок.Вставить(НРег(МетаРеквизит.Имя), МетаРеквизит.Имя); КонецЕсли; КонецЦикла; мКартыФайлов = Новый ТаблицаЗначений; мКартыФайлов.Колонки.Добавить("ИмяКаталогаПроцесса", Новый ОписаниеТипов("Строка")); мКартыФайлов.Колонки.Добавить("ИмяТекущегоФайла", Новый ОписаниеТипов("Строка")); мКартыФайлов.Колонки.Добавить("СигнатураТекущегоФайла", Новый ОписаниеТипов("Строка")); мКартыФайлов.Колонки.Добавить("ОтборПоСеансу"); мКартыФайлов.Колонки.Добавить("ПозицияНачала", Новый ОписаниеТипов("Число")); мКартыФайлов.Колонки.Добавить("ПозицияКонца", Новый ОписаниеТипов("Число")); мКартыФайлов.Колонки.Добавить("НачалоПериода", Новый ОписаниеТипов("Дата")); мКартыФайлов.Колонки.Добавить("КонецПериода", Новый ОписаниеТипов("Дата")); мКартыФайлов.Колонки.Добавить("ДатаИзмененияФайла", Новый ОписаниеТипов("Дата")); мКартыФайлов.Индексы.Добавить("ИмяКаталогаПроцесса, ИмяТекущегоФайла, СигнатураТекущегоФайла, ОтборПоСеансу"); мСвойстваСИменамиБД = Новый Структура(); мСвойстваСИменамиБД.Вставить("ТекстSDBL", Ложь); мСвойстваСИменамиБД.Вставить("ТекстSDBLШаблон", Ложь); мСвойстваСИменамиБД.Вставить("ТекстСУБД", Истина); мСвойстваСИменамиБД.Вставить("ТекстСУБДШаблон", Ложь); мСвойстваСИменамиБД.Вставить("ПланСУБД", Истина); мСвойстваСИменамиБД.Вставить("Взаимоблокировка", Ложь); мСвойстваСИменамиБД.Вставить("Regions", Ложь); мСвойстваСИменамиБД.Вставить("Locks", Ложь); мСерверныеТипыПроцессов = Новый Структура; мСерверныеТипыПроцессов.Вставить("_adminprocess"); // ##AdminProcess## мСерверныеТипыПроцессов.Вставить("_rphost"); мСерверныеТипыПроцессов.Вставить("_rmngr"); мСерверныеТипыПроцессов.Вставить("_ragent"); МаксТысячСобытий = 100; мАдресЧужойСхемыБД = ""; шБуква = мПлатформа.шБуква; шГраничныйСимволИмени = "([^&" + шБуква + "\d]|^|$)";