//ирПортативный Перем ирПортативный Экспорт; //ирПортативный Перем ирОбщий Экспорт; //ирПортативный Перем ирСервер Экспорт; //ирПортативный Перем ирКэш Экспорт; //ирПортативный Перем ирПривилегированный Экспорт; Перем мТаблицаКолонок Экспорт; Перем мСписокКолонок Экспорт; Перем КлючиЗагруженныхСтрок; Перем мСвойстваСИменамиБД Экспорт; Перем RegExpПараметры; Перем RegExpМета; Перем шБуква; Перем шГраничныйСимволИмени; //Перем МинимальнаяДатаЗагрузки Экспорт; Перем мЧисловыеСвойства; Перем мТипСУБД Экспорт; Перем мСерверныеТипыПроцессов Экспорт; Перем мКартыФайлов; Перем мПлатформа; //Трассировка Перем КонецПериодаКлиента Экспорт; Перем НачалоПериодаКлиента Экспорт; Перем КонецПериодаСервера Экспорт; Перем НачалоПериодаСервера Экспорт; Перем мИдентификаторТрассы Экспорт; Перем мНепустыеКолонкиЖурнала Экспорт; Перем мСоответствиеКолонок; // СдвигВремени - Число - в секундах задается, нужно для компенсации разницы времени между компьютерами // ОтборПоПроцессу и ОтборПоСеансу частично игнорируются когда ЗагружатьТолькоТекущийСеанс = Истина Функция ПрочитатьПроизвольныйЖурнал(СообщитьРазмер = Неопределено, СдвигВремени = 0, ОтборПоПроцессу = Неопределено, ОтборПоСеансу = Неопределено, НаСервере = Неопределено) НеизвестныеСвойства = Новый Соответствие(); Если Ложь Или НаСервере <> Неопределено Или Не ЗначениеЗаполнено(КаталогЖурнала) Тогда КаталогЖурнала = ПолучитьКаталогТекущегоЖурнала(НаСервере = Истина); Если Не ЗначениеЗаполнено(КаталогЖурнала) Тогда Возврат Ложь; КонецЕсли; КонецЕсли; Если Не ирОбщий.ЛиКаталогДоступенЛкс(КаталогЖурнала) Тогда Возврат Ложь; КонецЕсли; Если ЗагружатьТолькоТекущийСеанс Тогда Если Ложь Или ирКэш.ЭтоФайловаяБазаЛкс() Или Не НаСервере = Истина Тогда ОтборПоПроцессу = ирКэш.Получить().ПолучитьИдентификаторПроцессаОС(); КонецЕсли; Если НаСервере = Истина Тогда ОтборПоСеансу = НомерСеансаИнформационнойБазы(); КонецЕсли; КонецЕсли; лПоследнееВремяНачалаЗагрузки = ТекущаяДата(); Если ПериодПоследниеМинуты > 0 Тогда НачалоПериода = лПоследнееВремяНачалаЗагрузки - 60 * ПериодПоследниеМинуты; КонецПериода = Неопределено; КонецЕсли; //Если ТаблицаЖурнала.Количество() = 0 Тогда // МинимальнаяДатаЗагрузки = ТекущаяДата() + 100000; //КонецЕсли; //Если МинимальнаяДатаЗагрузки > НачалоПериода Тогда // ТаблицаЖурнала.Очистить(); //КонецЕсли; //РежимДозагрузки = Истина // И ТаблицаЖурнала.Количество() > 0 // И МинимальнаяДатаЗагрузки <= НачалоПериода; Если СообщитьРазмер = Неопределено Тогда СообщитьРазмер = (ТаблицаЖурнала.Количество() = 0); КонецЕсли; Если ТаблицаЖурнала.Количество() = 0 Тогда мКартыФайлов.Очистить(); КонецЕсли; ирОбщий.ЛиКаталогТехножурналаНедоступенЛкс(КаталогЖурнала); ФайлыЖурнала = НайтиФайлы(КаталогЖурнала, "*.log", Истина); ОбщийРазмер = 0; Для Каждого ФайлЖурнала Из ФайлыЖурнала Цикл ОбщийРазмер = ОбщийРазмер + ФайлЖурнала.Размер(); КонецЦикла; Если СообщитьРазмер Тогда Сообщить("В журнале """ + КаталогЖурнала + """ обнаружено " + Формат(Цел(ОбщийРазмер / 1024), "ЧН=") + " КБ логов"); КонецЕсли; //БезопасныйРазмерЖурнала = 10*1000*1000; // 10МБ //Если ОбщийРазмер > БезопасныйРазмерЖурнала Тогда // Ответ = Вопрос("Размер журнала составляет " + Формат(Цел(ОбщийРазмер / 1000000)) + " МБ. // |Чтение журнала может продолжаться длительное время, продолжить?", РежимДиалогаВопрос.ДаНет); //Иначе // Ответ = КодВозвратаДиалога.Да; //КонецЕсли; //Если Ответ = КодВозвратаДиалога.Нет Тогда // Возврат Ложь; //КонецЕсли; НеОбрабатывать = Ложь; СтрокаСобытия = ""; СтруктураЗаписиТЖ = Новый Структура(); РеквизитыТЧ = Метаданные().ТабличныеЧасти.ТаблицаЖурнала.Реквизиты; шСимвол = "[" + шБуква + "\d\._#{}-]"; ШаблонСвойствоЗначение = ",([\w\:]+)=(?:'\s*([^']*)'|""\s*([^""]*)""|([^'""\n\r,]*))"; Шаблон = "(\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 Тогда ИндикаторФайла = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ЧислоПорций, "" + ИмяФайлаСРодителем + "\" + ФайлЖурнала.Имя); Иначе ИндикаторФайла = Неопределено; КонецЕсли; Пока Истина Цикл КартаФайла.ДатаИзменения = ФайлЖурнала.ПолучитьВремяИзменения(); ПорцияТекстаФайла = ЧтениеТекста.Прочитать(РазмерПорции); Если Ложь Или ПорцияТекстаФайла = Неопределено Или ПустаяСтрока(ПорцияТекстаФайла) Тогда Прервать; КонецЕсли; #Если Клиент Тогда Если ИндикаторФайла <> Неопределено Тогда ирОбщий.ОбработатьИндикаторЛкс(ИндикаторФайла); КонецЕсли; #КонецЕсли Если Истина И АбсолютнаяПозицияВФайле >= КартаФайла.ПозицияНачала И АбсолютнаяПозицияВФайле + СтрДлина(ПорцияТекстаФайла) + СтрДлина(ТекстФайла) < КартаФайла.ПозицияКонца Тогда АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + СтрДлина(ПорцияТекстаФайла) + СтрДлина(ТекстФайла); Продолжить; КонецЕсли; ТекстФайла = ТекстФайла + ПорцияТекстаФайла; Попытка Вхождения = RegExp.Execute(ТекстФайла); Исключение Сообщить("Ошибка анализа файла """ + ФайлЖурнала.ПолноеИмя + """: " + ОписаниеОшибки()); Прервать; КонецПопытки; Если КомментироватьЗагрузку Тогда Сообщить("Анализ порции " + СтрДлина(ТекстФайла) + " символов обнаружил " + Вхождения.Count + " событий"); КонецЕсли; СтрокаТекущегоКонтекста = Неопределено; СтрокаТЧ = Неопределено; Для Каждого Вхождение Из Вхождения Цикл #Если Клиент Тогда ОбработкаПрерыванияПользователя(); #КонецЕсли СтрокаТЧ = Неопределено; АбсолютнаяПозицияВхождения = АбсолютнаяПозицияВФайле + Вхождение.FirstIndex; Если Истина И КартаФайла.ПозицияНачала > -1 И АбсолютнаяПозицияВхождения >= КартаФайла.ПозицияНачала И АбсолютнаяПозицияВхождения < КартаФайла.ПозицияКонца Тогда Продолжить; КонецЕсли; СтрокаВремениЗаписи = СтрокаЧасаЗаписи + СтрЗаменить(Вхождение.SubMatches(0), ":", ""); ДатаВремяЗаписи = Дата(СтрокаВремениЗаписи); Если Не ЛиФайлВИнтервалеПолностью Тогда //ЛиДатаВИнтервале = ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(ДатаВремяЗаписи, лНачалоПериода, КонецПериода); //Если Не ЛиДатаВИнтервале Тогда // Продолжить; //КонецЕсли; Если Истина И ЗначениеЗаполнено(НачалоПериода) И ДатаВремяЗаписи < НачалоПериода Тогда Продолжить; КонецЕсли; Если Истина И ЗначениеЗаполнено(КонецПериода) И ДатаВремяЗаписи > КонецПериода Тогда Прервать; КонецЕсли; КонецЕсли; Если ПозицияНачалаСчитанныхДанных = -1 Тогда ПозицияНачалаСчитанныхДанных = АбсолютнаяПозицияВхождения; КонецЕсли; КонецМикросекунды = Вхождение.SubMatches(1); //КлючСтроки = МоментВремени + ";" + ФайлЖурнала.ПолноеИмя; //Если РежимДозагрузки Тогда // Если КлючиЗагруженныхСтрок[КлючСтроки] = 1 Тогда // Продолжить; // КонецЕсли; //КонецЕсли; Если СтрДлина(КонецМикросекунды) = 6 Тогда //Это 8.3 ЧислоМикросекунд = Число(КонецМикросекунды); ПродолжительностьВМикросекундах = Число(Вхождение.SubMatches(2)); Иначе //Это 8.2 ЧислоМикросекунд = Число(КонецМикросекунды) * 100; ПродолжительностьВМикросекундах = Число(Вхождение.SubMatches(2)) * 100; КонецЕсли; СтрокаТЧ = ТаблицаЖурнала.Добавить(); СтрокаТЧ.Дата = ДатаВремяЗаписи - СдвигВремени; СтрокаТЧ.МоментВремени = ПолучитьМоментВремени(СтрокаТЧ.Дата, КонецМикросекунды); СтрокаТЧ.ИмяФайлаЛога = ФайлЖурнала.ПолноеИмя; СтрокаТЧ.ПроцессОС = ИдентификаторПроцесса; //СтрокаТЧ.ТекстЖурнала = Вхождение.Value; // Теперь это только для отладки будем включать СтрокаТЧ.Длительность = ПродолжительностьВМикросекундах / 1000; // Переводим длительность в миллисекунды Длительность1Секунды = Цел(ПродолжительностьВМикросекундах / 1000000); Длительность1Микросекунды = ПродолжительностьВМикросекундах - Длительность1Секунды * 1000000; ДатаНачала = СтрокаТЧ.Дата - Длительность1Секунды; НачалоМикросекунды = КонецМикросекунды - Длительность1Микросекунды; Если НачалоМикросекунды < 0 Тогда ДатаНачала = ДатаНачала - 1; НачалоМикросекунды = 1000000 + НачалоМикросекунды; КонецЕсли; СтрокаТЧ.ДатаНачала = ДатаНачала; СтрокаТЧ.МоментВремениНачала = ПолучитьМоментВремени(ДатаНачала, НачалоМикросекунды); СтрокаТЧ.Событие = ВРег(Вхождение.SubMatches(3)); ВхожденияСвойств = RegExp2.Execute(Вхождение.SubMatches(4)); Для Каждого ВхождениеСвойства Из ВхожденияСвойств Цикл //Для Индекс = 0 По мТаблицаКолонок.Количество() - 1 Цикл //Индекс + СмещениеПервойКолонки ИмяСвойства = ВхождениеСвойства.SubMatches(0); ЗначениеСвойства = ВхождениеСвойства.SubMatches(3); Если ирОбщий.ЛиПустаяПодгруппаRegExpЛкс(ЗначениеСвойства) Тогда ЗначениеСвойства = ВхождениеСвойства.SubMatches(2); КонецЕсли; Если ирОбщий.ЛиПустаяПодгруппаRegExpЛкс(ЗначениеСвойства) Тогда ЗначениеСвойства = ВхождениеСвойства.SubMatches(1); КонецЕсли; Если ирОбщий.ЛиПустаяПодгруппаRegExpЛкс(ЗначениеСвойства) Тогда Продолжить; КонецЕсли; ИмяКолонкиТЧ = мСоответствиеКолонок[ИмяСвойства]; Если ИмяКолонкиТЧ = Неопределено Тогда Если НеизвестныеСвойства[ИмяСвойства] <> Неопределено Тогда НеизвестныеСвойства[ИмяСвойства] = 1; Сообщить("Обнаружено неизвестное свойство """ + ИмяСвойства + """ события " + СтрокаТЧ.Событие); КонецЕсли; Продолжить; КонецЕсли; //Если мЧисловыеСвойства.Свойство(ИмяКолонкиТЧ) Тогда // Если Не ЗначениеЗаполнено(ЗначениеСвойства) Тогда // ЗначениеСвойства = 0; // Иначе // Попытка // ЗначениеСвойства = Число(ЗначениеСвойства); // Исключение // ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения числового свойства """ + ИмяКолонкиТЧ + """"; // КонецПопытки; // КонецЕсли; //КонецЕсли; Если Не мНепустыеКолонкиЖурнала.Свойство(ИмяКолонкиТЧ) Тогда Если ЗначениеЗаполнено(ЗначениеСвойства) Тогда мНепустыеКолонкиЖурнала.Вставить(ИмяКолонкиТЧ); КонецЕсли; КонецЕсли; Попытка СтрокаТЧ[ИмяКолонкиТЧ] = ЗначениеСвойства; Исключение ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения свойства """ + ИмяКолонкиТЧ + """"; КонецПопытки; КонецЦикла; //АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + Вхождение.Length; Если Истина И ОтборПоСеансу <> Неопределено И СтрокаТЧ.Сеанс <> ОтборПоСеансу Тогда ТаблицаЖурнала.Удалить(СтрокаТЧ); СтрокаТЧ = Неопределено; #Если _ Тогда СтрокаТЧ = ТаблицаЖурнала.Добавить(); #КонецЕсли Продолжить; КонецЕсли; //Если НаСервере <> Неопределено Тогда // СтрокаТЧ.НаСервере = НаСервере; //Иначе Если Ложь Или СтрокаТЧ.Событие = "SCOM" Тогда СтрокаТЧ.НаСервере = Истина; Иначе ИмяТипаПроцесса = "_" + СтрЗаменить(СтрокаТЧ.ТипПроцессаОС, "#", ""); Попытка СтрокаТЧ.НаСервере = мСерверныеТипыПроцессов.Свойство(ИмяТипаПроцесса); Исключение // Бывают типы процессов с UID, к сожалению тогда невозможно определить КонецПопытки; КонецЕсли; //КонецЕсли; Если СтрокаТЧ.Контекст <> "" Тогда СтрокаТЧ.СтрокаМодуля = СокрЛП(СтрПолучитьСтроку(СтрокаТЧ.Контекст, СтрЧислоСтрок(СтрокаТЧ.Контекст))); Если БазовыйУровеньСтека > 0 Тогда ЗаполнитьСтрокуБазовогоУровня(СтрокаТЧ); КонецЕсли; КонецЕсли; Если ВключитьСвойстваСИменамиМетаданных Тогда ЗаполнитьСвойстваСИменамиМетаданных(СтрокаТЧ); КонецЕсли; //Если ДатаВремяЗаписи > лПоследнееВремяНачалаЗагрузки - НаложениеПриДозагрузкеСекунд Тогда // НовыеКлючиЗагруженныхСтрок[КлючСтроки] = 1; //КонецЕсли; Если ирОбщий.СтрокиРавныЛкс(СтрокаТЧ.Событие, "Context") Тогда // Встроим контекст в предыдущие события Индекс = ТаблицаЖурнала.Количество() - 2; Пока Индекс >= 0 Цикл СтрокаБезКонтекста = ТаблицаЖурнала[Индекс]; Индекс = Индекс - 1; Если Ложь Или СтрокаБезКонтекста.Сеанс <> СтрокаТЧ.Сеанс Или СтрокаБезКонтекста.Инфобаза <> СтрокаТЧ.Инфобаза Тогда Прервать; КонецЕсли; Если Не СтрокаБезКонтекста.СтрокаМодуля = "" Тогда Прервать; КонецЕсли; ЗаполнитьЗначенияСвойств(СтрокаБезКонтекста, СтрокаТЧ, "СтрокаМодуля, Контекст"); КонецЦикла; КонецЕсли; КонецЦикла; // Для отката к началу последнего события РазмерТекущейПорции = СтрДлина(ПорцияТекстаФайла); АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + СтрДлина(ТекстФайла); Если РазмерТекущейПорции = РазмерПорции Тогда Если СтрокаТЧ <> Неопределено Тогда ТаблицаЖурнала.Удалить(ТаблицаЖурнала.Количество() - 1); КонецЕсли; Если Вхождение <> Неопределено Тогда ТекстФайла = Сред(ТекстФайла, Вхождение.FirstIndex); Иначе ТекстФайла = Прав(ТекстФайла, 1000); // Страховка КонецЕсли; АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле - СтрДлина(ТекстФайла); Иначе ТекстФайла = ""; КонецЕсли; КонецЦикла; Если ИндикаторФайла <> Неопределено Тогда ирОбщий.ОсвободитьИндикаторПроцессаЛкс(); КонецЕсли; КартаФайла.ПозицияКонца = АбсолютнаяПозицияВФайле; Если Истина И ПозицияНачалаСчитанныхДанных <> -1 И (Ложь Или КартаФайла.ПозицияНачала = -1 Или КартаФайла.ПозицияНачала > ПозицияНачалаСчитанныхДанных) Тогда КартаФайла.ПозицияНачала = ПозицияНачалаСчитанныхДанных; КонецЕсли; Если Ложь Или Не ЗначениеЗаполнено(КонецПериода) Или КонецПериода > КартаФайла.КонецПериода Тогда КартаФайла.КонецПериода = КонецПериода; КонецЕсли; Если Ложь Или Не ЗначениеЗаполнено(НачалоПериода) Или НачалоПериода < КартаФайла.НачалоПериода Тогда КартаФайла.НачалоПериода = НачалоПериода; КонецЕсли; КонецЦикла; ирОбщий.ОсвободитьИндикаторПроцессаЛкс(); //КлючиЗагруженныхСтрок = НовыеКлючиЗагруженныхСтрок; //Если НаСервере = Истина Тогда // ЭтотОбъект.ПоследнееВремяНачалаЗагрузкиСервера = лПоследнееВремяНачалаЗагрузки; //Иначе // ЭтотОбъект.ПоследнееВремяНачалаЗагрузки = лПоследнееВремяНачалаЗагрузки; //КонецЕсли; //МинимальнаяДатаЗагрузки = Мин(НачалоПериода, МинимальнаяДатаЗагрузки); ТаблицаЖурнала.Сортировать("МоментВремени"); //ТаблицаЖурнала.Сортировать("МоментВремениНачала"); //Пустота производных колонок мНепустыеКолонкиЖурнала.Вставить("Длительность"); мНепустыеКолонкиЖурнала.Вставить("Дата"); мНепустыеКолонкиЖурнала.Вставить("ДатаНачала"); //мНепустыеКолонкиЖурнала.Вставить("Картинка"); Если мНепустыеКолонкиЖурнала.Свойство("Контекст") Тогда мНепустыеКолонкиЖурнала.Вставить("СтрокаМодуля"); мНепустыеКолонкиЖурнала.Вставить("СтрокаБазовогоМодуля"); КонецЕсли; Возврат Истина; КонецФункции Функция ПолучитьМоментВремени(Дата, Микросекунды) Результат = Формат(Дата, "ДФ=yyyyMMddHHmmss") + XMLСтрока(Микросекунды); Возврат Результат; КонецФункции Функция ЗаполнитьСтрокуБазовогоУровня(СтрокаТЧ) Если БазовыйУровеньСтека > 0 Тогда //МаркерБазовогоМодуля = Символы.Таб + мИмяБазовогоМодуля + " : "; //ПозицияМаркераМодуля = Найти(СтрокаТЧ.Контекст, МаркерБазовогоМодуля); //КонецСтроки = Сред(СтрокаТЧ.Контекст, ПозицияМаркераМодуля + СтрДлина(МаркерБазовогоМодуля)); НовоеЗначение = СокрЛ(СтрПолучитьСтроку(СтрокаТЧ.Контекст, БазовыйУровеньСтека)); Иначе НовоеЗначение = ""; КонецЕсли; ирОбщий.ПрисвоитьЕслиНеРавноЛкс(СтрокаТЧ.СтрокаМодуляБазовогоУровня, НовоеЗначение); Возврат Неопределено; КонецФункции // ПопытокЧтения - Число, используется только при РежимТрассы = Истина Функция ПрочитатьСобственныйЖурналДвухСторон(УдалитьДополнительныеСобытия = Истина, ИменаНеполезныхКолонок = "", РежимТрассы = Истина, ПопытокЧтения = 10, СмещениеБазовогоУровня = Неопределено) Если РежимТрассы Тогда Если мИдентификаторТрассы = Неопределено Тогда Если Не ирКэш.ЭтоФайловаяБазаЛкс() Тогда ирОбщий.ЛиТехножурналВключенЛкс(Истина, Истина); КонецЕсли; ирОбщий.ЛиТехножурналВключенЛкс(, Истина); Возврат Ложь; КонецЕсли; КонецЕсли; Если РежимТрассы Тогда ЭтотОбъект.ВключитьСвойстваСИменамиМетаданных = Ложь; // Для ускорения выключаем, т.к. фильтрация будет многостадийной ЭтотОбъект.ЗагружатьЖурналКлиента = Истина; ЭтотОбъект.ЗагружатьЖурналСервера = Не ирКэш.ЭтоФайловаяБазаЛкс(); ЭтотОбъект.ЗагружатьТолькоТекущийСеанс = Истина; КонецЕсли; ВыраниватьДатуПоСерверу = Ложь; #Если Клиент Тогда ВыраниватьДатуПоСерверу = ВосстановитьЗначение("ирАнализТехножурнала.ВыраниватьДатуПоСерверу") = Истина; #КонецЕсли Если РежимТрассы Тогда РазницаВремениКлиентСервер = НачалоПериодаКлиента - НачалоПериодаСервера; Иначе РазницаВремениКлиентСервер = ирОбщий.ПолучитьТекущуюДатуЛкс() - ирОбщий.ПолучитьТекущуюДатуЛкс(Истина); КонецЕсли; Если Истина И Не ирКэш.Получить().ЭтоФайловаяБаза И ЗагружатьЖурналСервера Тогда ЭтотОбъект.КаталогЖурнала = ""; Если ВыраниватьДатуПоСерверу Тогда СдвигВремени = 0; Иначе СдвигВремени = -РазницаВремениКлиентСервер; КонецЕсли; РезультатСервера = ПрочитатьСобственныйЖурналОднойСтороны(НачалоПериодаСервера, КонецПериодаСервера, Истина, СдвигВремени, РежимТрассы, ПопытокЧтения, СмещениеБазовогоУровня); КонецЕсли; Если ЗагружатьЖурналКлиента Тогда ЭтотОбъект.КаталогЖурнала = ""; Если ВыраниватьДатуПоСерверу Тогда СдвигВремени = РазницаВремениКлиентСервер; Иначе СдвигВремени = 0; КонецЕсли; РезультатКлиента = ПрочитатьСобственныйЖурналОднойСтороны(НачалоПериодаКлиента, КонецПериодаКлиента, Ложь, СдвигВремени, РежимТрассы, ПопытокЧтения, СмещениеБазовогоУровня); КонецЕсли; Если Истина И РезультатКлиента = Неопределено И РезультатСервера = Неопределено Тогда Возврат Ложь; КонецЕсли; Если УдалитьДополнительныеСобытия Тогда УдалитьСтрокиПоОтбору(Новый Структура("Действие", "getExecSQLStatistics")); УдалитьСтрокиПоОтбору(Новый Структура("Событие", "CONTEXT")); КонецЕсли; Если РежимТрассы Тогда ЭтотОбъект.ВключитьСвойстваСИменамиМетаданных = Истина; КонецЕсли; Если ВключитьСвойстваСИменамиМетаданных Тогда ОбновитьСвойстваВТерминахМетаданных(); КонецЕсли; //ОбновитьСтрокиБазовогоУровня(); Возврат Истина; КонецФункции Функция ПрочитатьСобственныйЖурналОднойСтороны(НачалоПериода = Неопределено, КонецПериода = Неопределено, НаСервере = Истина, СдвигВремени = 0, РежимТрассы = Истина, ПопытокЧтения = 10, СмещениеБазовогоУровня = Неопределено) Если НачалоПериода <> Неопределено Тогда ЭтотОбъект.НачалоПериода = НачалоПериода; КонецЕсли; Если КонецПериода <> Неопределено Тогда ЭтотОбъект.КонецПериода = КонецПериода; КонецЕсли; ТехножурналВключен = ирОбщий.ЛиТехножурналВключенЛкс(НаСервере); Если Истина И Не ТехножурналВключен И РежимТрассы Тогда Возврат Неопределено; КонецЕсли; МассивТиповСУБД = Новый Массив(); Если ирКэш.ЭтоФайловаяБазаЛкс() Тогда МассивТиповСУБД.Добавить("DBV8DBENG"); //ОтборТЧ = Новый Структура("Событие", "SDBL"); Иначе МассивТиповСУБД.Добавить("DBMSSQL"); МассивТиповСУБД.Добавить("DBPOSTGRS"); МассивТиповСУБД.Добавить("DBORACLE"); МассивТиповСУБД.Добавить("DB2"); //ОтборТЧ = Новый Структура("Событие", "CONTEXT"); КонецЕсли; СообщитьРазмер = Неопределено; Для Счетчик = 1 По ПопытокЧтения Цикл #Если Клиент Тогда ОбработкаПрерыванияПользователя(); #КонецЕсли Если Счетчик > 1 Тогда #Если Клиент Тогда Состояние("Ожидание техножурнала"); #КонецЕсли ирКэш.Получить().Sleep(500); СообщитьРазмер = Ложь; КонецЕсли; ЖурналСчитан = ПрочитатьПроизвольныйЖурнал(СообщитьРазмер, СдвигВремени, , , НаСервере); Если Не ЖурналСчитан Тогда Возврат Неопределено; КонецЕсли; //ТехножурналВключен = ирОбщий.ЛиТехножурналВключенЛкс(Истина); //Если ТехножурналВключен Тогда // Если АвтоочисткаТехножурнала Тогда // КаталогТекущегоЖурнала = ПолучитьКаталогТекущегоЖурнала(); // Если ЗначениеЗаполнено(КаталогТекущегоЖурнала) Тогда // ирОбщий.ОчиститьКаталогЖурналаЛкс(КаталогТекущегоЖурнала, Истина, Ложь); // КонецЕсли; // КонецЕсли; //КонецЕсли; Если РежимТрассы Тогда МаркерНачала = Новый Структура("Описание", "{(1, 1)}: Ожидается выражение ""ВЫБРАТЬ"" |<>НачалоТрассы_" + мИдентификаторТрассы); МаркерКонца = Новый Структура("Описание", "{(1, 1)}: Ожидается выражение ""ВЫБРАТЬ"" |<>КонецТрассы_" + мИдентификаторТрассы); // Удаляем лишние строки до маркера начала и после маркера конца НайденныеСтроки = ТаблицаЖурнала.НайтиСтроки(МаркерНачала); Если НайденныеСтроки.Количество() = 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; ЭтотОбъект.КонецПериодаСервера = Неопределено; ЭтотОбъект.КонецПериодаКлиента = Неопределено; ЭтотОбъект.НачалоПериодаСервера = Неопределено; ЭтотОбъект.НачалоПериодаКлиента = Неопределено; Если Ложь Или ЗагружатьЖурналКлиента Или ЗагружатьЖурналСервера Тогда ЖурналПрочитан = ПрочитатьСобственныйЖурналДвухСторон(,, Ложь); Иначе ЖурналПрочитан = ПрочитатьПроизвольныйЖурнал(); КонецЕсли; Возврат ЖурналПрочитан; КонецФункции // ТолькоПустые - заполнять только ранее не заполненные свойства Процедура ЗаполнитьСвойстваСИменамиМетаданных(ВыбраннаяСтрока) Экспорт Если ВыбраннаяСтрока.СвойстваСИменамиМетаданныхАктуальны Тогда Возврат; КонецЕсли; Для Каждого ИмяСвойства Из мСвойстваСИменамиБД Цикл Если Найти(ИмяСвойства, "БезПараметров") > 0 Тогда Продолжить; КонецЕсли; Попытка Пустышка = ТипЗнч(ВыбраннаяСтрока[ИмяСвойства]); // т.к. строки длинные, то их копирование в новую переменную накладно Исключение // Такого свойства нет - пропускаем Продолжить; КонецПопытки; ЗначениеСвойства = ВыбраннаяСтрока[ИмяСвойства]; Если Истина И ЗначениеЗаполнено(ЗначениеСвойства) И (Ложь Или ВыбраннаяСтрока.Инфобаза = "" Или ирОбщий.СтрокиРавныЛкс(ВыбраннаяСтрока.Инфобаза, НСтр(СтрокаСоединенияИнформационнойБазы(), "Ref"))) Тогда Попытка ТипСУБД = ВыбраннаяСтрока.Событие; Исключение ТипСУБД = Сред(ИмяСвойства, СтрДлина("Текст") + 1); // Опасно КонецПопытки; //Попытка ТекстМета = ПеревестиТекстЗапросаВТерминыМетаданных(ЗначениеСвойства, , , ТипСУБД); //Исключение // ТекстМета = ""; //КонецПопытки; //Если ТекстМета <> "" Тогда ВыбраннаяСтрока[ИмяСвойства + "Мета"] = ТекстМета; //КонецЕсли; Иначе // База чужая. Не делаем преобразования ВыбраннаяСтрока[ИмяСвойства + "Мета"] = ЗначениеСвойства; КонецЕсли; КонецЦикла; Если Не ЗначениеЗаполнено(ВыбраннаяСтрока.ТекстБезПараметровSDBLМета) Тогда Инфобаза = ""; ТекстSDBLМета = ""; Попытка Инфобаза = ВыбраннаяСтрока.Инфобаза; ТекстSDBLМета = ВыбраннаяСтрока.ТекстSDBLМета; Исключение КонецПопытки; Если Ложь Или Инфобаза = "" Или ирОбщий.СтрокиРавныЛкс(Инфобаза, НСтр(СтрокаСоединенияИнформационнойБазы(), "Ref")) Тогда Если Истина И ТекстSDBLМета <> "" Тогда ВыбраннаяСтрока.ТекстБезПараметровSDBLМета = RegExpПараметры.Replace(ТекстSDBLМета, "&P"); Иначе ВыбраннаяСтрока.ТекстБезПараметровSDBLМета = ПеревестиТекстЗапросаВТерминыМетаданных(ВыбраннаяСтрока.ТекстБезПараметровSDBL); КонецЕсли; КонецЕсли; КонецЕсли; ВыбраннаяСтрока.СвойстваСИменамиМетаданныхАктуальны = Истина; КонецПроцедуры Функция ПолучитьКаталогТекущегоЖурнала(НаСервере) Экспорт Результат = Неопределено; Если НаСервере Тогда #Если Клиент Тогда Результат = ВосстановитьЗначение("ирАнализТехножурнала.КаталогЖурналаСервера"); #КонецЕсли КонецЕсли; Если Не ЗначениеЗаполнено(Результат) Тогда Результат = ирОбщий.ПолучитьКаталогТехножурналаЛкс(НаСервере); Если Не ЗначениеЗаполнено(Результат) Тогда Сообщить("Технологический журнал выключен. Невозможно определить каталог журнала по умолчанию."); Возврат Неопределено; КонецЕсли; Если НаСервере Тогда КлиентЗапущенНаКомпьютереСервера = ирОбщий.ЛиКлиентЗапущенНаКомпьютереСервераЛкс(); Если Не КлиентЗапущенНаКомпьютереСервера Тогда Если ЭтоЛокальныйПутьЛкс(Результат) Тогда Сообщить("Клиент запущен не на компьютере сервера (" + ирСервер.ПолучитьИмяКомпьютераЛкс() + "), а в серверной настройке техножурнала указан локальный каталог. Необходимо указать сетевой путь к техножурналу сервера"); #Если Клиент Тогда ФормаНастройки = ПолучитьФорму("НастройкаЧтения"); РезультатНастройки = ФормаНастройки.ОткрытьМодально(); Если РезультатНастройки = Истина Тогда Результат = ВосстановитьЗначение("ирАнализТехножурнала.КаталогЖурналаСервера"); Иначе Результат = Неопределено; КонецЕсли; #КонецЕсли КонецЕсли; КонецЕсли; КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Функция ЭтоЛокальныйПутьЛкс(Путь) Экспорт ЭтоЛокальныйРесурс = Ложь Или Найти(НРег(Путь), "\\localhost") = 1 Или Найти(НРег(Путь), "\\127.0.0.1") = 1 Или Лев(Путь, 2) <> "\\"; Возврат ЭтоЛокальныйРесурс; КонецФункции // ЭтоЛокальныйПуть() Функция ОткрытьСПараметрами(пКаталогЖурнала) Экспорт Форма = ПолучитьФорму(); Форма.Открыть(); Форма.КаталогЖурнала = пКаталогЖурнала; Возврат Форма; КонецФункции Функция ОткрытьСОтбором(НачалоПериода = Неопределено, КонецПериода = Неопределено, СтруктураОтбора = Неопределено) Экспорт Форма = ПолучитьФорму(,,); Форма.Открыть(); Отбор = Форма.ЭлементыФормы.ТаблицаЖурнала.ОтборСтрок; Отбор.Сбросить(); Если НачалоПериода <> Неопределено Тогда Форма.НачалоПериода = НачалоПериода; КонецЕсли; Если КонецПериода <> Неопределено Тогда Форма.КонецПериода = КонецПериода; КонецЕсли; Если СтруктураОтбора <> Неопределено Тогда Для Каждого КлючИЗначение Из СтруктураОтбора Цикл Отбор[КлючИЗначение.Ключ].Установить(КлючИЗначение.Значение); КонецЦикла; КонецЕсли; Возврат Форма; КонецФункции Функция ПолучитьИмяСвойстваБезМета(Знач МестноеИмя) Экспорт Если ирОбщий.СтрокиРавныЛкс(Прав(МестноеИмя, 4), "мета") Тогда МестноеИмя = Лев(МестноеИмя, СтрДлина(МестноеИмя) - 4); КонецЕсли; Возврат МестноеИмя; КонецФункции Процедура ОбновитьСвойстваВТерминахМетаданных() Экспорт ВыбранныеСтроки = ТаблицаЖурнала.НайтиСтроки(Новый Структура("СвойстваСИменамиМетаданныхАктуальны", Ложь)); Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ВыбранныеСтроки.Количество(), "Перевод в термины метаданных"); Для Каждого СтрокаТаблицыЖурнала Из ВыбранныеСтроки Цикл ирОбщий.ОбработатьИндикаторЛкс(Индикатор); ЗаполнитьСвойстваСИменамиМетаданных(СтрокаТаблицыЖурнала); КонецЦикла; ирОбщий.ОсвободитьИндикаторПроцессаЛкс(); КонецПроцедуры Процедура ОбновитьСтрокиБазовогоУровня() Экспорт //Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ТаблицаЖурнала.Количество()); Для Каждого СтрокаТаблицыЖурнала Из ТаблицаЖурнала Цикл //ирОбщий.ОбработатьИндикаторЛкс(Индикатор); ЗаполнитьСтрокуБазовогоУровня(СтрокаТаблицыЖурнала); КонецЦикла; //Для Каждого СтрокаКонтекста Из Контексты Цикл // ЗаполнитьСтрокуБазовогоУровня(СтрокаКонтекста); //КонецЦикла; КонецПроцедуры Процедура ЗаполнитьТекстSDBLБезПараметров() Экспорт Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ТаблицаЖурнала.Количество()); Для Каждого СтрокаТаблицыЖурнала Из ТаблицаЖурнала Цикл ирОбщий.ОбработатьИндикаторЛкс(Индикатор); Если Истина И СтрокаТаблицыЖурнала.ТекстSDBL <> "" И СтрокаТаблицыЖурнала.ТекстБезПараметровSDBL = "" Тогда СтрокаТаблицыЖурнала.ТекстБезПараметровSDBL = RegExpПараметры.Replace(СтрокаТаблицыЖурнала.ТекстSDBL, "&P"); КонецЕсли; КонецЦикла; КонецПроцедуры Процедура ОставитьТолькоСтрокиПоОтбору(СтруктураОтбора) Экспорт НужныеСтроки = ТаблицаЖурнала.НайтиСтроки(СтруктураОтбора); КоличествоСтрок = ТаблицаЖурнала.Количество(); Для Счетчик = 1 По КоличествоСтрок Цикл Индекс = КоличествоСтрок - Счетчик; СтрокаЖурнала = ТаблицаЖурнала[Индекс]; Если НужныеСтроки.Найти(СтрокаЖурнала) = Неопределено Тогда ТаблицаЖурнала.Удалить(СтрокаЖурнала); КонецЕсли; КонецЦикла; КонецПроцедуры Процедура УдалитьСтрокиПоОтбору(СтруктураОтбора) Экспорт НенужныеСтроки = ТаблицаЖурнала.НайтиСтроки(СтруктураОтбора); Для Каждого НенужнаяСтрока Из НенужныеСтроки Цикл ТаблицаЖурнала.Удалить(НенужнаяСтрока); КонецЦикла; КонецПроцедуры Процедура ЗаписатьМаркерВТехножурнал(Маркер, ДляКлиента = Истина, ДляСервера = Истина) Экспорт Если ДляКлиента Тогда ЗапросМаркер = Новый Запрос(); ЗапросМаркер.Текст = Маркер; Попытка ЗапросМаркер.Выполнить(); // Генерируем для клиента маркер-событие QERR Исключение КонецПопытки; КонецЕсли; Если Истина И ДляСервера И Не ирКэш.ЭтоФайловаяБазаЛкс() Тогда Попытка ирСервер.ВыполнитьЗапросЛкс(Маркер); // Генерируем для сервереа маркер-событие QERR Исключение КонецПопытки; КонецЕсли; КонецПроцедуры Функция НачатьТрассу(ПрефиксТрассы = "", ВыводитьСообщения = Ложь) Экспорт // Попробовать сделать проверку регистрации событий QERR в настройке техножурнала на сервере Если Не ирКэш.ЭтоФайловаяБазаЛкс() Тогда ТехножурналСервераВключен = ирОбщий.ЛиТехножурналВключенЛкс(Истина, ВыводитьСообщения); КонецЕсли; ТехножурналКлиентаВключен = ирОбщий.ЛиТехножурналВключенЛкс(, ВыводитьСообщения); Если Истина И ТехножурналСервераВключен <> Истина И Не ТехножурналКлиентаВключен Тогда Возврат Ложь; КонецЕсли; ЭтотОбъект.КонецПериодаСервера = Неопределено; ЭтотОбъект.КонецПериодаКлиента = Неопределено; ЭтотОбъект.НачалоПериодаСервера = ирОбщий.ПолучитьТекущуюДатуЛкс(Истина); ЭтотОбъект.НачалоПериодаКлиента = ирОбщий.ПолучитьТекущуюДатуЛкс(Ложь); мИдентификаторТрассы = ПрефиксТрассы + "_" + СтрЗаменить(Новый УникальныйИдентификатор(), "-", ""); ЗаписатьМаркерВТехножурнал("НачалоТрассы_" + мИдентификаторТрассы); Возврат Истина; КонецФункции Функция КончитьТрассу() Экспорт Если ЗначениеЗаполнено(ЭтотОбъект.КонецПериодаКлиента) Тогда Возврат Ложь; КонецЕсли; ЭтотОбъект.КонецПериодаСервера = ирОбщий.ПолучитьТекущуюДатуЛкс(Истина); ЭтотОбъект.КонецПериодаКлиента = ирОбщий.ПолучитьТекущуюДатуЛкс(Ложь); ЗаписатьМаркерВТехножурнал("КонецТрассы_" + мИдентификаторТрассы); Возврат Истина; КонецФункции #Если Клиент Тогда Функция ПоказатьТрассу(УдалитьДополнительныеСобытия = Истина, ИменаНеполезныхКолонок = "", ПопытокЧтения = 10, СмещениеБазовогоУровня = Неопределено) Экспорт Если ЭтотОбъект.КонецПериодаСервера = Неопределено Тогда Предупреждение("Сформируйте трассу заново"); Возврат Неопределено; КонецЕсли; ОчиститьТаблицуЖурнала(); ЖурналПрочитан = ПрочитатьСобственныйЖурналДвухСторон(УдалитьДополнительныеСобытия, ИменаНеполезныхКолонок, Истина, ПопытокЧтения, СмещениеБазовогоУровня); Если Не ЖурналПрочитан Тогда Возврат Неопределено; КонецЕсли; ВыраниватьДатуПоСерверу = ВосстановитьЗначение("ирАнализТехножурнала.ВыраниватьДатуПоСерверу") = Истина; лКаталогЖурнала = КаталогЖурнала; ФормаАнализа = ПолучитьФорму(); ФормаАнализа.ЭтоТрасса = Истина; ФормаАнализа.Открыть(); ФормаАнализа.ЗагружатьТолькоТекущийСеанс = Истина; ФормаАнализа.ЗагружатьЖурналКлиента = Истина; ФормаАнализа.ЗагружатьЖурналСервера = Не ирКэш.ЭтоФайловаяБазаЛкс(); Если ВыраниватьДатуПоСерверу Тогда ФормаАнализа.КонецПериода = КонецПериодаСервера; ФормаАнализа.НачалоПериода = НачалоПериодаСервера; Иначе ФормаАнализа.КонецПериода = КонецПериодаКлиента; ФормаАнализа.НачалоПериода = НачалоПериодаКлиента; КонецЕсли; ФормаАнализа.КаталогЖурнала = лКаталогЖурнала; ФормаАнализа.УстановитьРежимИтогов(ТаблицаЖурнала.Количество() > 20); ФормаАнализа.ПериодПоследниеМинуты = 0; ФормаАнализа.ОбновитьДоступность(); ФормаАнализа.ЭлементыФормы.ПанельНастройки.ТекущаяСтраница = ФормаАнализа.ЭлементыФормы.ПанельНастройки.Страницы.Анализ; ФормаАнализа.УстановитьБесполезныеКолонки(ИменаНеполезныхКолонок); Возврат ФормаАнализа; КонецФункции Функция ОчиститьТаблицуЖурнала() Экспорт мНепустыеКолонкиЖурнала = Новый Структура(); ТаблицаЖурнала.Очистить(); Возврат Неопределено; КонецФункции Функция ОткрытьТекстБДВКонверторе(ТекстSDBL, ОткрытьСтраницуЗапроса = Истина, КлючУникальности = Неопределено, ЭтоТекстSDBL = Истина) Экспорт ФормаЗапроса = ПолучитьФорму("КонверторВМета", , КлючУникальности); ФормаЗапроса.ЭтоТекстSDBL = ЭтоТекстSDBL; ФормаЗапроса.ЭлементыФормы.ТекстБД.УстановитьТекст(ТекстSDBL); Если ОткрытьСтраницуЗапроса Тогда ПанельОсновная = ФормаЗапроса.ЭлементыФормы.ПанельОсновная; ПанельОсновная.ТекущаяСтраница = ПанельОсновная.Страницы.ТекстСМетаданными; КонецЕсли; ФормаЗапроса.Открыть(); Возврат Неопределено; КонецФункции #КонецЕсли Функция ПолучитьВариантПросмотраТекстПоИмениРеквизита(ИмяРеквизита) Экспорт Если Ложь Или мСвойстваСИменамиБД.Найти(ПолучитьИмяСвойстваБезМета(ИмяРеквизита)) <> Неопределено Или ирОбщий.СтрокиРавныЛкс(ИмяРеквизита, "ТекстЗапроса1С") Тогда ВариантПросмотра = "ЯзыкЗапросов"; ИначеЕсли ирОбщий.СтрокиРавныЛкс(ИмяРеквизита, "Контекст") <> Неопределено Тогда ВариантПросмотра = "ВстроенныйЯзык"; Иначе ВариантПросмотра = "Компактный"; КонецЕсли; Возврат ВариантПросмотра; КонецФункции Функция ПреобразоватьЗначениеВSDBL(Ссылка) Экспорт СтруктураБД = ирКэш.ПолучитьСтруктуруХраненияБДЛкс(); СтруктураПоиска = Новый Структура("Метаданные, Назначение", Ссылка.Метаданные().ПолноеИмя(), "Основная"); СтрокаТаблицы = СтруктураБД.НайтиСтроки(СтруктураПоиска)[0]; RegExp = ирКэш.Получить().RegExp; RegExp.Pattern = "\d+"; РезультатПоиска = RegExp.Execute(СтрокаТаблицы.ИмяТаблицыХранения); Текст = РезультатПоиска.Item(0).Value + ":" + ирОбщий.ПолучитьГУИДИнверсныйИзПрямогоЛкс("" + Ссылка.УникальныйИдентификатор()); Возврат Текст; КонецФункции Функция ПолучитьСтруктуруЗапросаИзТекстаБД(ТекстБД, ТипСУБД = "", ПересобратьТекст = Ложь) Экспорт Текст = ТекстБД; //ТаблицаПараметров = Новый ТаблицаЗначений; //ТаблицаПараметров.Колонки.Добавить("Значение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 = "([A-F0-9]+):([A-F0-9]+|0x[A-F0-9]+)"; // замена ссылочных констант Вхождения = RegExp.Execute(Текст); Для Каждого Вхождение Из Вхождения Цикл ЗначениеSDBL = Вхождение.Value; Если СтрДлина(ЗначениеSDBL) < 32 Тогда // Защита от частей литерала Дата Продолжить; КонецЕсли; Если ТаблицаПараметров.Найти(ЗначениеSDBL, "ЗначениеSDBL") = Неопределено Тогда ЗначениеПараметра = ирОбщий.ПреобразоватьЗначениеИзSDBLЛкс(ЗначениеSDBL); СтрокаПараметра = ирОбщий.НайтиДобавитьПараметрСсылкуВТаблицуЛкс(ТаблицаПараметров,,, ЗначениеПараметра); СтрокаПараметра.ЗначениеSDBL = ЗначениеSDBL; ОбъектМД = ирОбщий.ПолучитьМетаданныеЛкс(ЗначениеПараметра); Если ОбъектМД <> Неопределено Тогда СтрокаПараметра.Метаданные = ОбъектМД.ПолноеИмя(); КонецЕсли; Текст = СтрЗаменить(Текст, ЗначениеSDBL, "&" + СтрокаПараметра.Имя); КонецЕсли; КонецЦикла; КонецЕсли; 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+)'\}"; // литералы Дата Текст = RegExp.Replace(Текст, "DATETIME($1,$2,$3,$4,$5,$6)"); RegExp.Pattern = "N'([^']*)'"; // для замены литералов Строка MSSQL Текст = RegExp.Replace(Текст, """$1"""); ТаблицаТаблиц = Новый ТаблицаЗначений; ТекстМета = ПеревестиТекстЗапросаВТерминыМетаданных(Текст,,, ТипСУБД, ТаблицаТаблиц); ТаблицаТаблиц.Сортировать("ИмяМета"); Если ПересобратьТекст Тогда ПолеТекста = ирОбщий.ПолучитьОбъектПоПолномуИмениМетаданныхЛкс("Обработка.ирКлсПолеТекстовогоДокументаСКонтекстнойПодсказкой"); ПолеТекста.ИнициализироватьНеинтерактивно(1); //ПолеТекста.ПолеТекстовогоДокумента = ПолеТекстаЗапроса; КонструкторЗапроса = ПолеТекста.ПолучитьФорму("КонструкторЗапроса"); Если ЗначениеЗаполнено(ТипСУБД) Тогда ДиалектSQL = "MSSQL"; Иначе ДиалектSQL = "1С"; КонецЕсли; Если ПолеТекста.ЗагрузитьТекстВКонструктор(ТекстМета, КонструкторЗапроса,, ДиалектSQL) Тогда ТекстМета = КонструкторЗапроса.СобратьПолныйТекст(, Истина); КонецЕсли; КонецЕсли; Результат = Новый Структура(); Результат.Вставить("Текст", ТекстМета); Результат.Вставить("Параметры", ТаблицаПараметров); Результат.Вставить("Таблицы", ТаблицаТаблиц); Возврат Результат; КонецФункции Функция НайтиВызовыМетодовМодулей(ИмяМодуля, НомерНачальнойСтроки, НомерКонечнойСтроки, ТолькоОдну = Истина) Результат = Новый Массив(); Для Каждого СтрокаТаблицы Из ТаблицаЖурнала Цикл ФрагментыНачальнойСтрокиМодуля = ирОбщий.ПолучитьМассивИзСтрокиСРазделителемЛкс(СтрокаТаблицы.СтрокаМодуля, ":", Истина); Если ФрагментыНачальнойСтрокиМодуля[0] <> ИмяМодуля Тогда Результат.Вставить(0, СтрокаТаблицы); Если ТолькоОдну Тогда Прервать; КонецЕсли; КонецЕсли; НомерСтрокиМодуля = Число(ФрагментыНачальнойСтрокиМодуля[1]); Если Ложь Или НомерСтрокиМодуля < НомерНачальнойСтроки Или НомерСтрокиМодуля > НомерКонечнойСтроки Тогда Результат.Вставить(0, СтрокаТаблицы); Если ТолькоОдну Тогда Прервать; КонецЕсли; КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции // Получить словарь имен таблиц входящих в запрос и соответствующих // шаблонам словаря метаданных // // Параметры: // ТекстЗапроса - Строка, текст запроса для которого строится словарь // СловарьШаблоновМетаданных - Соответствие, словарь шаблонов метаданных // ТипСУБД - Строка (Перечисление.ТипСУБД) // // Возвращаемое значение: // Соответствие - Словарь имен таблиц запроса // Функция ПолучитьСловарьЗапроса(Знач ТекстЗапроса, СловарьШаблоновМетаданных, ТипСУБД = "") Экспорт Перем КоличествоСимволов; ТекстЗапроса = НРег(ТекстЗапроса); ДлинаТекстаЗапроса = СтрДлина(ТекстЗапроса); СловарьЗапроса = Новый Соответствие; //Если НРег(ТипСУБД) = НРег("DB2") Тогда // ТекстЗапроса = ВРег(ТекстЗапроса); //КонецЕсли; ЗавершающиеСимволы = " )(.,][" + Символы.ПС + Символы.ВК; Для Каждого СтрокаСловаряМетаданных Из СловарьШаблоновМетаданных Цикл // Скопировать текст запроса для обработки Текст = ТекстЗапроса; // Искать имя таблицы по шаблону Пока Истина Цикл // Получить начало шаблона Если СтрокаСловаряМетаданных.Значение = 0 Тогда Шаблон = СтрокаСловаряМетаданных.Ключ; Иначе Шаблон = Лев(СтрокаСловаряМетаданных.Ключ, Найти(СтрокаСловаряМетаданных.Ключ, "1") - 1); КонецЕсли; ЭлементСловаря = Неопределено; ДлинаШаблона = СтрДлина(Шаблон); ДлинаТекста = СтрДлина(Текст); // Найти позицию вхождения шаблона в тексте запроса ПозицияШаблона = Найти(Текст, Шаблон); // Если шаблона в тексте запроса нет, прекратить поиск этого шаблона Если ПозицияШаблона = 0 Или ДлинаТекста < ПозицияШаблона + ДлинаШаблона - 1 Тогда Прервать; КонецЕсли; // Удалить из текста запроса обработанный фрагмент Текст = Прав(Текст, ДлинаТекста - ПозицияШаблона - ДлинаШаблона + 1); ЭлементСловаря = Шаблон; // Если шаблон содержит счетчик Если СтрокаСловаряМетаданных.Значение <> 0 Тогда // Получить значение счетчика ЗначениеЧисла = ПолучитьЧислоСтрокой(Текст, КоличествоСимволов); Если ЗначениеЧисла = Неопределено Тогда ЭлементСловаря = Неопределено; Продолжить; КонецЕсли; // Удалить из текста запроса текстовое представление счетчика имени ЭлементСловаря = ЭлементСловаря + ЗначениеЧисла; Текст = Прав(Текст, СтрДлина(Текст) - КоличествоСимволов); // Если счетчиков больше одного Для Сч = 1 По СтрокаСловаряМетаданных.Значение - 1 Цикл // Получить следующий фрагмент шаблона ПозицияПервогоСлота = Найти(СтрокаСловаряМетаданных.Ключ, Строка(Сч)); ПозицияВторогоСлота = Найти(СтрокаСловаряМетаданных.Ключ, Строка(Сч + 1)); ФрагментШаблона = Сред(СтрокаСловаряМетаданных.Ключ, ПозицияПервогоСлота + 1, ПозицияВторогоСлота - ПозицияПервогоСлота - 1); ДлинаФрагментаШаблона = СтрДлина(ФрагментШаблона); ДлинаТекста = СтрДлина(Текст); Если ДлинаФрагментаШаблона > ДлинаТекста Или Лев(Текст, ДлинаФрагментаШаблона) <> ФрагментШаблона Тогда ЭлементСловаря = Неопределено; Прервать; КонецЕсли; // Получить значение счетчика для фрагмента шаблона Текст = Прав(Текст, ДлинаТекста - ДлинаФрагментаШаблона); ЗначениеЧисла = ПолучитьЧислоСтрокой(Текст, КоличествоСимволов); Текст = Прав(Текст, СтрДлина(Текст) - КоличествоСимволов); Если ЗначениеЧисла = Неопределено Тогда ЭлементСловаря = Неопределено; Прервать; КонецЕсли; // Дополнить имя таблицы найденым значением шаблона ЭлементСловаря = ЭлементСловаря + ФрагментШаблона + ЗначениеЧисла; КонецЦикла; Если ЭлементСловаря = Неопределено Тогда Продолжить; КонецЕсли; КонецЕсли; // Если найдено имя таблицы по шаблону Если ЭлементСловаря <> Неопределено Тогда ДлинаТекста = СтрДлина(Текст); // Проверить окончание имени для полного соответствия шаблону Если ДлинаТекста > 0 Тогда ЗавершающийСимвол = Лев(Текст, 1); Текст = Прав(Текст, ДлинаТекста - 1); Если Найти(ЗавершающиеСимволы, ЗавершающийСимвол) = 0 Тогда Продолжить; КонецЕсли; КонецЕсли; // Сохранить найденное имя таблицы СловарьЗапроса.Вставить(ЭлементСловаря); КонецЕсли; КонецЦикла; КонецЦикла; Возврат СловарьЗапроса; КонецФункции // ПолучитьСловарьЗапроса() // Получить число из строки в которой число находится в начале строки // // Праметры: // ИсходнаяСтрока - Строка, строка в которой находится число // // Возвращаемое значение: // Число - если оно есть, неопределено, если числа нет // Функция ПолучитьЧислоСтрокой(ИсходнаяСтрока, КоличествоСимволов) КоличествоСимволов = 0; ДлинаСтроки = СтрДлина(ИсходнаяСтрока); Для Сч = 1 По ДлинаСтроки Цикл ТекущийСимвол = КодСимвола(Сред(ИсходнаяСтрока, Сч, 1)); Если 48 <= ТекущийСимвол И ТекущийСимвол <= 57 Тогда КоличествоСимволов = КоличествоСимволов + 1; Иначе Прервать; КонецЕсли; КонецЦикла; Если КоличествоСимволов > 0 Тогда Возврат Лев(ИсходнаяСтрока, КоличествоСимволов); Иначе Возврат Неопределено; КонецЕсли; КонецФункции // ПолучитьЧислоСтрокой() // Перевести часть запроса из терминов СУБД в термины метаданных // // Параметры: // Запрос - Строка, сапрос в терминах СУБД // СтруктураХраненияБазыДанных - ТаблицаЗначений // СловарьШаблоновМетаданных - Соответствие, подробности в функции // ПолучитьСловарьШаблоновМетаданных() // ТипСУБД - Строка, (Перечисление.ТипСУБД) // выхТаблицы - ТаблицаЗначений, *Неопределено - описание использованных в тексте таблиц, заполняется только если таблица передана (без колонок) // // Возвращаемое значение: // Строка, запрос в терминах метаданных // Функция ПеревестиТекстЗапросаВТерминыМетаданных(Знач Запрос, СтруктураХраненияБазыДанных = Неопределено, СловарьШаблоновМетаданных = Неопределено, Знач ТипСУБД = "", выхТаблицы = Неопределено) Экспорт Если ирОбщий.СтрокиРавныЛкс(ТипСУБД, "sdbl") Тогда ТипСУБД = ""; КонецЕсли; Если СтруктураХраненияБазыДанных = Неопределено Тогда СтруктураХраненияБазыДанных = ирКэш.ПолучитьСтруктуруХраненияБДЛкс(ЗначениеЗаполнено(ТипСУБД)); КонецЕсли; Если СловарьШаблоновМетаданных = Неопределено Тогда СловарьШаблоновМетаданных = ирКэш.ПолучитьСловарьШаблоновМетаданных(ЗначениеЗаполнено(ТипСУБД)); КонецЕсли; Запрос = Запрос + Символы.ПС; СловарьЗапроса = ПолучитьСловарьЗапроса(Запрос, СловарьШаблоновМетаданных, ТипСУБД); Если НРег(ТипСУБД) = НРег("DB2") Тогда Запрос = ВРег(Запрос); КонецЕсли; // Поиск имен таблиц в строке запроса Если СловарьЗапроса.Количество() > 10 Тогда Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(СловарьЗапроса.Количество(), "Преобразование в имена метаданных"); КонецЕсли; Если выхТаблицы <> Неопределено Тогда #Если _ Тогда выхТаблицы = Новый ТаблицаЗначений; #КонецЕсли выхТаблицы.Колонки.Очистить(); выхТаблицы.Колонки.Добавить("ИмяБД", Новый ОписаниеТипов("Строка")); выхТаблицы.Колонки.Добавить("ИмяМета", Новый ОписаниеТипов("Строка")); //выхТаблицы.Колонки.Добавить("ПсевдонимБД", Новый ОписаниеТипов("Строка")); //выхТаблицы.Колонки.Добавить("ПсевдонимМета", Новый ОписаниеТипов("Строка")); КонецЕсли; Для Каждого СтрокаСловаряЗапроса Из СловарьЗапроса Цикл Если Индикатор <> Неопределено Тогда ирОбщий.ОбработатьИндикаторЛкс(Индикатор); КонецЕсли; ОписаниеТаблицы = Неопределено; Если выхТаблицы <> Неопределено Тогда Если Найти(СтрокаСловаряЗапроса.Ключ, ".") = 0 Тогда ОписаниеТаблицы = выхТаблицы.Добавить(); ОписаниеТаблицы.ИмяБД = СтрокаСловаряЗапроса.Ключ; КонецЕсли; КонецЕсли; // Получить имя таблицы СтрокаСтруктуры = СтруктураХраненияБазыДанных.Найти(ирОбщий.ПолучитьПоследнийФрагментЛкс(СтрокаСловаряЗапроса.Ключ), "КраткоеИмяТаблицыХранения"); Если СтрокаСтруктуры = Неопределено Тогда // Видимо чужие метаданные Продолжить; КонецЕсли; ИмяТаблицы = СтрокаСтруктуры.КраткоеИмяТаблицыХранения; МетаПолноеИмяТаблицы = СтрокаСтруктуры.ИмяТаблицы; // Антибаг платформы 8.2.16 http://partners.v8.1c.ru/forum/thread.jsp?id=1090307#1090307 Если ПустаяСтрока(МетаПолноеИмяТаблицы) Тогда МетаПолноеИмяТаблицы = ""; Если ЗначениеЗаполнено(СтрокаСтруктуры.Метаданные) Тогда МетаПолноеИмяТаблицы = СтрокаСтруктуры.Метаданные + "."; КонецЕсли; МетаПолноеИмяТаблицы = МетаПолноеИмяТаблицы + СтрокаСтруктуры.Назначение; КонецЕсли; Синонимы = ПолучитьСинонимы(Запрос, ИмяТаблицы, МетаПолноеИмяТаблицы, ТипСУБД); //Синонимы.Вставить(ИмяТаблицы, МетаИмяТаблицы); Если ОписаниеТаблицы <> Неопределено Тогда ОписаниеТаблицы.ИмяМета = МетаПолноеИмяТаблицы; КонецЕсли; Для Каждого СтрокаПоля Из СтрокаСтруктуры.Поля Цикл Если Найти(Запрос, СтрокаПоля.ИмяПоляХранения) = 0 Тогда Продолжить; КонецЕсли; // Заменить имя поля Если Не ПустаяСтрока(СтрокаПоля.ИмяПоля) Тогда МетаИмяПоля = СтрокаПоля.ИмяПоля; // Антибаг платформы. У некоторых полей почему то пустое имя, а должно быть непустое ИначеЕсли Истина И СтрокаСтруктуры.Назначение = "ТабличнаяЧасть" И Найти(СтрокаПоля.ИмяПоляХранения, "_Reference") > 0 Тогда МетаИмяПоля = "Ссылка"; Иначе Продолжить; КонецЕсли; RegExpМета.Pattern = шГраничныйСимволИмени + СтрокаПоля.ИмяПоляХранения + шГраничныйСимволИмени; // Можно оптимизировать путем создания шаблона мультизамены Запрос = RegExpМета.Replace(Запрос, "$1" + МетаИмяПоля + "$2"); КонецЦикла; Для Каждого Синоним Из Синонимы Цикл // Заменить псевдоним таблицы 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") Или ирОбщий.СтрокиРавныЛкс(Синоним, "ORDER") Или ирОбщий.СтрокиРавныЛкс(Синоним, "THEN") Тогда Продолжить; КонецЕсли; Синонимы.Вставить(Синоним, ПсевдонимТаблицы + "_" + Синоним); КонецЦикла; Возврат Синонимы; КонецФункции // ПолучитьСинонимы() //ирПортативный #Если Клиент Тогда //ирПортативный Контейнер = Новый Структура(); //ирПортативный Оповестить("ирПолучитьБазовуюФорму", Контейнер); //ирПортативный Если Не Контейнер.Свойство("ирПортативный", ирПортативный) Тогда //ирПортативный ПолноеИмяФайлаБазовогоМодуля = ВосстановитьЗначение("ирПолноеИмяФайлаОсновногоМодуля"); //ирПортативный ирПортативный = ВнешниеОбработки.ПолучитьФорму(ПолноеИмяФайлаБазовогоМодуля); //ирПортативный КонецЕсли; //ирПортативный ирОбщий = ирПортативный.ПолучитьОбщийМодульЛкс("ирОбщий"); //ирПортативный ирКэш = ирПортативный.ПолучитьОбщийМодульЛкс("ирКэш"); //ирПортативный ирСервер = ирПортативный.ПолучитьОбщийМодульЛкс("ирСервер"); //ирПортативный ирПривилегированный = ирПортативный.ПолучитьОбщийМодульЛкс("ирПривилегированный"); //ирПортативный #КонецЕсли мПлатформа = ирКэш.Получить(); мНепустыеКолонкиЖурнала = Новый Структура(); //ЭтотОбъект.НаложениеПриДозагрузкеСекунд = 30; RegExpПараметры = мПлатформа.ПолучитьНовыйВычислительРегулярныхВыражений(); RegExpПараметры.IgnoreCase = Истина; RegExpПараметры.Global = Истина; RegExpПараметры.Pattern = "[A-F0-9]+:[A-F0-9]+|0x[A-F0-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 мСписокКолонок.Добавить("FileWild", "FileWild"); // События: DBV8DBENG мСписокКолонок.Добавить("LocaleName", "LocaleName"); // События: DBV8DBENG мСписокКолонок.Добавить("To", "To"); // События: DBV8DBENG мСписокКолонок.Добавить("From", "From_"); // События: DBV8DBENG мСписокКолонок.Добавить("ToCat", "ToCat"); // События: DBV8DBENG мСписокКолонок.Добавить("FromCat", "FromCat"); // События: DBV8DBENG мСписокКолонок.Добавить("Move", "Move"); // События: DBV8DBENG мСписокКолонок.Добавить("tableName", "tableName"); // События: DBV8DBENG мСписокКолонок.Добавить("What", "What"); // События: DBV8DBENG мСписокКолонок.Добавить("AppID", "AppID"); // События: QERR, DBMSSQL (дублируется t:applicationName), SDBL (дублирует t:applicationName) мСписокКолонок.Добавить("Index", "Index_"); мСписокКолонок.Добавить("Result", "Result"); мСписокКолонок.Добавить("Prm", "Prm"); мСписокКолонок.Добавить("setUnhandledExceptionFilter", "setUnhandledExceptionFilter"); мСписокКолонок.Добавить("Module", "МодульКонфигурации"); // События: EXCPCNTX мСписокКолонок.Добавить("ClientID", "Клиент"); // События: EXCPCNTX, SCALL, EXCP (дублируется t:clientID ?) мСписокКолонок.Добавить("Retexcp", "Retexcp"); // События: SCALL мТаблицаКолонок = Новый ТаблицаЗначений; мТаблицаКолонок.Колонки.Добавить("ВнутреннееИмя", Новый ОписаниеТипов("Строка")); мТаблицаКолонок.Колонки.Добавить("ИмяВТаблице", Новый ОписаниеТипов("Строка")); мТаблицаКолонок.Индексы.Добавить("ВнутреннееИмя"); мТаблицаКолонок.Индексы.Добавить("ИмяВТаблице"); мЧисловыеСвойства = Новый Структура; мСоответствиеКолонок = Новый Соответствие; Для Каждого ЭлементСписка Из мСписокКолонок Цикл мСоответствиеКолонок.Вставить(ЭлементСписка.Значение, ЭлементСписка.Представление); СтрокаСоответствия = мТаблицаКолонок.Добавить(); СтрокаСоответствия.ВнутреннееИмя = ЭлементСписка.Значение; СтрокаСоответствия.ИмяВТаблице = ЭлементСписка.Представление; Если Метаданные().ТабличныеЧасти.ТаблицаЖурнала.Реквизиты[ЭлементСписка.Представление].Тип.СодержитТип(Тип("Число")) Тогда мЧисловыеСвойства.Вставить(ЭлементСписка.Представление); КонецЕсли; КонецЦикла; мКартыФайлов = Новый ТаблицаЗначений; мКартыФайлов.Колонки.Добавить("ПолноеИмяФайла", Новый ОписаниеТипов("Строка")); мКартыФайлов.Колонки.Добавить("Сигнатура", Новый ОписаниеТипов("Строка")); мКартыФайлов.Колонки.Добавить("ОтборПоСеансу"); мКартыФайлов.Колонки.Добавить("ПозицияНачала", Новый ОписаниеТипов("Число")); мКартыФайлов.Колонки.Добавить("ПозицияКонца", Новый ОписаниеТипов("Число")); мКартыФайлов.Колонки.Добавить("НачалоПериода", Новый ОписаниеТипов("Дата")); мКартыФайлов.Колонки.Добавить("КонецПериода", Новый ОписаниеТипов("Дата")); мКартыФайлов.Колонки.Добавить("ДатаИзменения", Новый ОписаниеТипов("Дата")); мКартыФайлов.Индексы.Добавить("ПолноеИмяФайла, Сигнатура, ОтборПоСеансу"); мСвойстваСИменамиБД = Новый Массив(); мСвойстваСИменамиБД.Добавить("ТекстSDBL"); мСвойстваСИменамиБД.Добавить("ТекстСУБД"); мСвойстваСИменамиБД.Добавить("ПланСУБД"); мСвойстваСИменамиБД.Добавить("ТекстБезПараметровSDBL"); мСвойстваСИменамиБД.Добавить("Взаимоблокировка"); мСерверныеТипыПроцессов = Новый Структура; мСерверныеТипыПроцессов.Вставить("_adminprocess"); // ##AdminProcess## мСерверныеТипыПроцессов.Вставить("_rphost"); мСерверныеТипыПроцессов.Вставить("_rmngr"); мСерверныеТипыПроцессов.Вставить("_ragent"); шБуква = мПлатформа.шБуква; шГраничныйСимволИмени = "([^&" + шБуква + "\d]|^|$)";