Моё почтение, господа.
На досуге решил сочинить свою личную консоль запросов — обработку общего назначения с основными возможностями.
Работа над обработкой была начата летом 2021 г. после прочтения книги "Язык запросов 1С" — поначалу в учебных целях. Впоследствии консоль стала основным рабочим инструментом при работе с запросами: отлаживаю в ней запросы проведения / отражения в учёте в конфигурациях ERP/УХ.
При разработке акцент был сделан в первую очередь на эргономичность. Поэтому не было цели утяжелять обработку решениями, могущими повлиять на её отзывчивость. Связанным требованием стало использование штатных возможностей платформы в своей естественной среде обитания.
Параллельно с этим была поставлена задача по изучению объектной модели запроса и реализации собственного экспериментального конструктора запроса, который вошёл в состав консоли в очередном релизе. Режима компоновки данных в нём нет. Если консоль запросов периодически обновляется, то релиз конструктора — один, и работа над ним заняла очень много времени. Определение "экспериментальный" использую намеренно.
Эти и прочие (связанные общей темой) разработки вошли в состав одного расширения. Всё написано с нуля.
Все обработки могут быть выгружены в файл и использоваться как внешние.
Текущий состав:
— Обработка Консоль запросов
— Обработка Навигатор
— Обработка Структура хранения базы данных
— Обработка Движения документа
— Документ Корректировка регистров
— Обработка Хранилище настроек
Обработка Консоль запросов
Слева расположено дерево запросов, справа — текущий запрос.
Чтобы не нагружать форму, выбор текущего запроса (выделяется отдельным цветом) осуществляется через DoubleClick.
Параметры запроса заполняются автоматически (по кнопке Заполнить).
Колонки таблицы значений, созданной из описания временной таблицы создаются автоматически, но тип значения колонок указывается самостоятельно.
Значение параметра запроса можно преобразовать в список значений.
Значение типа Дата можно преобразовать в Границу (от даты / момента времени).
Значение можно установить программно через выражение / инструкцию.
Некоторые типы значений параметров запроса преобразуются при передаче между формой и запросом (туда и обратно).
Так, тип МоментВремени в форме это ссылка на документ, тип Тип это ОписаниеТипов. При передаче в запрос ссылка на документ преобразуется в МоментВремени, ОписаниеТипов в Тип. При перехвате запроса выполняется обратное преобразование.
В таблице формы "Врем. таблицы" есть колонка "Используемая ВТ". Здесь можно выбрать "предопределённую" временную таблицу. Чтобы добавить выбор предопределённой временной таблицы, нужно доработать модуль обработки.
Сейчас добавлена 1 таблица ВидыСубконто (видоизменённая функция из типовой конфигурации). Эта временная таблица формируется при отражении документа в регламентированном учёте в типовых конфигурациях. Добавление этой таблицы было связано с тем, что она не может быть помещена из таблицы значений, так как содержит тип колонки Тип.
В текущей версии обработки возможность помещения из таблиц значений с колонками типа значения Тип и МоментВремени реализована (за счёт использования промежуточных таблиц).
При проектировании запроса может быть такое, что в контексте уже существует какой-то менеджер временных таблиц, и необходимо в начале запроса разместить текст формирования временных таблиц; либо мы сами хотим разделить запрос на составные части.
Для этих целей в обработку добавлена таблица "Используемые запросы". Здесь можно выбрать запрос (или запросы), которые будут выполняться перед началом выполнения основного запроса. Менеджер временных таблиц будет передан в основной запрос.
Предварительные запросы выполняются таким же способом как и основной (то есть у них могут быть свои временные таблицы и проч.). Один и тот же запрос может быть и основным и использоваться как предварительный. Если запрос выполняется как предварительный, вложенного выполнения своих предварительных запросов у него нет.
Помещение временных таблиц основного запроса производится только если таблица не найдена в МВТ.
Результат запроса выводится в табличный документ.
Запросы (сохранённый запрос также можно выгрузить из регистра) сериализуются как дерево значений в файлы с расширениями
bmqval — простая сериализация через ЗначениеВСтрокуВнутр;
bmqxml — выгрузка в xml через СериализаторXDTO; объём файла здесь больше, и время чтения/записи тоже.
Реализованы следующие способы сохранения запроса из отладчика.
1) Помещение во временное хранилище
2) Преобразование в строку
3) Сохранение в регистр
Для случая, когда в базе данное расширение отсутствует, предусмотрена кнопка "Подключить консоль запросов".
Может быть, возможен и такой способ получения запроса в строку (если файл обработки расположен на сервере):
ВнешниеОбработки.Создать("<Каталог>\bm_КонсольЗапросов.epf", Истина, ОбщегоНазначения.ОписаниеЗащитыБезПредупреждений()).ЗапросВХ(Запрос)
В разделе Инструкция можно исполнить программный код. Если обработка запущена в типовой конфигурации, будет вызван метод ОбщегоНазначения.ВыполнитьВБезопасномРежиме, иначе — в аналогичной процедуре модуля обработки.
По умолчанию доступен параметр ТекстДокумент, который можно использовать в качестве консоли вывода. Параметр Запрос по умолчанию недоступен — для использования текущего запроса нужно установить флажок.
На отдельной странице реализован "быстрый выбор" таблицы.
Окно настроек обработки:
Было реализовано чтение логов техножурнала по текущему запросу / инструкции.
Каталог текущих логов автоматически не заполняется — папка указывается вручную (при выборе каталога исходным каталогом является каталог логов техножурнала). Чтение логов протестировано на windows для файлового режима работы, mssql и postgresql.
Для работы с техножурналом надо только заполнить каталог текущих логов и установить флаг "Тег запроса". В отличие от консоли запросов ИТС обработка не генерирует конфигурацию техножурнала (она уже должна быть настроена), определение идентификатора процесса 1С также отсутствует — поэтому каталог текущих логов выбирается вручную.
Путь к файлу конфигурации журнала формируется справочно (если найден; если он есть, то может быть и не найден).
В безопасном режиме флаг работы с ТЖ недоступен.
Некоторые моменты
В дерево запросов добавлена колонка "Исключение". Означает, что произошло исключение при установке текста схемы запроса. Понадобилась в связи с тем, что рабочий текст запроса может быть не прочтён схемой запроса. Например, "ВЫБРАТЬ Номенклатура ИЗ ВременнаяТаблица".
Конечно, если запрос проектируется в конструкторе, колонка не нужна, но информация полезна, если запрос перехвачен. Если текст запроса вызывает исключение в схеме запроса, но сам запрос выполняется, и выполняется пакетно, в заголовке вывода будет указано "Сформировано без схемы запроса", а вместо наименований временных таблиц будут номера запросов.
Как-то раз запрос не хотел сохраняться из отладчика. Выяснилось, что при получении данных временной таблицы возникает ошибка: Неоднозначное поле ИмяПоля SELECT * FROM <<?>>ИмяПоля. Поскольку ошибка была только один раз (некий запрос при печати счёта-фактуры), то обрамлять данный участок кода в попытку в релизе не стали. Но расширение в базе доработали, написали в исключении Новый ТаблицаЗначений(), и заполнили потом таблицу в конструкторе ТЗ.
Обработка Консоль запросов. Схема запроса
Исторически у этого конструктора сформировалось наименование "Схема запроса". Наверно потому, что сначала это было просто дерево, отображающее объектную схему запроса. В то же время название достаточно удобно, чтобы отличать его от встроенного тонкого конструктора запроса. На командной панели обработки они и соседствуют с названиями "Конструктор" и "Схема".
На главной странице расположено дерево схемы запроса. Его составными элементами являются запрос, оператор и источник. Рядом отображается текст текущего запроса. В дерево можно добавить запрос, оператор и источник-вложенный запрос. Удалить можно запрос или оператор. Текст текущего запроса может быть изменён — при этом будет изменено и дерево схемы.
Оператор запроса открывается в отдельной странице. Слева расположены источники, справа — страницы с разнообразными свойствами. Там же находится дерево таблиц. Его структура не обязательно соответствует структуре доступных таблиц схемы запроса. Например, внешние источники данных было решено подчинить общей ветке, перерасчёты - продублировать рядом с регистрами расчёта, виртуальные таблицы связать с физическими.
В источники можно добавить таблицу из дерева таблиц и описание временной таблицы. Можно удалить источник, переименовать, заменить (как в привычном конструкторе).
Особенность работы с вложенным запросом такова, что добавить его возможно в дереве схемы (он будет подчинён оператору как источник, но в то же время являться и вложенным запросом), а удаление происходит из оператора.
У одного запроса может быть несколько операторов. В дереве схемы главным является первый оператор (с индексом 0). Только при открытии главного оператора доступны некоторые свойства и изменение состава/порядка колонок. Если операторы поменять местами, то главным станет другой оператор, т.е. признак завязан только на порядковый номер.
При работе с полями выборки можно включить "режим замены" (если оператор не главный, режим включен по умолчанию). В этом случае можно только устанавливать выражения полей (перетаскиванием или редактированием).
Как правило, добавление строк таблиц формы (источников, выбираемых полей, соединений, отборов и проч.) происходит через перетаскивание. Может быть так, что добавить строку можно и через перетаскивание, и через кнопку Добавить.
Для таблицы соединений реализован следующий приём добавления соединения: перетаскиваем на таблицу по порядку поле источника и поле приёмника (в обработке так называются левая и правая таблицы).
У группировок схемы запроса есть такие особенности:
— если указано поле, содержащее агрегатную функцию, то группировки формируются автоматически
— если указано хотя бы одно выражение группировки, то остальные формируются автоматически
Поэтому по умолчанию первая группировка именуется в обработке как "Авто". Стоит понимать так, что не обязательно указывать группировки явно.
Чтобы применить агрегатную функцию, нужно выделить нужную строку (из "выбираемых полей") и вызвать соответствующую команду.
Параметры источников для удобства вынесены в одну общую таблицу.
У таких свойств запроса как Порядок и Контрольные точки итогов элементом коллекции могут выступать как произвольные выражения схемы запроса, так и колонки запроса. Колонка добавляется перетаскиванием из выбираемых полей, выражение — перетаскиванием или через кнопку Добавить.
Находясь в форме схемы запроса, можно передать и выполнить в консоли текст схемы запроса по текущий запрос. Если форма схемы будет закрыта без сохранения, то в консоли восстанавливается исходный текст запроса текущей строки.
Режим схемы компоновки данных не реализован.
Из нюансов внутренней реализации выделю следующее.
Во время разработки было потрачено много (очень много) времени на попытки разобраться в корректном управлении составом вложенных таблиц (вложенная табличная часть в выборке) через методы объектной модели, когда это выходит за рамки обычного добавления колонок табличных частей — но не удалось: что-то работало как надо, а что-то искажало текст запроса.
Простые выборки / объединения работали, но для тестирования использовались, может, совсем уж выдуманные запросы с объединением нескольких вложенных таблиц (включая пустые) с произвольными полями.
На момент разработки был совершён экскурс в штатный тонкий конструктор, но это не помогло решить проблему, ибо была связана с платформой, а не программным кодом. Сделал вывод, что реализация класса СхемаЗапроса и не документирована полностью, и не всегда работает должным образом.
Хорошо, что у запроса выбора есть методы получения и установки текста запроса, которые позволили обойти это затруднение (правда, ключевые слова на английском языке учтены не были).
Но на практике такие запросы, конечно, практически не встречаются.
У соединений есть такая особенность, что при чтении схемы условие связи раскладывается на операнды (к примеру какое-то составное И). При обратной установке соединений это может привести к ошибке ("противоречивая связь"). Поэтому при чтении схемы условия с одинаковой связью объединяются.
При работе с запросом используется "ленивое" обновление схемы запроса. Так, при простом перетаскивании поля в таблицу обращения к серверу и обновления схемы запроса не будет. При вызове окна редактирования произвольного выражения схема будет обновлена частично. Перед переименованием, удалением, заменой источника схема обновляется полностью. В этом есть свои плюсы и минусы. Такой способ был выбран, т.к. было лень возиться с динамическим обновлением схемы (не знаю насколько оно вообще уместно).
При обновлении схемы свойства запроса и оператора заполняются заново: например, выбираемые поля полностью очищаются.
Чтобы предупредить возможное исключение "Неоднозначное поле", таблицы операторов заранее анализируются на предмет этой ошибки. Желательно сразу же переименовать конфликтующую таблицу. Иначе может быть такой случай: перетащили таблицу (получили предупреждение), перетащили поля, добавили какие-то соединения, при обновлении схемы запроса уже получаем исключение, переименовываем таблицу, и форма обновляется из необновлённой схемы запроса: исчезают некоторые выбираемые поля, соединения и проч.
Обработка Навигатор
История создания: понадобился простой кастомный редактор объекта, в том числе с собственной формой выбора, так как подчас форма выбора (списка) в типовой конфигурации — не совсем то или далеко не то, что нужно. В итоге получился миниатюрный навигатор/редактор по базе данных.
Как устроены иные редакторы, не изучал. В данном случае для каждого объекта заполняется отдельный экземпляр "формы объекта". При создании на сервере объект базы данных загружается в форму через метод ЗначениеВРеквизитФормы (реквизит — не основной), для каждой коллекции (табличной части или набора записей) создаются сопутствующие элементы формы. Реквизиты шапки отображаются в таблице значений. Факультативно в форме объекта строка табличной части выводится в отдельную таблицу (можно включить/отключить опцию).
Работы с хранилищем значения нет.
Кроме ссылочных объектов, поддерживаются и "нессылочные" списки.
Поддерживается форма записи независимого регистра сведений.
Внешними источниками заниматься не хотелось, но в итоге была реализована поддержка динамических списков таблиц и формы объекта таблицы с типом данных таблицы "ОбъектныеДанные".
Для выбора значения не из формы выбора по умолчанию предусмотрена кнопка "Выбрать значение". Можно выбрать значение реквизита объекта, реквизита табличной части (в зависимости от того какая страница активна). Ещё одна кнопка продублирована в таблице реквизитов строки табличной части.
По умолчанию кнопки записи в форме объекта неактивны (дабы предотвратить случайное нажатие). Чтобы кнопки стали доступны, необходимо нажать кнопку "Редактировать объект" (карандашик).
Для формы списка реализован поиск по UUID / URL, для дерева конфигурации возможен поиск только по URL. Поддержка навигационных ссылок регистров сведений и внешних источников данных не реализована.
Установка пути к данным колонок таблицы формы динамического списка обрамлена в попытку, так как по неизвестной причине у некоторых колонок возникало исключение: если повторяется колонка с типом ХранилищеЗначения (на самом деле такие колонки выводятся как строка "<Хранилище значения>"), у одной колонки типа Строка у той же проблемной таблицы. Такие колонки пропускаются, но на форму выводится соответствующая информация.
Обработка Структура хранения базы данных
Простенькая обработка
Обработка Движения документа
Необходимо добавить в расширение и тип параметра команды необходимые типы документов.
Если же открыть обработку отдельно, то можно выбрать любой тип документа.
Документ Корректировка регистров
Необходимо добавить в расширение и движения документа необходимые типы документов.
Обработка Хранилище настроек
Простенькая обработка для работы с хранилищами настроек типа СтандартноеХранилищеНастроекМенеджер.
История версий
09.22 — первая публикация
01.23 — конструктор запроса, обработка "Структура хранения базы данных"
08.23 — работа с программным кодом
08.24 — обработка "Движения документа", документ "Корректировка регистров"
11.24:
— Выполнение запросов с временными таблицами с колонками типа Тип, МоментВремени.
— Функция ЗапросВСтроку.
01.25:
— Возможность задания фиксированной ширины колонок при выводе результата в табличный документ (может быть удобно для выгрузки в файл)
— Сохранение результатов запроса при переключении между запросами
— Выполнение запросов в фоновом задании (требуется программный интерфейс БСП и наличие данного расширения)
— Чтение логов техножурнала
02.25 — Выполнение предварительных запросов для формирования временных таблиц.
05.25:
— Функция ЗапросВХ.
— Быстрый выбор таблицы в консоли запросов
— Обработка "Навигатор"
— Обработка "Хранилище настроек"
Выполнено и протестировано на платформах 8.3.24.1624, 8.3.25.1394
P.S. При установке расширения на используемую конфигурацию, возможно, необходимо будет пофиксить пару контролируемых свойств. Мы делаем следующим образом.
Проверено на следующих конфигурациях и релизах:
- 1С:ERP Управление предприятием 2, релизы 2.5.20.80, 2.5.17.172