Описывает вложенную таблицу схемы запроса.
Полное описание, параметры и ограничения
ВложеннаяТаблицаСхемыЗапроса (QuerySchemaNestedTable)
ВложеннаяТаблицаСхемыЗапроса (QuerySchemaNestedTable)
Доступен, начиная с версии 8.3.5.
Свойства:
Имя (Name)
Поля (Fields)
Описание:
Описывает вложенную таблицу схемы запроса.
Доступность:
Сервер, толстый клиент, внешнее соединение.
Использование в версии:
Доступен, начиная с версии 8.3.5.
Методическая информация
Практические примеры
Табличная часть в запросе: доступное описание, выбранные поля и вложенные колонки
Разбираем собственный список сборок с вложенными деталями. Отличаем описание доступных реквизитов от выбранной вложенной таблицы и её колонки; удваиваем выражение количества, проверяем весь запрос по независимому эталону и восстанавливаем его. Данные не читаются.
Где и как запускать
Полный серверный общий модуль УчебныеЗадачи своей новой конфигурации УчебныеВложенные85; в1С не запускался.
Подготовка
Нужна НОВАЯ отдельная учебная база, не копия рабочей: платформа точно8.5.1.1343, имя конфигурации УчебныеВложенные85, совместимость Не использовать. Никаких расширений, фоновых заданий, подписок на события и иных бизнес-объектов. Все модули вручную пустые, кроме данного общего модуля. Здесь ничего в1С не запускается.
Единственный справочник УчебныеСборки85: неиерархический, код Строка3, наименование40, без владельцев, реквизитов и предопределённых элементов. Единственная табличная часть Детали: два реквизита КодДетали Строка3 и Количество Число10,0. Не создавайте элементов и строк: нужен только собственный состав метаданных.
Общий модуль УчебныеЗадачи: Сервер=Да, Вызов сервера=Да, Клиент=Нет, Глобальный=Нет, Привилегированный=Нет. Вставьте весь основной модуль. Своя внешняя обработка УчебныеВложения85 → управляемая Форма: команда/кнопка Выполнить с действием Выполнить; реквизиты не нужны. Полный отдельный модуль формы приведён ниже.
Будущая ручная подготовка только вне опыта: завершить прежний свой сеанс, сохранить конфигурацию, Конфигурация → Обновить конфигурацию базы данных (F7), затем свежий собственный клиент и своя обработка. F7, клиент, BSL и контрольный опыт здесь не выполнялись.
Процедура ВыполнитьПример() Экспорт
ПроверитьСвойПустойСтенд();
ПроверитьСвоюМодельДеталей();
ИсходныйТекст = "ВЫБРАТЬ Сборки.Код КАК Код,
|Сборки.Детали.(КодДетали КАК КодДетали, Количество КАК Количество) КАК Детали
|ИЗ Справочник.УчебныеСборки85 КАК Сборки";
УдвоенныйТекст = "ВЫБРАТЬ Сборки.Код КАК Код,
|Сборки.Детали.(КодДетали КАК КодДетали, Количество * 2 КАК Количество) КАК Детали
|ИЗ Справочник.УчебныеСборки85 КАК Сборки";
Схема = СоздатьСвоюВложеннуюСхему(ИсходныйТекст);
ИсходныйЭталон = СоздатьСвоюВложеннуюСхему(ИсходныйТекст);
УдвоенныйЭталон = СоздатьСвоюВложеннуюСхему(УдвоенныйТекст);
СравнитьСвоиВложенныеСхемы(Схема, ИсходныйЭталон);
ПроверитьСвойПовторныйРазборВложения(Схема, ИсходныйЭталон);
Копия = СоздатьСвоюВложеннуюСхему(Схема.ПолучитьТекстЗапроса());
Текущая = ПроверитьСвоюВложеннуюСтруктуру(Схема);
Удвоенная = ПроверитьСвоюВложеннуюСтруктуру(УдвоенныйЭталон);
Если Текущая.Поля.Получить(1) = Удвоенная.Поля.Получить(1) Тогда
ВызватьИсключение "Исходное и удвоенное полные выражения должны различаться";
КонецЕсли;
Текущая.Поля.Установить(1, Новый ВыражениеСхемыЗапроса(Строка(Удвоенная.Поля.Получить(1))));
СравнитьСвоиВложенныеСхемы(Схема, УдвоенныйЭталон);
ПроверитьСвойПовторныйРазборВложения(Схема, УдвоенныйЭталон);
СравнитьСвоиВложенныеСхемы(Копия, ИсходныйЭталон);
Текущая = ПроверитьСвоюВложеннуюСтруктуру(Схема);
Исходная = ПроверитьСвоюВложеннуюСтруктуру(ИсходныйЭталон);
Текущая.Поля.Установить(1, Новый ВыражениеСхемыЗапроса(Строка(Исходная.Поля.Получить(1))));
СравнитьСвоиВложенныеСхемы(Схема, ИсходныйЭталон);
ПроверитьСвойПовторныйРазборВложения(Схема, ИсходныйЭталон);
СравнитьСвоиВложенныеСхемы(Копия, ИсходныйЭталон);
Сообщить("Верхние колонки: Код и Детали. Внутренние: КодДетали и Количество. Выражение количества восстановлено; копия не менялась");
КонецПроцедуры
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен свой новый стенд: единственный справочник сборок с собственной табличной частью";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвойТипВложенногоПоля(Описание, ОжидаемыйТип)
Если ТипЗнч(Описание) <> Тип("ОписаниеТипов") Тогда
ВызватьИсключение "Нужно описание полного типа своего поля";
КонецЕсли;
Типы = Описание.Типы();
Если Типы.Количество() <> 1 Или Типы[0] <> ОжидаемыйТип Тогда
ВызватьИсключение "Не совпал полный набор типов своего поля";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоюМодельДеталей()
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Для собственного разбора не нужен привилегированный режим";
КонецЕсли;
МетаСборки = Метаданные.Справочники.Найти("УчебныеСборки85");
Если МетаСборки = Неопределено Тогда
ВызватьИсключение "Нужен свой справочник УчебныеСборки85";
КонецЕсли;
Если МетаСборки.Иерархический Или МетаСборки.ДлинаКода <> 3 Или МетаСборки.ДлинаНаименования <> 40
Или МетаСборки.Реквизиты.Количество() <> 0 Или МетаСборки.ТабличныеЧасти.Количество() <> 1 Тогда
ВызватьИсключение "Нужна только собственная согласованная модель сборок";
КонецЕсли;
МетаДетали = МетаСборки.ТабличныеЧасти.Найти("Детали");
Если МетаДетали = Неопределено Тогда
ВызватьИсключение "Нужна собственная табличная часть Детали";
КонецЕсли;
Если МетаДетали.Реквизиты.Количество() <> 2 Тогда
ВызватьИсключение "В собственной табличной части ровно два реквизита";
КонецЕсли;
МетаКод = МетаДетали.Реквизиты.Найти("КодДетали");
МетаКоличество = МетаДетали.Реквизиты.Найти("Количество");
Если МетаКод = Неопределено Или МетаКоличество = Неопределено Тогда
ВызватьИсключение "Нужны собственные КодДетали и Количество";
КонецЕсли;
ПроверитьСвойТипВложенногоПоля(МетаКод.Тип, Тип("Строка"));
ПроверитьСвойТипВложенногоПоля(МетаКоличество.Тип, Тип("Число"));
Если МетаКод.Тип.КвалификаторыСтроки.Длина <> 3
Или МетаКоличество.Тип.КвалификаторыЧисла.Разрядность <> 10
Или МетаКоличество.Тип.КвалификаторыЧисла.РазрядностьДробнойЧасти <> 0 Тогда
ВызватьИсключение "Не совпали квалификаторы собственных реквизитов";
КонецЕсли;
КонецПроцедуры
Функция СоздатьСвоюВложеннуюСхему(Текст)
Схема = Новый СхемаЗапроса;
Схема.РежимКомпоновкиДанных = Ложь;
Схема.УстановитьТекстЗапроса(Текст);
Возврат Схема;
КонецФункции
Процедура ПроверитьСвойКонецИмени(Имя, ОжидаемыйКонец)
Если ТипЗнч(Имя) <> Тип("Строка") Тогда
ВызватьИсключение "Нужно строковое имя собственного описания";
КонецЕсли;
Части = СтрРазделить(НРег(Имя), ".");
Если Части.Количество() = 0 Или Части[Части.Количество() - 1] <> НРег(ОжидаемыйКонец) Тогда
ВызватьИсключение "Не совпал собственный реквизит или имя табличной части";
КонецЕсли;
КонецПроцедуры
Функция ПроверитьСвоюВложеннуюСтруктуру(Схема)
Если Схема.РежимКомпоновкиДанных Или Схема.ПакетЗапросов.Количество() <> 1 Тогда
ВызватьИсключение "Нужен единственный собственный обычный запрос";
КонецЕсли;
Выбор = Схема.ПакетЗапросов.Получить(0);
Если ТипЗнч(Выбор) <> Тип("ЗапросВыбораСхемыЗапроса") Или Выбор.Операторы.Количество() <> 1 Тогда
ВызватьИсключение "Нужен собственный запрос выбора с одним оператором";
КонецЕсли;
Оператор = Выбор.Операторы.Получить(0);
Если ТипЗнч(Оператор) <> Тип("ОператорВыбратьСхемыЗапроса") Или Оператор.Источники.Количество() <> 1 Тогда
ВызватьИсключение "Нужен один собственный физический источник";
КонецЕсли;
Таблица = Оператор.Источники.Получить(0).Источник;
Если ТипЗнч(Таблица) <> Тип("ТаблицаСхемыЗапроса")
Или НРег(Таблица.ИмяТаблицы) <> НРег("Справочник.УчебныеСборки85") Или Таблица.Псевдоним <> "Сборки" Тогда
ВызватьИсключение "Не совпал собственный справочник и его псевдоним";
КонецЕсли;
Доступная = Таблица.ДоступныеПоля.Найти("Детали");
Если ТипЗнч(Доступная) <> Тип("ДоступнаяВложеннаяТаблицаСхемыЗапроса")
Или ТипЗнч(Доступная.Поля) <> Тип("ДоступныеПоляСхемыЗапроса") Тогда
ВызватьИсключение "Нужно настоящее описание доступной собственной табличной части";
КонецЕсли;
ПроверитьСвойКонецИмени(Доступная.Имя, "Детали");
ДоступныйКод = Доступная.Поля.Найти("КодДетали");
ДоступноеКоличество = Доступная.Поля.Найти("Количество");
Если ТипЗнч(ДоступныйКод) <> Тип("ДоступноеПолеСхемыЗапроса")
Или ТипЗнч(ДоступноеКоличество) <> Тип("ДоступноеПолеСхемыЗапроса") Тогда
ВызватьИсключение "Нужны два реальных доступных реквизита собственной табличной части";
КонецЕсли;
ПроверитьСвойКонецИмени(ДоступныйКод.Имя, "КодДетали");
ПроверитьСвойКонецИмени(ДоступноеКоличество.Имя, "Количество");
ПроверитьСвойТипВложенногоПоля(ДоступныйКод.ТипЗначения, Тип("Строка"));
ПроверитьСвойТипВложенногоПоля(ДоступноеКоличество.ТипЗначения, Тип("Число"));
Если Оператор.ВыбираемыеПоля.Количество() <> 2 Или Выбор.Колонки.Количество() <> 2 Тогда
ВызватьИсключение "Верхний уровень должен содержать код и одну вложенную таблицу";
КонецЕсли;
Код = Выбор.Колонки.Получить(0);
Если ТипЗнч(Код) <> Тип("КолонкаСхемыЗапроса") Или Код.Псевдоним <> "Код" Или Код.Поля.Количество() <> 1 Тогда
ВызватьИсключение "Первая верхняя колонка должна быть обычным кодом";
КонецЕсли;
Если ТипЗнч(Код.Поля.Получить(0)) <> Тип("ВыражениеСхемыЗапроса")
Или Код.Поля.Получить(0) <> Новый ВыражениеСхемыЗапроса("Сборки.Код")
Или Оператор.ВыбираемыеПоля.Получить(0) <> Код.Поля.Получить(0) Тогда
ВызватьИсключение "Не совпало полное обычное выражение кода";
КонецЕсли;
ПроверитьСвойТипВложенногоПоля(Код.ТипЗначения, Тип("Строка"));
Вложенная = Оператор.ВыбираемыеПоля.Получить(1);
ВложеннаяКолонка = Выбор.Колонки.Получить(1);
Если ТипЗнч(Вложенная) <> Тип("ВложеннаяТаблицаСхемыЗапроса")
Или ТипЗнч(ВложеннаяКолонка) <> Тип("КолонкаВложеннаяТаблицаСхемыЗапроса") Тогда
ВызватьИсключение "Вторые поле и колонка должны быть именно вложенной таблицей";
КонецЕсли;
ПроверитьСвойКонецИмени(Вложенная.Имя, "Детали");
Если ТипЗнч(Вложенная.Поля) <> Тип("ПоляСхемыЗапроса")
Или ТипЗнч(ВложеннаяКолонка.Колонки) <> Тип("КолонкиСхемыЗапроса")
Или ТипЗнч(ВложеннаяКолонка.Поля) <> Тип("ПоляКолонкиСхемыЗапроса")
Или ВложеннаяКолонка.Псевдоним <> "Детали" Или ВложеннаяКолонка.Поля.Количество() <> 1 Тогда
ВызватьИсключение "Не совпали полные типы вложенных коллекций и внешний псевдоним";
КонецЕсли;
ИзКолонки = ВложеннаяКолонка.Поля.Получить(0);
Если ТипЗнч(ИзКолонки) <> Тип("ВложеннаяТаблицаСхемыЗапроса") Тогда
ВызватьИсключение "Поле вложенной колонки должно содержать настоящее вложенное описание";
КонецЕсли;
Если ИзКолонки.Имя <> Вложенная.Имя Или ИзКолонки.Поля.Количество() <> Вложенная.Поля.Количество() Тогда
ВызватьИсключение "Выбранное вложенное поле и поле колонки должны описывать одну собственную таблицу";
КонецЕсли;
Если Вложенная.Поля.Количество() <> 2 Или ВложеннаяКолонка.Колонки.Количество() <> 2 Тогда
ВызватьИсключение "Во вложенной таблице ровно две выбранные колонки";
КонецЕсли;
Имена = СтрРазделить("КодДетали,Количество", ",");
Типы = СтрРазделить("Строка,Число", ",");
Для Индекс = 0 По 1 Цикл
Колонка = ВложеннаяКолонка.Колонки.Получить(Индекс);
Если ТипЗнч(Колонка) <> Тип("КолонкаСхемыЗапроса") Или Колонка.Псевдоним <> Имена[Индекс]
Или Колонка.Поля.Количество() <> 1 Тогда
ВызватьИсключение "Не совпал порядок и псевдонимы всех внутренних колонок";
КонецЕсли;
Выражение = Вложенная.Поля.Получить(Индекс);
Если ТипЗнч(Выражение) <> Тип("ВыражениеСхемыЗапроса")
Или ТипЗнч(Колонка.Поля.Получить(0)) <> Тип("ВыражениеСхемыЗапроса")
Или Выражение <> Колонка.Поля.Получить(0)
Или Выражение <> ИзКолонки.Поля.Получить(Индекс) Тогда
ВызватьИсключение "Внутренние поля и колонки должны содержать одинаковые полные выражения";
КонецЕсли;
ПроверитьСвойТипВложенногоПоля(Колонка.ТипЗначения, Тип(Типы[Индекс]));
КонецЦикла;
Возврат Вложенная;
КонецФункции
Процедура СравнитьСвоиВложенныеСхемы(Схема, Эталон)
Факт = ПроверитьСвоюВложеннуюСтруктуру(Схема);
Ожидание = ПроверитьСвоюВложеннуюСтруктуру(Эталон);
Если Факт.Имя <> Ожидание.Имя Или Схема.ПолучитьТекстЗапроса() <> Эталон.ПолучитьТекстЗапроса() Тогда
ВызватьИсключение "Не совпал полный собственный запрос с независимо разобранным эталоном";
КонецЕсли;
Для Индекс = 0 По 1 Цикл
Если Факт.Поля.Получить(Индекс) <> Ожидание.Поля.Получить(Индекс) Тогда
ВызватьИсключение "Не совпало полное выражение внутренней колонки";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ПроверитьСвойПовторныйРазборВложения(Схема, Эталон)
Повторная = СоздатьСвоюВложеннуюСхему(Схема.ПолучитьТекстЗапроса());
СравнитьСвоиВложенныеСхемы(Повторная, Эталон);
КонецПроцедурыУчебныеВложения85.Форма
Своя внешняя обработка УчебныеВложения85 → управляемая Форма → Модуль
Полный отдельный модуль собственной формы: модель запроса работает на сервере, здесь не запускалась.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
Сообщить("Вложенная таблица: описание, колонки, удвоение выражения и восстановление проверены");
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныеЗадачи.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
Первый уровень запроса содержит Код и Детали; второй задаётся скобками после Сборки.Детали. Внутри явно выбраны КодДетали и Количество. Это вложенная таблица в поле выборки, а не отдельный источник Справочник.УчебныеСборки85.Детали.
Сначала проверить собственную конфигурацию и полные типы метаданных. Из текущего физического источника получить доступную Детали через ДоступныеПоля.Найти. Проверить ДоступнаяВложеннаяТаблицаСхемыЗапроса, её строковое Имя и коллекцию доступных полей; найти оба собственных реквизита и проверить их полные наборы типов.
Из ВыбираемыеПоля.Получить(1) получить ВложеннаяТаблицаСхемыЗапроса. Из верхних Колонки.Получить(1) получить КолонкаВложеннаяТаблицаСхемыЗапроса. Проверить все три разных коллекции: доступные поля, выбранные выражения ПоляСхемыЗапроса и поля колонки ПоляКолонкиСхемыЗапроса. Связь последней с текущей вложенной таблицей проверяется отдельно.
У вложенной колонки внешний псевдоним Детали и ровно две внутренние обычные колонки: КодДетали Строка, Количество Число, порядок0/1. Проверяются все выражения полей и колонок, источник, верхний код и полные наборы типов, а не только размеры коллекций. Формат квалификации Имя не угадывается: проверяется конечное собственное имя, а затем полное имя и весь канонический текст сравниваются с самостоятельным эталоном.
Независимо разобрать два явно написанных своих запроса: исходный и с Количество * 2. Взять полное выражение второй внутренней колонки удвоенного эталона, преобразовать документированным способом к строке и создать новое ВыражениеСхемыЗапроса. Передать его в текущая.Поля.Установить(1,...), не присваивать readonly имя или псевдоним вложенной колонки.
Три полных контрольных разбора проверяют исходную схему, удвоенное выражение и восстановление. На каждом этапе сравнивается весь канонический текст с отдельным авторским эталоном и каждое внутреннее выражение. Исходная копия остаётся неизменной. После изменения дочерние описания получаются заново.
Как проверить результат
Будущий результат модели: верхний уровень Код/Детали, внутренний КодДетали/Количество; меняется только формула количества на Количество * 2, потом возвращается исходная. Для воображаемой строки с количеством3 формулы означают3 и6, но ни такая строка, ни результат запроса здесь не создаются и не исполняются.
Будущий отрицательный контроль: только в первом вызове Текущая.Поля.Установить заменить второй аргумент на Новый ВыражениеСхемыЗапроса("3"), оставив УдвоенныйТекст и эталон неизменными. Полное сравнение должно отказать при тех же именах, количестве колонок и типе Число. Вернуть код, сохранить/F7 вне опыта и открыть новый свой сеанс. Здесь контроль не выполнялся.
runtimeVerifiedScenarios=0. Проверка справки и исходников не является запуском конструктора, выполнением запроса, проверкой формы или доказательством полученных данных.
Ожидаемый результат
Урок показывает три объекта одной табличной части и безопасное изменение именно её внутреннего выражения с полным восстановлением и независимой копией.
На что обратить внимание
Все семь свойств трёх вложенных дескрипторов readonly. Полученную коллекцию выбранных полей можно менять документированным Установить, но свойство Поля, имя и псевдоним вложенной колонки не присваиваются. У обычной внутренней колонки другой контракт псевдонима.
Получить верхних колонок возвращает обычную или вложенную колонку. Получить полей колонки допускает также Неопределено; перед обращением к дочерним свойствам здесь проверяются точные типы.
Доступные поля включают стандартные реквизиты табличной части: не утверждается, что их всего два. Ровно два — это явно выбранные внутренние поля, а не весь список доступных полей.
ВыражениеСхемыЗапроса документированно поддерживает преобразование к строке и сравнение по строке. Относительные имена внутренних выражений не выдумываются: полное выражение берётся из отдельно разобранного своего текста.
Это только модель в памяти: нет Запрос.Выполнить, записей, транзакций, сети и рабочих конфигураций. При выполнении запроса вложенное значение было бы РезультатЗапроса; нынешние дескрипторы не являются результатами данных.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.