RDT1C/DataProcessors/ирАнализТехножурнала/Ext/ObjectModule.bsl
2016-12-04 00:14:16 +03:00

1582 lines
102 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Перем мТаблицаКолонок Экспорт;
Перем мСписокКолонок Экспорт;
Перем КлючиЗагруженныхСтрок;
Перем мСвойстваСИменамиБД Экспорт;
Перем 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 Тогда
// Продолжить;
// КонецЕсли;
//КонецЕсли;
СтрокаТЧ = ТаблицаЖурнала.Добавить();
СтрокаТЧ.МоментВремени = Число(МоментВремени) - СдвигВремени * 10000;
СтрокаТЧ.ИмяФайлаЛога = ФайлЖурнала.ПолноеИмя;
СтрокаТЧ.Дата = ДатаВремяЗаписи - СдвигВремени;
СтрокаТЧ.ПроцессОС = ИдентификаторПроцесса;
//СтрокаТЧ.ТекстЖурнала = Вхождение.Value; // Теперь это только для отладки будем включать
СтрокаТЧ.Длительность = Число(Вхождение.SubMatches(2)) / 10; // Делаем из десятитысячных тысячные (мс) секудны
СтрокаТЧ.Событие = ВРег(Вхождение.SubMatches(3));
ВхожденияСвойств = RegExp2.Execute(Вхождение.SubMatches(4));
Для Каждого ВхождениеСвойства Из ВхожденияСвойств Цикл
//Для Индекс = 0 По мТаблицаКолонок.Количество() - 1 Цикл
//Индекс + СмещениеПервойКолонки
ИмяСвойства = ВхождениеСвойства.SubMatches(0);
ЗначениеСвойства = ВхождениеСвойства.SubMatches(3);
Если ирНеглобальный.ЛиПустаяПодгруппаRegExpЛкс(ЗначениеСвойства) Тогда
ЗначениеСвойства = ВхождениеСвойства.SubMatches(2);
КонецЕсли;
Если ирНеглобальный.ЛиПустаяПодгруппаRegExpЛкс(ЗначениеСвойства) Тогда
ЗначениеСвойства = ВхождениеСвойства.SubMatches(1);
КонецЕсли;
Если ирНеглобальный.ЛиПустаяПодгруппаRegExpЛкс(ЗначениеСвойства) Тогда
Продолжить;
КонецЕсли;
ИмяКолонкиТЧ = мСоответствиеКолонок[ИмяСвойства];
Если ИмяКолонкиТЧ = Неопределено Тогда
Если КомментироватьЗагрузку Тогда
Сообщить("Обнаружено неизвестное свойство """ + ИмяСвойства + """");
КонецЕсли;
Продолжить;
КонецЕсли;
//Если мЧисловыеСвойства.Свойство(ИмяКолонкиТЧ) Тогда
// Если Не ЗначениеЗаполнено(ЗначениеСвойства) Тогда
// ЗначениеСвойства = 0;
// Иначе
// Попытка
// ЗначениеСвойства = Число(ЗначениеСвойства);
// Исключение
// ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения числового свойства """ + ИмяКолонкиТЧ + """";
// КонецПопытки;
// КонецЕсли;
//КонецЕсли;
Если Не мНепустыеКолонкиЖурнала.Свойство(ИмяКолонкиТЧ) Тогда
Если ЗначениеЗаполнено(ЗначениеСвойства) Тогда
мНепустыеКолонкиЖурнала.Вставить(ИмяКолонкиТЧ);
КонецЕсли;
КонецЕсли;
Попытка
СтрокаТЧ[ИмяКолонкиТЧ] = ЗначениеСвойства;
Исключение
ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения свойства """ + ИмяКолонкиТЧ + """";
КонецПопытки;
КонецЦикла;
//АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + Вхождение.Length;
Если Истина
И ОтборПоСеансу <> Неопределено
И СтрокаТЧ.Сеанс <> ОтборПоСеансу
Тогда
ТаблицаЖурнала.Удалить(СтрокаТЧ);
СтрокаТЧ = Неопределено;
#Если _ Тогда
СтрокаТЧ = ТаблицаЖурнала.Добавить();
#КонецЕсли
Продолжить;
КонецЕсли;
//Если НаСервере <> Неопределено Тогда
// СтрокаТЧ.НаСервере = НаСервере;
//Иначе
Если Ложь
Или СтрокаТЧ.Событие = "SCOM"
Тогда
СтрокаТЧ.НаСервере = Истина;
Иначе
ИмяТипаПроцесса = "_" + СтрЗаменить(СтрокаТЧ.ТипПроцессаОС, "#", "");
Попытка
СтрокаТЧ.НаСервере = мСерверныеТипыПроцессов.Свойство(ИмяТипаПроцесса);
Исключение
// Бывают типы процессов с UID, к сожалению тогда невозможно определить
КонецПопытки;
КонецЕсли;
//КонецЕсли;
Если СтрокаТЧ.Контекст <> "" Тогда
СтрокаТЧ.СтрокаМодуля = СокрЛП(СтрПолучитьСтроку(СтрокаТЧ.Контекст, СтрЧислоСтрок(СтрокаТЧ.Контекст)));
Если БазовыйУровеньСтека > 0 Тогда
ЗаполнитьСтрокуБазовогоУровня(СтрокаТЧ);
КонецЕсли;
КонецЕсли;
Если ВключитьСвойстваСИменамиМетаданных Тогда
ЗаполнитьСвойстваСИменамиМетаданных(СтрокаТЧ);
КонецЕсли;
//Если ДатаВремяЗаписи > лПоследнееВремяНачалаЗагрузки - НаложениеПриДозагрузкеСекунд Тогда
// НовыеКлючиЗагруженныхСтрок[КлючСтроки] = 1;
//КонецЕсли;
Если ирНеглобальный.СтрокиРавныЛкс(СтрокаТЧ.Событие, "Context") Тогда
// Встроим контекст в предыдущие события
Индекс = ТаблицаЖурнала.Количество() - 2;
Пока Индекс >= 0 Цикл
СтрокаБезКонтекста = ТаблицаЖурнала[Индекс];
Индекс = Индекс - 1;
Если Ложь
Или СтрокаБезКонтекста.Сеанс <> СтрокаТЧ.Сеанс
Или СтрокаБезКонтекста.Инфобаза <> СтрокаТЧ.Инфобаза
Тогда
Прервать;
КонецЕсли;
Если Не СтрокаБезКонтекста.СтрокаМодуля = "" Тогда
Прервать;
КонецЕсли;
ЗаполнитьЗначенияСвойств(СтрокаБезКонтекста, СтрокаТЧ, "СтрокаМодуля, Контекст");
КонецЦикла;
КонецЕсли;
КонецЦикла;
// Для отката к началу последнего события
РазмерТекущейПорции = СтрДлина(ПорцияТекстаФайла);
АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + СтрДлина(ТекстФайла);
Если РазмерТекущейПорции = РазмерПорции Тогда
Если СтрокаТЧ <> Неопределено Тогда
ТаблицаЖурнала.Удалить(ТаблицаЖурнала.Количество() - 1);
КонецЕсли;
Если Вхождение <> Неопределено Тогда
ТекстФайла = Сред(ТекстФайла, Вхождение.FirstIndex);
Иначе
ТекстФайла = Прав(ТекстФайла, 1000); // Страховка
КонецЕсли;
АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле - СтрДлина(ТекстФайла);
Иначе
ТекстФайла = "";
КонецЕсли;
КонецЦикла;
Если ИндикаторФайла <> Неопределено Тогда
ЛксОсвободитьИндикаторПроцесса();
КонецЕсли;
КартаФайла.ПозицияКонца = АбсолютнаяПозицияВФайле;
Если Истина
И ПозицияНачалаСчитанныхДанных <> -1
И (Ложь
Или КартаФайла.ПозицияНачала = -1
Или КартаФайла.ПозицияНачала > ПозицияНачалаСчитанныхДанных)
Тогда
КартаФайла.ПозицияНачала = ПозицияНачалаСчитанныхДанных;
КонецЕсли;
Если Ложь
Или Не ЗначениеЗаполнено(КонецПериода)
Или КонецПериода > КартаФайла.КонецПериода
Тогда
КартаФайла.КонецПериода = КонецПериода;
КонецЕсли;
Если Ложь
Или Не ЗначениеЗаполнено(НачалоПериода)
Или НачалоПериода < КартаФайла.НачалоПериода
Тогда
КартаФайла.НачалоПериода = НачалоПериода;
КонецЕсли;
КонецЦикла;
ЛксОсвободитьИндикаторПроцесса();
//КлючиЗагруженныхСтрок = НовыеКлючиЗагруженныхСтрок;
//Если НаСервере = Истина Тогда
// ЭтотОбъект.ПоследнееВремяНачалаЗагрузкиСервера = лПоследнееВремяНачалаЗагрузки;
//Иначе
// ЭтотОбъект.ПоследнееВремяНачалаЗагрузки = лПоследнееВремяНачалаЗагрузки;
//КонецЕсли;
//МинимальнаяДатаЗагрузки = Мин(НачалоПериода, МинимальнаяДатаЗагрузки);
ТаблицаЖурнала.Сортировать("МоментВремени");
Возврат Истина;
КонецФункции
Функция ЗаполнитьСтрокуБазовогоУровня(СтрокаТЧ)
Если БазовыйУровеньСтека > 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(Ссылка) Экспорт
СтруктураБД = ирКэш.ПолучитьСтруктуруХраненияБДЛкс();
СтруктураПоиска = Новый Структура("Метаданные, Назначение", Ссылка.Метаданные().ПолноеИмя(), "Основная");
СтрокаТаблицы = СтруктураБД.НайтиСтроки(СтруктураПоиска)[0];
RegExp = ирКэш.Получить().RegExp;
RegExp.Pattern = "\d+";
РезультатПоиска = RegExp.Execute(СтрокаТаблицы.ИмяТаблицыХранения);
Текст = РезультатПоиска.Item(0).Value + ":" + ЛксПолучитьГУИДИнверсныйИзПрямого("" + Ссылка.УникальныйИдентификатор());
Возврат Текст;
КонецФункции
Функция ПолучитьСтруктуруЗапросаИзТекстаSDBL(ТекстSDBL) Экспорт
RegExp = мПлатформа.RegExp;
RegExp.Pattern = "([A-F0-9]+):([A-F0-9]+|0x[A-F0-9]+)"; // анализа и замены значений параметров
Вхождения = RegExp.Execute(ТекстSDBL);
Текст = ТекстSDBL;
//ТаблицаПараметров = Новый ТаблицаЗначений;
//ТаблицаПараметров.Колонки.Добавить("ЗначениеSDBL", Новый ОписаниеТипов("Строка"));
//ТаблицаПараметров.Колонки.Добавить("Значение");
//ТаблицаПараметров.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
ТаблицаПараметров = ПараметрыЗапроса.ВыгрузитьКолонки();
ТаблицаПараметров.Индексы.Добавить("ЗначениеSDBL");
ТаблицаПараметров.Индексы.Добавить("Имя");
Для Каждого Вхождение Из Вхождения Цикл
ЗначениеSDBL = Вхождение.Value;
Если ТаблицаПараметров.Найти(ЗначениеSDBL, "ЗначениеSDBL") = Неопределено Тогда
ЗначениеПараметра = ирНеглобальный.ПреобразоватьЗначениеИзSDBLЛкс(ЗначениеSDBL);
Если ЗначениеПараметра <> Неопределено Тогда
СтрокаПараметра = ирНеглобальный.НайтиДобавитьПараметрСсылкуВТаблицуЛкс(ТаблицаПараметров,,, ЗначениеПараметра);
СтрокаПараметра.ЗначениеSDBL = ЗначениеSDBL;
ОбъектМД = ЛксПолучитьМетаданные(ЗначениеПараметра);
Если ОбъектМД <> Неопределено Тогда
СтрокаПараметра.Метаданные = ОбъектМД.ПолноеИмя();
КонецЕсли;
Текст = СтрЗаменить(Текст, ЗначениеSDBL, "&" + СтрокаПараметра.Имя);
КонецЕсли;
КонецЕсли;
КонецЦикла;
RegExp.Pattern = "#(T[\d" + мПлатформа.шБуква + "]+)"; // анализа и замены значений параметров
Текст = RegExp.Replace(Текст, "_$1");
ТаблицаТаблиц = Новый ТаблицаЗначений;
ТекстМета = ПолучитьЗапросВТерминахМетаданных(Текст,,,,ТаблицаТаблиц);
ТаблицаТаблиц.Сортировать("ИмяМета");
Результат = Новый Структура();
Результат.Вставить("Текст", ТекстМета);
Результат.Вставить("Параметры", ТаблицаПараметров);
Результат.Вставить("Таблицы", ТаблицаТаблиц);
Возврат Результат;
КонецФункции
Функция НайтиВызовыМетодовМодулей(ИмяМодуля, НомерНачальнойСтроки, НомерКонечнойСтроки, ТолькоОдну = Истина)
Результат = Новый Массив();
Для Каждого СтрокаТаблицы Из ТаблицаЖурнала Цикл
ФрагментыНачальнойСтрокиМодуля = ЛксПолучитьМассивИзСтрокиСРазделителем(СтрокаТаблицы.СтрокаМодуля, ":", Истина);
Если ФрагментыНачальнойСтрокиМодуля[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 Тогда
Индикатор = ЛксПолучитьИндикаторПроцесса(СловарьЗапроса.Количество(), "Преобразование в имена метаданных");
КонецЕсли;
Если выхТаблицы <> Неопределено Тогда
#Если _ Тогда
выхТаблицы = Новый ТаблицаЗначений;
#КонецЕсли
выхТаблицы.Колонки.Очистить();
выхТаблицы.Колонки.Добавить("ИмяБД", Новый ОписаниеТипов("Строка"));
выхТаблицы.Колонки.Добавить("ИмяМета", Новый ОписаниеТипов("Строка"));
//выхТаблицы.Колонки.Добавить("ПсевдонимБД", Новый ОписаниеТипов("Строка"));
//выхТаблицы.Колонки.Добавить("ПсевдонимМета", Новый ОписаниеТипов("Строка"));
КонецЕсли;
Для Каждого СтрокаСловаряЗапроса Из СловарьЗапроса Цикл
Если Индикатор <> Неопределено Тогда
ЛксОбработатьИндикатор(Индикатор);
КонецЕсли;
Если выхТаблицы <> Неопределено Тогда
ОписаниеТаблицы = выхТаблицы.Добавить();
ОписаниеТаблицы.ИмяБД = СтрокаСловаряЗапроса.Ключ;
КонецЕсли;
// Получить имя таблицы
СтрокаСтруктуры = СтруктураХраненияБазыДанных.Найти(СтрокаСловаряЗапроса.Ключ, "КраткоеИмяТаблицыХранения");
Если СтрокаСтруктуры = Неопределено Тогда
// Видимо чужие метаданные
Продолжить;
КонецЕсли;
ИмяТаблицы = СтрокаСтруктуры.КраткоеИмяТаблицыХранения;
МетаПолноеИмяТаблицы = СтрокаСтруктуры.ИмяТаблицы;
// Антибаг платформы 8.2.16 http://partners.v8.1c.ru/forum/thread.jsp?id=1090307#1090307
Если ПустаяСтрока(МетаПолноеИмяТаблицы) Тогда
МетаПолноеИмяТаблицы = "";
Если ЗначениеЗаполнено(СтрокаСтруктуры.Метаданные) Тогда
МетаПолноеИмяТаблицы = СтрокаСтруктуры.Метаданные + ".";
КонецЕсли;
МетаПолноеИмяТаблицы = МетаПолноеИмяТаблицы + СтрокаСтруктуры.Назначение;
КонецЕсли;
Синонимы = ПолучитьСинонимы(Запрос, ИмяТаблицы, МетаПолноеИмяТаблицы, ТипСУБД);
//Синонимы.Вставить(ИмяТаблицы, МетаИмяТаблицы);
Если выхТаблицы <> Неопределено Тогда
ОписаниеТаблицы.ИмяМета = МетаПолноеИмяТаблицы;
КонецЕсли;
Для Каждого СтрокаПоля Из СтрокаСтруктуры.Поля Цикл
Если Найти(Запрос, СтрокаПоля.ИмяПоляХранения) = 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", "ИсключениеОС");
мСписокКолонок.Добавить("ClientID", "Клиент");
мСписокКолонок.Добавить("Interface", "Интерфейс");
мСписокКолонок.Добавить("Method", "Метод");
мСписокКолонок.Добавить("Exception", "ТипИсключения");
мСписокКолонок.Добавить("Descr", "Описание");
мСписокКолонок.Добавить("ClientComputerName", "КомпьютерКлиента");
мСписокКолонок.Добавить("ServerComputerName", "КомпьютерСервера");
мСписокКолонок.Добавить("UserName", "Пользователь");
мСписокКолонок.Добавить("ConnectString", "СтрокаСоединения");
мСписокКолонок.Добавить("ProcessName", "ТипПроцессаОС");
мСписокКолонок.Добавить("SrcProcessName", "Инфобаза");
мСписокКолонок.Добавить("Trans", "Транзакция");
мСписокКолонок.Добавить("Func", "Действие");
мСписокКолонок.Добавить("Sdbl", "ТекстSDBL");
мСписокКолонок.Добавить("dbpid", "ПроцессСУБД");
мСписокКолонок.Добавить("Sql", "ТекстСУБД");
мСписокКолонок.Добавить("NParams", "КоличествоПараметров");
мСписокКолонок.Добавить("Rows", "ЧислоСтрок");
мСписокКолонок.Добавить("RowsAffected", "ЧислоИзменныхСтрок");
мСписокКолонок.Добавить("planSQLText", "ПланСУБД");
мСписокКолонок.Добавить("Context", "Контекст");
мСписокКолонок.Добавить("CatName", "КаталогСУБД");
мСписокКолонок.Добавить("FileName", "ФайлСУБД");
мСписокКолонок.Добавить("DeadlockConnectionIntersections", "Взаимоблокировка");
мСписокКолонок.Добавить("Finish", "ПричинаЗавершения");
// Свойства найденные экспериментально. Они не документированы.
мСписокКолонок.Добавить("FileWild", "FileWild");
мСписокКолонок.Добавить("LocaleName", "LocaleName");
мСписокКолонок.Добавить("To", "To");
мСписокКолонок.Добавить("From", "From_");
мСписокКолонок.Добавить("ToCat", "ToCat");
мСписокКолонок.Добавить("FromCat", "FromCat");
мСписокКолонок.Добавить("Move", "Move");
мСписокКолонок.Добавить("tableName", "tableName");
мСписокКолонок.Добавить("What", "What");
мСписокКолонок.Добавить("Index", "Index_");
мСписокКолонок.Добавить("Result", "Result");
мСписокКолонок.Добавить("Prm", "Prm");
мТаблицаКолонок = Новый ТаблицаЗначений;
мТаблицаКолонок.Колонки.Добавить("ВнутреннееИмя", Новый ОписаниеТипов("Строка"));
мТаблицаКолонок.Колонки.Добавить("ИмяВТаблице", Новый ОписаниеТипов("Строка"));
мТаблицаКолонок.Индексы.Добавить("ВнутреннееИмя");
мТаблицаКолонок.Индексы.Добавить("ИмяВТаблице");
мЧисловыеСвойства = Новый Структура;
мСоответствиеКолонок = Новый Соответствие;
Для Каждого ЭлементСписка Из мСписокКолонок Цикл
мСоответствиеКолонок.Вставить(ЭлементСписка.Значение, ЭлементСписка.Представление);
СтрокаСоответствия = мТаблицаКолонок.Добавить();
СтрокаСоответствия.ВнутреннееИмя = ЭлементСписка.Значение;
СтрокаСоответствия.ИмяВТаблице = ЭлементСписка.Представление;
Если Метаданные().ТабличныеЧасти.ТаблицаЖурнала.Реквизиты[ЭлементСписка.Представление].Тип.СодержитТип(Тип("Число")) Тогда
мЧисловыеСвойства.Вставить(ЭлементСписка.Представление);
КонецЕсли;
КонецЦикла;
мКартыФайлов = Новый ТаблицаЗначений;
мКартыФайлов.Колонки.Добавить("ПолноеИмяФайла", Новый ОписаниеТипов("Строка"));
мКартыФайлов.Колонки.Добавить("Сигнатура", Новый ОписаниеТипов("Строка"));
мКартыФайлов.Колонки.Добавить("ОтборПоСеансу");
мКартыФайлов.Колонки.Добавить("ПозицияНачала", Новый ОписаниеТипов("Число"));
мКартыФайлов.Колонки.Добавить("ПозицияКонца", Новый ОписаниеТипов("Число"));
мКартыФайлов.Колонки.Добавить("НачалоПериода", Новый ОписаниеТипов("Дата"));
мКартыФайлов.Колонки.Добавить("КонецПериода", Новый ОписаниеТипов("Дата"));
мКартыФайлов.Колонки.Добавить("ДатаИзменения", Новый ОписаниеТипов("Дата"));
мКартыФайлов.Индексы.Добавить("ПолноеИмяФайла, Сигнатура, ОтборПоСеансу");
мСвойстваСИменамиБД = Новый Массив();
мСвойстваСИменамиБД.Добавить("ТекстSDBL");
мСвойстваСИменамиБД.Добавить("ТекстСУБД");
мСвойстваСИменамиБД.Добавить("ПланСУБД");
мСвойстваСИменамиБД.Добавить("ТекстБезПараметровSDBL");
мСвойстваСИменамиБД.Добавить("Взаимоблокировка");
мСерверныеТипыПроцессов = Новый Структура;
мСерверныеТипыПроцессов.Вставить("_adminprocess"); // ##AdminProcess##
мСерверныеТипыПроцессов.Вставить("_rphost");
мСерверныеТипыПроцессов.Вставить("_rmngr");
мСерверныеТипыПроцессов.Вставить("_ragent");
шБуква = мПлатформа.шБуква;
шГраничныйСимволИмени = "([^&" + шБуква + "\d]|^|$)";