Получить имена полей из текста запроса

1. Drak0n 187 08.05.19 09:50 Сейчас в теме
Добрый день.
Стоит задача получать имена полей из текста запроса. Если запрос создавался под текущую конфигурацию - тут просто
СхемаЗапроса = Новый СхемаЗапроса;
СхемаЗапроса.УстановитьТекстЗапроса(ТекстЗапроса);
Колонки = СхемаЗапроса.ПакетЗапросов[0].Колонки;

Но если запрос нельзя выполнить в текущей конфигурации - способ не работает. Может кто знает универсальный способ?
shalupov61; kild; scanner1980; +3 Ответить
По теме из базы знаний
Ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
3. alex-l19041 8 08.05.19 10:06 Сейчас в теме
(1) текст запроса - строка... можно "разобрать" строку имена полей идут после "КАК" до запятой
4. Oldsad 08.05.19 10:07 Сейчас в теме
(3)
достаточно нетривиальная задача
6. Ганс 08.05.19 10:12 Сейчас в теме
(3) не обязательно, наименование может формироваться из пути реквизита или некоторые вместо как используют просто пробел! Боюсь не получиться таким путём
5. MaxxiMiliSan 251 08.05.19 10:12 Сейчас в теме
(1) выгрузи результат запроса в таблицу - а из таблицы можно получить имена полей
7. dhurricane 08.05.19 10:25 Сейчас в теме
(5) По условию задачи запрос нельзя выполнить в текущей конфигурации.
8. MaxxiMiliSan 251 08.05.19 10:28 Сейчас в теме
(7) ну тогда нужно найти все запятые между ВЫБРАТЬ и ИЗ и анализировать текст ДО них. Если встречается слово КАК, тогда имя поля будет между КАК и запятой или словом ИЗ.
alex-l19041; +1 Ответить
9. tusv 210 08.05.19 10:29 Сейчас в теме
(1)Не схемой единой жив 1Сник
Построитель = Новый ПостроительЗапроса(ТекстЗапроса);
Построитель.ЗаполнитьНастройки();
Для Сч=0  по Построитель.ВыбранныеПоля.Количество()-1 Цикл
	Поле = Построитель.ВыбранныеПоля[сч];
КонецЦикла;
kild; &rew; +2 Ответить
10. MaxxiMiliSan 251 08.05.19 10:30 Сейчас в теме
(9) а построитель не сругнется на неправильный запрос?
31. makfromkz 35 10.05.19 06:30 Сейчас в теме
(10)Ответить примерно так:
ПолеПостроителяЗапроса
ПолеПостроителяЗапроса
............................................
34. &rew 49 23.08.21 09:32 Сейчас в теме
(9)
Построитель = Новый ПостроительЗапроса(ТекстЗапроса);
Построитель.ЗаполнитьНастройки();
Для Сч=0 по Построитель.ВыбранныеПоля.Количество()-1 Цикл
Поле = Построитель.ВыбранныеПоля[сч];
КонецЦикла;

Натолкнули на мысль. Вот если у нас уже есть ВыборкаИзРезультатаЗапроса, но нет самого текста запроса (например внутри какой либо функции или в процедуре общего модуля) то получаем Владельца - РезультатЗапрос, а тут уже коллекция колонок:
<НашаВыборка>.Владелец().Колонки и уже пляшем
14. spacecraft 08.05.19 11:11 Сейчас в теме
(1) да в общем-то простая задачка парсинга.
МассивИменПолей = Новый Массив;
м1 = СтрРазделить(ТекстЗапрос, ";", Ложь);
ТекстЗапроса = м1[м1.ВГраница()];
ТекстЗапроса = НРег(ТекстЗапрос);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"выбрать",";");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"из",";");
м1 = СтрРазделить(ТекстЗапроса, ";",Ложь);
ТекстПолей = м1[0];
м1 = СтрРазделить(ТекстПолей, ",", Ложь);
Для Каждого ТекстПоля Из м1 Цикл
	мИмяПоля = СтрРазделить(ТекстПоля, ". ", Ложь);
	ИмяПоля = мИмяПоля[мИмяПоля.ВГраница()];
	МассивИменПолей.Добавить(ИмяПоля);
КонецЦикла;
Показать

Имена полей будет в нижнем регистре.
Правда это не универсальное решение. Для простых запросов. Но для понять принципа думаю достаточно.
15. MaxxiMiliSan 251 08.05.19 11:40 Сейчас в теме
(14) если в наименовании переменной будет ИЗ, например КоличествоИзмененное, тогда этот вариант не сработает
16. spacecraft 08.05.19 11:48 Сейчас в теме
(15) да там много чего не сработает. Это просто руководство к действию. Конкретно для ИЗ, можно пробелы учесть
33. makfromkz 35 11.05.19 05:26 Сейчас в теме
(1)А можно предложить
ВЫБРАТЬ *
ИЗ ......


?
А потом разбирать вашим способом
2. VmvLer 08.05.19 10:00 Сейчас в теме
либо писать свой анализатор лексем - это почти компилятор.
либо все-таки выполнить запрос и получить имена из колонок результата.
11. SlavaKron 08.05.19 10:36 Сейчас в теме
12. MaxxiMiliSan 251 08.05.19 10:42 Сейчас в теме
(11) следовательно, такой вариант не подойдет
13. Drak0n 187 08.05.19 11:06 Сейчас в теме
В общем - все плохо. Спасибо за обсуждение.
23. tusv 210 08.05.19 12:07 Сейчас в теме
(13)Ну не чавчем. Чё там парсить то между "выбрать"(sel ect) и " из" (" fr om")
Заменить переносы строки и табы на пробел, загнать стрРазделить в массив
Обходи себе массив. Главное помнить что алиас может начинаться после " как ", " as " и последнего пробела, а может псевдонима и не быть тогда, если последний символ ")" или "конец" или "end" возвращаем "Поле" с нарастающим индексом.
Ну и на закуску возвращаем поле с заменой точки на пустую строку.
Как бэ все просто
24. SlavaKron 08.05.19 12:13 Сейчас в теме
(21)
Действительно. На самом деле, вариантов много, о которые можно споткнуться:
КАК может опускаться
могут быть многоуровневые конструкции: "ПоступлениеТоваровУслугТовары.Номенклатура.Код" даст НоменклатураКод
могут быть безымянные поля
17. SlavaKron 08.05.19 11:57 Сейчас в теме
Вроде бы всё учёл:
	Текст = СтрЗаменить(СтрЗаменить(ТекстЗапроса, Символы.ПС, " "), Символы.Таб, " ");
	
	Пока СтрНайти(Текст, "  ") > 0 Цикл
		Текст = СтрЗаменить(Текст, "  ", " ");
	КонецЦикла;
	
	Текст = " " + ВРег(Текст);
	
	ПозицияВыбрать = СтрНайти(Текст, " ВЫБРАТЬ ");
	
	НаборыПолей = Новый Массив;
	
	Пока ПозицияВыбрать > 0 Цикл
		ПозицияИЗ = СтрНайти(Текст, " ИЗ ", , ПозицияВыбрать + 9);
		Если ПозицияИЗ = 0 Тогда
			ПозицияИЗ = СтрДлина(Текст) + 1;
		КонецЕсли;
		ОбластьПолей = Сред(Текст, ПозицияВыбрать + 9, ПозицияИЗ - ПозицияВыбрать - 9);
		// удаляем выражения в скобках, так как они могут содеражть "КАК" и запятые
		ПозицияОткрывающейСкобки = СтрНайти(ОбластьПолей, "(");
		Пока ПозицияОткрывающейСкобки > 0 Цикл
			
			ПозицияЗакрывающейСкобки = СтрНайти(ОбластьПолей, ")");
			ВыражениеВСкобках = Сред(ОбластьПолей, ПозицияОткрывающейСкобки + 1, ПозицияЗакрывающейСкобки - ПозицияОткрывающейСкобки - 1);
			
			Пока СтрЧислоВхождений(ВыражениеВСкобках, "(") <> СтрЧислоВхождений(ВыражениеВСкобках, ")") Цикл
				ПозицияЗакрывающейСкобки = СтрНайти(ОбластьПолей, ")", , ПозицияЗакрывающейСкобки + 1);
				ВыражениеВСкобках = Сред(ОбластьПолей, ПозицияОткрывающейСкобки + 1, ПозицияЗакрывающейСкобки - ПозицияОткрывающейСкобки - 1);
			КонецЦикла;
			
			ОбластьПолей = Лев(ОбластьПолей, ПозицияОткрывающейСкобки - 1) + Сред(ОбластьПолей, ПозицияЗакрывающейСкобки + 1);
			ПозицияОткрывающейСкобки = СтрНайти(ОбластьПолей, "(");
		КонецЦикла;
		
		ВыраженияПолей = СтрРазделить(ОбластьПолей, ",", Ложь);
		МассивПолей = Новый Массив;
		НомерБезымянногоПоля = 1;
		Для Каждого Выражение Из ВыраженияПолей Цикл
			ПозицияКАК = СтрНайти(Выражение, " КАК ", НаправлениеПоиска.СКонца);
			Если ПозицияКАК > 0 Тогда
				ИмяПоля = Сред(Выражение, ПозицияКАК + 5);
				
			Иначе
				ИмяПоля = "Поле" + Формат(НомерБезымянногоПоля, "ЧГ=");
				НомерБезымянногоПоля = НомерБезымянногоПоля + 1;
			КонецЕсли;
			МассивПолей.Добавить(ИмяПоля);
			Сообщить(ИмяПоля);
		КонецЦикла;
		
		НаборыПолей.Добавить(МассивПолей);
		ПозицияВыбрать = СтрНайти(Текст, " ВЫБРАТЬ ", , ПозицияВыбрать + 9);
	КонецЦикла;
Показать
Прикрепленные файлы:
ПарсерТекстаЗапроса.epf
Светлый ум; +1 Ответить
18. MaxxiMiliSan 251 08.05.19 12:02 Сейчас в теме
(17) правильно ли я понял, что из запроса
ВЫБРАТЬ 
д.Наименование 
из Справочник.Номенклатура как д


я получу массив, в котором будет "Поле1", так как КАК нет в самом запросе
22. SlavaKron 08.05.19 12:07 Сейчас в теме
21. catena 110 08.05.19 12:06 Сейчас в теме
26. tusv 210 08.05.19 12:57 Сейчас в теме
(17)Такую конструкцию тоже обработает?
ВЫБРАТЬ "бла бла, Бда, жужужу" ХитоеПоле
ОБЪЕДИНИТЬ
ВЫБРАТЬ "П,2,1,лдло!.,5,3"
27. MaxxiMiliSan 251 08.05.19 12:59 Сейчас в теме
(26) кстати правильно нужно еще анализировать ОБЪЕДИНИТЬ ВСЕ, а точнее игнорировать все что после первых ВЫБРАТЬ ИЗ
30. makfromkz 35 10.05.19 06:19 Сейчас в теме
(17)Попробовал вашу обработку, на объединениях добавляет:
ДОКТ
СЧЕТДТ
СЧЕТКТ
Поле1
Поле2
Поле3
..........
.........
.........


а исходный текст запроса:
ВЫБРАТЬ
	Типовой.Регистратор КАК Докт,
	Типовой.СчетДт КАК СчетДт,
	Типовой.СчетКт КАК СчетКт
ИЗ
	РегистрБухгалтерии.Типовой КАК Типовой
ГДЕ
	Типовой.СчетДт В ИЕРАРХИИ(&СчетДт6хх)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	Типовой.Регистратор,
	Типовой.СчетДт,
	Типовой.СчетКт
ИЗ
	РегистрБухгалтерии.Типовой КАК Типовой
ГДЕ
	Типовой.СчетКт В ИЕРАРХИИ(&СчетДт6хх)
...........................
Показать
19. VmvLer 08.05.19 12:03 Сейчас в теме
а трехтажные вложенные запросы тоже распарсит?
20. SlavaKron 08.05.19 12:04 Сейчас в теме
(19) Добавит в виде отдельного набора полей. Но да, вы правы, надо обрабатывать ";", а не " ВЫБРАТЬ ".
25. tusv 210 08.05.19 12:15 Сейчас в теме
и да Ищем поля после последней точки с запятой
28. MaxxiMiliSan 251 08.05.19 13:00 Сейчас в теме
и еще нужно учитывать пакеты. Поэтому нужно искать поля среди последнего пакета внутри первого (так как может быть ОБЪЕДИНИТЬ ВСЕ ) ВЫБРАТЬ ИЗ
29. VmvLer 08.05.19 13:13 Сейчас в теме
а еще нужно писать или искать анализатор лексем как я и сказал на старте.
можно, конечно, попросить разработчиков платформы показать его.

каждые 30 сообщений можно повторять эту мантру)
32. user1218675 10.05.19 16:07 Сейчас в теме
Спасибо за обсуждение
Оставьте свое сообщение
Вакансии
1С аналитик
Москва
зарплата от 210 000 руб.
Полный день

Руководитель направления 1С
Москва
зарплата от 350 000 руб.
Полный день

1С Программист
Москва
зарплата от 180 000 руб.
Полный день

Программист 1С
Москва
зарплата от 180 000 руб. до 220 000 руб.
Полный день

Аналитик 1С / Бизнес-аналитик
Нижний Новгород
зарплата от 100 000 руб. до 250 000 руб.
Временный (на проект)