mirror of
https://github.com/tormozit/RDT1C.git
synced 2025-12-17 13:14:11 +00:00
2730 lines
198 KiB
Plaintext
2730 lines
198 KiB
Plaintext
//ирПортативный Перем ирПортативный Экспорт;
|
||
//ирПортативный Перем ирОбщий Экспорт;
|
||
//ирПортативный Перем ирСервер Экспорт;
|
||
//ирПортативный Перем ирКэш Экспорт;
|
||
//ирПортативный Перем ирПривилегированный Экспорт;
|
||
|
||
Перем мТаблицаКолонок Экспорт;
|
||
Перем мСписокКолонок Экспорт;
|
||
//Перем КлючиЗагруженныхСтрок;
|
||
Перем мСвойстваСИменамиБД Экспорт;
|
||
Перем RegExpПараметры;
|
||
Перем RegExpМета;
|
||
Перем шБуква;
|
||
Перем шГраничныйСимволИмени;
|
||
//Перем МинимальнаяДатаЗагрузки Экспорт;
|
||
//Перем мЧисловыеСвойства;
|
||
|
||
Перем мИменаВозвращаемыхСвойств Экспорт;
|
||
Перем мТипСУБД Экспорт;
|
||
Перем мПлатформа Экспорт;
|
||
Перем мКартыФайлов Экспорт;
|
||
Перем мНепустыеКолонкиЖурнала Экспорт;
|
||
|
||
Перем мСерверныеТипыПроцессов Экспорт;
|
||
//Перем мСоставСвойствСобытий Экспорт;
|
||
Перем мСвойстваСобытий Экспорт;
|
||
Перем мАдресЧужойСхемыБД Экспорт;
|
||
|
||
Перем КонецПериодаКлиента Экспорт;
|
||
Перем НачалоПериодаКлиента Экспорт;
|
||
Перем КонецПериодаСервера Экспорт;
|
||
Перем НачалоПериодаСервера Экспорт;
|
||
Перем мИдентификаторТрассы Экспорт;
|
||
Перем мЛиТрассаПоПользователю Экспорт;
|
||
Перем мТрассаСУБДXML;
|
||
Перем мСоответствиеКолонок;
|
||
Перем мСоединениеАДО;
|
||
Перем мИдентификаторБазыДанных;
|
||
Перем мУдержательСоединенияБД;
|
||
Перем мИдентификаторСоединенияБД;
|
||
Перем мЛиСерверMSSQLПоддерживаетТрассировку;
|
||
Перем мТаблицаЖурнала;
|
||
|
||
// СдвигВремени - Число - в секундах задается, нужно для компенсации разницы времени между компьютерами
|
||
// ОтборПоПроцессу частично игнорируются когда ЗагружатьТолькоТекущийСеанс = Истина
|
||
Функция ПрочитатьПроизвольныйЖурнал(СообщитьРазмер = Неопределено, СдвигВремени = 0, ОтборПоПроцессу = Неопределено, ОтборПоСеансу = Неопределено,
|
||
НаСервере = Неопределено)
|
||
|
||
#Если Сервер И Не Сервер Тогда
|
||
мПлатформа = Обработки.ирПлатформа.Создать();
|
||
#КонецЕсли
|
||
НеизвестныеСвойства = Новый Соответствие();
|
||
Если Ложь
|
||
Или (НаСервере <> Неопределено И Не мЛиТрассаПоПользователю)
|
||
Или Не ЗначениеЗаполнено(КаталогЖурнала)
|
||
Тогда
|
||
КаталогЖурнала = ПолучитьКаталогТекущегоЖурнала(НаСервере = Истина);
|
||
Если Не ЗначениеЗаполнено(КаталогЖурнала) Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Если Не ирОбщий.ЛиКаталогДоступенЛкс(КаталогЖурнала) Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
Если НаСервере <> Истина Тогда
|
||
ОтборПоСеансу = Неопределено;
|
||
КонецЕсли;
|
||
Если мЛиТрассаПоПользователю Тогда
|
||
ОтборПоПользователю = ИмяПользователя();
|
||
КонецЕсли;
|
||
Если ЗагружатьТолькоТекущийСеанс Тогда
|
||
Если Ложь
|
||
Или ирКэш.ЛиФайловаяБазаЛкс()
|
||
Или НаСервере <> Истина
|
||
Тогда
|
||
ОтборПоПроцессу = мПлатформа.ИдентификаторПроцессаОС();
|
||
КонецЕсли;
|
||
Если ОтборПоСеансу = Неопределено Тогда
|
||
ОтборПоПользователю = ИмяПользователя();
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
лПоследнееВремяНачалаЗагрузки = ТекущаяДата();
|
||
Если ПериодПоследниеМинуты > 0 Тогда
|
||
НачалоПериода = лПоследнееВремяНачалаЗагрузки - 60 * ПериодПоследниеМинуты;
|
||
КонецПериода = Неопределено;
|
||
КонецЕсли;
|
||
//Если ТаблицаЖурнала.Количество() = 0 Тогда
|
||
// МинимальнаяДатаЗагрузки = ТекущаяДата() + 100000;
|
||
//КонецЕсли;
|
||
//Если МинимальнаяДатаЗагрузки > НачалоПериода Тогда
|
||
// ТаблицаЖурнала.Очистить();
|
||
//КонецЕсли;
|
||
//РежимДозагрузки = Истина
|
||
// И ТаблицаЖурнала.Количество() > 0
|
||
// И МинимальнаяДатаЗагрузки <= НачалоПериода;
|
||
Если СообщитьРазмер = Неопределено Тогда
|
||
СообщитьРазмер = (мКартыФайлов.Количество() = 0) Или КомментироватьЗагрузку;
|
||
КонецЕсли;
|
||
|
||
ирОбщий.ЛиКаталогТехножурналаНедоступенЛкс(КаталогЖурнала);
|
||
ФайлыЖурнала = НайтиФайлы(КаталогЖурнала, "*.log", Истина);
|
||
ОбщийРазмер = 0;
|
||
Для Каждого ФайлЖурнала Из ФайлыЖурнала Цикл
|
||
ОбщийРазмер = ОбщийРазмер + ФайлЖурнала.Размер();
|
||
КонецЦикла;
|
||
Если СообщитьРазмер Тогда
|
||
ирОбщий.СообщитьЛкс("В каталоге """ + КаталогЖурнала + """ обнаружено для обработки " + Формат(Цел(ОбщийРазмер / 1024), "ЧН=") + "КБ логов");
|
||
ПредставлениеОтбора = "";
|
||
Если СписокЗагружаемыхТиповСобытий.Количество() > 0 Тогда
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " события " + СписокЗагружаемыхТиповСобытий;
|
||
КонецЕсли;
|
||
ПредставлениеПериода = ирОбщий.ПредставлениеПериодаЛкс(НачалоПериода, КонецПериода);
|
||
Если ЗначениеЗаполнено(ПредставлениеПериода) Тогда
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " " + ПредставлениеПериода;
|
||
КонецЕсли;
|
||
Если ЗначениеЗаполнено("" + ФильтрЗагрузки) Тогда
|
||
Если ЗначениеЗаполнено(ПредставлениеОтбора) Тогда
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " И";
|
||
КонецЕсли;
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " " + ФильтрЗагрузки;
|
||
КонецЕсли;
|
||
Если ЗначениеЗаполнено(ОтборПоПроцессу) Тогда
|
||
Если ЗначениеЗаполнено(ПредставлениеОтбора) Тогда
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " И";
|
||
КонецЕсли;
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " Процесс=" + XMLСтрока(ОтборПоПроцессу);
|
||
КонецЕсли;
|
||
Если ЗначениеЗаполнено(ОтборПоСеансу) Тогда
|
||
Если ЗначениеЗаполнено(ПредставлениеОтбора) Тогда
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " И";
|
||
КонецЕсли;
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " Сеанс=" + XMLСтрока(ОтборПоСеансу);
|
||
КонецЕсли;
|
||
Если ЗначениеЗаполнено(ОтборПоПользователю) Тогда
|
||
Если ЗначениеЗаполнено(ПредставлениеОтбора) Тогда
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " И";
|
||
КонецЕсли;
|
||
ПредставлениеОтбора = ПредставлениеОтбора + " Пользователь=""" + ОтборПоПользователю + """";
|
||
КонецЕсли;
|
||
Если ЗначениеЗаполнено(ПредставлениеОтбора) Тогда
|
||
ирОбщий.СообщитьЛкс("Отбор загрузки:" + ПредставлениеОтбора);
|
||
КонецЕсли;
|
||
Если мПлатформа.ИдентификаторыПроцессовОтладчиков().Количество() > 0 Тогда
|
||
ирОбщий.СообщитьЛкс("Возможно подключен отладчик и тогда он замедляет загрузку логов. Отключите отладчик для ускорения загрузки.");
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
//лНачалоПериода = НачалоПериода;
|
||
//Если Не РежимДозагрузки Тогда
|
||
// //ТаблицаЖурнала.Очистить();
|
||
// КлючиЗагруженныхСтрок = Новый Соответствие;
|
||
//Иначе
|
||
// Если НаСервере = Истина Тогда
|
||
// лДатаЗагрузки = ПоследнееВремяНачалаЗагрузкиСервера;
|
||
// Иначе
|
||
// лДатаЗагрузки = ПоследнееВремяНачалаЗагрузки;
|
||
// КонецЕсли;
|
||
// Если ЗначениеЗаполнено(лДатаЗагрузки) Тогда
|
||
// лНачалоПериода = лДатаЗагрузки - НаложениеПриДозагрузкеСекунд;
|
||
// КонецЕсли;
|
||
//КонецЕсли;
|
||
Если УдалятьДанныеВнеПериода Тогда
|
||
ТаблицаЖурнала.Сортировать("МоментВремени");
|
||
КоличествоСтрок = ТаблицаЖурнала.Количество();
|
||
Пока Истина
|
||
И КоличествоСтрок > 0
|
||
И ТаблицаЖурнала[0].Дата < НачалоПериода
|
||
Цикл
|
||
ТаблицаЖурнала.Удалить(0);
|
||
КоличествоСтрок = КоличествоСтрок - 1;
|
||
КонецЦикла;
|
||
Если ЗначениеЗаполнено(КонецПериода) Тогда
|
||
ИндексСтроки = КоличествоСтрок - 1;
|
||
Пока Истина
|
||
И КоличествоСтрок > 0
|
||
И ТаблицаЖурнала[ИндексСтроки].Дата > КонецПериода
|
||
Цикл
|
||
ТаблицаЖурнала.Удалить(ИндексСтроки);
|
||
ИндексСтроки = ИндексСтроки - 1;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
#Если Сервер И Не Сервер Тогда
|
||
ЗагрузитьРезультатЧтенияФайлаВПотоке();
|
||
ПрочитатьФайлЖурнала();
|
||
#КонецЕсли
|
||
СтруктураПотоков = ирОбщий.НоваяСтруктураМногопоточнойОбработкиЛкс("ПрочитатьФайлЖурнала", ЭтотОбъект, "ЗагрузитьРезультатЧтенияФайлаВПотоке", 1, ВыполнятьНаСервере, КоличествоПотоков);
|
||
Если СтруктураПотоков.ФактическоеКоличествоПотоков > 1 Тогда
|
||
ЗаголовокИндикации = "Выполняем загрузку в " + СтруктураПотоков.ФактическоеКоличествоПотоков + " потоков";
|
||
КонецЕсли;
|
||
Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ОбщийРазмер, "Загрузка журнала");
|
||
РазмерОбработанныхДанных = 0;
|
||
Для Каждого ФайлЖурнала Из ФайлыЖурнала Цикл
|
||
#Если Сервер И Не Сервер Тогда
|
||
ФайлЖурнала = Новый Файл;
|
||
#КонецЕсли
|
||
Попытка
|
||
РазмерФайла = ФайлЖурнала.Размер();
|
||
Исключение
|
||
ирОбщий.СообщитьЛкс("Пропускаем недоступный файл " + ФайлЖурнала.ПолноеИмя, СтатусСообщения.Внимание);
|
||
Продолжить;
|
||
КонецПопытки;
|
||
РазмерОбработанныхДанных = РазмерОбработанныхДанных + РазмерФайла;
|
||
ирОбщий.ОбработатьИндикаторЛкс(Индикатор, РазмерОбработанныхДанных);
|
||
ПолноеИмяКаталогаПроцесса = Лев(ФайлЖурнала.Путь, СтрДлина(ФайлЖурнала.Путь) - 1);
|
||
Длина1 = СтрДлина(ПолноеИмяКаталогаПроцесса);
|
||
СтрокаЧасаЗаписи = "20" + Сред(ФайлЖурнала.ПолноеИмя, Длина1 + 2, 8);
|
||
ДатаЧасЗаписи = Дата(СтрокаЧасаЗаписи + "0000");
|
||
ИдентификаторПроцессаСтрока = ирОбщий.СтрокаБезКонцаЛкс(ирОбщий.ПоследнийФрагментЛкс(ФайлЖурнала.Путь, "_"), 1);
|
||
Попытка
|
||
ИдентификаторПроцесса = Число(ИдентификаторПроцессаСтрока);
|
||
Исключение
|
||
Если КомментироватьЗагрузку Тогда
|
||
ирОбщий.СообщитьЛкс("Пропускаем файл " + ФайлЖурнала.ПолноеИмя + " из каталога с некорректным именем", СтатусСообщения.Внимание);
|
||
КонецЕсли;
|
||
Продолжить;
|
||
КонецПопытки;
|
||
//ЛиДатаВИнтервале = ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(ДатаЧасЗаписи, НачалоЧаса(лНачалоПериода), НачалоЧаса(КонецПериода));
|
||
ЛиДатаВИнтервале = ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(ДатаЧасЗаписи, НачалоЧаса(НачалоПериода), НачалоЧаса(КонецПериода));
|
||
Если Ложь
|
||
Или Не ЛиДатаВИнтервале
|
||
Или (Истина
|
||
И ОтборПоПроцессу <> Неопределено
|
||
И ИдентификаторПроцесса <> ОтборПоПроцессу)
|
||
Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Попытка
|
||
ЧтениеТекста = Новый ЧтениеТекста(ФайлЖурнала.ПолноеИмя, КодировкаТекста.UTF8, ,,Ложь);
|
||
//ТекстовыйДокумент.Прочитать(ФайлЖурнала.ПолноеИмя, КодировкаТекста.UTF8);
|
||
Исключение
|
||
ирОбщий.СообщитьЛкс("Не удалось прочитать открыть для чтения файл " + ФайлЖурнала.ПолноеИмя, СтатусСообщения.Внимание);
|
||
Продолжить;
|
||
КонецПопытки;
|
||
СигнатураФайла = ЧтениеТекста.Прочитать(20); // Для идентификации файла
|
||
Если ПустаяСтрока(СигнатураФайла) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
ЧтениеТекста.Закрыть();
|
||
ПараметрыОбработкиФайла = Новый Структура;
|
||
ПараметрыОбработкиФайла.Вставить("ОтборПоПроцессу", ОтборПоПроцессу);
|
||
ПараметрыОбработкиФайла.Вставить("ОтборПоСеансу", ОтборПоСеансу);
|
||
ПараметрыОбработкиФайла.Вставить("ОтборПоПользователю", ОтборПоПользователю);
|
||
ПараметрыОбработкиФайла.Вставить("СдвигВремени", СдвигВремени);
|
||
ПараметрыОбработкиФайла.Вставить("ФильтрЗагрузки", ФильтрЗагрузки);
|
||
ПараметрыОбработкиФайла.Вставить("НомерСеанса", НомерСеансаИнформационнойБазы());
|
||
ПараметрыОбработкиФайла.Вставить("мКартыФайлов", мКартыФайлов);
|
||
ПараметрыОбработкиФайла.Вставить("КоличествоЗагруженныхСобытий", мТаблицаЖурнала.Количество());
|
||
ПараметрыОбработкиФайла.Вставить("ФайлЖурнала", ФайлЖурнала.ПолноеИмя);
|
||
ЛокальныеПараметры = Новый Структура;
|
||
ЛокальныеПараметры.Вставить("Индикатор", Индикатор);
|
||
ЛокальныеПараметры.Вставить("РазмерОбработанныхДанных", РазмерОбработанныхДанных);
|
||
ирОбщий.ДобавитьОбъектВОчередьМногопоточнойОбработкиЛкс(СтруктураПотоков, ПараметрыОбработкиФайла, ЛокальныеПараметры, РазмерФайла < 100000);
|
||
Если ТаблицаЖурнала.Количество() > МаксТысячСобытий * 1000 Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
ирОбщий.ОжидатьЗавершенияВсехПотоковОбработкиЛкс(СтруктураПотоков);
|
||
ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
|
||
|
||
УдалитьСтрокиВнеФильтра();
|
||
//КлючиЗагруженныхСтрок = НовыеКлючиЗагруженныхСтрок;
|
||
//Если НаСервере = Истина Тогда
|
||
// ЭтотОбъект.ПоследнееВремяНачалаЗагрузкиСервера = лПоследнееВремяНачалаЗагрузки;
|
||
//Иначе
|
||
// ЭтотОбъект.ПоследнееВремяНачалаЗагрузки = лПоследнееВремяНачалаЗагрузки;
|
||
//КонецЕсли;
|
||
//МинимальнаяДатаЗагрузки = Мин(НачалоПериода, МинимальнаяДатаЗагрузки);
|
||
ТаблицаЖурнала.Сортировать("МоментВремени");
|
||
//ТаблицаЖурнала.Сортировать("МоментВремениНачала");
|
||
|
||
ОпределитьНепустыеКолонки();
|
||
Возврат Истина;
|
||
|
||
КонецФункции
|
||
|
||
// Параметры:
|
||
// ОтборПоПроцессу - ? -
|
||
// ОтборПоСеансу - Число -
|
||
// РазмерФайла - Примитивный -
|
||
// СдвигВремени - ? -
|
||
// ФайлЖурнала - Файл -
|
||
// ФильтрЗагрузки - ? -
|
||
// ТипВыхода - Строка - Служебный параметр для перехода после вызова метода
|
||
Функция ПрочитатьФайлЖурнала(Параметры) Экспорт
|
||
|
||
мКартыФайлов = Параметры.мКартыФайлов;
|
||
ОтборПоПроцессу = Параметры.ОтборПоПроцессу;
|
||
ОтборПоСеансу = Параметры.ОтборПоСеансу;
|
||
ОтборПоПользователю = Параметры.ОтборПоПользователю;
|
||
СдвигВремени = Параметры.СдвигВремени;
|
||
ФайлЖурнала = Параметры.ФайлЖурнала;
|
||
ФильтрЗагрузки = Параметры.ФильтрЗагрузки;
|
||
КоличествоЗагруженныхСобытий = Параметры.КоличествоЗагруженныхСобытий;
|
||
ВозвращатьРезультат = Параметры.НомерСеанса <> НомерСеансаИнформационнойБазы();
|
||
ДостигнутоПредельноеКоличество = Ложь;
|
||
ДобавитьОбязательныеНепустыеКолонки();
|
||
ФайлЖурнала = Новый Файл(ФайлЖурнала);
|
||
РазмерФайла = ФайлЖурнала.Размер();
|
||
РегВыражение1 = мПлатформа.RegExp;
|
||
РегВыражение2 = мПлатформа.RegExp2;
|
||
#Если Сервер И Не Сервер Тогда
|
||
РегВыражение1 = Обработки.ирОболочкаРегВыражение.Создать();
|
||
РегВыражение2 = РегВыражение1;
|
||
мПлатформа = Обработки.ирПлатформа.Создать();
|
||
мТаблицаЖурнала = ТаблицаЖурнала;
|
||
#КонецЕсли
|
||
шСимвол = "[" + шБуква + "\d\._#{}-]";
|
||
//ШаблонСвойствоЗначение = "([\w\:]+)=(?:'\s*((?:.|\n|\r)*?)'|""\s*([^""]*)""|([^'""\n\r,]*))(?:,|\r|$)"; // Так были очень большие трассы вычисления RegExp
|
||
ШаблонСвойствоЗначение = "([\w\:]+)=(?:'\s*([\s\S]*?)'|""\s*((?:""""|[^""])*)""|([^'""\n\r,]*))(?:,|\r|\n|$)+";
|
||
Шаблон = "(\d\d:\d\d)\.(\d+)-(\d+),(" + шСимвол + "+),(\d+),((?:" + ШаблонСвойствоЗначение + ")*)";
|
||
РегВыражение1.Pattern = Шаблон;
|
||
//RegExp.Multiline = Истина;
|
||
РегВыражение1.Global = Истина;
|
||
РегВыражение2.Pattern = ШаблонСвойствоЗначение;
|
||
РегВыражение2.Global = Истина;
|
||
ПустаяДата = Дата("00010101");
|
||
МаксКоличествоСобытий = КоличествоЗагруженныхСобытий + МаксТысячСобытий * 1000;
|
||
//НовыеКлючиЗагруженныхСтрок = Новый Соответствие();
|
||
Если КомментироватьЗагрузку Тогда
|
||
ирОбщий.СообщитьЛкс("Читаем " + ФайлЖурнала.ПолноеИмя + ", размер - " + РазмерФайла);
|
||
КонецЕсли;
|
||
ПолноеИмяКаталогаПроцесса = Лев(ФайлЖурнала.Путь, СтрДлина(ФайлЖурнала.Путь) - 1);
|
||
Длина1 = СтрДлина(ПолноеИмяКаталогаПроцесса);
|
||
СтрокаЧасаЗаписи = "20" + Сред(ФайлЖурнала.ПолноеИмя, Длина1 + 2, 8);
|
||
ДатаЧасЗаписи = Дата(СтрокаЧасаЗаписи + "0000");
|
||
ИдентификаторПроцессаСтрока = ирОбщий.СтрокаБезКонцаЛкс(ирОбщий.ПоследнийФрагментЛкс(ФайлЖурнала.Путь, "_"), 1);
|
||
ИдентификаторПроцесса = Число(ИдентификаторПроцессаСтрока);
|
||
//ЛиФайлВИнтервалеПолностью = ирОбщий.ЛиДатаВИнтервалеБезГраницЛкс(ДатаЧасЗаписи, НачалоЧаса(лНачалоПериода), НачалоЧаса(КонецПериода));
|
||
//ЛиДатаВИнтервале = ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(ДатаЧасЗаписи, НачалоЧаса(лНачалоПериода), НачалоЧаса(КонецПериода));
|
||
ЛиФайлВИнтервалеПолностью = ирОбщий.ЛиДатаВИнтервалеБезГраницЛкс(ДатаЧасЗаписи, НачалоЧаса(НачалоПериода), НачалоЧаса(КонецПериода));
|
||
ЛиДатаВИнтервале = ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(ДатаЧасЗаписи, НачалоЧаса(НачалоПериода), НачалоЧаса(КонецПериода));
|
||
ТекстФайла = ""; // Уничтожаем старый текст, т.к. он может быть очень большим
|
||
Попытка
|
||
ЧтениеТекста = Новый ЧтениеТекста(ФайлЖурнала.ПолноеИмя, КодировкаТекста.UTF8, ,,Ложь);
|
||
//ТекстовыйДокумент.Прочитать(ФайлЖурнала.ПолноеИмя, КодировкаТекста.UTF8);
|
||
Исключение
|
||
ирОбщий.СообщитьЛкс("Не удалось прочитать данные из файла " + ФайлЖурнала.ПолноеИмя, СтатусСообщения.Внимание);
|
||
Возврат Неопределено;
|
||
КонецПопытки;
|
||
СигнатураФайла = ЧтениеТекста.Прочитать(20); // Для идентификации файла
|
||
Если ПустаяСтрока(СигнатураФайла) Тогда
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
|
||
РазмерПорции = 2 * 1000 * 1000; // Подобрано экспериментально
|
||
КраткоеИмяКаталогаПроцесса = ирОбщий.ПоследнийФрагментЛкс(ПолноеИмяКаталогаПроцесса, "\");
|
||
ЧислоПорций = Цел(РазмерФайла / РазмерПорции) + 1;
|
||
ЧтениеТекста = Новый ЧтениеТекста(ФайлЖурнала.ПолноеИмя, КодировкаТекста.UTF8, ,,Ложь);
|
||
АбсолютнаяПозицияВФайле = 0;
|
||
КлючКарты = Новый Структура("ИмяКаталогаПроцесса, ИмяТекущегоФайла, СигнатураТекущегоФайла, ОтборПоСеансу",
|
||
КраткоеИмяКаталогаПроцесса, ФайлЖурнала.Имя, СигнатураФайла, "" + ЗагружатьТолькоТекущийСеанс + ОтборПоСеансу);
|
||
СтрокиКарт = мКартыФайлов.НайтиСтроки(КлючКарты);
|
||
Если СтрокиКарт.Количество() > 0 Тогда
|
||
КартаФайла = СтрокиКарт[0];
|
||
Иначе
|
||
КартаФайла = мКартыФайлов.Добавить();
|
||
ЗаполнитьЗначенияСвойств(КартаФайла, КлючКарты);
|
||
КартаФайла.КонецПериода = Дата(1000, 1, 1);
|
||
КонецЕсли;
|
||
Если ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(НачалоПериода, КартаФайла.НачалоПериода, КартаФайла.КонецПериода) Тогда
|
||
АбсолютнаяПозицияВФайле = КартаФайла.ПозицияКонца;
|
||
ИначеЕсли Ложь
|
||
Или НачалоПериода > КартаФайла.НачалоПериода
|
||
Или КонецПериода < КартаФайла.КонецПериода
|
||
Тогда
|
||
// Периоды не сшиваются. Очищаем карту.
|
||
КартаФайла.ПозицияНачала = -1;
|
||
КартаФайла.ПозицияКонца = -1;
|
||
КартаФайла.НачалоПериода = НачалоПериода;
|
||
КартаФайла.КонецПериода = КонецПериода;
|
||
КартаФайла.ДатаИзмененияФайла = Неопределено;
|
||
КонецЕсли;
|
||
Если АбсолютнаяПозицияВФайле > 0 Тогда
|
||
Если ЗначениеЗаполнено(КартаФайла.ДатаИзмененияФайла) Тогда
|
||
Если КартаФайла.ДатаИзмененияФайла = ФайлЖурнала.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс() Тогда
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
ЧтениеТекста.Прочитать(АбсолютнаяПозицияВФайле);
|
||
КонецЕсли;
|
||
ПозицияНачалаСчитанныхДанных = -1;
|
||
Если ЧислоПорций > 1 Тогда
|
||
ИндикаторФайла = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ЧислоПорций, "" + КраткоеИмяКаталогаПроцесса + "\" + ФайлЖурнала.Имя);
|
||
Иначе
|
||
ИндикаторФайла = Неопределено;
|
||
КонецЕсли;
|
||
РазрешенныеТипыСобытий = Неопределено;
|
||
Если СписокЗагружаемыхТиповСобытий.Количество() > 0 Тогда
|
||
РазрешенныеТипыСобытий = Новый Структура;
|
||
Для Каждого ТипСобытия Из СписокЗагружаемыхТиповСобытий.ВыгрузитьЗначения() Цикл
|
||
РазрешенныеТипыСобытий.Вставить(ТипСобытия);
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
СтрокаТЧ = Неопределено;
|
||
РазмерТекущейПорции = 0;
|
||
ПоследниеСобытияПоТипам = Новый Соответствие;
|
||
Пока Истина Цикл
|
||
КартаФайла.ДатаИзмененияФайла = ФайлЖурнала.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс();
|
||
ПорцияТекстаФайла = ЧтениеТекста.Прочитать(РазмерПорции);
|
||
Если Ложь
|
||
Или ПорцияТекстаФайла = Неопределено
|
||
Или ПустаяСтрока(ПорцияТекстаФайла)
|
||
Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
Если ИндикаторФайла <> Неопределено Тогда
|
||
ирОбщий.ОбработатьИндикаторЛкс(ИндикаторФайла);
|
||
КонецЕсли;
|
||
Если Истина
|
||
И АбсолютнаяПозицияВФайле >= КартаФайла.ПозицияНачала
|
||
И АбсолютнаяПозицияВФайле + СтрДлина(ПорцияТекстаФайла) + СтрДлина(ТекстФайла) < КартаФайла.ПозицияКонца
|
||
Тогда
|
||
АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + СтрДлина(ПорцияТекстаФайла) + СтрДлина(ТекстФайла);
|
||
Продолжить;
|
||
КонецЕсли;
|
||
ТекстФайла = ТекстФайла + ПорцияТекстаФайла;
|
||
РазборТекстаРазрешен = Истина;
|
||
ОписаниеОшибки = "";
|
||
МаксимальныйРазмерТекстДляАнализа = 20000000; // Экспериментально подобрано http://devtool1c.ucoz.ru/forum/2-270-1#1145
|
||
Если СтрДлина(ТекстФайла) > МаксимальныйРазмерТекстДляАнализа Тогда
|
||
Если Истина
|
||
И РазмерТекущейПорции = РазмерПорции
|
||
И СтрокаТЧ <> Неопределено
|
||
Тогда
|
||
СтрокаТЧ.ТекстSDBL = "<?>";
|
||
СтрокаТЧ.ТекстСУБД = "<?>";
|
||
ирОбщий.СообщитьЛкс("При анализе файла """ + ФайлЖурнала.ПолноеИмя + """ некоторые свойства события пропущены, т.к. оно превышает допустимый размер "
|
||
+ XMLСтрока(Цел(МаксимальныйРазмерТекстДляАнализа/1024/1024)) + "МБ: " + Лев(СокрЛ(СтрЗаменить(ТекстФайла, Символы.ПС, "")), 80) + "...");
|
||
Иначе
|
||
ОписаниеОшибки = "Событие превышает допустимый размер 20МБ";
|
||
КонецЕсли;
|
||
РазборТекстаРазрешен = Ложь;
|
||
Иначе
|
||
Если Истина
|
||
И РазмерТекущейПорции = РазмерПорции
|
||
И СтрокаТЧ <> Неопределено
|
||
Тогда
|
||
мТаблицаЖурнала.Удалить(СтрокаТЧ);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Вхождения = РегВыражение1.НайтиВхождения("");
|
||
Если РазборТекстаРазрешен Тогда
|
||
Попытка
|
||
Вхождения = РегВыражение1.НайтиВхождения(ТекстФайла);
|
||
Исключение
|
||
ОписаниеОшибки = ОписаниеОшибки();
|
||
КонецПопытки;
|
||
КонецЕсли;
|
||
Если ОписаниеОшибки <> "" Тогда
|
||
ирОбщий.СообщитьЛкс("При анализе файла """ + ФайлЖурнала.ПолноеИмя + """ пропущена порция """ + Лев(СокрЛ(СтрЗаменить(ТекстФайла, Символы.ПС, "")), 80) + "..."":
|
||
| " + ОписаниеОшибки);
|
||
Иначе
|
||
Если КомментироватьЗагрузку Тогда
|
||
ирОбщий.СообщитьЛкс("Анализ порции " + СтрДлина(ТекстФайла) + " символов обнаружил " + Вхождения.Количество() + " событий");
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
СтрокаТекущегоКонтекста = Неопределено;
|
||
СтрокаТЧ = Неопределено;
|
||
Вхождение = Неопределено;
|
||
Для Каждого Вхождение Из Вхождения Цикл
|
||
#Если Клиент Тогда
|
||
ОбработкаПрерыванияПользователя();
|
||
#КонецЕсли
|
||
СтрокаТЧ = Неопределено;
|
||
АбсолютнаяПозицияВхождения = АбсолютнаяПозицияВФайле + Вхождение.FirstIndex;
|
||
Если Истина
|
||
И КартаФайла.ПозицияНачала > -1
|
||
И АбсолютнаяПозицияВхождения >= КартаФайла.ПозицияНачала
|
||
И АбсолютнаяПозицияВхождения < КартаФайла.ПозицияКонца
|
||
Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
СтрокаВремениЗаписи = СтрокаЧасаЗаписи + СтрЗаменить(Вхождение.SubMatches(0), ":", "");
|
||
ДатаТекущегоСобытия = Дата(СтрокаВремениЗаписи);
|
||
Если Не ЛиФайлВИнтервалеПолностью Тогда
|
||
//ЛиДатаВИнтервале = ирОбщий.ЛиДатаВИнтервалеСГраницамиЛкс(ДатаТекущегоСобытия, лНачалоПериода, КонецПериода);
|
||
//Если Не ЛиДатаВИнтервале Тогда
|
||
// Продолжить;
|
||
//КонецЕсли;
|
||
Если Истина
|
||
И ЗначениеЗаполнено(НачалоПериода)
|
||
И ДатаТекущегоСобытия < НачалоПериода
|
||
Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Если Истина
|
||
И ЗначениеЗаполнено(КонецПериода)
|
||
И ДатаТекущегоСобытия > КонецПериода
|
||
Тогда
|
||
Вхождение = Неопределено;
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
ТипСобытия = ВРег(Вхождение.SubMatches(3));
|
||
Если Истина
|
||
И РазрешенныеТипыСобытий <> Неопределено
|
||
И Не РазрешенныеТипыСобытий.Свойство(ТипСобытия)
|
||
Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Если ПозицияНачалаСчитанныхДанных = -1 Тогда
|
||
ПозицияНачалаСчитанныхДанных = АбсолютнаяПозицияВхождения;
|
||
КонецЕсли;
|
||
КонецМикросекунды = Вхождение.SubMatches(1);
|
||
//КлючСтроки = МоментВремени + ";" + ФайлЖурнала.ПолноеИмя;
|
||
//Если РежимДозагрузки Тогда
|
||
// Если КлючиЗагруженныхСтрок[КлючСтроки] = 1 Тогда
|
||
// Продолжить;
|
||
// КонецЕсли;
|
||
//КонецЕсли;
|
||
Если СтрДлина(КонецМикросекунды) = 6 Тогда
|
||
//Это 8.3
|
||
ЧислоМикросекунд = Число(КонецМикросекунды);
|
||
ПродолжительностьВМикросекундах = Число(Вхождение.SubMatches(2));
|
||
Иначе
|
||
//Это 8.2
|
||
ЧислоМикросекунд = Число(КонецМикросекунды) * 100;
|
||
ПродолжительностьВМикросекундах = Число(Вхождение.SubMatches(2)) * 100;
|
||
КонецЕсли;
|
||
Если мТаблицаЖурнала.Количество() = МаксКоличествоСобытий Тогда
|
||
УдалитьСтрокиВнеФильтра();
|
||
Если мТаблицаЖурнала.Количество() = МаксКоличествоСобытий Тогда
|
||
ДостигнутоПредельноеКоличество = Истина;
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
СтрокаТЧ = мТаблицаЖурнала.Добавить();
|
||
ТекстДинамическихСвойств = Вхождение.SubMatches(5);
|
||
ПоследнееСобытиеТипа = ПоследниеСобытияПоТипам[ТипСобытия];
|
||
ДинамическиеСвойстваВзятыИзКэша = Истина
|
||
И ПоследнееСобытиеТипа <> Неопределено
|
||
И ПоследнееСобытиеТипа.ТекстДинамическихСвойств = ТекстДинамическихСвойств
|
||
И мТаблицаЖурнала.Индекс(ПоследнееСобытиеТипа.СтрокаТаблицы) >= 0; // Строку, на которую ссылается кэш, могли удалить на стыке порций. Поэтому проверяем ее существование
|
||
Если ДинамическиеСвойстваВзятыИзКэша Тогда
|
||
Если ТипЗнч(ПоследнееСобытиеТипа.СписокСвойств) = Тип("Массив") Тогда
|
||
ПоследнееСобытиеТипа.СписокСвойств = ирОбщий.СтрСоединитьЛкс(ПоследнееСобытиеТипа.СписокСвойств);
|
||
КонецЕсли;
|
||
ЗаполнитьЗначенияСвойств(СтрокаТЧ, ПоследнееСобытиеТипа.СтрокаТаблицы, ПоследнееСобытиеТипа.СписокСвойств);
|
||
Иначе
|
||
ДинамическиеСвойстваВзятыИзКэша = Ложь;
|
||
КонецЕсли;
|
||
СтрокаТЧ.ИмяФайлаЛога = ФайлЖурнала.ПолноеИмя;
|
||
СтрокаТЧ.ПроцессОС = ИдентификаторПроцесса;
|
||
СтрокаТЧ.Событие = ТипСобытия;
|
||
СтрокаТЧ.Дата = ДатаТекущегоСобытия - СдвигВремени;
|
||
СтрокаТЧ.МоментВремени = ПолучитьМоментВремени(СтрокаТЧ.Дата, КонецМикросекунды);
|
||
//СтрокаТЧ.ТекстЖурнала = Вхождение.Value; // Теперь это только для отладки будем включать
|
||
СтрокаТЧ.Длительность = ПродолжительностьВМикросекундах / 1000; // Переводим длительность в миллисекунды
|
||
Длительность1Секунды = Цел(ПродолжительностьВМикросекундах / 1000000);
|
||
Длительность1Микросекунды = ПродолжительностьВМикросекундах - Длительность1Секунды * 1000000;
|
||
ДатаНачала = СтрокаТЧ.Дата - Длительность1Секунды;
|
||
НачалоМикросекунды = КонецМикросекунды - Длительность1Микросекунды;
|
||
Если НачалоМикросекунды < 0 Тогда
|
||
ДатаНачала = ДатаНачала - 1;
|
||
НачалоМикросекунды = 1000000 + НачалоМикросекунды;
|
||
КонецЕсли;
|
||
СтрокаТЧ.ДатаНачала = ДатаНачала;
|
||
СтрокаТЧ.МоментВремениНачала = ПолучитьМоментВремени(ДатаНачала, НачалоМикросекунды);
|
||
СтрокаТЧ.Вложенность = Число(Вхождение.SubMatches(4));
|
||
Если Не ДинамическиеСвойстваВзятыИзКэша Тогда
|
||
СписокСвойств = Новый Массив;
|
||
ВхожденияСвойств = РегВыражение2.НайтиВхождения(ТекстДинамическихСвойств,, Истина);
|
||
|
||
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
|
||
#Если Сервер И Не Сервер Тогда
|
||
Для Каждого ВхождениеСвойства Из ВхожденияСвойств Цикл
|
||
//Для Индекс = 0 По мТаблицаКолонок.Количество() - 1 Цикл
|
||
ИмяСвойства = ВхождениеСвойства.SubMatches(0);
|
||
ЗначениеСвойства = ВхождениеСвойства.SubMatches(3);
|
||
Если ЗначениеСвойства = Неопределено Тогда // Скорость критична
|
||
ЗначениеСвойства = ВхождениеСвойства.SubMatches(2);
|
||
КонецЕсли;
|
||
Если ЗначениеСвойства = Неопределено Тогда // Скорость критична
|
||
ЗначениеСвойства = ВхождениеСвойства.SubMatches(1);
|
||
КонецЕсли;
|
||
Если ЗначениеСвойства = Неопределено Тогда // Скорость критична
|
||
Продолжить;
|
||
КонецЕсли;
|
||
ИмяКолонкиТЧ = мСоответствиеКолонок[НРег(ИмяСвойства)];
|
||
Если ИмяКолонкиТЧ = Неопределено Тогда
|
||
СтрокаТЧ.НеизвестныеСвойства = СтрокаТЧ.НеизвестныеСвойства + ИмяСвойства + "=" + ЗначениеСвойства + ", ";
|
||
СписокСвойств.Добавить("НеизвестныеСвойства");
|
||
Иначе
|
||
//Если мЧисловыеСвойства.Свойство(ИмяКолонкиТЧ) Тогда
|
||
// Если Не ЗначениеЗаполнено(ЗначениеСвойства) Тогда
|
||
// ЗначениеСвойства = 0;
|
||
// Иначе
|
||
// Попытка
|
||
// ЗначениеСвойства = Число(ЗначениеСвойства);
|
||
// Исключение
|
||
// ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения числового свойства """ + ИмяКолонкиТЧ + """";
|
||
// КонецПопытки;
|
||
// КонецЕсли;
|
||
//КонецЕсли;
|
||
Если ТипЗнч(СтрокаТЧ[ИмяКолонкиТЧ]) = Тип("Булево") Тогда
|
||
ЗначениеСвойства = ?(ЗначениеСвойства = "1" Или Нрег(ЗначениеСвойства) = "true", Истина, Ложь);
|
||
КонецЕсли;
|
||
Если Не мНепустыеКолонкиЖурнала.Свойство(ИмяКолонкиТЧ) Тогда
|
||
Если ЗначениеЗаполнено(ЗначениеСвойства) Тогда
|
||
мНепустыеКолонкиЖурнала.Вставить(ИмяКолонкиТЧ);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Попытка
|
||
СтрокаТЧ[ИмяКолонкиТЧ] = ЗначениеСвойства;
|
||
Исключение
|
||
ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения свойства """ + ИмяКолонкиТЧ + """";
|
||
КонецПопытки;
|
||
СписокСвойств.Добавить(ИмяКолонкиТЧ);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
#КонецЕсли
|
||
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
|
||
Для Каждого ВхождениеСвойства Из ВхожденияСвойств Цикл ИмяСвойства = ВхождениеСвойства.SubMatches(0); ЗначениеСвойства = ВхождениеСвойства.SubMatches(3); Если ЗначениеСвойства = Неопределено Тогда ЗначениеСвойства = ВхождениеСвойства.SubMatches(2); КонецЕсли; Если ЗначениеСвойства = Неопределено Тогда ЗначениеСвойства = ВхождениеСвойства.SubMatches(1); КонецЕсли; Если ЗначениеСвойства = Неопределено Тогда Продолжить; КонецЕсли; ИмяКолонкиТЧ = мСоответствиеКолонок[НРег(ИмяСвойства)]; Если ИмяКолонкиТЧ = Неопределено Тогда СтрокаТЧ.НеизвестныеСвойства = СтрокаТЧ.НеизвестныеСвойства + ИмяСвойства + "=" + ЗначениеСвойства + ", "; СписокСвойств.Добавить("НеизвестныеСвойства"); Иначе Если ТипЗнч(СтрокаТЧ[ИмяКолонкиТЧ]) = Тип("Булево") Тогда ЗначениеСвойства = ?(ЗначениеСвойства = "1" Или Нрег(ЗначениеСвойства) = "true", Истина, Ложь); КонецЕсли; Если Не мНепустыеКолонкиЖурнала.Свойство(ИмяКолонкиТЧ) Тогда Если ЗначениеЗаполнено(ЗначениеСвойства) Тогда мНепустыеКолонкиЖурнала.Вставить(ИмяКолонкиТЧ); КонецЕсли; КонецЕсли; Попытка СтрокаТЧ[ИмяКолонкиТЧ] = ЗначениеСвойства; Исключение ВызватьИсключение "Некорректное представление """ + ЗначениеСвойства + """ значения свойства """ + ИмяКолонкиТЧ + """"; КонецПопытки; СписокСвойств.Добавить(ИмяКолонкиТЧ); КонецЕсли; КонецЦикла;
|
||
|
||
//АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + Вхождение.Length;
|
||
Если Ложь
|
||
Или (Истина
|
||
И ОтборПоСеансу <> Неопределено
|
||
И СтрокаТЧ.Сеанс <> ОтборПоСеансу)
|
||
Или (Истина
|
||
И ОтборПоПользователю <> Неопределено
|
||
И СтрокаТЧ.Пользователь <> ОтборПоПользователю)
|
||
Тогда
|
||
мТаблицаЖурнала.Удалить(СтрокаТЧ);
|
||
СтрокаТЧ = Неопределено;
|
||
#Если Сервер И Не Сервер Тогда
|
||
СтрокаТЧ = мТаблицаЖурнала.Добавить();
|
||
#КонецЕсли
|
||
Продолжить;
|
||
КонецЕсли;
|
||
//Если НаСервере <> Неопределено Тогда
|
||
// СтрокаТЧ.НаСервере = НаСервере;
|
||
//Иначе
|
||
Если Ложь
|
||
Или ТипСобытия = "SCOM"
|
||
Тогда
|
||
СтрокаТЧ.НаСервере = Истина;
|
||
Иначе
|
||
ИмяТипаПроцесса = "_" + СтрЗаменить(СтрокаТЧ.ТипПроцессаОС, "#", "");
|
||
Попытка
|
||
СтрокаТЧ.НаСервере = мСерверныеТипыПроцессов.Свойство(ИмяТипаПроцесса);
|
||
Исключение
|
||
// Бывают типы процессов с UID, к сожалению тогда невозможно определить
|
||
КонецПопытки;
|
||
КонецЕсли;
|
||
//КонецЕсли;
|
||
Если СтрокаТЧ.Контекст <> "" Тогда
|
||
КонтекстТД = Новый ТекстовыйДокумент;
|
||
КонтекстТД.УстановитьТекст(СтрокаТЧ.Контекст);
|
||
СтрокаТЧ.СтрокаМодуля = СокрЛП(КонтекстТД.ПолучитьСтроку(КонтекстТД.КоличествоСтрок()));
|
||
Если БазовыйУровеньСтека > 0 Тогда
|
||
ЗаполнитьСтрокуБазовогоУровня(СтрокаТЧ);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
ПоследниеСобытияПоТипам[ТипСобытия] = Новый Структура("СтрокаТаблицы, ТекстДинамическихСвойств, СписокСвойств", СтрокаТЧ, ТекстДинамическихСвойств, СписокСвойств);
|
||
КонецЕсли;
|
||
//Если ДатаТекущегоСобытия > лПоследнееВремяНачалаЗагрузки - НаложениеПриДозагрузкеСекунд Тогда
|
||
// НовыеКлючиЗагруженныхСтрок[КлючСтроки] = 1;
|
||
//КонецЕсли;
|
||
Если ирОбщий.СтрокиРавныЛкс(ТипСобытия, "Context") Тогда
|
||
// Встроим контекст в предыдущие события
|
||
Индекс = мТаблицаЖурнала.Количество() - 2;
|
||
Пока Индекс >= 0 Цикл
|
||
СтрокаБезКонтекста = мТаблицаЖурнала[Индекс];
|
||
Индекс = Индекс - 1;
|
||
Если Ложь
|
||
Или СтрокаБезКонтекста.Сеанс <> СтрокаТЧ.Сеанс
|
||
Или СтрокаБезКонтекста.Инфобаза <> СтрокаТЧ.Инфобаза
|
||
Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
Если СтрокаБезКонтекста.СтрокаМодуля <> "" Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
ЗаполнитьЗначенияСвойств(СтрокаБезКонтекста, СтрокаТЧ, "СтрокаМодуля, Контекст");
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
Если ДостигнутоПредельноеКоличество Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
// Для отката к началу последнего события
|
||
РазмерТекущейПорции = СтрДлина(ПорцияТекстаФайла);
|
||
АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле + СтрДлина(ТекстФайла);
|
||
Если РазмерТекущейПорции = РазмерПорции Тогда
|
||
//Если СтрокаТЧ <> Неопределено Тогда
|
||
// ТаблицаЖурнала.Удалить(ТаблицаЖурнала.Количество() - 1);
|
||
//КонецЕсли;
|
||
Если Вхождение <> Неопределено Тогда
|
||
ТекстФайла = Сред(ТекстФайла, Вхождение.FirstIndex);
|
||
Иначе
|
||
ТекстФайла = Прав(ТекстФайла, 1000); // Страховка
|
||
КонецЕсли;
|
||
АбсолютнаяПозицияВФайле = АбсолютнаяПозицияВФайле - СтрДлина(ТекстФайла);
|
||
Иначе
|
||
ТекстФайла = "";
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
Если ИндикаторФайла <> Неопределено Тогда
|
||
ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
|
||
КонецЕсли;
|
||
Если ДостигнутоПредельноеКоличество Тогда
|
||
ТекстСообщения = "Загрузка остановлена по достижению максимального количества событий в таблице";
|
||
Если Не ЗначениеЗаполнено("" + ФильтрЗагрузки) Тогда
|
||
ТекстСообщения = ТекстСообщения + ". Если задать фильтр отображения таблицы, то будет предложено применить его при загрузке нового журнала.";
|
||
КонецЕсли;
|
||
ирОбщий.СообщитьЛкс(ТекстСообщения);
|
||
Иначе
|
||
КартаФайла.ПозицияКонца = АбсолютнаяПозицияВФайле;
|
||
Если Истина
|
||
И ПозицияНачалаСчитанныхДанных <> -1
|
||
И (Ложь
|
||
Или КартаФайла.ПозицияНачала = -1
|
||
Или КартаФайла.ПозицияНачала > ПозицияНачалаСчитанныхДанных)
|
||
Тогда
|
||
КартаФайла.ПозицияНачала = ПозицияНачалаСчитанныхДанных;
|
||
КонецЕсли;
|
||
Если Ложь
|
||
Или Не ЗначениеЗаполнено(КонецПериода)
|
||
Или КонецПериода > КартаФайла.КонецПериода
|
||
Тогда
|
||
КартаФайла.КонецПериода = КонецПериода;
|
||
КонецЕсли;
|
||
Если Ложь
|
||
Или Не ЗначениеЗаполнено(НачалоПериода)
|
||
Или НачалоПериода < КартаФайла.НачалоПериода
|
||
Тогда
|
||
КартаФайла.НачалоПериода = НачалоПериода;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Результат = Неопределено;
|
||
Если ВозвращатьРезультат Тогда
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("КлючКарты", КлючКарты);
|
||
Результат.Вставить("КартаФайла", ирОбщий.СтруктураИзСтрокиТаблицыИлиДереваИлиВыборкиЛкс(КартаФайла));
|
||
Результат.Вставить("ТаблицаЖурнала", мТаблицаЖурнала);
|
||
Результат.Вставить("РазмерФайла", РазмерФайла);
|
||
Результат.Вставить("НепустыеКолонкиЖурнала", мНепустыеКолонкиЖурнала);
|
||
КонецЕсли;
|
||
Возврат Результат;
|
||
КонецФункции
|
||
|
||
Процедура ЗагрузитьРезультатЧтенияФайлаВПотоке(Знач Результат, Знач ЛокальныеПараметры) Экспорт
|
||
|
||
Если Результат = Неопределено Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
мТаблицаЖурнала = ирОбщий.ОбъединитьТаблицыЗначенийЛкс(Результат.ТаблицаЖурнала, мТаблицаЖурнала, Результат.НепустыеКолонкиЖурнала, мНепустыеКолонкиЖурнала);
|
||
ирОбщий.СкопироватьУниверсальнуюКоллекциюЛкс(Результат.НепустыеКолонкиЖурнала, мНепустыеКолонкиЖурнала);
|
||
СтрокиКарт = мКартыФайлов.НайтиСтроки(Результат.КлючКарты);
|
||
Если СтрокиКарт.Количество() > 0 Тогда
|
||
КартаФайла = СтрокиКарт[0];
|
||
Иначе
|
||
КартаФайла = мКартыФайлов.Добавить();
|
||
КонецЕсли;
|
||
ЗаполнитьЗначенияСвойств(КартаФайла, Результат.КартаФайла);
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция _СписокСвойствИзСтруктуры(Знач СтруктураСвойств)
|
||
#Если Сервер И Не Сервер Тогда
|
||
СтруктураСвойств = Новый Структура;
|
||
#КонецЕсли
|
||
МассивСвойств = Новый Массив;
|
||
Для Каждого КлючИЗначение Из СтруктураСвойств Цикл
|
||
МассивСвойств.Добавить(КлючИЗначение.Ключ);
|
||
КонецЦикла;
|
||
СписокСвойств1 = ирОбщий.СтрСоединитьЛкс(МассивСвойств);
|
||
Возврат СписокСвойств1;
|
||
|
||
КонецФункции
|
||
|
||
Функция РеквизитыДляСервера(Параметры) Экспорт
|
||
|
||
//Результат = ирОбщий.РеквизитыОбработкиЛкс(ЭтотОбъект);
|
||
//
|
||
ИменаПередаваемыхСвойств = мИменаВозвращаемыхСвойств + ",
|
||
|мАдресЧужойСхемыБД,
|
||
|НачалоПериодаКлиента,
|
||
|КонецПериодаКлиента,
|
||
|НачалоПериодаСервера,
|
||
|КонецПериодаСервера,
|
||
|мЛиАнализТрассыЗапроса,
|
||
|мИдентификаторТрассы";
|
||
Результат = Новый Структура(ИменаПередаваемыхСвойств);
|
||
ЗаполнитьЗначенияСвойств(Результат, ЭтотОбъект, ИменаПередаваемыхСвойств);
|
||
Для Каждого МетаРеквизит Из Метаданные().Реквизиты Цикл
|
||
Результат.Вставить(МетаРеквизит.Имя, ЭтотОбъект[МетаРеквизит.Имя]);
|
||
КонецЦикла;
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Процедура УдалитьСтрокиВнеФильтра()
|
||
|
||
Если ЗначениеЗаполнено("" + ФильтрЗагрузки) Тогда
|
||
Построитель = Новый ПостроительЗапроса;
|
||
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаЖурнала);
|
||
ирОбщий.СкопироватьОтборПостроителяЛкс(Построитель.Отбор, ФильтрЗагрузки);
|
||
ТаблицаЖурнала.Загрузить(Построитель.Результат.Выгрузить());
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ОпределитьНепустыеКолонки() Экспорт
|
||
|
||
Если мНепустыеКолонкиЖурнала.Количество() = 0 Тогда // Загрузили данные из файла
|
||
// Долгая операция
|
||
Для Каждого Реквизит Из Метаданные().ТабличныеЧасти.ТаблицаЖурнала.Реквизиты Цикл
|
||
Если ТаблицаЖурнала.НайтиСтроки(Новый Структура(Реквизит.Имя, Реквизит.Тип.ПривестиЗначение())).Количество() < ТаблицаЖурнала.Количество() Тогда
|
||
мНепустыеКолонкиЖурнала.Вставить(Реквизит.Имя);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
ДобавитьОбязательныеНепустыеКолонки();
|
||
//Пустота производных колонок
|
||
Если мНепустыеКолонкиЖурнала.Свойство("Контекст") Тогда
|
||
мНепустыеКолонкиЖурнала.Вставить("СтрокаМодуля");
|
||
мНепустыеКолонкиЖурнала.Вставить("СтрокаБазовогоМодуля");
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ДобавитьОбязательныеНепустыеКолонки() Экспорт
|
||
|
||
мНепустыеКолонкиЖурнала.Вставить("Событие");
|
||
мНепустыеКолонкиЖурнала.Вставить("ИмяФайлаЛога");
|
||
мНепустыеКолонкиЖурнала.Вставить("ПроцессОС");
|
||
мНепустыеКолонкиЖурнала.Вставить("НаСервере");
|
||
мНепустыеКолонкиЖурнала.Вставить("Вложенность");
|
||
мНепустыеКолонкиЖурнала.Вставить("Длительность");
|
||
мНепустыеКолонкиЖурнала.Вставить("Дата");
|
||
мНепустыеКолонкиЖурнала.Вставить("ДатаНачала");
|
||
мНепустыеКолонкиЖурнала.Вставить("МоментВремени");
|
||
мНепустыеКолонкиЖурнала.Вставить("МоментВремениНачала");
|
||
мНепустыеКолонкиЖурнала.Вставить("СтрокаМодуля");
|
||
мНепустыеКолонкиЖурнала.Вставить("НеизвестныеСвойства");
|
||
//мНепустыеКолонкиЖурнала.Вставить("Картинка");
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ПолучитьМоментВремени(Дата, Микросекунды) Экспорт
|
||
|
||
Результат = Формат(Дата, "ДФ=yyyyMMddHHmmss") + Формат(Микросекунды, "ЧЦ=6; ЧВН=; ЧГ=");
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Функция РазностьМоментовВремени(МоментВремениУменьшаемый, МоментВремениВычитаемый) Экспорт
|
||
|
||
Если СтрДлина(МоментВремениВычитаемый) <> СтрДлина(МоментВремениВычитаемый) Тогда
|
||
ВызватьИсключение "Размерность моментов времени не совпадает";
|
||
КонецЕсли;
|
||
ДлинаЧастиДаты = 14;
|
||
ДатаУменьшаемая = Дата(Лев(МоментВремениУменьшаемый, ДлинаЧастиДаты));
|
||
ДатаВычитаемая = Дата(Лев(МоментВремениВычитаемый, ДлинаЧастиДаты));
|
||
РазрядностьДолейСекунд = СтрДлина(МоментВремениУменьшаемый) - ДлинаЧастиДаты;
|
||
РазностьСекунд = ДатаУменьшаемая - ДатаВычитаемая;
|
||
Результат = РазностьСекунд;
|
||
Для Счетчик = 1 По РазрядностьДолейСекунд Цикл
|
||
Результат = Результат * 10;
|
||
КонецЦикла;
|
||
Результат = Результат + Число(Сред(МоментВремениУменьшаемый, ДлинаЧастиДаты + 1)) - Число(Сред(МоментВремениВычитаемый, ДлинаЧастиДаты + 1));
|
||
Возврат Результат;
|
||
|
||
КонецФункции // РазностьМоментовВремени()
|
||
|
||
Функция ЗаполнитьСтрокуБазовогоУровня(СтрокаТЧ)
|
||
|
||
Если БазовыйУровеньСтека > 0 Тогда
|
||
//МаркерБазовогоМодуля = Символы.Таб + мИмяБазовогоМодуля + " : ";
|
||
//ПозицияМаркераМодуля = Найти(СтрокаТЧ.Контекст, МаркерБазовогоМодуля);
|
||
//КонецСтроки = Сред(СтрокаТЧ.Контекст, ПозицияМаркераМодуля + СтрДлина(МаркерБазовогоМодуля));
|
||
НовоеЗначение = СокрЛ(СтрПолучитьСтроку(СтрокаТЧ.Контекст, БазовыйУровеньСтека));
|
||
Иначе
|
||
НовоеЗначение = "";
|
||
КонецЕсли;
|
||
ирОбщий.ПрисвоитьЕслиНеРавноЛкс(СтрокаТЧ.СтрокаМодуляБазовогоУровня, НовоеЗначение);
|
||
Возврат Неопределено;
|
||
|
||
КонецФункции
|
||
|
||
// ПопытокЧтения - Число, используется только при РежимТрассы = Истина
|
||
Функция ПрочитатьСобственныйЖурналДвухСторон(УдалитьДополнительныеСобытия = Истина, ИменаНеполезныхКолонок = "", РежимТрассы = Истина, ЖдатьСекунд = 2, СмещениеБазовогоУровня = Неопределено,
|
||
ОтборПоСеансу = Неопределено)
|
||
|
||
Если РежимТрассы Тогда
|
||
Если мИдентификаторТрассы = Неопределено Тогда
|
||
Если Не ирКэш.ЛиФайловаяБазаЛкс() Тогда
|
||
ирОбщий.ЛиТехножурналВключенЛкс(Истина, Истина, Истина, мЛиТрассаПоПользователю);
|
||
КонецЕсли;
|
||
ирОбщий.ЛиТехножурналВключенЛкс(, Истина, Истина, мЛиТрассаПоПользователю);
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
//ЭтотОбъект.ЗагружатьЖурналКлиента = Истина;
|
||
//ЭтотОбъект.ЗагружатьЖурналСервера = Не ирКэш.ЛиФайловаяБазаЛкс();
|
||
//ЭтотОбъект.ЗагружатьТолькоТекущийСеанс = Истина;
|
||
КонецЕсли;
|
||
ВыраниватьДатуПоСерверу = Ложь;
|
||
#Если Клиент Тогда
|
||
ВыраниватьДатуПоСерверу = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.ВыраниватьДатуПоСерверу") = Истина;
|
||
#КонецЕсли
|
||
Если РежимТрассы Тогда
|
||
РазницаВремениКлиентСервер = НачалоПериодаКлиента - НачалоПериодаСервера;
|
||
Иначе
|
||
РазницаВремениКлиентСервер = ирОбщий.РазницаВремениКлиентСерверЛкс();
|
||
КонецЕсли;
|
||
Если Истина
|
||
И Не ирКэш.Получить().ЭтоФайловаяБаза
|
||
И ЗагружатьЖурналСервера
|
||
Тогда
|
||
ЭтотОбъект.КаталогЖурнала = "";
|
||
Если ВыраниватьДатуПоСерверу Тогда
|
||
СдвигВремени = 0;
|
||
Иначе
|
||
СдвигВремени = -РазницаВремениКлиентСервер;
|
||
КонецЕсли;
|
||
РезультатСервера = ПрочитатьСобственныйЖурналОднойСтороны(НачалоПериодаСервера, КонецПериодаСервера, Истина, СдвигВремени, РежимТрассы, ЖдатьСекунд, СмещениеБазовогоУровня, ОтборПоСеансу);
|
||
Если РезультатСервера = Неопределено Тогда
|
||
ирОбщий.СообщитьЛкс("Не удалось найти маркеры трассы в логах техножурнала сервера " + КаталогЖурнала + ". Проверьте включенность регистрации события QERR в настройке техножурнала");
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
РезультатКлиента = Неопределено;
|
||
Если Ложь
|
||
Или Не РежимТрассы
|
||
Или Не мЛиТрассаПоПользователю
|
||
Или ирКэш.Получить().ЭтоФайловаяБаза
|
||
Тогда
|
||
#Если Клиент Тогда
|
||
Если ЗагружатьЖурналКлиента Тогда
|
||
ЭтотОбъект.КаталогЖурнала = "";
|
||
Если ВыраниватьДатуПоСерверу Тогда
|
||
СдвигВремени = РазницаВремениКлиентСервер;
|
||
Иначе
|
||
СдвигВремени = 0;
|
||
КонецЕсли;
|
||
РезультатКлиента = ПрочитатьСобственныйЖурналОднойСтороны(НачалоПериодаКлиента, КонецПериодаКлиента, Ложь, СдвигВремени, РежимТрассы, ЖдатьСекунд, СмещениеБазовогоУровня, ОтборПоСеансу);
|
||
Если РезультатКлиента = Неопределено Тогда
|
||
ирОбщий.СообщитьЛкс("Не удалось найти маркеры трассы в логах техножурнала клиента " + КаталогЖурнала + ". Проверьте включенность регистрации события QERR в настройке техножурнала");
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
#КонецЕсли
|
||
КонецЕсли;
|
||
Если УдалитьДополнительныеСобытия Тогда
|
||
УдалитьСтрокиПоОтборуЛкс(Новый Структура("Действие", "getExecSQLStatistics"));
|
||
УдалитьСтрокиПоОтборуЛкс(Новый Структура("Событие", "CONTEXT"));
|
||
КонецЕсли;
|
||
Если РежимТрассы Тогда
|
||
ЭтотОбъект.ВключитьСвойстваСИменамиМетаданных = Истина;
|
||
КонецЕсли;
|
||
Если Истина
|
||
И РезультатКлиента = Неопределено
|
||
И РезультатСервера = Неопределено
|
||
Тогда
|
||
Если мТаблицаЖурнала.Количество() = 0 Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
//Если ВключитьСвойстваСИменамиМетаданных Тогда
|
||
// ОбновитьСвойстваВТерминахМетаданных();
|
||
//КонецЕсли;
|
||
//ОбновитьСтрокиБазовогоУровня();
|
||
Возврат Истина;
|
||
|
||
КонецФункции
|
||
|
||
Функция ПрочитатьСобственныйЖурналОднойСтороны(НачалоПериода = Неопределено, КонецПериода = Неопределено, НаСервере = Истина, СдвигВремени = 0,
|
||
РежимТрассы = Истина, ЖдатьСекунд = 2, СмещениеБазовогоУровня = Неопределено, ОтборПоСеансу = Неопределено)
|
||
|
||
Если НачалоПериода <> Неопределено Тогда
|
||
ЭтотОбъект.НачалоПериода = НачалоПериода;
|
||
КонецЕсли;
|
||
Если КонецПериода <> Неопределено Тогда
|
||
ЭтотОбъект.КонецПериода = КонецПериода;
|
||
КонецЕсли;
|
||
ТехножурналВключен = ирОбщий.ЛиТехножурналВключенЛкс(НаСервере,, Истина, РежимТрассы И мЛиТрассаПоПользователю);
|
||
Если Истина
|
||
И Не ТехножурналВключен
|
||
И РежимТрассы
|
||
Тогда
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
МассивТиповСУБД = Новый Массив();
|
||
Если ирКэш.ЛиФайловаяБазаЛкс() Тогда
|
||
МассивТиповСУБД.Добавить("DBV8DBENG");
|
||
//ОтборТЧ = Новый Структура("Событие", "SDBL");
|
||
Иначе
|
||
МассивТиповСУБД.Добавить("DBMSSQL");
|
||
МассивТиповСУБД.Добавить("DBPOSTGRS");
|
||
МассивТиповСУБД.Добавить("DBORACLE");
|
||
МассивТиповСУБД.Добавить("DB2");
|
||
//ОтборТЧ = Новый Структура("Событие", "CONTEXT");
|
||
КонецЕсли;
|
||
СообщитьРазмер = Неопределено;
|
||
МаркерНачалаНайден = Ложь;
|
||
ДлительностьОднойПаузы = 0.5;
|
||
Для Счетчик = 1 По ЖдатьСекунд / ДлительностьОднойПаузы + 1 Цикл
|
||
#Если Клиент Тогда
|
||
ОбработкаПрерыванияПользователя();
|
||
#КонецЕсли
|
||
Если Счетчик > 1 Тогда
|
||
ирОбщий.СостояниеЛкс("Ожидание техножурнала " + КаталогЖурнала + "...");
|
||
ирОбщий.ПаузаЛкс(ДлительностьОднойПаузы);
|
||
СообщитьРазмер = Ложь;
|
||
КонецЕсли;
|
||
ЖурналСчитан = ПрочитатьПроизвольныйЖурнал(СообщитьРазмер, СдвигВремени, , ОтборПоСеансу, НаСервере);
|
||
Если Не ЖурналСчитан Тогда
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
//ТехножурналВключен = ирОбщий.ЛиТехножурналВключенЛкс(Истина,, Истина);
|
||
//Если ТехножурналВключен Тогда
|
||
// Если АвтоочисткаТехножурнала Тогда
|
||
// КаталогТекущегоЖурнала = ПолучитьКаталогТекущегоЖурнала();
|
||
// Если ЗначениеЗаполнено(КаталогТекущегоЖурнала) Тогда
|
||
// ирОбщий.ОчиститьКаталогТехножурналаЛкс(КаталогТекущегоЖурнала, Истина, Ложь);
|
||
// КонецЕсли;
|
||
// КонецЕсли;
|
||
//КонецЕсли;
|
||
Если РежимТрассы Тогда
|
||
Если Ложь
|
||
Или Не ирКэш.ЛиПортативныйРежимЛкс()
|
||
Или Не НаСервере
|
||
Тогда
|
||
МаркерНачала = Новый Структура("Описание", "{(1, 1)}: Ожидается выражение ""ВЫБРАТЬ""
|
||
|<<?>>НачалоТрассы_" + мИдентификаторТрассы);
|
||
МаркерКонца = Новый Структура("Описание", "{(1, 1)}: Ожидается выражение ""ВЫБРАТЬ""
|
||
|<<?>>КонецТрассы_" + мИдентификаторТрассы);
|
||
Иначе
|
||
МаркерНачала = Новый Структура("ТекстSDBL", "SELECT
|
||
|""НачалоТрассы_" + мИдентификаторТрассы + """
|
||
|");
|
||
МаркерКонца = Новый Структура("ТекстSDBL", "SELECT
|
||
|""КонецТрассы_" + мИдентификаторТрассы + """
|
||
|");
|
||
КонецЕсли;
|
||
|
||
// Удаляем лишние строки до маркера начала и после маркера конца
|
||
Если Не МаркерНачалаНайден Тогда
|
||
НайденныеСтроки = мТаблицаЖурнала.НайтиСтроки(МаркерНачала);
|
||
Если НайденныеСтроки.Количество() = 0 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
НачальнаяСтрока = НайденныеСтроки[0];
|
||
#Если Сервер И Не Сервер Тогда
|
||
НачальнаяСтрока = мТаблицаЖурнала.Добавить();
|
||
#КонецЕсли
|
||
Если СмещениеБазовогоУровня <> Неопределено Тогда
|
||
ЭтотОбъект.БазовыйУровеньСтека = СтрЧислоСтрок(НачальнаяСтрока.Контекст) + СмещениеБазовогоУровня;
|
||
КонецЕсли;
|
||
КонечныйИндекс = мТаблицаЖурнала.Индекс(НачальнаяСтрока);
|
||
Для Индекс = 0 По КонечныйИндекс Цикл
|
||
//Если мТаблицаЖурнала[0].НаСервере = НаСервере Тогда
|
||
мТаблицаЖурнала.Удалить(0);
|
||
//КонецЕсли;
|
||
КонецЦикла;
|
||
МаркерНачалаНайден = Истина;
|
||
КонецЕсли;
|
||
|
||
НайденныеСтроки = мТаблицаЖурнала.НайтиСтроки(МаркерКонца);
|
||
Если НайденныеСтроки.Количество() = 0 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
КонечнаяСтрока = НайденныеСтроки[0];
|
||
НачальныйИндекс = мТаблицаЖурнала.Индекс(КонечнаяСтрока);
|
||
Если Ложь
|
||
Или НаСервере
|
||
Или ирКэш.ЛиФайловаяБазаЛкс()
|
||
Тогда
|
||
КонечнаяСтрока1 = мТаблицаЖурнала[НачальныйИндекс];
|
||
Если МассивТиповСУБД.Найти(КонечнаяСтрока1.Событие) <> Неопределено Тогда // Опасно. Учитывается регистр букв
|
||
мТипСУБД = КонечнаяСтрока1.Событие;
|
||
НачальныйИндекс = НачальныйИндекс - 1;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
НачальноеКоличество = мТаблицаЖурнала.Количество();
|
||
Для Индекс = 1 По НачальноеКоличество - НачальныйИндекс Цикл
|
||
СтрокаЖурнала = мТаблицаЖурнала[НачальноеКоличество - Индекс];
|
||
Если СтрокаЖурнала.НаСервере = НаСервере Тогда
|
||
мТаблицаЖурнала.Удалить(СтрокаЖурнала);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Пока Истина
|
||
И мТаблицаЖурнала.Количество() > 0
|
||
И мТаблицаЖурнала[0].НаСервере = НаСервере
|
||
И Найти(мТаблицаЖурнала[0].Контекст, "Обработка.ирАнализТехножурнала.МодульОбъекта") > 0
|
||
Цикл
|
||
мТаблицаЖурнала.Удалить(0);
|
||
КонецЦикла;
|
||
Пока Истина
|
||
И мТаблицаЖурнала.Количество() > 0
|
||
И мТаблицаЖурнала[мТаблицаЖурнала.Количество() - 1].НаСервере = НаСервере
|
||
И Найти(мТаблицаЖурнала[мТаблицаЖурнала.Количество() - 1].Контекст, "Обработка.ирАнализТехножурнала.МодульОбъекта") > 0
|
||
Цикл
|
||
мТаблицаЖурнала.Удалить(мТаблицаЖурнала.Количество() - 1);
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
Прервать;
|
||
КонецЦикла;
|
||
Если РежимТрассы Тогда
|
||
Если КонечнаяСтрока = Неопределено Тогда
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
// ФрагментыНачальнойСтрокиМодуля = ирОбщий.СтрРазделитьЛкс(мТаблицаЖурнала[0].СтрокаМодуля, ":", Истина);
|
||
// ФрагментыКонечнойСтрокиМодуля = ирОбщий.СтрРазделитьЛкс(мТаблицаЖурнала[мТаблицаЖурнала.Количество() - 1].СтрокаМодуля, ":", Истина);
|
||
// ИмяМодуляНачальнойСтроки = ФрагментыНачальнойСтрокиМодуля[0];
|
||
// ИмяМодуляКонечнойСтроки = ФрагментыКонечнойСтрокиМодуля[0];
|
||
// НомерНачальнойСтроки = Число(ФрагментыНачальнойСтрокиМодуля[1]);
|
||
// НомерКонечнойСтроки = Число(ФрагментыКонечнойСтрокиМодуля[1]);
|
||
// ЕстьВызовыМетодовМодулей = Ложь
|
||
// Или ИмяМодуляНачальнойСтроки <> ИмяМодуляНачальнойСтроки
|
||
// Или НомерНачальнойСтроки > НомерКонечнойСтроки;
|
||
// СтрокиВызововМетодов = НайтиВызовыМетодовМодулей(ИмяМодуляНачальнойСтроки, НомерНачальнойСтроки, НомерКонечнойСтроки, Истина);
|
||
// Если СтрокиВызововМетодов.Количество() > 0 Тогда
|
||
// Ответ = Вопрос("В трассе обнаружены вызовы методов модулей. Хотите удалить их из трассы?", РежимДиалогаВопрос.ДаНет);
|
||
// Если Ответ = КодВозвратаДиалога.Да Тогда
|
||
// СтрокиВызововМетодов = НайтиВызовыМетодовМодулей(ИмяМодуляНачальнойСтроки, НомерНачальнойСтроки, НомерКонечнойСтроки, Ложь);
|
||
// Для Каждого СтрокаВызоваМетода Из СтрокиВызововМетодов Цикл
|
||
// мТаблицаЖурнала.Удалить(СтрокаВызоваМетода);
|
||
// КонецЦикла;
|
||
// КонецЕсли;
|
||
// КонецЕсли;
|
||
КонецЕсли;
|
||
Возврат Истина;
|
||
|
||
КонецФункции
|
||
|
||
Функция ПрочитатьЖурнал(Параметры) Экспорт
|
||
|
||
ЭтотОбъект.ФильтрЗагрузки = Параметры.ФильтрЗагрузки;
|
||
УдалитьДополнительныеСобытия = Параметры.УдалитьДополнительныеСобытия;
|
||
ИменаНеполезныхКолонок = Параметры.ИменаНеполезныхКолонок;
|
||
РежимТрассы = Параметры.РежимТрассы;
|
||
ЖдатьСекунд = Параметры.ЖдатьСекунд;
|
||
ОтборПоСеансу = Параметры.ОтборПоСеансу;
|
||
СмещениеБазовогоУровня = Параметры.СмещениеБазовогоУровня;
|
||
Если Не РежимТрассы Тогда
|
||
ЭтотОбъект.КонецПериодаСервера = Неопределено;
|
||
ЭтотОбъект.КонецПериодаКлиента = Неопределено;
|
||
ЭтотОбъект.НачалоПериодаСервера = Неопределено;
|
||
ЭтотОбъект.НачалоПериодаКлиента = Неопределено;
|
||
КонецЕсли;
|
||
Если Ложь
|
||
Или ЗагружатьЖурналКлиента
|
||
Или ЗагружатьЖурналСервера
|
||
Тогда
|
||
ЖурналПрочитан = ПрочитатьСобственныйЖурналДвухСторон(УдалитьДополнительныеСобытия, ИменаНеполезныхКолонок, РежимТрассы, ЖдатьСекунд, СмещениеБазовогоУровня, ОтборПоСеансу);
|
||
Иначе
|
||
ЖурналПрочитан = ПрочитатьПроизвольныйЖурнал(,,, ОтборПоСеансу);
|
||
Если ВключитьСвойстваСИменамиМетаданных Тогда
|
||
ОбновитьСвойстваВТерминахМетаданных();
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Результат = Новый Структура(мИменаВозвращаемыхСвойств);
|
||
ЗаполнитьЗначенияСвойств(Результат, ЭтотОбъект);
|
||
Результат.Вставить("Успех", ЖурналПрочитан);
|
||
Результат.Вставить("ТаблицаЖурнала", мТаблицаЖурнала);
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
// ТолькоПустые - заполнять только ранее не заполненные свойства
|
||
Процедура ЗаполнитьСвойстваСИменамиМетаданных(ВыбраннаяСтрока, Принудительно = Ложь) Экспорт
|
||
|
||
Если Не Принудительно И ВыбраннаяСтрока.СвойстваСИменамиМетаданныхАктуальны Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
Попытка
|
||
Инфобаза = ВыбраннаяСтрока.Инфобаза;
|
||
Исключение
|
||
Инфобаза = "";
|
||
КонецПопытки;
|
||
ЧужаяСхемаБД = ирОбщий.ПолучитьЧужуюСхемуБДЛкс(мАдресЧужойСхемыБД);
|
||
ЭтоГарантированоСобытиеВыбраннойЧужойБазы = Истина
|
||
И ЗначениеЗаполнено(Инфобаза)
|
||
И ЧужаяСхемаБД <> Неопределено
|
||
И ирОбщий.СтрокиРавныЛкс(Инфобаза, НСтр(ЧужаяСхемаБД.СтрокаСоединения, "Ref"));
|
||
ЭтоГарантированоСобытиеСобственнойБазы = Истина
|
||
И ЗначениеЗаполнено(Инфобаза)
|
||
И Не ЭтоГарантированоСобытиеВыбраннойЧужойБазы
|
||
И ирОбщий.СтрокиРавныЛкс(Инфобаза, НСтр(СтрокаСоединенияИнформационнойБазы(), "Ref"));
|
||
НайденныеТаблицы = Новый ТаблицаЗначений;
|
||
Для Каждого КлючИЗначение Из мСвойстваСИменамиБД Цикл
|
||
ИмяСвойства = КлючИЗначение.Ключ;
|
||
Если Найти(ИмяСвойства, "Шаблон") > 0 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Попытка
|
||
Пустышка = ТипЗнч(ВыбраннаяСтрока[ИмяСвойства]); // т.к. строки длинные, то их копирование в новую переменную накладно
|
||
Исключение
|
||
// Такого свойства нет - пропускаем
|
||
Продолжить;
|
||
КонецПопытки;
|
||
ЗначениеСвойства = ВыбраннаяСтрока[ИмяСвойства];
|
||
// Берем только имя базы, т.к. кластер может быть по-разному написан
|
||
Если Истина
|
||
И ЗначениеЗаполнено(ЗначениеСвойства)
|
||
И (Ложь
|
||
Или Инфобаза = ""
|
||
Или ЭтоГарантированоСобытиеСобственнойБазы
|
||
Или ЭтоГарантированоСобытиеВыбраннойЧужойБазы)
|
||
Тогда
|
||
ЛиМенаБД = КлючИЗначение.Значение;
|
||
Если Не ЛиМенаБД Тогда
|
||
ТипСУБД = "";
|
||
Иначе
|
||
Попытка
|
||
ТипСУБД = ВыбраннаяСтрока.Событие;
|
||
Исключение
|
||
ТипСУБД = Сред(ИмяСвойства, СтрДлина("Текст") + 1); // Опасно
|
||
КонецПопытки;
|
||
КонецЕсли;
|
||
//Попытка
|
||
ТекстМета = ПеревестиТекстБДВТерминыМетаданных(ЗначениеСвойства, , , ТипСУБД, НайденныеТаблицы,, Ложь,, ЭтоГарантированоСобытиеСобственнойБазы);
|
||
//Исключение
|
||
// ТекстМета = "";
|
||
//КонецПопытки;
|
||
//Если ТекстМета <> "" Тогда
|
||
ВыбраннаяСтрока[ИмяСвойства + "Мета"] = ТекстМета;
|
||
//КонецЕсли;
|
||
Иначе
|
||
// База чужая. Не делаем преобразования
|
||
//ВыбраннаяСтрока[ИмяСвойства + "Мета"] = ЗначениеСвойства;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
Если НайденныеТаблицы.Количество() > 0 Тогда
|
||
НайденныеТаблицы.Свернуть("ИмяМета");
|
||
НайденныеТаблицы.Сортировать("ИмяМета");
|
||
ВыбраннаяСтрока.ТаблицыМетаданных = ирОбщий.СтрСоединитьЛкс(НайденныеТаблицы.ВыгрузитьКолонку("ИмяМета"));
|
||
мНепустыеКолонкиЖурнала.Вставить("ТаблицыМетаданных");
|
||
КонецЕсли;
|
||
Попытка
|
||
ТекстSDBLШаблонМета = ВыбраннаяСтрока.ТекстSDBLШаблонМета;
|
||
Исключение
|
||
ТекстSDBLШаблонМета = Неопределено;
|
||
КонецПопытки;
|
||
Если ТекстSDBLШаблонМета <> Неопределено Тогда
|
||
Инфобаза = "";
|
||
ТекстSDBLМета = "";
|
||
Попытка
|
||
Инфобаза = ВыбраннаяСтрока.Инфобаза;
|
||
ТекстSDBLМета = ВыбраннаяСтрока.ТекстSDBLМета;
|
||
Исключение
|
||
КонецПопытки;
|
||
Если Ложь
|
||
Или Инфобаза = ""
|
||
Или ЭтоГарантированоСобытиеСобственнойБазы
|
||
Или ЭтоГарантированоСобытиеВыбраннойЧужойБазы
|
||
Тогда
|
||
Если Истина
|
||
И ТекстSDBLМета <> ""
|
||
Тогда
|
||
ВыбраннаяСтрока.ТекстSDBLШаблонМета = ПолучитьШаблонТекстаБД(ТекстSDBLМета);
|
||
Иначе
|
||
ВыбраннаяСтрока.ТекстSDBLШаблонМета = ПеревестиТекстБДВТерминыМетаданных(ВыбраннаяСтрока.ТекстSDBLШаблон,,,,,, Ложь,, ЭтоГарантированоСобытиеСобственнойБазы);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Попытка
|
||
ТекстСУБДШаблонМета = ВыбраннаяСтрока.ТекстСУБДШаблонМета;
|
||
Исключение
|
||
ТекстСУБДШаблонМета = Неопределено;
|
||
КонецПопытки;
|
||
Если ТекстСУБДШаблонМета <> Неопределено Тогда
|
||
Инфобаза = "";
|
||
ТекстСУБДМета = "";
|
||
Попытка
|
||
Инфобаза = ВыбраннаяСтрока.Инфобаза;
|
||
ТекстСУБДМета = ВыбраннаяСтрока.ТекстСУБДМета;
|
||
Исключение
|
||
КонецПопытки;
|
||
Если Ложь
|
||
Или Инфобаза = ""
|
||
Или ЭтоГарантированоСобытиеСобственнойБазы
|
||
Или ЭтоГарантированоСобытиеВыбраннойЧужойБазы
|
||
Тогда
|
||
Если Истина
|
||
И ТекстСУБДМета <> ""
|
||
Тогда
|
||
ВыбраннаяСтрока.ТекстСУБДШаблонМета = ПолучитьШаблонТекстаБД(ТекстСУБДМета);
|
||
Иначе
|
||
ВыбраннаяСтрока.ТекстСУБДШаблонМета = ПеревестиТекстБДВТерминыМетаданных(ВыбраннаяСтрока.ТекстСУБДШаблон,,, мТипСУБД,,, Ложь,, ЭтоГарантированоСобытиеСобственнойБазы);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
ВыбраннаяСтрока.СвойстваСИменамиМетаданныхАктуальны = Истина;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ПолучитьКаталогТекущегоЖурнала(НаСервере) Экспорт
|
||
|
||
Результат = ирОбщий.КаталогЧтенияТехножурналаЛкс(НаСервере, Истина, мЛиТрассаПоПользователю);
|
||
Если Не ЗначениеЗаполнено(Результат) Тогда
|
||
Если НаСервере Тогда
|
||
ТекстКлиентСервер = "сервера";
|
||
Иначе
|
||
ТекстКлиентСервер = "клиента";
|
||
КонецЕсли;
|
||
ирОбщий.СообщитьЛкс("Технологический журнал " + ТекстКлиентСервер + " выключен. Невозможно определить каталог журнала по умолчанию.");
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
Если НаСервере Тогда
|
||
КлиентЗапущенНаКомпьютереСервера = ирОбщий.ЛиКлиентЗапущенНаКомпьютереСервераЛкс();
|
||
Если Не КлиентЗапущенНаКомпьютереСервера Тогда
|
||
Если ЭтоЛокальныйПутьЛкс(Результат) Тогда
|
||
ирОбщий.СообщитьЛкс("Клиент запущен не на компьютере сервера (" + ирСервер.ИмяКомпьютераЛкс() +
|
||
"), а в серверной настройке техножурнала указан локальный каталог. Необходимо указать сетевой путь к техножурналу сервера");
|
||
#Если Клиент Тогда
|
||
ФормаНастройки = ПолучитьФорму("НастройкаЧтения");
|
||
РезультатНастройки = ФормаНастройки.ОткрытьМодально();
|
||
Если РезультатНастройки = Истина Тогда
|
||
Если мЛиТрассаПоПользователю Тогда
|
||
Результат = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.КаталогТрассыПоПользователю");
|
||
Иначе
|
||
Результат = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.КаталогЖурналаСервера");
|
||
КонецЕсли;
|
||
Иначе
|
||
Результат = Неопределено;
|
||
КонецЕсли;
|
||
#КонецЕсли
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Функция ЭтоЛокальныйПутьЛкс(Путь) Экспорт
|
||
|
||
ЭтоЛокальныйРесурс = Ложь
|
||
Или Найти(НРег(Путь), "\\localhost") = 1
|
||
Или Найти(НРег(Путь), "\\127.0.0.1") = 1
|
||
Или Лев(Путь, 2) <> "\\";
|
||
Возврат ЭтоЛокальныйРесурс;
|
||
|
||
КонецФункции // ЭтоЛокальныйПуть()
|
||
|
||
Функция ОткрытьСПараметрами(пКаталогЖурнала) Экспорт
|
||
|
||
Форма = ПолучитьФорму();
|
||
Форма.Открыть();
|
||
ЭтотОбъект.ЗагружатьТолькоТекущийСеанс = Ложь;
|
||
ЭтотОбъект.ЗагружатьЖурналСервера = Ложь;
|
||
ЭтотОбъект.ЗагружатьЖурналКлиента = Ложь;
|
||
Форма.ОбновитьДоступность();
|
||
Форма.КаталогЖурнала = пКаталогЖурнала;
|
||
Возврат Форма;
|
||
|
||
КонецФункции
|
||
|
||
Функция ОткрытьСОтбором(НачалоПериода = Неопределено, КонецПериода = Неопределено, СтруктураОтбора = Неопределено) Экспорт
|
||
|
||
Форма = ПолучитьФорму(,,);
|
||
Форма.Открыть();
|
||
Отбор = Форма.ЭлементыФормы.ТаблицаЖурнала.ОтборСтрок;
|
||
Отбор.Сбросить();
|
||
Если НачалоПериода <> Неопределено Тогда
|
||
Форма.НачалоПериода = НачалоПериода;
|
||
КонецЕсли;
|
||
Если КонецПериода <> Неопределено Тогда
|
||
Форма.КонецПериода = КонецПериода;
|
||
КонецЕсли;
|
||
Если СтруктураОтбора <> Неопределено Тогда
|
||
Для Каждого КлючИЗначение Из СтруктураОтбора Цикл
|
||
Отбор[КлючИЗначение.Ключ].Установить(КлючИЗначение.Значение);
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
Возврат Форма;
|
||
|
||
КонецФункции
|
||
|
||
Функция ПолучитьИмяСвойстваБезМета(Знач МестноеИмя) Экспорт
|
||
|
||
Если ирОбщий.СтрокиРавныЛкс(Прав(МестноеИмя, 4), "мета") Тогда
|
||
МестноеИмя = Лев(МестноеИмя, СтрДлина(МестноеИмя) - 4);
|
||
КонецЕсли;
|
||
Возврат МестноеИмя;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ОбновитьСвойстваВТерминахМетаданных() Экспорт
|
||
|
||
ВыбранныеСтроки = мТаблицаЖурнала.НайтиСтроки(Новый Структура("СвойстваСИменамиМетаданныхАктуальны", Ложь));
|
||
Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ВыбранныеСтроки.Количество(), "Перевод в термины метаданных");
|
||
Для Каждого СтрокаТаблицыЖурнала Из ВыбранныеСтроки Цикл
|
||
ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
|
||
ЗаполнитьСвойстваСИменамиМетаданных(СтрокаТаблицыЖурнала);
|
||
КонецЦикла;
|
||
ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ОбновитьСтрокиБазовогоУровня() Экспорт
|
||
|
||
//Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(мТаблицаЖурнала.Количество());
|
||
Для Каждого СтрокаТаблицыЖурнала Из мТаблицаЖурнала Цикл
|
||
//ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
|
||
ЗаполнитьСтрокуБазовогоУровня(СтрокаТаблицыЖурнала);
|
||
КонецЦикла;
|
||
//Для Каждого СтрокаКонтекста Из Контексты Цикл
|
||
// ЗаполнитьСтрокуБазовогоУровня(СтрокаКонтекста);
|
||
//КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ПолучитьШаблонТекстаБД(ТекстБД, Знач ЗаменаПеременныхФрагментов = "7") Экспорт
|
||
#Если Сервер И Не Сервер Тогда
|
||
RegExpПараметры = Обработки.ирОболочкаРегВыражение.Создать();
|
||
#КонецЕсли
|
||
СложнаяЗамена = RegExpПараметры.ТекущийДвижок() = "PCRE2";
|
||
Если СложнаяЗамена Тогда
|
||
// https://www.hostedredmine.com/issues/928414
|
||
Префикс = "[!@!~=+]";
|
||
ЗаменаПеременныхФрагментов = Префикс + ЗаменаПеременныхФрагментов;
|
||
КонецЕсли;
|
||
ШаблонТекстаБД = RegExpПараметры.Replace(ТекстБД, "$1$2" + ЗаменаПеременныхФрагментов);
|
||
Если СложнаяЗамена Тогда
|
||
ШаблонТекстаБД = СтрЗаменить(ШаблонТекстаБД, Префикс, "");
|
||
КонецЕсли;
|
||
Возврат ШаблонТекстаБД;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ЗаполнитьСвойстваШаблоны() Экспорт
|
||
|
||
Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ТаблицаЖурнала.Количество());
|
||
Для Каждого СтрокаТаблицыЖурнала Из ТаблицаЖурнала Цикл
|
||
ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
|
||
Если Истина
|
||
И СтрокаТаблицыЖурнала.ТекстSDBL <> ""
|
||
И СтрокаТаблицыЖурнала.ТекстSDBLШаблон = ""
|
||
Тогда
|
||
СтрокаТаблицыЖурнала.ТекстSDBLШаблон = ПолучитьШаблонТекстаБД(СтрокаТаблицыЖурнала.ТекстSDBL);
|
||
КонецЕсли;
|
||
Если Истина
|
||
И СтрокаТаблицыЖурнала.ТекстСУБД <> ""
|
||
И СтрокаТаблицыЖурнала.ТекстСУБДШаблон = ""
|
||
Тогда
|
||
СтрокаТаблицыЖурнала.ТекстСУБДШаблон = ПолучитьШаблонТекстаБД(СтрокаТаблицыЖурнала.ТекстСУБД);
|
||
КонецЕсли;
|
||
Если Истина
|
||
И СтрокаТаблицыЖурнала.Описание <> ""
|
||
И СтрокаТаблицыЖурнала.ОписаниеШаблон = ""
|
||
Тогда
|
||
СтрокаТаблицыЖурнала.ОписаниеШаблон = ПолучитьШаблонТекстаБД(СтрокаТаблицыЖурнала.Описание);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ОставитьТолькоСтрокиПоОтбору(СтруктураОтбора) Экспорт
|
||
|
||
НужныеСтроки = ТаблицаЖурнала.НайтиСтроки(СтруктураОтбора);
|
||
КоличествоСтрок = ТаблицаЖурнала.Количество();
|
||
Для Счетчик = 1 По КоличествоСтрок Цикл
|
||
Индекс = КоличествоСтрок - Счетчик;
|
||
СтрокаЖурнала = ТаблицаЖурнала[Индекс];
|
||
Если НужныеСтроки.Найти(СтрокаЖурнала) = Неопределено Тогда
|
||
ТаблицаЖурнала.Удалить(СтрокаЖурнала);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура УдалитьСтрокиПоОтборуЛкс(СтруктураОтбора) Экспорт
|
||
|
||
НенужныеСтроки = мТаблицаЖурнала.НайтиСтроки(СтруктураОтбора);
|
||
Для Каждого НенужнаяСтрока Из НенужныеСтроки Цикл
|
||
мТаблицаЖурнала.Удалить(НенужнаяСтрока);
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ЗаписатьМаркерВТехножурнал(Маркер, ДляКлиента = Истина, ДляСервера = Истина, выхТекущаяДатаКлиента = Неопределено, выхТекущаяДатаСервера = Неопределено) Экспорт
|
||
|
||
ЗапросМаркер = Новый Запрос();
|
||
выхТекущаяДатаКлиента = ТекущаяДата();
|
||
выхТекущаяДатаСервера = выхТекущаяДатаКлиента;
|
||
Если ДляКлиента Тогда
|
||
ЗапросМаркер.Текст = Маркер;
|
||
Попытка
|
||
ЗапросМаркер.Выполнить(); // Генерируем для клиента маркер-событие QERR
|
||
Исключение
|
||
КонецПопытки;
|
||
КонецЕсли;
|
||
Если Истина
|
||
И ДляСервера
|
||
И Не ирКэш.ЛиФайловаяБазаЛкс()
|
||
Тогда
|
||
Если Не ирКэш.ЛиПортативныйРежимЛкс() Тогда
|
||
Попытка
|
||
ирСервер.ВыполнитьЗапросЛкс(Маркер,,, выхТекущаяДатаСервера); // Генерируем для сервера маркер-событие QERR
|
||
Исключение
|
||
КонецПопытки;
|
||
Иначе
|
||
ЗапросМаркер.Текст = "ВЫБРАТЬ """ + Маркер + """";
|
||
Попытка
|
||
ЗапросМаркер.Выполнить(); // Генерируем для клиента маркер-событие SDBL
|
||
Исключение
|
||
// Может возникнуть ошибка "В данной транзакции уже происходили ошибки!"
|
||
КонецПопытки;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ИдентификаторТрассыБД() Экспорт
|
||
ДатаМиллисекунды = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
||
Генератор = Новый ГенераторСлучайныхЧисел(ДатаМиллисекунды);
|
||
СгенерированноеЧисло = Генератор.СлучайноеЧисло(100000000, 900000000);
|
||
Возврат СгенерированноеЧисло;
|
||
КонецФункции
|
||
|
||
Функция НачатьТрассу(ПрефиксТрассы = "", ВыводитьСообщения = Ложь, выхТекущаяДатаСервера = Неопределено) Экспорт
|
||
|
||
Если ВыводитьСообщения Тогда
|
||
// Попробовать сделать проверку регистрации событий QERR в настройке техножурнала на сервере
|
||
// Вызовы ЛиТехножурналВключенЛкс могут быть очень долгими, если в анализе техножурнала пользователь сохранил сетевой путь к логам на сервере и он недоступен
|
||
Если Не ирКэш.ЛиФайловаяБазаЛкс() Тогда
|
||
ТехножурналСервераВключен = ирОбщий.ЛиТехножурналВключенЛкс(Истина, ВыводитьСообщения,, мЛиТрассаПоПользователю);
|
||
КонецЕсли;
|
||
ТехножурналКлиентаВключен = ирОбщий.ЛиТехножурналВключенЛкс(, ВыводитьСообщения,, мЛиТрассаПоПользователю);
|
||
Если Истина
|
||
И ТехножурналСервераВключен <> Истина
|
||
И Не ТехножурналКлиентаВключен
|
||
Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
ЭтотОбъект.КонецПериодаСервера = Неопределено;
|
||
ЭтотОбъект.КонецПериодаКлиента = Неопределено;
|
||
ИспользоватьТрассуСУБД = Истина
|
||
И ирОбщий.ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.СобиратьТрассу") = Истина
|
||
И ирОбщий.ЛиПровайдерАДОДляЭтойБазыГотовЛкс()
|
||
И ЛиСерверMSSQLПоддерживаетТрассировку();
|
||
мИдентификаторТрассы = ПрефиксТрассы + "_" + СтрЗаменить(Новый УникальныйИдентификатор(), "-", "");
|
||
ЗаписатьМаркерВТехножурнал("НачалоТрассы_" + мИдентификаторТрассы,,, НачалоПериодаКлиента, НачалоПериодаСервера);
|
||
выхТекущаяДатаСервера = НачалоПериодаСервера;
|
||
|
||
мУдержательСоединенияБД = Неопределено;
|
||
мИдентификаторСоединенияБД = Неопределено;
|
||
Если ИспользоватьТрассуСУБД Тогда
|
||
// https://www.hostedredmine.com/issues/926150
|
||
мИдентификаторБазыДанных = ИдентификаторБазыДанных();
|
||
ТекстЗапроса = ПолучитьМакет("SQLServer_СкриптОчисткиДанных").ПолучитьТекст();
|
||
ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс(ТекстЗапроса,,,,,, мСоединениеАДО);
|
||
ИдентификаторТрассы = XMLСтрока(ИдентификаторТрассыБД());
|
||
ИдентификаторСессии = XMLСтрока(НомерСеансаИнформационнойБазы());
|
||
ЗапросСозданияСессии = ПолучитьМакет("SQLServer_СкриптСессииОпределенияСессииСУБД").ПолучитьТекст();
|
||
ЗапросСозданияСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросСозданияСессии, "{ИдентификаторСессии}", ИдентификаторСессии);
|
||
ЗапросСозданияСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросСозданияСессии, "{ИдентификатоЗапроса}", XMLСтрока(ИдентификаторТрассы));
|
||
ЗапросСозданияСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросСозданияСессии, "{ИдентификаторБазыДанных}", мИдентификаторБазыДанных);
|
||
ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс(ЗапросСозданияСессии,,,,,, мСоединениеАДО);
|
||
мУдержательСоединенияБД = Новый МенеджерВременныхТаблиц;
|
||
ЗапросУдержаниеСоединения = Новый Запрос;
|
||
ЗапросУдержаниеСоединения.МенеджерВременныхТаблиц = мУдержательСоединенияБД;
|
||
ЗапросУдержаниеСоединения.Текст =
|
||
"ВЫБРАТЬ ПЕРВЫЕ " + ИдентификаторТрассы + "
|
||
| " + ИдентификаторТрассы + " КАК Число,
|
||
| 0293843834892983011884662710842 КАК ДополнительноеЧисло
|
||
|ПОМЕСТИТЬ ВТ_ПроизвольныеЗначения";
|
||
ЗапросУдержаниеСоединения.Выполнить();
|
||
ЗапросДанныеСессии = ПолучитьМакет("SQLServer_СкриптПолученияДанныхРасширенныхСобытий").ПолучитьТекст();
|
||
ЗапросДанныеСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросДанныеСессии, "{ИмяСессии}", "getSessionForQuery");
|
||
ЗапросДанныеСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросДанныеСессии, "{ИдентификаторСессии}", ИдентификаторСессии);
|
||
РезультатЗапроса = ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс(ЗапросДанныеСессии,,,,,, мСоединениеАДО);
|
||
Для Каждого СтрокаРезультата Из РезультатЗапроса Цикл
|
||
ЧтениеXML = Новый ЧтениеXML;
|
||
ЧтениеXML.УстановитьСтроку(СтрокаРезультата.Data);
|
||
ПостроительDOM = Новый ПостроительDOM;
|
||
ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
|
||
Разыменователь = Новый РазыменовательПространствИменDOM(ДокументDOM);
|
||
НайденныеСобытия = ДокументDOM.ВычислитьВыражениеXPath("/RingBufferTarget/event", ДокументDOM, Разыменователь, ТипРезультатаDOMXPath.Любой);
|
||
УзелСобытие = НайденныеСобытия.ПолучитьСледующий();
|
||
Пока УзелСобытие <> Неопределено Цикл
|
||
СвойстваСобытия = Новый Соответствие;
|
||
Для Каждого ЭлементСобытия Из УзелСобытие.ДочерниеУзлы Цикл
|
||
ИмяСвойства = СокрЛП(ЭлементСобытия.Атрибуты.ПолучитьИменованныйЭлемент("name").Значение);
|
||
ЗначениеСвойства = СокрЛП(ЭлементСобытия.ПоследнийДочерний.ТекстовоеСодержимое);
|
||
Если Не ЗначениеЗаполнено(ЗначениеСвойства) Тогда
|
||
ЗначениеСвойства = СокрЛП(ЭлементСобытия.ТекстовоеСодержимое);
|
||
КонецЕсли;
|
||
СвойстваСобытия.Вставить(ИмяСвойства, ЗначениеСвойства);
|
||
КонецЦикла;
|
||
ТекстЗапроса = СвойстваСобытия["batch_text"];
|
||
Если Не ЗначениеЗаполнено(ТекстЗапроса) Тогда
|
||
ТекстЗапроса = СвойстваСобытия["statement"];
|
||
КонецЕсли;
|
||
Если Не ЗначениеЗаполнено(ТекстЗапроса) Тогда
|
||
ТекстЗапроса = СвойстваСобытия["sql_text"];
|
||
КонецЕсли;
|
||
Если Найти(ТекстЗапроса, "CREATE EVENT SESSION") > 0 Тогда
|
||
УзелСобытие = НайденныеСобытия.ПолучитьСледующий();
|
||
Продолжить;
|
||
ИначеЕсли Найти(ТекстЗапроса, ИдентификаторТрассы) > 0 Тогда
|
||
мИдентификаторСоединенияБД = СвойстваСобытия["session_id"];
|
||
Прервать;
|
||
КонецЕсли;
|
||
УзелСобытие = НайденныеСобытия.ПолучитьСледующий();
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
ЗапросУдалениеСессии = ПолучитьМакет("SQLServer_СкриптУдаленияСессииСбораДанных").ПолучитьТекст();
|
||
ЗапросУдалениеСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросУдалениеСессии, "{ИмяСессии}", "getSessionForQuery");
|
||
ЗапросУдалениеСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросУдалениеСессии, "{ИдентификаторСессии}", ИдентификаторСессии);
|
||
ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс(ЗапросУдалениеСессии,,,,,, мСоединениеАДО);
|
||
Если Не ЗначениеЗаполнено(мИдентификаторСоединенияБД) Тогда
|
||
мУдержательСоединенияБД = Неопределено;
|
||
ирОбщий.СообщитьЛкс("Не удалось определить идентификатор соединения СУБД. Трасса СУБД будет недоступна.");
|
||
КонецЕсли;
|
||
Если мИдентификаторСоединенияБД <> Неопределено Тогда
|
||
ЗапросСозданияСессии = ПолучитьМакет("SQLServer_СкриптСбораДанныхОЗапросах").ПолучитьТекст();
|
||
ЗапросСозданияСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросСозданияСессии, "{ИдентификаторСессии}", ИдентификаторСессии);
|
||
ЗапросСозданияСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросСозданияСессии, "{ИдентификаторСоединения}", XMLСтрока(мИдентификаторСоединенияБД));
|
||
ЗапросСозданияСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросСозданияСессии, "{ИдентификаторБазыДанных}", мИдентификаторБазыДанных);
|
||
ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс(ЗапросСозданияСессии,,,,,, мСоединениеАДО);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Возврат Истина;
|
||
|
||
КонецФункции
|
||
|
||
Функция ИдентификаторБазыДанных()
|
||
|
||
Если мИдентификаторБазыДанных <> Неопределено Тогда
|
||
Возврат мИдентификаторБазыДанных;
|
||
КонецЕсли;
|
||
РезультатЗапроса = ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс("SELECT DB_ID() AS DatabaseId",,,,,, мСоединениеАДО);
|
||
мИдентификаторБазыДанных = РезультатЗапроса[0][0];
|
||
Возврат мИдентификаторБазыДанных;
|
||
|
||
КонецФункции
|
||
|
||
Функция ЛиСерверMSSQLПоддерживаетТрассировку() Экспорт
|
||
|
||
Если мЛиСерверMSSQLПоддерживаетТрассировку <> Неопределено Тогда
|
||
Возврат мЛиСерверMSSQLПоддерживаетТрассировку;
|
||
КонецЕсли;
|
||
мЛиСерверMSSQLПоддерживаетТрассировку = Ложь;
|
||
РезультатЗапроса = ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс("SELECT @@VERSION AS SQLServerVersion",,,,,, мСоединениеАДО);
|
||
Если РезультатЗапроса <> Неопределено Тогда
|
||
ВерсияСУБД = РезультатЗапроса[0][0];
|
||
Если Найти(ВерсияСУБД, "Microsoft SQL Server 2008") = 0 Тогда
|
||
мЛиСерверMSSQLПоддерживаетТрассировку = Истина;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Возврат мЛиСерверMSSQLПоддерживаетТрассировку;
|
||
|
||
КонецФункции
|
||
|
||
Функция КончитьТрассу(выхТекущаяДатаСервера = Неопределено) Экспорт
|
||
|
||
Если ЗначениеЗаполнено(ЭтотОбъект.КонецПериодаКлиента) Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
Если мИдентификаторСоединенияБД <> Неопределено Тогда
|
||
Попытка
|
||
ИдентификаторСессии = XMLСтрока(НомерСеансаИнформационнойБазы());
|
||
ЗапросДанныеСессии = ПолучитьМакет("SQLServer_СкриптПолученияДанныхРасширенныхСобытий").ПолучитьТекст();
|
||
ЗапросДанныеСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросДанныеСессии, "{ИмяСессии}", "getQueriesInfo");
|
||
ЗапросДанныеСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросДанныеСессии, "{ИдентификаторСессии}", ИдентификаторСессии);
|
||
РезультатБД = ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс(ЗапросДанныеСессии,,,,,, мСоединениеАДО);
|
||
Если РезультатБД.Количество() = 0 Тогда
|
||
ирОбщий.СообщитьЛкс("Трасса СУБД пуста. Вероятно была получена другим экземляром инструмента.");
|
||
Иначе
|
||
мТрассаСУБДXML = РезультатБД[0][0];
|
||
КонецЕсли;
|
||
Исключение
|
||
ирОбщий.СообщитьЛкс(ОписаниеОшибки());
|
||
КонецПопытки;
|
||
ТекстЗапроса = ПолучитьМакет("SQLServer_СкриптОчисткиДанных").ПолучитьТекст();
|
||
ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс(ТекстЗапроса,,,,,, мСоединениеАДО);
|
||
КонецЕсли;
|
||
ЗаписатьМаркерВТехножурнал("КонецТрассы_" + мИдентификаторТрассы,,, КонецПериодаКлиента, КонецПериодаСервера);
|
||
выхТекущаяДатаСервера = КонецПериодаСервера;
|
||
мУдержательСоединенияБД = Неопределено;
|
||
мИдентификаторСоединенияБД = Неопределено;
|
||
Возврат Истина;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ЗагрузитьТрассуСУБД() Экспорт
|
||
|
||
Если Не ЗначениеЗаполнено(мТрассаСУБДXML) Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
ИдентификаторСессии = XMLСтрока(НомерСеансаИнформационнойБазы());
|
||
НомерПоПорядку = 1;
|
||
ЧтениеXML = Новый ЧтениеXML;
|
||
ЧтениеXML.УстановитьСтроку(мТрассаСУБДXML);
|
||
ПостроительDOM = Новый ПостроительDOM;
|
||
ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
|
||
Разыменователь = Новый РазыменовательПространствИменDOM(ДокументDOM);
|
||
РезультатПоискаСобытий = ДокументDOM.ВычислитьВыражениеXPath("/RingBufferTarget/event", ДокументDOM, Разыменователь, ТипРезультатаDOMXPath.Любой);
|
||
МассивОператоров = Новый Массив;
|
||
МассивИДПланов = Новый Массив;
|
||
УзелСобытие = РезультатПоискаСобытий.ПолучитьСледующий();
|
||
НачальныйИндексСтроки = мТаблицаЖурнала.Количество();
|
||
Пока УзелСобытие <> Неопределено Цикл
|
||
ИмяСобытия = СокрЛП(УзелСобытие.Атрибуты.ПолучитьИменованныйЭлемент("name").ТекстовоеСодержимое);
|
||
СвойстваСобытия = Новый Соответствие;
|
||
Для Каждого ЭлементСобытия Из УзелСобытие.ДочерниеУзлы Цикл
|
||
ИмяСвойства = СокрЛП(ЭлементСобытия.Атрибуты.ПолучитьИменованныйЭлемент("name").Значение);
|
||
ЗначениеСвойства = СокрЛП(ЭлементСобытия.ПоследнийДочерний.ТекстовоеСодержимое);
|
||
Если НЕ ЗначениеЗаполнено(ЗначениеСвойства) Тогда
|
||
ЗначениеСвойства = СокрЛП(ЭлементСобытия.ТекстовоеСодержимое);
|
||
КонецЕсли;
|
||
СвойстваСобытия.Вставить(ИмяСвойства, ЗначениеСвойства);
|
||
КонецЦикла;
|
||
ТекстЗапроса = СвойстваСобытия["statement"];
|
||
Если НЕ ЗначениеЗаполнено(ТекстЗапроса) Тогда
|
||
ТекстЗапроса = СвойстваСобытия["batch_text"];
|
||
КонецЕсли;
|
||
Если НЕ ЗначениеЗаполнено(ТекстЗапроса) Тогда
|
||
ТекстЗапроса = СвойстваСобытия["sql_text"];
|
||
КонецЕсли;
|
||
Если Найти(ТекстЗапроса, "CREATE EVENT SESSION") > 0 Тогда
|
||
УзелСобытие = РезультатПоискаСобытий.ПолучитьСледующий();
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Если ИмяСобытия = "rpc_completed" ИЛИ ИмяСобытия = "sql_batch_completed" Тогда
|
||
КонецМилисекунды = "";
|
||
ДатаСобытияСтрока = СокрЛП(УзелСобытие.Атрибуты.ПолучитьИменованныйЭлемент("timestamp").ТекстовоеСодержимое);
|
||
ДатаСобытияСтрока = ирОбщий.ПервыйФрагментЛкс(ДатаСобытияСтрока, "Z");
|
||
ДатаСобытия = МестноеВремя(ПреобразоватьКДате(ДатаСобытияСтрока, КонецМилисекунды));
|
||
ДлительностьМикросекунд = СвойстваСобытия["duration"];
|
||
ДатаНачала = ДатаСобытия - Цел(ДлительностьМикросекунд / 1000000);
|
||
МоментВремени = Формат(ДатаСобытия, "ДФ=ггггММддЧЧммсс") + КонецМилисекунды + Формат(НомерПоПорядку, "ЧЦ=3; ЧВН=");
|
||
НачалоМилисекунды = КонецМилисекунды - Цел(ДлительностьМикросекунд / 1000);
|
||
Если НачалоМилисекунды < 0 Тогда
|
||
ДатаНачала = ДатаНачала - 1;
|
||
НачалоМилисекунды = 1000 + НачалоМилисекунды;
|
||
КонецЕсли;
|
||
МоментВремениНачала = Формат(ДатаНачала, "ДФ=ггггММддЧЧммсс") + НачалоМилисекунды + Формат(НомерПоПорядку, "ЧЦ=3; ЧВН=");
|
||
СтрокаТаблицы = мТаблицаЖурнала.Добавить();
|
||
СтрокаТаблицы.МоментВремени = МоментВремени;
|
||
СтрокаТаблицы.Дата = ДатаСобытия;
|
||
СтрокаТаблицы.ДатаНачала = ДатаНачала;
|
||
СтрокаТаблицы.Длительность = ДлительностьМикросекунд / 1000;
|
||
СтрокаТаблицы.НаСервере = Истина;
|
||
СтрокаТаблицы.ТипПроцессаОС = "sqlservr";
|
||
СтрокаТаблицы.МоментВремениНачала = МоментВремениНачала;
|
||
СтрокаТаблицы.CPUTime = СвойстваСобытия["cpu_time"] / 1000;
|
||
СтрокаТаблицы.ЛогическиПрочитано = СвойстваСобытия["logical_reads"];
|
||
СтрокаТаблицы.ФизическиПрочитано = СвойстваСобытия["physical_reads"];
|
||
СтрокаТаблицы.ЛогическиЗаписано = СвойстваСобытия["writes"];
|
||
//СтрокаТаблицы.ИмяОбъекта = СвойстваСобытия["object_name"];
|
||
//СтрокаТаблицы.Приложение = СвойстваСобытия["client_app_name"];
|
||
//СтрокаТаблицы.ИдентификаторЯдраПроцессора = СвойстваСобытия["cpu_id"];
|
||
//СтрокаТаблицы.Соединение_ = СвойстваСобытия["client_pid"];
|
||
//СтрокаТаблицы.Системный = ПреобразоватьКБулево(СвойстваСобытия["is_system"]);
|
||
СтрокаТаблицы.ЧислоСтрок = СвойстваСобытия["row_count"];
|
||
СтрокаТаблицы.ТекстСУБД = ТекстЗапроса;
|
||
Если МассивОператоров.Количество() = 1 Тогда
|
||
ИдентификаторПланаЗапроса = МассивОператоров.Получить(0).Получить("plan_handle");
|
||
НачалоИдентификатораПланаЗапроса = "<plan handle='0x";
|
||
Если Найти(ИдентификаторПланаЗапроса, НачалоИдентификатораПланаЗапроса) > 0 Тогда
|
||
ДлинаИдентификатораПланаЗапроса = СтрДлина(ИдентификаторПланаЗапроса) - СтрДлина(НачалоИдентификатораПланаЗапроса) - 3;
|
||
ИдентификаторПланаЗапроса = Сред(ИдентификаторПланаЗапроса, СтрДлина(НачалоИдентификатораПланаЗапроса) + 1, ДлинаИдентификатораПланаЗапроса);
|
||
КонецЕсли;
|
||
СтрокаТаблицы.ПланСУБД = "0x" + ВРег(ИдентификаторПланаЗапроса);
|
||
МассивИДПланов.Добавить(СтрокаТаблицы.ПланСУБД);
|
||
КонецЕсли;
|
||
СтрокаТаблицы.Событие = ИмяСобытия;
|
||
СтрокаТаблицы.Дата = ДатаСобытия;
|
||
МассивОператоров.Очистить();
|
||
НомерПоПорядку = НомерПоПорядку + 1;
|
||
Иначе
|
||
МассивОператоров.Добавить(СвойстваСобытия);
|
||
КонецЕсли;
|
||
УзелСобытие = РезультатПоискаСобытий.ПолучитьСледующий();
|
||
КонецЦикла;
|
||
Если МассивИДПланов.Количество() > 0 Тогда
|
||
ТекстЗапроса = ПолучитьМакет("SQLServer_СкриптЧтенияПланаЗапроса").ПолучитьТекст();
|
||
ТекстЗапроса = ирОбщий.СтрЗаменитьЛкс(ТекстЗапроса, "{ИдентификаторПланаЗапроса}", ирОбщий.СтрСоединитьЛкс(МассивИДПланов));
|
||
ТаблицаПлановЗапросов = ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс(ТекстЗапроса,,,,,, мСоединениеАДО);
|
||
Для Индекс = НачальныйИндексСтроки По мТаблицаЖурнала.Количество() - 1 Цикл
|
||
СтрокаРезультата = ТаблицаПлановЗапросов.Найти(мТаблицаЖурнала[Индекс].ПланСУБД, "plan_handle");
|
||
Если СтрокаРезультата <> Неопределено Тогда
|
||
мТаблицаЖурнала[Индекс].ПланСУБД = СтрокаРезультата.query_plan;
|
||
Иначе
|
||
мТаблицаЖурнала[Индекс].ПланСУБД = МаркерПланЗапросаНеНайден();
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
ЗапросУдалениеСессии = ПолучитьМакет("SQLServer_СкриптУдаленияСессииСбораДанных").ПолучитьТекст();
|
||
ЗапросУдалениеСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросУдалениеСессии, "{ИмяСессии}", "getQueriesInfo");
|
||
ЗапросУдалениеСессии = ирОбщий.СтрЗаменитьЛкс(ЗапросУдалениеСессии, "{ИдентификаторСессии}", ИдентификаторСессии);
|
||
ирОбщий.ВыполнитьЗапросКЭтойБазеЧерезADOЛкс(ЗапросУдалениеСессии);
|
||
мНепустыеКолонкиЖурнала.Очистить();
|
||
ОпределитьНепустыеКолонки();
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция МаркерПланЗапросаНеНайден() Экспорт
|
||
|
||
Возврат "<Не найден в кэше СУБД>";
|
||
|
||
КонецФункции
|
||
|
||
Функция ПреобразоватьКБулево(Знач ИсходноеЗначение)
|
||
Если ТипЗнч(ИсходноеЗначение) = Тип("Строка") Тогда
|
||
ИсходноеЗначение = ВРег(ИсходноеЗначение);
|
||
Если ИсходноеЗначение = "TRUE" Тогда
|
||
Возврат Истина;
|
||
Иначе
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
ИначеЕсли ТипЗнч(ИсходноеЗначение) = Тип("Булево") Тогда
|
||
Возврат ИсходноеЗначение;
|
||
ИначеЕсли ТипЗнч(ИсходноеЗначение) = Тип("Число") Тогда
|
||
Возврат (ИсходноеЗначение > 0);
|
||
Иначе
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
КонецФункции
|
||
|
||
Функция ПреобразоватьКДате(Знач ИсходноеЗначение, выхТысячнаяДоляСекунды = "")
|
||
|
||
ДатаСтрока = СтрЗаменить(ИсходноеЗначение, "-", "");
|
||
ДатаСтрока = СтрЗаменить(ДатаСтрока, ":", "");
|
||
ДатаСтрока = СтрЗаменить(ДатаСтрока, "T", "");
|
||
Фрагменты = ирОбщий.СтрРазделитьЛкс(ДатаСтрока);
|
||
выхТысячнаяДоляСекунды = Фрагменты[1];
|
||
ДатаСтрока = Фрагменты[0];
|
||
ДатаЗначение = Неопределено;
|
||
Попытка
|
||
ДатаЗначение = Дата(ДатаСтрока);
|
||
Исключение
|
||
ДатаЗначение = Дата(1,1,1);
|
||
КонецПопытки;
|
||
Возврат ДатаЗначение;
|
||
|
||
КонецФункции
|
||
|
||
Функция ПолучитьТекстSQLДляПоискаВТехножурнале(Текст) Экспорт
|
||
|
||
RegExpМета.Pattern = "([^A-ZА-ЯЁ_0-9]|^)(?:@P\d+)";
|
||
Результат = RegExpМета.Replace(Текст, "$1?");
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
#Если Клиент Тогда
|
||
|
||
Функция ПоказатьТрассу(УдалитьДополнительныеСобытия = Истина, ИменаНеполезныхКолонок = "", ЖдатьСекунд = 2, СмещениеБазовогоУровня = Неопределено, ЗагружатьТолькоТекущийСеанс = Ложь,
|
||
ЗагружатьЖурналКлиента = Истина, ЛиТрассаПоПользователю = Ложь) Экспорт
|
||
|
||
Если ЭтотОбъект.КонецПериодаСервера = Неопределено Тогда
|
||
Предупреждение("Сформируйте трассу заново");
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
ОчиститьТаблицуЖурнала();
|
||
лКаталогЖурнала = КаталогЖурнала;
|
||
мЛиТрассаПоПользователю = ЛиТрассаПоПользователю Или ЗагружатьТолькоТекущийСеанс;
|
||
ФормаАнализа = ПолучитьФорму();
|
||
ФормаАнализа.ЭтоТрасса = Истина;
|
||
ФормаАнализа.Открыть();
|
||
ФормаАнализа.ЗагружатьТолькоТекущийСеанс = ЗагружатьТолькоТекущийСеанс;
|
||
ФормаАнализа.ЗагружатьЖурналКлиента = ЗагружатьЖурналКлиента;
|
||
ФормаАнализа.ЗагружатьЖурналСервера = Не ирКэш.ЛиФайловаяБазаЛкс();
|
||
ВыраниватьДатуПоСерверу = ирОбщий.ВосстановитьЗначениеЛкс("ирАнализТехножурнала.ВыраниватьДатуПоСерверу") = Истина;
|
||
Если ВыраниватьДатуПоСерверу Тогда
|
||
ФормаАнализа.КонецПериода = КонецПериодаСервера;
|
||
ФормаАнализа.НачалоПериода = НачалоПериодаСервера;
|
||
Иначе
|
||
ФормаАнализа.КонецПериода = КонецПериодаКлиента;
|
||
ФормаАнализа.НачалоПериода = НачалоПериодаКлиента;
|
||
КонецЕсли;
|
||
ФормаАнализа.КаталогЖурнала = лКаталогЖурнала;
|
||
ФормаАнализа.ПериодПоследниеМинуты = 0;
|
||
ФормаАнализа.ОбновитьТаблицуЖурнала(УдалитьДополнительныеСобытия, ИменаНеполезныхКолонок, Истина, ЖдатьСекунд, СмещениеБазовогоУровня);
|
||
ФормаАнализа.УстановитьРежимИтогов(ТаблицаЖурнала.Количество() > 30);
|
||
ФормаАнализа.ОбновитьДоступность();
|
||
ФормаАнализа.ЭлементыФормы.ПанельНастройки.ТекущаяСтраница = ФормаАнализа.ЭлементыФормы.ПанельНастройки.Страницы.Анализ;
|
||
ФормаАнализа.УстановитьБесполезныеКолонки(ИменаНеполезныхКолонок);
|
||
мЛиТрассаПоПользователю = Ложь;
|
||
Возврат ФормаАнализа;
|
||
|
||
КонецФункции
|
||
|
||
Функция ОчиститьТаблицуЖурнала() Экспорт
|
||
|
||
мНепустыеКолонкиЖурнала = Новый Структура();
|
||
ТаблицаЖурнала.Очистить();
|
||
мКартыФайлов.Очистить();
|
||
Возврат Неопределено;
|
||
|
||
КонецФункции
|
||
|
||
Функция ОткрытьТекстБДВКонверторе(ТекстБД, СразуПеревестиВМета = Истина, КлючУникальности = Неопределено, ЭтоТекстSDBL = Истина) Экспорт
|
||
|
||
ФормаЗапроса = ПолучитьФорму("КонверторТекстаСУБД", , КлючУникальности);
|
||
ФормаЗапроса.ЭтоТекстSDBL = ЭтоТекстSDBL;
|
||
ФормаЗапроса.ЭлементыФормы.ТекстБД.УстановитьТекст(ТекстБД);
|
||
ФормаЗапроса.ПереводитьВМета = СразуПеревестиВМета;
|
||
ФормаЗапроса.Открыть();
|
||
Возврат Неопределено;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ОткрытьПланЗапросаСУБДЛкс(Знач ПланЗапроса) Экспорт
|
||
|
||
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("sqlplan");
|
||
//СтандартнаяОбработка = Ложь;
|
||
Если ЗначениеЗаполнено(ПланЗапроса) Тогда
|
||
ПланЗапроса = ОтформатироватьТекстXML(ПланЗапроса);
|
||
Ответ = Вопрос("Перевести план запроса в термины метаданных?", РежимДиалогаВопрос.ДаНет,, КодВозвратаДиалога.Да);
|
||
Если Ответ = КодВозвратаДиалога.Да Тогда
|
||
ПланЗапроса = ирКэш.ПолучитьАнализТехножурналаЛкс().ПеревестиТекстБДВТерминыМетаданных(ПланЗапроса,,, "DBMSSQL",, 999999);
|
||
КонецЕсли;
|
||
ТекстовыйДокумент = Новый ТекстовыйДокумент;
|
||
ТекстовыйДокумент.УстановитьТекст(ПланЗапроса);
|
||
ТекстовыйДокумент.Записать(ИмяВременногоФайла);
|
||
ЗапуститьПриложение(ИмяВременногоФайла);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ОтформатироватьТекстXML(ТекстXML) Экспорт
|
||
|
||
Если Не ЗначениеЗаполнено(ТекстXML) Тогда
|
||
Возврат "";
|
||
КонецЕсли;
|
||
Дом = ирОбщий.ПрочитатьТекстВДокументDOMЛкс("<_>" + ТекстXML + "</_>");
|
||
ЗаписьXML = Новый ЗаписьXML;
|
||
ЗаписьДОМ = Новый ЗаписьDOM;
|
||
ОтформатированныйТекст = "";
|
||
Для Каждого ДочернийУзел Из ДОМ.ПервыйДочерний.ДочерниеУзлы Цикл
|
||
ЗаписьXML.УстановитьСтроку();
|
||
ЗаписьДОМ.Записать(ДочернийУзел, ЗаписьXML);
|
||
Если ОтформатированныйТекст <> "" Тогда
|
||
ОтформатированныйТекст = ОтформатированныйТекст + Символы.ПС;
|
||
КонецЕсли;
|
||
ОтформатированныйТекст = ОтформатированныйТекст + ЗаписьXML.Закрыть();
|
||
КонецЦикла;
|
||
Возврат ОтформатированныйТекст;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ОткрытьНастройкуТехножурналаДляРегистрацииВыполненияЗапроса(Знач ТекстБД, ЭтоТекстSDBL = Ложь, ТипСУБД = Неопределено, ИмяБазы = "") Экспорт
|
||
|
||
Если Не ЭтоТекстSDBL Тогда
|
||
ТекстБД = ПолучитьТекстSQLДляПоискаВТехножурнале(ТекстБД);
|
||
КонецЕсли;
|
||
Если СтрДлина(ТекстБД) > 1000 Тогда
|
||
ТекстБД = Лев(ТекстБД , 1000) + "%";
|
||
КонецЕсли;
|
||
ТекстБД = ПолучитьШаблонТекстаБД(ТекстБД, "%");
|
||
ТекстБД = СтрЗаменить(ТекстБД, Символы.ПС, "%");
|
||
ТекстБД = СтрЗаменить(ТекстБД, "%%", "%");
|
||
ФормаНастройки = ирОбщий.ПолучитьФормуЛкс("Обработка.ирНастройкаТехножурнала.Форма");
|
||
ФормаНастройки.Открыть();
|
||
ФормаНастройки.НаСервере = Не ирКэш.Получить().ЭтоФайловаяБаза;
|
||
ФормаНастройки.ПриИзмененииПравилаПолученияФайлаНастройки();
|
||
Ответ = Вопрос("Хотите создать новую настройку?", РежимДиалогаВопрос.ДаНет);
|
||
Если Ответ = КодВозвратаДиалога.Да Тогда
|
||
ФормаНастройки.ЗагрузитьФайлНастройки("ШаблонЗаписьИсключительныхСитуаций", Истина, Истина, Ложь);
|
||
КонецЕсли;
|
||
СтрокаКаталога = ФормаНастройки.ТабличноеПолеЖурналы[0];
|
||
ФормаНастройки.ЭлементыФормы.ТабличноеПолеЖурналы.ТекущаяСтрока = СтрокаКаталога;
|
||
ФормаЖурнала = ФормаНастройки.ОткрытьФормуРедактированияЖурнала();
|
||
Если ЭтоТекстSDBL Тогда
|
||
УстановитьОтборПоСвойствуСобытияВФормеЖурнала(ФормаЖурнала, "SDBL", "sdbl", ТекстБД, , ИмяБазы);
|
||
Иначе
|
||
Если Не ЗначениеЗаполнено(ТипСУБД) Тогда
|
||
ВызватьИсключение "Для текста СУБД необходимо указать тип СУБД";
|
||
КонецЕсли;
|
||
УстановитьОтборПоСвойствуСобытияВФормеЖурнала(ФормаЖурнала, ТипСУБД, "sql", ТекстБД, , ИмяБазы);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Сравнение - Строка - как оно задается в настройке техножурнала (eq, ne, like и т.д.)
|
||
Процедура УстановитьОтборПоСвойствуСобытияВФормеЖурнала(ФормаЖурнала, ИмяСобытия, Знач ИмяСвойства, Знач ШаблонЗапроса, Сравнение = "like", Знач ИмяБазы = "") Экспорт
|
||
|
||
ТабличноеПолеСписокСобытий = ФормаЖурнала.ЭлементыФормы.ТабличноеПолеСписокСобытий;
|
||
ТабличноеПолеСписокСобытий.ВыделенныеСтроки.Очистить();
|
||
СтрокаСобытия = ФормаЖурнала.УстановитьРегистрациюСобытия(ИмяСобытия, Истина);
|
||
ТабличноеПолеСписокСобытий.ТекущаяСтрока = СтрокаСобытия;
|
||
ФормаЖурнала.УстановитьЭлементОтбораВВыделенныхГруппахИ(ИмяСвойства, ШаблонЗапроса, Сравнение);
|
||
Если Истина
|
||
И ЗначениеЗаполнено(ИмяБазы)
|
||
И Не ирКэш.ЛиФайловаяБазаЛкс()
|
||
Тогда
|
||
// К сожалению в файловой СУБД это свойство не заполняется
|
||
//ФормаЖурнала.КП_ДетальныйФильтрСобытийТекущаяБаза();
|
||
ФормаЖурнала.УстановитьЭлементОтбораВВыделенныхГруппахИ("p:processname", ИмяБазы);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
#КонецЕсли
|
||
|
||
Функция ПолучитьВариантПросмотраТекстПоИмениРеквизита(ИмяРеквизита) Экспорт
|
||
|
||
Если Ложь
|
||
Или мСвойстваСИменамиБД.Свойство(ПолучитьИмяСвойстваБезМета(ИмяРеквизита))
|
||
Или ирОбщий.СтрокиРавныЛкс(ИмяРеквизита, "ТекстЗапроса1С")
|
||
Тогда
|
||
ВариантПросмотра = "ЯзыкЗапросов";
|
||
ИначеЕсли ирОбщий.СтрокиРавныЛкс(ИмяРеквизита, "Контекст") <> Неопределено Тогда
|
||
ВариантПросмотра = "ВстроенныйЯзык";
|
||
Иначе
|
||
ВариантПросмотра = "Компактный";
|
||
КонецЕсли;
|
||
Возврат ВариантПросмотра;
|
||
|
||
КонецФункции
|
||
|
||
Функция ПреобразоватьЗначениеВSDBL(Ссылка) Экспорт
|
||
|
||
СтруктураБД = ирКэш.СтруктураХраненияБДЛкс(,, мАдресЧужойСхемыБД);
|
||
Если ТипЗнч(Ссылка) = Тип("Строка") Тогда
|
||
Текст = "";
|
||
Иначе
|
||
СтруктураПоиска = Новый Структура("Метаданные, Назначение", Ссылка.Метаданные().ПолноеИмя(), "Основная");
|
||
СтрокаТаблицы = СтруктураБД.НайтиСтроки(СтруктураПоиска)[0];
|
||
RegExp = ирКэш.Получить().RegExp;
|
||
RegExp.Pattern = "\d+";
|
||
РезультатПоиска = RegExp.НайтиВхождения(СтрокаТаблицы.ИмяТаблицыХранения);
|
||
Текст = РезультатПоиска[0].Value + ":" + ирОбщий.ПолучитьГУИДИнверсныйИзПрямогоЛкс("" + Ссылка.УникальныйИдентификатор());
|
||
КонецЕсли;
|
||
Возврат Текст;
|
||
|
||
КонецФункции
|
||
|
||
Функция СтруктураЗапросаИзТекстаБД(ТекстБД, ТипСУБД = "", ПересобратьТекст = Ложь, ПеревестиИндексы = Истина, ПереводитьВМета = Истина, ЗаменитьHexЛитералы = Ложь,
|
||
ВстраиватьПараметры = Истина) Экспорт
|
||
|
||
Текст = ТекстБД;
|
||
//ТаблицаПараметров = Новый ТаблицаЗначений;
|
||
//ТаблицаПараметров.Колонки.Добавить("ЗначениеSDBL", Новый ОписаниеТипов("Строка"));
|
||
//ТаблицаПараметров.Колонки.Добавить("Значение");
|
||
//ТаблицаПараметров.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
|
||
ТаблицаПараметров = ПараметрыЗапроса.ВыгрузитьКолонки();
|
||
ТаблицаПараметров.Индексы.Добавить("ЗначениеSDBL");
|
||
ТаблицаПараметров.Индексы.Добавить("Имя");
|
||
RegExp = мПлатформа.RegExp;
|
||
RegExp.Global = Истина;
|
||
RegExp.Multiline = Истина;
|
||
Если ЗначениеЗаполнено(ТипСУБД) Тогда
|
||
Если ПереводитьВМета Тогда
|
||
RegExp.Pattern = "TRef\s*=\s*(0x[\da-z]+)"; // замена обращений к типам
|
||
Вхождения = RegExp.НайтиВхождения(Текст);
|
||
ОбработанныеОбращения = Новый Соответствие;
|
||
Для Каждого Вхождение Из Вхождения Цикл
|
||
ЗначениеСУБД = Вхождение.Value;
|
||
Если ОбработанныеОбращения[ЗначениеСУБД] = Неопределено Тогда
|
||
ПолноеИмяМД = ирОбщий.МетаданныеПоНомеруСсылочнойТаблицыЛкс(ирОбщий.СтрокаHEXtoINTЛкс(Вхождение.SubMatches(0)), мАдресЧужойСхемыБД);
|
||
Если ПолноеИмяМД <> Неопределено Тогда
|
||
ЗаменаСтроки = "TRef = " + ПолноеИмяМД;
|
||
ОбработанныеОбращения[ЗначениеСУБД] = ЗаменаСтроки;
|
||
Текст = СтрЗаменить(Текст, ЗначениеСУБД, ЗаменаСтроки);
|
||
Иначе
|
||
ОбработанныеОбращения[ЗначениеСУБД] = 1;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
RegExp.Pattern = "^\s*\(@P\d+\s+\w+(?:\(\d+(?:,\d+)?\))?(,@P\d+\s+\w+(?:\(\d+(?:,\d+)?\))?)*\)"; // для удаления типов параметров MSSQL
|
||
Текст = RegExp.Replace(Текст, "");
|
||
|
||
// sp_executesql
|
||
// {ОписаниеРегулярногоВыражения.Начало} конструктор из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
|
||
// Перем шЗначениеПараметра, шТипПараметра, шКорень;
|
||
// {Шаблон.Начало}
|
||
// + <шЗначениеПараметра> = (N?'([^']*)'|[^',]+)
|
||
// + <шТипПараметра> = @([\w]+) ([^']+?)(?='|$|,@)
|
||
// + <шКорень> = exec sp_executesql N'([^']+)',N'((?:<шТипПараметра>,)*<шТипПараметра>)'((?:,<шЗначениеПараметра>)+)
|
||
// {Шаблон.Конец}
|
||
шЗначениеПараметра = "(N?'([^']*)'|[^',]+)";
|
||
шТипПараметра = "@([\w]+) ([^']+?)(?='|$|,@)";
|
||
шКорень = "exec sp_executesql N'([^']+)',N'((?:" + шТипПараметра + ",)*" + шТипПараметра + ")'((?:," + шЗначениеПараметра + ")+)";
|
||
// {ОписаниеРегулярногоВыражения.Конец}
|
||
Вхождения = ирОбщий.НайтиРегулярноеВыражениеЛкс(Текст, шКорень, "ТекстЗапроса, ТипыПараметров", Ложь,,, Ложь);
|
||
#Если Сервер И Не Сервер Тогда
|
||
Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
|
||
#КонецЕсли
|
||
Для каждого Вхождение Из Вхождения Цикл
|
||
Текст = Вхождение.ТекстЗапроса;
|
||
ВложенныеВхождения = ирОбщий.НайтиРегулярноеВыражениеЛкс(Вхождение.ТипыПараметров, шТипПараметра, "Имя, Тип",,,, Ложь);
|
||
#Если Сервер И Не Сервер Тогда
|
||
Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
|
||
#КонецЕсли
|
||
Для каждого ВложенноеВхождение Из ВложенныеВхождения Цикл
|
||
СтрокаПараметра = ТаблицаПараметров.Добавить();
|
||
СтрокаПараметра.Имя = ВложенноеВхождение.Имя;
|
||
СтрокаПараметра.Метаданные = ВложенноеВхождение.Тип;
|
||
КонецЦикла;
|
||
ВложенныеВхождения = ирОбщий.НайтиРегулярноеВыражениеЛкс(Вхождение.Подгруппы[6], шЗначениеПараметра,,,,, Ложь);
|
||
#Если Сервер И Не Сервер Тогда
|
||
Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
|
||
#КонецЕсли
|
||
ИндексПараметра = 0;
|
||
Для каждого ВложенноеВхождение Из ВложенныеВхождения Цикл
|
||
СтрокаПараметра = ТаблицаПараметров[ИндексПараметра];
|
||
ИндексПараметра = ИндексПараметра + 1;
|
||
СтрокаПараметра.Значение = ВложенноеВхождение.ТекстВхождения;
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
Иначе
|
||
RegExp.Pattern = "([A-F0-9]+):([A-F0-9]+|0x[A-F0-9]+)"; // замена ссылочных констант
|
||
Вхождения = RegExp.НайтиВхождения(Текст);
|
||
Для Каждого Вхождение Из Вхождения Цикл
|
||
ЗначениеSDBL = Вхождение.Value;
|
||
Если СтрДлина(ЗначениеSDBL) < 32 Тогда
|
||
// Защита от частей литерала Дата
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Если ТаблицаПараметров.Найти(ЗначениеSDBL, "ЗначениеSDBL") = Неопределено Тогда
|
||
шЗначениеПараметра = ирОбщий.ПреобразоватьЗначениеИзSDBLЛкс(ЗначениеSDBL, мАдресЧужойСхемыБД);
|
||
СтрокаПараметра = ирОбщий.НайтиДобавитьПараметрСсылкуВТаблицуЛкс(ТаблицаПараметров,,, шЗначениеПараметра);
|
||
СтрокаПараметра.ЗначениеSDBL = ЗначениеSDBL;
|
||
ОбъектМД = ирОбщий.ПолучитьМетаданныеЛкс(шЗначениеПараметра);
|
||
Если ОбъектМД <> Неопределено Тогда
|
||
СтрокаПараметра.Метаданные = ОбъектМД.ПолноеИмя();
|
||
КонецЕсли;
|
||
Если ПереводитьВМета Тогда
|
||
Текст = СтрЗаменить(Текст, ЗначениеSDBL, "&" + СтрокаПараметра.Имя);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
Если ЗаменитьHexЛитералы Тогда
|
||
RegExp.Pattern = "0x[\da-z]+"; // замена значений констант
|
||
Вхождения = RegExp.НайтиВхождения(Текст);
|
||
СоответствиеКонстант = Новый Соответствие;
|
||
Для Каждого Вхождение Из Вхождения Цикл
|
||
ЗначениеСУБД = Вхождение.Value;
|
||
Если СоответствиеКонстант[ЗначениеСУБД] = Неопределено Тогда
|
||
ЗаменаСтроки = "_" + ЗначениеСУБД;
|
||
СоответствиеКонстант[ЗначениеСУБД] = ЗаменаСтроки;
|
||
Текст = СтрЗаменить(Текст, ЗначениеСУБД, ЗаменаСтроки);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
//RegExp.Pattern = "#(T[\d_A-Z]+)"; // имена временных таблиц
|
||
//Текст = RegExp.Replace(Текст, "_$1");
|
||
RegExp.Pattern = "\{ts '(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)'\}"; // литералы Дата DBV8DBEng
|
||
Текст = RegExp.Replace(Текст, "DATETIME($1,$2,$3,$4,$5,$6)");
|
||
ТаблицаТаблиц = Новый ТаблицаЗначений;
|
||
Если ПереводитьВМета Тогда
|
||
RegExp.Pattern = "N'([^']*)'"; // для замены юникодных литералов типа Строка MSSQL
|
||
Текст = RegExp.Replace(Текст, """$1""");
|
||
КонецЕсли;
|
||
ТекстМета = ПеревестиТекстБДВТерминыМетаданных(Текст,,, ТипСУБД, ТаблицаТаблиц, 999999, ПеревестиИндексы, ПереводитьВМета);
|
||
Если Не ПереводитьВМета Тогда
|
||
ТекстМета = Текст;
|
||
КонецЕсли;
|
||
ТаблицаТаблиц.Сортировать("ИмяМета");
|
||
ЧастьПараметров = "";
|
||
Если ЗначениеЗаполнено(ТипСУБД) Тогда
|
||
ДиалектSQL = "MSSQL";
|
||
ПозицияНачалаПараметров = Найти(ТекстМета, "p_0:");
|
||
Если ПозицияНачалаПараметров > 0 Тогда
|
||
ЧастьПараметров = Сред(ТекстМета, ПозицияНачалаПараметров);
|
||
ТекстМета = Лев(ТекстМета, ПозицияНачалаПараметров - 1);
|
||
КонецЕсли;
|
||
Иначе
|
||
ДиалектSQL = "1С";
|
||
КонецЕсли;
|
||
ШаблонИмениПараметра = "Parameter";
|
||
Если ЗначениеЗаполнено(ЧастьПараметров) Тогда
|
||
ТекстовыйДокумент = Новый ТекстовыйДокумент;
|
||
ТекстовыйДокумент.УстановитьТекст(ЧастьПараметров);
|
||
Для Счетчик = 1 По ТекстовыйДокумент.КоличествоСтрок() Цикл
|
||
СтрокаПараметра = ТаблицаПараметров.Добавить();
|
||
Фрагменты = ирОбщий.СтрРазделитьЛкс(ТекстовыйДокумент.ПолучитьСтроку(Счетчик), ":");
|
||
СтрокаПараметра.Имя = СокрЛП(Фрагменты[0]);
|
||
СтрокаПараметра.Значение = СокрЛП(Фрагменты[1]);
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
МаркерСтрокиВРодномMSSQL = "N'";
|
||
МаркерБинариВРодномMSSQL = "0x";
|
||
Для Каждого СтрокаПараметра Из ТаблицаПараметров Цикл
|
||
Если ТипСУБД = "DBMSSQL" Тогда
|
||
ЛитералЗначения = СтрокаПараметра.Значение;
|
||
Если ЗначениеЗаполнено(СтрокаПараметра.Метаданные) Тогда
|
||
// ТипСобытия = sp_executesql
|
||
Если ирОбщий.СтрНачинаетсяСЛкс(ЛитералЗначения, МаркерСтрокиВРодномMSSQL) Тогда
|
||
ЛитералЗначения = ирОбщий.СтрокаБезКонцаЛкс(Сред(ЛитералЗначения, СтрДлина(МаркерСтрокиВРодномMSSQL) + 1), 1);
|
||
СтрокаПараметра.Значение1С = ЛитералЗначения;
|
||
ИначеЕсли ирОбщий.СтрНачинаетсяСЛкс(ЛитералЗначения, "'") Тогда
|
||
ЛитералЗначения = ирОбщий.СтрокаБезКонцаЛкс(Сред(ЛитералЗначения, 2), 1);
|
||
Попытка
|
||
СтрокаПараметра.Значение1С = ирОбщий.СтрокаВДатуЛкс(ЛитералЗначения);
|
||
Исключение
|
||
Пустышка = 0;
|
||
КонецПопытки;
|
||
Иначе
|
||
Попытка
|
||
СтрокаПараметра.Значение1С = Число(ЛитералЗначения);
|
||
Исключение
|
||
КонецПопытки;
|
||
КонецЕсли;
|
||
Иначе
|
||
// ТипСобытия = DBMSSQL
|
||
Если Прав(ЛитералЗначения, 1) = "N" Тогда
|
||
ЛитералЗначения = ирОбщий.СтрокаБезКонцаЛкс(ЛитералЗначения, 1);
|
||
Попытка
|
||
СтрокаПараметра.Значение1С = Число(ЛитералЗначения);
|
||
СтрокаПараметра.Метаданные = Тип("Число");
|
||
Исключение
|
||
Пустышка = 0;
|
||
КонецПопытки;
|
||
ИначеЕсли Лев(ЛитералЗначения, 1) = "'" Тогда
|
||
СтрокаПараметра.Значение1С = Сред(ирОбщий.СтрокаБезКонцаЛкс(ЛитералЗначения, 1), 2);
|
||
СтрокаПараметра.Метаданные = Тип("Строка");
|
||
ИначеЕсли СтрДлина(ЛитералЗначения) = СтрДлина("20010101000000") Тогда
|
||
ЛитералЗначения = "" + (Число(Лев(ЛитералЗначения, 1)) - 2) + Сред(ЛитералЗначения, 2);
|
||
Попытка
|
||
СтрокаПараметра.Значение1С = Дата(ЛитералЗначения);
|
||
СтрокаПараметра.Метаданные = Тип("Дата");
|
||
Исключение
|
||
Пустышка = 0;
|
||
КонецПопытки;
|
||
Иначе
|
||
СтрокаПараметра.Значение1С = ЛитералЗначения;
|
||
СтрокаПараметра.Метаданные = Тип("ДвоичныеДанные");
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
// Встроим имена парамаетров вместо знаков "?"
|
||
ЗаписьXML = Новый ЗаписьXML;
|
||
ЗаписьXML.УстановитьСтроку("");
|
||
ИндексПараметра = 0;
|
||
СтрокаПоиска = "?";
|
||
Пока ТекстМета <> "" Цикл
|
||
ПозицияПараметра = Найти(ТекстМета, СтрокаПоиска);
|
||
Если ПозицияПараметра > 0 Тогда
|
||
Если ИндексПараметра < ТаблицаПараметров.Количество() Тогда
|
||
СтрокаПараметра = ТаблицаПараметров[ИндексПараметра];
|
||
Иначе
|
||
СтрокаПараметра = ТаблицаПараметров.Добавить();
|
||
СтрокаПараметра.Имя = ШаблонИмениПараметра + XMLСтрока(ТаблицаПараметров.Количество());
|
||
КонецЕсли;
|
||
ЗаписьXML.ЗаписатьБезОбработки(Лев(ТекстМета, ПозицияПараметра - 1) + СтрокаПоиска + СтрокаПараметра.Имя);
|
||
ТекстМета = Сред(ТекстМета, ПозицияПараметра + СтрДлина(СтрокаПоиска));
|
||
ИндексПараметра = ИндексПараметра + 1;
|
||
Иначе
|
||
ЗаписьXML.ЗаписатьБезОбработки(ТекстМета);
|
||
ТекстМета = "";
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
ТекстМета = ЗаписьXML.Закрыть();
|
||
|
||
Если Истина
|
||
И ПересобратьТекст
|
||
И ЗначениеЗаполнено(ТекстМета)
|
||
Тогда
|
||
ПолеТекста = ирОбщий.СоздатьОбъектПоПолномуИмениМетаданныхЛкс("Обработка.ирКлсПолеТекстаПрограммы");
|
||
ПолеТекста.ИнициализироватьНеинтерактивно(1);
|
||
КонструкторЗапроса = ПолеТекста.ПолучитьФорму("КонструкторЗапроса");
|
||
КонструкторЗапроса.Английский1С = Не ПереводитьВМета;
|
||
ИменованныеПараметры = Истина;
|
||
Если ПолеТекста.ЗагрузитьТекстВКонструктор(ТекстМета, КонструкторЗапроса,, ДиалектSQL, ИменованныеПараметры) Тогда
|
||
ТекстМета = КонструкторЗапроса.СобратьПолныйТекст(, Истина);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Если ВстраиватьПараметры Тогда
|
||
ЗаписьXML = Новый ЗаписьXML;
|
||
ЗаписьXML.УстановитьСтроку("");
|
||
ИндексПараметра = 0;
|
||
Пока ТекстМета <> "" Цикл
|
||
ПозицияПараметра = 0;
|
||
Если ИндексПараметра < ТаблицаПараметров.Количество() Тогда
|
||
СтрокаПоиска = "?" + ТаблицаПараметров[ИндексПараметра].Имя;
|
||
ПозицияПараметра = Найти(ТекстМета, СтрокаПоиска);
|
||
КонецЕсли;
|
||
Если Истина
|
||
И ПозицияПараметра > 0
|
||
Тогда
|
||
ЗаписьXML.ЗаписатьБезОбработки(Лев(ТекстМета, ПозицияПараметра - 1) + ТаблицаПараметров[ИндексПараметра].Значение);
|
||
ИндексПараметра = ИндексПараметра + 1;
|
||
ТекстМета = Сред(ТекстМета, ПозицияПараметра + СтрДлина(СтрокаПоиска));
|
||
Иначе
|
||
ЗаписьXML.ЗаписатьБезОбработки(ТекстМета);
|
||
ТекстМета = "";
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
ТекстМета = ЗаписьXML.Закрыть();
|
||
КонецЕсли;
|
||
Результат = Новый Структура();
|
||
Результат.Вставить("Текст", ТекстМета);
|
||
Результат.Вставить("Параметры", ТаблицаПараметров);
|
||
Результат.Вставить("Таблицы", ТаблицаТаблиц);
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Функция НайтиВызовыМетодовМодулей(ИмяМодуля, НомерНачальнойСтроки, НомерКонечнойСтроки, ТолькоОдну = Истина)
|
||
|
||
Результат = Новый Массив();
|
||
Для Каждого СтрокаТаблицы Из ТаблицаЖурнала Цикл
|
||
ФрагментыНачальнойСтрокиМодуля = ирОбщий.СтрРазделитьЛкс(СтрокаТаблицы.СтрокаМодуля, ":", Истина);
|
||
Если ФрагментыНачальнойСтрокиМодуля[0] <> ИмяМодуля Тогда
|
||
Результат.Вставить(0, СтрокаТаблицы);
|
||
Если ТолькоОдну Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
НомерСтрокиМодуля = Число(ФрагментыНачальнойСтрокиМодуля[1]);
|
||
Если Ложь
|
||
Или НомерСтрокиМодуля < НомерНачальнойСтроки
|
||
Или НомерСтрокиМодуля > НомерКонечнойСтроки
|
||
Тогда
|
||
Результат.Вставить(0, СтрокаТаблицы);
|
||
Если ТолькоОдну Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
// Получить словарь имен таблиц входящих в запрос и соответствующих
|
||
// шаблонам словаря метаданных
|
||
//
|
||
// Параметры:
|
||
// ТекстЗапроса - Строка, текст запроса для которого строится словарь
|
||
// СловарьШаблоновМетаданных - Соответствие, словарь шаблонов метаданных
|
||
// ТипСУБД - Строка (Перечисление.ТипСУБД)
|
||
//
|
||
// Возвращаемое значение:
|
||
// Соответствие - Словарь имен таблиц запроса
|
||
//
|
||
Функция ИменаМетаданныхЗапросаСУБД(Знач ТекстЗапроса, СловарьШаблоновМетаданных, ТипСУБД = "") Экспорт
|
||
|
||
Результат = Новый ТаблицаЗначений;
|
||
Результат.Колонки.Добавить("Имя");
|
||
Результат.Колонки.Добавить("Длина");
|
||
ТекстЗапроса = НРег(ТекстЗапроса);
|
||
//Если НРег(ТипСУБД) = НРег("DB2") Тогда
|
||
// ТекстЗапроса = ВРег(ТекстЗапроса);
|
||
//КонецЕсли;
|
||
Для Каждого СтрокаСловаряМетаданных Из СловарьШаблоновМетаданных Цикл
|
||
ТаблицаВхождений = ирОбщий.НайтиРегулярноеВыражениеЛкс(ТекстЗапроса, СтрокаСловаряМетаданных.РегулярныйШаблон,,,,,, Истина);
|
||
#Если Сервер И Не Сервер Тогда
|
||
ТаблицаВхождений = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
|
||
#КонецЕсли
|
||
Для Каждого СтрокаВхождения Из ТаблицаВхождений Цикл
|
||
НоваяСтрока = Результат.Добавить();
|
||
НоваяСтрока.Имя = СтрокаВхождения.ТекстВхождения;
|
||
НоваяСтрока.Длина = СтрДлина(НоваяСтрока.Имя);
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
Результат.Сортировать("Длина Убыв");
|
||
Результат.Свернуть("Имя");
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции // ПолучитьСловарьЗапроса()
|
||
|
||
// Получить число из строки в которой число находится в начале строки
|
||
//
|
||
// Праметры:
|
||
// ИсходнаяСтрока - Строка, строка в которой находится число
|
||
//
|
||
// Возвращаемое значение:
|
||
// Число - если оно есть, неопределено, если числа нет
|
||
//
|
||
Функция ПолучитьЧислоСтрокой(ИсходнаяСтрока, КоличествоСимволов)
|
||
|
||
КоличествоСимволов = 0;
|
||
ДлинаСтроки = СтрДлина(ИсходнаяСтрока);
|
||
|
||
Для Сч = 1 По ДлинаСтроки Цикл
|
||
|
||
ТекущийСимвол = КодСимвола(Сред(ИсходнаяСтрока, Сч, 1));
|
||
|
||
Если 48 <= ТекущийСимвол И ТекущийСимвол <= 57 Тогда
|
||
КоличествоСимволов = КоличествоСимволов + 1;
|
||
Иначе
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Если КоличествоСимволов > 0 Тогда
|
||
Возврат Лев(ИсходнаяСтрока, КоличествоСимволов);
|
||
Иначе
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
|
||
КонецФункции // ПолучитьЧислоСтрокой()
|
||
|
||
// Перевести часть запроса из терминов СУБД в термины метаданных
|
||
//
|
||
// Параметры:
|
||
// Запрос - Строка, сапрос в терминах СУБД
|
||
// СтруктураХраненияБазыДанных - ТаблицаЗначений
|
||
// СловарьШаблоновМетаданных - Соответствие, подробности в функции
|
||
// ПолучитьСловарьШаблоновМетаданных()
|
||
// ТипСУБД - Строка, (Перечисление.ТипСУБД)
|
||
// выхТаблицы - ТаблицаЗначений, *Неопределено - описание использованных в тексте таблиц, заполняется только если таблица передана (без колонок)
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка, запрос в терминах метаданных
|
||
//
|
||
Функция ПеревестиТекстБДВТерминыМетаданных(Знач Текст, СтруктураХраненияБазыДанных = Неопределено,
|
||
СловарьШаблоновМетаданных = Неопределено, Знач ТипСУБД = "", выхТаблицы = Неопределено, ДопустимыйРазмер = 20000, ПереводитьИндексы = Истина, ПереводитьВМета = Истина,
|
||
ЭтоГарантированоТекстСобственнойБазы = Ложь) Экспорт
|
||
|
||
Если выхТаблицы <> Неопределено Тогда
|
||
#Если Сервер И Не Сервер Тогда
|
||
выхТаблицы = Новый ТаблицаЗначений;
|
||
#КонецЕсли
|
||
//выхТаблицы.Колонки.Очистить();
|
||
Если выхТаблицы.Колонки.Найти("ИмяБД") = Неопределено Тогда
|
||
выхТаблицы.Колонки.Добавить("ИмяБД", Новый ОписаниеТипов("Строка"));
|
||
КонецЕсли;
|
||
Если выхТаблицы.Колонки.Найти("ИмяМета") = Неопределено Тогда
|
||
выхТаблицы.Колонки.Добавить("ИмяМета", Новый ОписаниеТипов("Строка"));
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Если Ложь
|
||
Или Не ЗначениеЗаполнено(Текст)
|
||
Тогда
|
||
Возврат "";
|
||
КонецЕсли;
|
||
Если Истина
|
||
И ДопустимыйРазмер > 0
|
||
И СтрДлина(Текст) > ДопустимыйРазмер
|
||
И ПереводитьВМета
|
||
Тогда
|
||
Возврат РезультатПереводаСлишкомБольшогоТекста();
|
||
КонецЕсли;
|
||
Если ирОбщий.СтрокиРавныЛкс(ТипСУБД, "sdbl") Тогда
|
||
ТипСУБД = "";
|
||
КонецЕсли;
|
||
АдресЧужойСхемыБД = "";
|
||
Если Не ЭтоГарантированоТекстСобственнойБазы Тогда
|
||
АдресЧужойСхемыБД = мАдресЧужойСхемыБД;
|
||
КонецЕсли;
|
||
Если СтруктураХраненияБазыДанных = Неопределено Тогда
|
||
СтруктураХраненияБазыДанных = ирКэш.СтруктураХраненияБДЛкс(ЗначениеЗаполнено(ТипСУБД),, АдресЧужойСхемыБД);
|
||
КонецЕсли;
|
||
Если СловарьШаблоновМетаданных = Неопределено Тогда
|
||
СловарьШаблоновМетаданных = ирКэш.ПолучитьСловарьШаблоновМетаданныхЛкс(ЗначениеЗаполнено(ТипСУБД), АдресЧужойСхемыБД);
|
||
КонецЕсли;
|
||
Текст = Текст + Символы.ПС;
|
||
ИменаМетаданныхЗапроса = ИменаМетаданныхЗапросаСУБД(Текст, СловарьШаблоновМетаданных, ТипСУБД);
|
||
|
||
Если НРег(ТипСУБД) = НРег("DB2") Тогда
|
||
Текст = ВРег(Текст);
|
||
КонецЕсли;
|
||
|
||
// Поиск имен таблиц в строке запроса
|
||
Если ИменаМетаданныхЗапроса.Количество() > 10 Тогда
|
||
Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ИменаМетаданныхЗапроса.Количество(), "Преобразование в имена метаданных");
|
||
КонецЕсли;
|
||
Для Каждого ИмяМетаданного Из ИменаМетаданныхЗапроса Цикл
|
||
Если Индикатор <> Неопределено Тогда
|
||
ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
|
||
КонецЕсли;
|
||
ОписаниеТаблицы = Неопределено;
|
||
Если выхТаблицы <> Неопределено Тогда
|
||
Если Найти(ИмяМетаданного.Имя, ".") = 0 Тогда
|
||
ОписаниеТаблицы = выхТаблицы.Добавить();
|
||
ОписаниеТаблицы.ИмяБД = ИмяМетаданного.Имя;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
// Получить имя таблицы
|
||
СтрокаСтруктуры = СтруктураХраненияБазыДанных.Найти(ирОбщий.ПоследнийФрагментЛкс(ИмяМетаданного.Имя), "КраткоеИмяТаблицыХранения");
|
||
Если СтрокаСтруктуры = Неопределено Тогда
|
||
// Видимо чужие метаданные
|
||
Продолжить;
|
||
КонецЕсли;
|
||
ИмяТаблицы = СтрокаСтруктуры.КраткоеИмяТаблицыХранения;
|
||
МетаПолноеИмяТаблицы = СтрокаСтруктуры.ИмяТаблицы;
|
||
Если ОписаниеТаблицы <> Неопределено Тогда
|
||
ОписаниеТаблицы.ИмяМета = МетаПолноеИмяТаблицы;
|
||
КонецЕсли;
|
||
Если Не ПереводитьВМета Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Синонимы = ПолучитьСинонимы(Текст, ИмяТаблицы, МетаПолноеИмяТаблицы, ТипСУБД);
|
||
//Синонимы.Вставить(ИмяТаблицы, МетаИмяТаблицы);
|
||
ЭтоТабличнаяЧасть = СтрокаСтруктуры.Назначение = "ТабличнаяЧасть";
|
||
Для Каждого СтрокаПоля Из СтрокаСтруктуры.Поля Цикл
|
||
Если Найти(Текст, СтрокаПоля.ИмяПоляХранения) = 0 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
ПредставлениеПоля = ирОбщий.ПолучитьПредставлениеПоляБДЛкс(СтрокаПоля, ТипСУБД <> "", ЭтоТабличнаяЧасть);
|
||
Если Не ЗначениеЗаполнено(ПредставлениеПоля) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
RegExpМета.Pattern = шГраничныйСимволИмени + СтрокаПоля.ИмяПоляХранения + "([^&" + шБуква + "\d]|Balance|Turnover|Receipt|Expense|^|$)";
|
||
// Можно оптимизировать путем создания шаблона мультизамены
|
||
Текст = RegExpМета.Replace(Текст, "$1" + ПредставлениеПоля + "$2");
|
||
КонецЦикла;
|
||
Если ПереводитьИндексы Тогда
|
||
Для Каждого СтрокаИндекса Из СтрокаСтруктуры.Индексы Цикл
|
||
ПредставлениеИндекса = СтрокаИндекса.ИмяИндекса;
|
||
СтрокаДляЗамены = СтрокаИндекса.ИмяИндексаХранения;
|
||
Если ирОбщий.СтрокиРавныЛкс(ТипСУБД, "DBPOSTGRS") Тогда
|
||
СтрокаДляЗамены = ВРег(СтрокаИндекса.ИмяИндексаХранения);
|
||
ИначеЕсли ирОбщий.СтрокиРавныЛкс(ТипСУБД, "DBV8DBEng") Тогда
|
||
СтрокаДляЗамены = ВРег(СтрокаИндекса.ИмяИндексаХранения);
|
||
КонецЕсли;
|
||
// Имена индексов достаточно уникальны, чтобы использовать СтрЗаменить
|
||
Текст = СтрЗаменить(Текст, СтрокаДляЗамены, ПредставлениеИндекса);
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
Для Каждого Синоним Из Синонимы Цикл
|
||
// Заменить псевдоним таблицы
|
||
RegExpМета.Pattern = шГраничныйСимволИмени + Синоним.Ключ + шГраничныйСимволИмени;
|
||
Текст = RegExpМета.Replace(Текст, "$1" + Синоним.Значение + "$2");
|
||
//RegExpМета.Pattern = ИмяТаблицы + " " + Синоним.Ключ + шГраничныйСимволИмени;
|
||
//Запрос = RegExpМета.Replace(Текст, ИмяТаблицы + " AS " + Синоним.Значение + "$1");
|
||
КонецЦикла;
|
||
// Заменить имя таблицы
|
||
RegExpМета.Pattern = шГраничныйСимволИмени + СтрокаСтруктуры.ИмяТаблицыХранения + шГраничныйСимволИмени;
|
||
Текст = RegExpМета.Replace(Текст, "$1" + МетаПолноеИмяТаблицы + "$2");
|
||
Если НРег(СтрокаСтруктуры.ИмяТаблицыХранения) <> СтрокаСтруктуры.КраткоеИмяТаблицыХранения Тогда
|
||
RegExpМета.Pattern = шГраничныйСимволИмени + СтрокаСтруктуры.КраткоеИмяТаблицыХранения + шГраничныйСимволИмени;
|
||
Текст = RegExpМета.Replace(Текст, "$1" + ирОбщий.ПоследнийФрагментЛкс(МетаПолноеИмяТаблицы) + "$2");
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
Если Индикатор <> Неопределено Тогда
|
||
ирОбщий.ОсвободитьИндикаторПроцессаЛкс(Индикатор);
|
||
КонецЕсли;
|
||
// Заменим приведение к ссылочному типу
|
||
Если Не ЗначениеЗаполнено(ТипСУБД) Тогда
|
||
Текст = СтрЗаменить(Текст, "AS REF(", "AS (");
|
||
КонецЕсли;
|
||
Текст = СокрП(Текст);
|
||
Возврат Текст;
|
||
|
||
КонецФункции
|
||
|
||
Функция РезультатПереводаСлишкомБольшогоТекста() Экспорт
|
||
|
||
Возврат "<Текст слишком большой для быстрого перевода>"
|
||
|
||
КонецФункции
|
||
|
||
// Получить синонимы имени таблицы в запросе
|
||
//
|
||
// Параметры:
|
||
// Запрос - Строка, текст запроса
|
||
// ИмяТаблицы - Строка, имя таблицы для которой ищутся синонимы
|
||
// МетаИмяТаблицы - Строка, имя таблицы в терминах метаданных
|
||
//
|
||
// Возвращаемое занчение:
|
||
// Соответствие, имена синонимов и их мета имена
|
||
//
|
||
Функция ПолучитьСинонимы(Запрос, ИмяТаблицы, МетаИмяТаблицы, ТипСУБД = "") Экспорт
|
||
|
||
// Построить список синонимом ими таблицы
|
||
Синонимы = Новый Соответствие;
|
||
RegExpМета.Pattern = ИмяТаблицы + " " + "(?:([" + шБуква + "\d]+)|\(([" + шБуква + "\d]+)\))" + шГраничныйСимволИмени;
|
||
Вхождения = RegExpМета.НайтиВхождения(Запрос);
|
||
ПсевдонимТаблицы = ирОбщий.ПоследнийФрагментЛкс(МетаИмяТаблицы, ".");
|
||
Для Каждого Вхождение Из Вхождения Цикл
|
||
Синоним = Вхождение.SubMatches(0);
|
||
Если Синоним = Неопределено Тогда
|
||
Синоним = Вхождение.SubMatches(1);
|
||
КонецЕсли;
|
||
Если Ложь
|
||
Или (Истина
|
||
И ирОбщий.СтрокиРавныЛкс(ТипСУБД, "DBMSSQL")
|
||
И ирОбщий.СтрокиРавныЛкс(Синоним, "WITH"))
|
||
Или ирОбщий.СтрокиРавныЛкс(Синоним, "WHERE")
|
||
Или ирОбщий.СтрокиРавныЛкс(Синоним, "GROUP")
|
||
Или ирОбщий.СтрокиРавныЛкс(Синоним, "HAVING")
|
||
Или ирОбщий.СтрокиРавныЛкс(Синоним, "SET")
|
||
Или ирОбщий.СтрокиРавныЛкс(Синоним, "ORDER")
|
||
Или ирОбщий.СтрокиРавныЛкс(Синоним, "THEN")
|
||
Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Синонимы.Вставить(Синоним, ПсевдонимТаблицы + "_" + Синоним);
|
||
КонецЦикла;
|
||
|
||
Возврат Синонимы;
|
||
|
||
КонецФункции // ПолучитьСинонимы()
|
||
|
||
//ирПортативный лФайл = Новый Файл(ИспользуемоеИмяФайла);
|
||
//ирПортативный ПолноеИмяФайлаБазовогоМодуля = Лев(лФайл.Путь, СтрДлина(лФайл.Путь) - СтрДлина("Модули\")) + "ирПортативный.epf";
|
||
//ирПортативный #Если Клиент Тогда
|
||
//ирПортативный Контейнер = Новый Структура();
|
||
//ирПортативный Оповестить("ирПолучитьБазовуюФорму", Контейнер);
|
||
//ирПортативный Если Не Контейнер.Свойство("ирПортативный", ирПортативный) Тогда
|
||
//ирПортативный ирПортативный = ВнешниеОбработки.ПолучитьФорму(ПолноеИмяФайлаБазовогоМодуля);
|
||
//ирПортативный ирПортативный.Открыть();
|
||
//ирПортативный КонецЕсли;
|
||
//ирПортативный #Иначе
|
||
//ирПортативный ирПортативный = ВнешниеОбработки.Создать(ПолноеИмяФайлаБазовогоМодуля, Ложь); // Это будет второй экземпляр объекта
|
||
//ирПортативный #КонецЕсли
|
||
//ирПортативный ирОбщий = ирПортативный.ПолучитьОбщийМодульЛкс("ирОбщий");
|
||
//ирПортативный ирКэш = ирПортативный.ПолучитьОбщийМодульЛкс("ирКэш");
|
||
//ирПортативный ирСервер = ирПортативный.ПолучитьОбщийМодульЛкс("ирСервер");
|
||
//ирПортативный ирПривилегированный = ирПортативный.ПолучитьОбщийМодульЛкс("ирПривилегированный");
|
||
|
||
мПлатформа = ирКэш.Получить();
|
||
ЭтотОбъект.КоличествоПотоков = 8;
|
||
мНепустыеКолонкиЖурнала = Новый Структура();
|
||
//ЭтотОбъект.НаложениеПриДозагрузкеСекунд = 30;
|
||
RegExpПараметры = ирОбщий.НовыйВычислительРегВыражений();
|
||
Если RegExpПараметры <> Неопределено Тогда
|
||
RegExpПараметры.IgnoreCase = Истина;
|
||
RegExpПараметры.Global = Истина;
|
||
RegExpПараметры.Pattern = "([^A-ZА-ЯЁ_0-9]|^)(?:[A-F0-9]+:[A-F0-9]+|0x[A-F0-9]+|[A-F0-9]+(?:-[A-F0-9]+)+-[A-F0-9]+|(#TT?)[_A-F0-9]+|[0-9]+)"; // для стирания констант и имен временных таблиц
|
||
RegExpМета = ирОбщий.НовыйВычислительРегВыражений();
|
||
RegExpМета.IgnoreCase = Истина;
|
||
RegExpМета.Global = Истина;
|
||
КонецЕсли;
|
||
|
||
мСписокКолонок = Новый СписокЗначений;
|
||
//мСписокКолонок.Добавить("Name", "Событие"); // В некоторых случаях нужно
|
||
мСписокКолонок.Добавить("SrcName", "Источник");
|
||
мСписокКолонок.Добавить("OSThread", "ПотокОС");
|
||
мСписокКолонок.Добавить("process", "ТипПроцессаОС");
|
||
мСписокКолонок.Добавить("p:processName", "Инфобаза");
|
||
мСписокКолонок.Добавить("t:clientID", "Соединение_");
|
||
мСписокКолонок.Добавить("t:applicationName", "Приложение");
|
||
мСписокКолонок.Добавить("t:computerName", "Компьютер");
|
||
мСписокКолонок.Добавить("t:connectID", "TCPСоединение");
|
||
мСписокКолонок.Добавить("SessionID", "Сеанс");
|
||
мСписокКолонок.Добавить("Usr", "Пользователь");
|
||
мСписокКолонок.Добавить("OSException", "ИсключениеОС");
|
||
мСписокКолонок.Добавить("Interface", "Интерфейс");
|
||
мСписокКолонок.Добавить("Method", "Метод");
|
||
мСписокКолонок.Добавить("Exception", "ТипИсключения");
|
||
мСписокКолонок.Добавить("Descr", "Описание");
|
||
мСписокКолонок.Добавить("ClientComputerName", "КомпьютерКлиента");
|
||
мСписокКолонок.Добавить("ServerComputerName", "КомпьютерСервера");
|
||
мСписокКолонок.Добавить("UserName", "Пользователь");
|
||
мСписокКолонок.Добавить("ConnectString", "СтрокаСоединения");
|
||
мСписокКолонок.Добавить("ProcessName", "ТипПроцессаОС");
|
||
мСписокКолонок.Добавить("SrcProcessName", "Инфобаза");
|
||
//мСписокКолонок.Добавить("Trans", "Транзакция");
|
||
мСписокКолонок.Добавить("Func", "Действие");
|
||
мСписокКолонок.Добавить("Sdbl", "ТекстSDBL");
|
||
мСписокКолонок.Добавить("dbpid", "ПроцессСУБД");
|
||
мСписокКолонок.Добавить("Sql", "ТекстСУБД");
|
||
мСписокКолонок.Добавить("NParams", "КоличествоПараметров");
|
||
мСписокКолонок.Добавить("Rows", "ЧислоСтрок");
|
||
мСписокКолонок.Добавить("RowsAffected", "ЧислоИзменныхСтрок");
|
||
мСписокКолонок.Добавить("planSQLText", "ПланСУБД");
|
||
мСписокКолонок.Добавить("Context", "Контекст");
|
||
мСписокКолонок.Добавить("CatName", "КаталогСУБД");
|
||
мСписокКолонок.Добавить("WaitConnections", "Блокираторы");
|
||
мСписокКолонок.Добавить("FileName", "ФайлСУБД");
|
||
мСписокКолонок.Добавить("DeadlockConnectionIntersections", "Взаимоблокировка");
|
||
мСписокКолонок.Добавить("Finish", "ПричинаЗавершения");
|
||
мСписокКолонок.Добавить("Err", "ТипСообщения");
|
||
мСписокКолонок.Добавить("Txt", "ТекстСообщения");
|
||
мСписокКолонок.Добавить("URI", "Ресурс");
|
||
мСписокКолонок.Добавить("Administrator", "Администратор");
|
||
мСписокКолонок.Добавить("Body", "РазмерЗапроса");
|
||
мСписокКолонок.Добавить("Cluster", "НомерПорта");
|
||
мСписокКолонок.Добавить("Val", "ЗначениеПараметра");
|
||
|
||
// Свойства найденные экспериментально. Они не документированы.
|
||
мСписокКолонок.Добавить("Query", "ТекстЗапроса1С"); // События: QERR
|
||
мСписокКолонок.Добавить("From", "From_"); // События: DBV8DBENG
|
||
//мСписокКолонок.Добавить("AppID", "AppID"); // События: QERR, DBMSSQL (дублируется t:applicationName), SDBL (дублирует t:applicationName)
|
||
мСписокКолонок.Добавить("Index", "Index_");
|
||
//мСписокКолонок.Добавить("setUnhandledExceptionFilter", "setUnhandledExceptionFilter");
|
||
мСписокКолонок.Добавить("Module", "МодульКонфигурации"); // События: EXCPCNTX
|
||
мСписокКолонок.Добавить("ClientID", "Клиент"); // События: EXCPCNTX, SCALL, EXCP (дублируется t:clientID ?)
|
||
|
||
мТаблицаКолонок = Новый ТаблицаЗначений;
|
||
мТаблицаКолонок.Колонки.Добавить("ВнутреннееИмя", Новый ОписаниеТипов("Строка"));
|
||
мТаблицаКолонок.Колонки.Добавить("ИмяВТаблице", Новый ОписаниеТипов("Строка"));
|
||
мТаблицаКолонок.Индексы.Добавить("ВнутреннееИмя");
|
||
мТаблицаКолонок.Индексы.Добавить("ИмяВТаблице");
|
||
//мЧисловыеСвойства = Новый Структура;
|
||
мСоответствиеКолонок = Новый Соответствие;
|
||
МетаРеквизиты = Метаданные().ТабличныеЧасти.ТаблицаЖурнала.Реквизиты;
|
||
Для Каждого ЭлементСписка Из мСписокКолонок Цикл
|
||
мСоответствиеКолонок.Вставить(НРег(ЭлементСписка.Значение), ЭлементСписка.Представление);
|
||
СтрокаСоответствия = мТаблицаКолонок.Добавить();
|
||
СтрокаСоответствия.ВнутреннееИмя = ЭлементСписка.Значение;
|
||
СтрокаСоответствия.ИмяВТаблице = ЭлементСписка.Представление;
|
||
//Если МетаРеквизиты[ЭлементСписка.Представление].Тип.СодержитТип(Тип("Число")) Тогда
|
||
// мЧисловыеСвойства.Вставить(ЭлементСписка.Представление);
|
||
//КонецЕсли;
|
||
КонецЦикла;
|
||
Для Каждого МетаРеквизит Из МетаРеквизиты Цикл
|
||
Если мСоответствиеКолонок[МетаРеквизит.Имя] = Неопределено Тогда
|
||
мСоответствиеКолонок.Вставить(НРег(МетаРеквизит.Имя), МетаРеквизит.Имя);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
мКартыФайлов = Новый ТаблицаЗначений;
|
||
мКартыФайлов.Колонки.Добавить("ИмяКаталогаПроцесса", Новый ОписаниеТипов("Строка"));
|
||
мКартыФайлов.Колонки.Добавить("ИмяТекущегоФайла", Новый ОписаниеТипов("Строка"));
|
||
мКартыФайлов.Колонки.Добавить("СигнатураТекущегоФайла", Новый ОписаниеТипов("Строка"));
|
||
мКартыФайлов.Колонки.Добавить("ОтборПоСеансу");
|
||
мКартыФайлов.Колонки.Добавить("ПозицияНачала", Новый ОписаниеТипов("Число"));
|
||
мКартыФайлов.Колонки.Добавить("ПозицияКонца", Новый ОписаниеТипов("Число"));
|
||
мКартыФайлов.Колонки.Добавить("НачалоПериода", Новый ОписаниеТипов("Дата"));
|
||
мКартыФайлов.Колонки.Добавить("КонецПериода", Новый ОписаниеТипов("Дата"));
|
||
мКартыФайлов.Колонки.Добавить("ДатаИзмененияФайла", Новый ОписаниеТипов("Дата"));
|
||
мКартыФайлов.Индексы.Добавить("ИмяКаталогаПроцесса, ИмяТекущегоФайла, СигнатураТекущегоФайла, ОтборПоСеансу");
|
||
|
||
мСвойстваСИменамиБД = Новый Структура();
|
||
мСвойстваСИменамиБД.Вставить("ТекстSDBL", Ложь);
|
||
мСвойстваСИменамиБД.Вставить("ТекстSDBLШаблон", Ложь);
|
||
мСвойстваСИменамиБД.Вставить("ТекстСУБД", Истина);
|
||
мСвойстваСИменамиБД.Вставить("ТекстСУБДШаблон", Ложь);
|
||
мСвойстваСИменамиБД.Вставить("ПланСУБД", Истина);
|
||
мСвойстваСИменамиБД.Вставить("Взаимоблокировка", Ложь);
|
||
мСвойстваСИменамиБД.Вставить("Regions", Ложь);
|
||
мСвойстваСИменамиБД.Вставить("Locks", Ложь);
|
||
|
||
мСерверныеТипыПроцессов = Новый Структура;
|
||
мСерверныеТипыПроцессов.Вставить("_adminprocess"); // ##AdminProcess##
|
||
мСерверныеТипыПроцессов.Вставить("_rphost");
|
||
мСерверныеТипыПроцессов.Вставить("_rmngr");
|
||
мСерверныеТипыПроцессов.Вставить("_ragent");
|
||
|
||
мЛиТрассаПоПользователю = Ложь;
|
||
МаксТысячСобытий = 100;
|
||
мАдресЧужойСхемыБД = "";
|
||
шБуква = мПлатформа.шБуква;
|
||
шГраничныйСимволИмени = "([^&" + шБуква + "\d]|^|$)";
|
||
мИменаВозвращаемыхСвойств = "мКартыФайлов, мНепустыеКолонкиЖурнала, мТипСУБД";
|
||
мТаблицаЖурнала = ТаблицаЖурнала;
|
||
#Если Не Клиент Тогда
|
||
мТаблицаЖурнала = мТаблицаЖурнала.ВыгрузитьКолонки();
|
||
#КонецЕсли
|