RDT1C/DataProcessors/ирАнализТехножурнала/Ext/ObjectModule.bsl
Администратор ebf21867b6 Редактор пользователей
+В списке добавлена группа колонок свойств настроек управляемого приложения
        +Добавлена кнопка "Установить..." для установки настроек управляемого приложения выделенным пользователям
        +В форме запуска под пользователем добавлен флажок "Режим интерфейса "Такси""
        +Запуск под пользователем с флагом "Разрешить отладку" теперь сразу подключает текущий отладчик к запускаемому сеансу
    Общее
        +Команда "Запустить обычное приложение" теперь в обоих типах управляемого приложения открывает одинаковую форму, в которой добавлен включенный по умолчанию флажок "Текущий пользователь"
        +Команда "Запустить связанный тонкий клиент" теперь передает имя текущего пользователя в строке соединения
        +При включенной параметром запуска /EnableCheckModal проверке модальности теперь при первом в сеансе открытии любой формы подсистемы предлагается запуск нового сеанса без проверки модальности
    Интерфейсная панель.
        +В контекстном меню добавлена команда "Связанный динамический список", открывающая единое окно динамического списка, обновляющее список при активизации строки
    Динамический список
        +Добавлена кнопка "Связанный редактор объекта БД", открывающая прикрепленное окно редактора объекта БД, загружающее объект при активизации строки
        +Реализовано автоматическое обновление отображаемых строк при записи объекта в редакторе объекта БД
        *Реализован обход ошибки платформы установки табличному полю типа списка независимого непериодического регистра сведений без измерений
    Редактор объекта БД
        *Увеличена длина дробной части значений отбора набора записей
    Контекстная подсказка
        *Исправлена ошибка инициализации формы списка слов при отсутствии activex компоненты Forms20
    Консоль запросов
        *Кнопка "Найти в дереве запроса" теперь доступна только в режиме просмотра узла дерева запроса
        *При сохранении узла дерева запроса, текущий узел теперь ищется не по именам, а по индексам узлов
        *Исправлено зависание программы при копировании папки дерева запросов
        *Исправлено некорректное определение имени узла дерева запроса в некоторых случаях при наличии функции ЗНАЧЕНИЕ(...)
        *При выборе основного элемента результата пакетного запроса теперь игнорируются результаты уничтожения таблиц
    Редактор табличного документа
        +Добавлена кнопка "Сохранить"

3.70
    Консоль компоновки данных
        +В настройках компоновки в таблице условного оформления добавлен пример оформления текста в колонке "Пример"
    Консоль кода
        +Добавлено дерево алгоритмов
        +Изменен формат файлов на t1c, старый формат f1c доступен только для открытия файлов
        *После сохранения в файл теперь сбрасывается модифицированность формы
        +Добавлена кнопка объединения с файлом
        +Добавлено подменю последних открытых файлов
        +Для булевых параметров реализовано отображение флажка
    Консоль запросов
        +При генерации текста модуля пакетного запроса теперь добавляется установка переменных вида "Индекс_<ИмяЗапроса>=<Индекс>" для всех именованных запросов
        +Команде "Найти в дереве" назначено сочетание клавиш CTRL+T
        +Для булевых параметров реализовано отображение флажка
        *Исправлено некорректное отображение количества строк в дереве результата при наличии выборок итогов
    Общее
        *Исправлены ошибки работы подсистемы при наличии общего модуля с именем ОбменДанными
        *Кнопка "Установить одинаковую ширину для всех колонок" заменена на "Расширить все колонки на 5 символов"
    Синтакс-помощник
        *Исправлено построение дерева, сломавшееся несколько версий назад
    Управление службами серверов 1С
        *Исправлена ошибка чтения служб при наличии службы сервера 1С без ключа "range" в строке запуска
    Редактор объекта БД
        +Для наборов записей добавлена фиксированная колонка картинки вида движения регистра накопления
        +По умолчанию для списка движений теперь включен отбор "Только не пустые"
        +Кнопка открытия редактора для таблицы движений теперь передает текущую строку
    Подбор и обработка объектов
        +Реализована поддержка журналов документов в однотабличном режиме
    Динамический список
        +В режиме выбора в заголовке теперь добавляется "(выбор)"
    Интерфейсная панель
        +Теперь уважает настройку использования "Динамический список / Основная форма списка"

3.69
    Общее
        +Вместо форм выбора теперь по умолчанию всегда открывается динамический список
        -Кнопка "Редактировать список" для значения отбор компоновки везде удалена, теперь редактирование списка всегда выполняется в расширенном режиме
    Динамический список
        +Добавлен флажок "Вместо основной" сохраняемый в настройках пользователя в разрезе объектов метаданных, управляющий подменой форм выбора
    Консоль компоновки
        *Исправлена ошибка команды "переставить с родителем" для группировок колонок и строк таблиц
    Контекстная подсказка
        *Кнопка "Удалить переносы" теперь еще заменяет двойные кавычки обычными
    Конструктор запросов
        +Для списка доступных таблиц добавлена закладка-отбор "Параметр"
        +При добавлении таблицы-параметра в выбранные таблицы сразу устанавливать тип запроса и имя временной таблицы
    Консоль запросов
        *Исправлена вычисление группировок итогов с закомментированным словом ОБЩИЕ
        +Кнопки выполнения запроса разделены на "Выполнить отображаемый запрос (F7)" и "Выполнить полный запрос (F8)"
    Редактор объекта БД
        *Исправлена ошибка поиска значения в бизнес процессе

3.68
    Редактор констант
        +Добавлена частичная поддержка констант с типом значения "Хранилище значения"
    Динамический список
        +Добавлена кнопка открытия основной формы списка с передачей отбора, текущей строки и владельца формы
        *Исправлена свежая ошибки открытия журнала документов
    Менеджер табличного поля
        *Исправлено ограничение типа значений элементов отбора
    Редактор объекта БД
        +В элементах управления колонок набора записей и движений реализован учет многострочного режима и других свойств из метаданных
        *Исправлена свежая поломка привязок на вкладке "Связанные колонки"
    Управление службами 1с
        *Исправлено перезаполнение списка при изменении компьютера
    Консоль запросов
        +Реализовано сохранение и восстановление позиции в тексте запроса при переходе между запросами и переключении режима дерева запроса
        +Для поля текста запроса добавлена команда "найти в дереве запроса" (текущую позицию в тексте запроса)
    Поиск дублей и замена ссылок
        *Исправлена свежая ошибка выполнения замены в иерархическом справочнике без флажка "Изменять поля по связям параметров выбора"
    Расширенный ввод значений
        +Добавлено распознавание навигационных ссылок
    Общее
        +Кнопка запуска связанного тонкого клиента теперь при повторном нажатии позволяет открыть в редакторе объекта БД один из открытых в связанном сеансе объектов
    Контекстная подсказка
        +Включена поддержка 8.3.8 в низкоуровневом получении описаний объектов

3.67
    Управление службами серверов 1С
        *Устранена ошибка открытия при наличии в строке соединения порта
        *Исправлено открытие при ошибках подключения WMI
    Консоль компоновки
        *Исправлена ошибка расшифровки при наличии пользовательских настроек компоновки
        +В панели настроек добавлена закладка "Пользовательские настройки" только для просмотра
        +В подменю "Исследовать" добавлена команда "Пользовательские настройки"
        +При сохранении варианта настроек добавлен пункт "<Новый>"
        +Реализовано перетаскивание полей на строки-коллекции в структуре
    Консоль запросов
        *Исправлена некорректная работа команды "найти результат" дерева запроса
        *Исправлена некорректная работа команды "Встроить из подзапроса" дерева запроса
    Конструктор запросов
        *Исправлено обновление представления условия связи при перетаскивании элементов отбора между связями
    Подбор и обработка объектов
        *Исправлены свежие ошибки при обработке подчиненных регистров сведений
    Редактор объекта БД
        *Исправлена недоступность для изменения основной формы измененного объекта
        +Добавлена кнопка "Отрыть основную форму объекта по ссылке"
        +При двойном клике по имени регистра в списке движений открывается его форма списка с отбором по регистратору
        *Исправлен сломанный несколько версий назад расширенный ввод значений в поле Ссылка
    Общее
        +В панели инструментов добавлена кнопка "Запустить связанный тонкий клиент"
    Интерфейсная панель
        +Реализовано явное отображение пустых ссылок в дереве
    Динамический список
        +Добавлена команда "Редактор объекта БД ячейки"
    Поиск дублей и замена ссылок
        +При выполнении замены реализовано предотвращение зацикливания уровней путем поднятия до ближайшего корректного родителя
    Настройка техножурнала
        *Реализован обход проблемы платформы со смещением времени изменения файла на 1ч

3.66
    +Добавлен инструмент "Управление службами серверов 1С"
    Поиск дублей и замена ссылок
        *Исправлена ошибка вывода сообщения об ошибке при отказе в записи независимых регистров сведений
        *Исправлено неверное замещение неуникальных записей в подчиненных регистрах сведений
    Подбор и обработка объектов
        *Исправлены ошибки при работе с подчиненными регистрами сведений
    Общее
        *Исправлено восстановление пароля в форме подключения СУБД
        *Исправлено свежее незапланированное изменение в поведении кнопки "Редактор объекта БД"
    Консоль компоновки данных
        *Кнопка "Исполняемый запрос" теперь открывает консоль запросов немодально
    Различные значения колонки
        +Добавлена кнопка "В список"
        *Исправлено некорректное вычисление типов значений
    Редактор объекта БД
        +Реализована поддержка флагов "Многострочный режим" и "Расширенное редактирование" колонок табличных частей и наборов записей
2016-12-04 00:22:14 +03:00

2022 lines
134 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

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

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