Как получить имена полей из текста запроса в 1С без его выполнения?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Зачастую перед разработчиком встает задача проанализировать структуру запроса, не выполняя его в текущей базе данных. Это может быть нужно для создания конструкторов запросов, статических анализаторов кода или при работе с внешними отчетами. Рассмотрим основные подходы к решению этой задачи.

Использование объекта ПостроительЗапроса

Одним из наиболее эффективных инструментов для анализа структуры запроса является ПостроительЗапроса. Даже если запрос нельзя выполнить в текущей конфигурации (например, из-за отсутствия некоторых объектов метаданных), ПостроительЗапроса может попытаться разобрать текст и выделить выбранные поля.

Разберем, как это реализовать на практике:


Построитель = Новый ПостроительЗапроса(ТекстЗапроса);
Построитель.ЗаполнитьНастройки();
Для Каждого Поле Из Построитель.ВыбранныеПоля Цикл
    // Здесь мы получаем доступ к объекту поля
    ИмяПоля = Поле.Имя;
    Представление = Поле.Представление;
КонецЦикла;

Важное замечание: Метод ЗаполнитьНастройки может вызвать ошибку, если текст запроса содержит синтаксические ошибки или несовместимые с платформой конструкции. Однако для большинства корректных запросов этот метод позволяет извлечь список полей без обращения к базе данных.

Использование метаданных результата запроса

Если запрос уже был выполнен в контексте процедуры или функции, нам не нужно парсить текст. Мы можем обратиться к результату выполнения напрямую. Если у нас есть ВыборкаИзРезультатаЗапроса, мы можем выйти на РезультатЗапроса, который содержит коллекцию колонок.

Рассмотрим, как получить имена полей через владельца выборки:


// Предположим, у нас есть Выборка
Колонки = Выборка.Владелец.Колонки;
Для Каждого Колонка Из Колонки Цикл
    Сообщить(Колонка.Имя);
КонецЦикла;

Этот метод является самым точным, так как он опирается на реальные метаданные, полученные в процессе выполнения запроса.

Алгоритмический парсинг текста запроса

Если ни один из вышеперечисленных методов не подходит, приходится прибегать к ручному разбору текста (парсингу). Это сложная задача, требующая учета конструкции ВЫБРАТЬ, КАК и игнорирования текста в скобках или строковых литералах.

Разберем базовый алгоритм, который поможет выделить поля в простых запросах:

  1. Приведите весь текст к верхнему регистру для удобства поиска.
  2. Замените символы переноса строк и табуляции на пробелы для стандартизации.
  3. Найдите позицию ключевого слова ВЫБРАТЬ и позицию первого ИЗ.
  4. Извлеките подстроку между этими ключевыми словами — это будет область наших полей.
  5. Удалите из этой области выражения в скобках (подзапросы), так как они могут содержать собственные запятые и служебные слова.
  6. Разделите полученную строку по символу запятой ,.
  7. Для каждого элемента массива проверьте наличие ключевого слова КАК. Если оно есть, все, что идет после него — это и есть имя поля.

Ниже представлен пример кода, реализующий упрощенный парсинг:


Текст = СтрЗаменить(СтрЗаменить(ТекстЗапроса, Символы.ПС, " "), Символы.Таб, " ");
// ... (очистка лишних пробелов)
ПозицияВыбрать = СтрНайти(Текст, " ВЫБРАТЬ ");
ПозицияИЗ = СтрНайти(Текст, " ИЗ ", , ПозицияВыбрать + 9);
ОбластьПолей = Сред(Текст, ПозицияВыбрать + 9, ПозицияИЗ - ПозицияВыбрать - 9);
ВыраженияПолей = СтрРазделить(ОбластьПолей, ",", Ложь);
Для Каждого Выражение Из ВыраженияПолей Цикл
    ПозицияКАК = СтрНайти(Выражение, " КАК ", НаправлениеПоиска.СКонца);
    Если ПозицияКАК > 0 Тогда
        ИмяПоля = СокрЛП(Сред(Выражение, ПозицияКАК + 5));
    Иначе
        // Имя по умолчанию, если псевдоним не задан
        ИмяПоля = "Поле" + Формат(Номер, "ЧГ=");
    КонецЕсли;
КонецЦикла;

Почему парсинг — это сложно?

Мы должны понимать, что создание универсального парсера запросов — это задача написания компилятора. Основные трудности, с которыми мы столкнемся:

Рекомендация: Если ваша задача критична для стабильности системы, лучше использовать ПостроительЗапроса с имитацией структуры метаданных (mock) или выполнять запрос в специально выделенной «песочнице». Это позволит избежать ошибок, связанных с хрупкостью строковых алгоритмов разбора.

← На главную