Четыре собственные записи двух источников превращаются в полную инструкцию с UNION, порядком и итогами. Вторая форма опускает необязательные элементы и выбирает УБЫВ; оба native обхода проверяются целиком.
Где и как запускать
Полный серверный общий модуль УчебныйЯзык новой собственной пустой конфигурации УчебныеПравилаЗапросов85, платформа8.5.1.1343. BSL/запросы/1С здесь не запускались.
Подготовка
В отдельной учебной базе 8.5.1.1343 создайте общий модуль УчебныйЯзык: Сервер=Истина, Глобальный=Ложь, ВызовСервера=Ложь, Привилегированный=Ложь. Клиентские и внешнее соединение отключены; ПовторноеИспользованиеВозвращаемыхЗначений=НеИспользовать.
Вставьте весь приведённый текст в этот общий модуль. ВыполнитьПример — экспортная точка входа; остальные процедуры и функции располагаются рядом, а не внутри неё.
В своей внешней учебной обработке создайте управляемую форму, команду Выполнить и кнопку. Клиентский обработчик Выполнить(Команда) вызывает свою процедуру ВыполнитьНаСервере(); она имеет директиву &НаСервереБезКонтекста и одну строку УчебныйЯзык.ВыполнитьПример();. Это серверный вызов общего модуля, а не разрешение клиенту прямо обращаться к серверной библиотеке.
Все товары, количества и строки придуманы в этом модуле. Запись документов, подключение к чужой базе, файлы, сеть и печать не используются. В рабочие общие модули текст не вставляйте.
HTML только показывает BSL. Код в 1С не запускался; перечисленные результаты и отрицательные опыты проверяйте самостоятельно в собственном стенде.
Создайте НОВУЮ отдельную пустую учебную базу8.5.1.1343, не копию приложения. Имя конфигурации УчебныеПравилаЗапросов85, совместимость отключена. Нет справочников, документов, перечислений, регистров, планов, последовательностей, бизнес-процессов, общих реквизитов, подписок, регламентных заданий, внешних источников или расширений базы/сеанса. Единственный сеанс; ошибки прав не считаются результатом.
Все модули сеанса/приложения, остальные обработчики и формы вручную пусты. Создайте только свой общий модуль УчебныйЯзык: Сервер=Истина, Глобальный=Ложь, ВызовСервера=Ложь, Привилегированный=Ложь. Клиентские/внешнее соединение выключены; повторное использование=НеИспользовать. Полный основной текст заменяет этот модуль целиком, все helpers рядом с экспортной точкой, не внутри.
Сначала подготовьте метаданные и вставьте ПОЛНЫЙ серверный модуль. Затем в новом Конфигураторе сохраните конфигурацию и нажмите F7: обновить конфигурацию базы данных. Обновление выполняйте вне транзакции, только для своего нового пустого стенда; дождитесь окончания. До F7 проверка Метаданные.Имя может не отражать подготовленную конфигурацию. После подготовки отдельной формы начните свежий сеанс 1С и только тогда нажмите Выполнить. Здесь Конфигуратор/F7/1С не выполнялись.
Новая собственная внешняя обработка УчебныйПускПолнойГрамматики85 → управляемая Форма → команда Выполнить, одноимённое действие и кнопка. Остальные модули пусты. Полный отдельный модуль формы:
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
Сообщить("Собственные полные проверки завершены");
КонецПроцедуры&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныйЯзык.ВыполнитьПример();
КонецПроцедурыGuard сверяет пустой состав метаданных, все3read-only источника расширений и отсутствие изменений расширениями, запрещает активную чужую транзакцию. Текст пустых модулей — явное ручное условие, не результат недоступного BSL-чтения. Хранилище данного урока: четыре строки памяти, две ВТ одного своего менеджера. Никаких прикладных записей/чтения объектов/транзакций.
Python — только фиксированная модель данных/ожиданий и статические проверки. Direct HBK подтверждает текст установленной справки, но не исполнение BSL/запросов или маршрутизацию Дата акселератора. Полные результаты нужно вручную проверить в новом своём стенде.
Процедура ВыполнитьПример() Экспорт
ПроверитьСвойПустойСтенд();
Менеджер = Неопределено;
Попытка
Менеджер = Новый МенеджерВременныхТаблиц;
ПроверитьСвоеЦелое(0);
ПроверитьСвоеЦелое(9999);
ПроверитьОтказСвоегоЦелого(Неопределено);
ПроверитьОтказСвоегоЦелого(Null);
ПроверитьОтказСвоегоЦелого(Истина);
ПроверитьОтказСвоегоЦелого("7");
ПроверитьОтказСвоегоЦелого(-1);
ПроверитьОтказСвоегоЦелого(10000);
ПроверитьОтказСвоегоЦелого(0.5);
ПроверитьОтказСвоейГруппы(Неопределено);
ПроверитьОтказСвоейГруппы(Null);
ПроверитьОтказСвоейГруппы(Истина);
ПроверитьОтказСвоейГруппы("AB");
ПроверитьОтказСвоейГруппы("C");
ИсточникА = СоздатьСвойТипизированныйИсточникГрупп();
ОжиданияА = Новый Массив;
ОжиданияА.Добавить(Новый Структура("Группа,Количество", "A", 2));
ОжиданияА.Добавить(Новый Структура("Группа,Количество", "B", 5));
ПроверитьСвойВводГруппы("A", 2);
Запись = ИсточникА.Добавить();
Запись.Группа = "A";
Запись.Количество = 2;
ПроверитьСвойВводГруппы("B", 5);
Запись = ИсточникА.Добавить();
Запись.Группа = "B";
Запись.Количество = 5;
Поля = Новый Массив;
Поля.Добавить("Группа");
Поля.Добавить("Количество");
ПроверитьСвоюПолнуюТаблицу(ИсточникА, ОжиданияА, Поля, Ложь);
Загрузка = Новый Запрос;
Загрузка.МенеджерВременныхТаблиц = Менеджер;
Загрузка.Текст = "ВЫБРАТЬ Д.Группа КАК Группа, Д.Количество КАК Количество ПОМЕСТИТЬ СвояА ИЗ &Источник КАК Д";
Загрузка.УстановитьПараметр("Источник", ИсточникА);
Загрузка.Выполнить();
ИсточникБ = СоздатьСвойТипизированныйИсточникГрупп();
ОжиданияБ = Новый Массив;
ОжиданияБ.Добавить(Новый Структура("Группа,Количество", "A", 3));
ОжиданияБ.Добавить(Новый Структура("Группа,Количество", "B", 7));
ПроверитьСвойВводГруппы("A", 3);
Запись = ИсточникБ.Добавить();
Запись.Группа = "A";
Запись.Количество = 3;
ПроверитьСвойВводГруппы("B", 7);
Запись = ИсточникБ.Добавить();
Запись.Группа = "B";
Запись.Количество = 7;
Поля = Новый Массив;
Поля.Добавить("Группа");
Поля.Добавить("Количество");
ПроверитьСвоюПолнуюТаблицу(ИсточникБ, ОжиданияБ, Поля, Ложь);
Загрузка = Новый Запрос;
Загрузка.МенеджерВременныхТаблиц = Менеджер;
Загрузка.Текст = "ВЫБРАТЬ Д.Группа КАК Группа, Д.Количество КАК Количество ПОМЕСТИТЬ СвояБ ИЗ &Источник КАК Д";
Загрузка.УстановитьПараметр("Источник", ИсточникБ);
Загрузка.Выполнить();
ПроверитьСвоиИсточникиГрамматики(Менеджер, ИсточникА, ИсточникБ, ОжиданияА, ОжиданияБ);
ОжиданияГрупп = Новый Массив;
ОжиданияГрупп.Добавить(Новый Структура("Группа,Количество", "A", 5));
ОжиданияГрупп.Добавить(Новый Структура("Группа,Количество", "B", 12));
ОжиданияДеталей = Новый Массив;
ОжиданияДеталей.Добавить(Новый Структура("Группа,Количество", "A", 2));
ОжиданияДеталей.Добавить(Новый Структура("Группа,Количество", "A", 3));
ОжиданияДеталей.Добавить(Новый Структура("Группа,Количество", "B", 5));
ОжиданияДеталей.Добавить(Новый Структура("Группа,Количество", "B", 7));
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Менеджер;
Запрос.Текст = "ВЫБРАТЬ Д.Группа КАК Группа, Д.Количество КАК Количество ИЗ СвояА КАК Д
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ Д.Группа КАК Группа, Д.Количество КАК Количество ИЗ СвояБ КАК Д
|УПОРЯДОЧИТЬ ПО Группа ВОЗР, Количество ВОЗР
|ИТОГИ СУММА(Количество) ПО Группа КАК Группы";
Результат = Запрос.Выполнить();
ПроверитьСвойПолныйОбход(Результат, ОжиданияГрупп, ОжиданияДеталей);
ПроверитьСвоиИсточникиГрамматики(Менеджер, ИсточникА, ИсточникБ, ОжиданияА, ОжиданияБ);
ОжиданияГрупп = Новый Массив;
ОжиданияГрупп.Добавить(Новый Структура("Группа,Количество", "B", 5));
ОжиданияГрупп.Добавить(Новый Структура("Группа,Количество", "A", 2));
ОжиданияДеталей = Новый Массив;
ОжиданияДеталей.Добавить(Новый Структура("Группа,Количество", "B", 5));
ОжиданияДеталей.Добавить(Новый Структура("Группа,Количество", "A", 2));
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Менеджер;
Запрос.Текст = "ВЫБРАТЬ Д.Группа Группа, Д.Количество Количество ИЗ СвояА Д
|УПОРЯДОЧИТЬ ПО Группа УБЫВ, Количество ВОЗР
|ИТОГИ СУММА(Количество) ПО Группа КАК Группы";
Результат = Запрос.Выполнить();
ПроверитьСвойПолныйОбход(Результат, ОжиданияГрупп, ОжиданияДеталей);
ПроверитьСвоиИсточникиГрамматики(Менеджер, ИсточникА, ИсточникБ, ОжиданияА, ОжиданияБ);
ПроверитьОтказСвоегоТекста(Менеджер, "ВЫБРАТЬ Д.Группа [КАК] Группа, Д.Количество КАК Количество ИЗ СвояА КАК Д");
ПроверитьОтказСвоегоТекста(Менеджер, "ВЫБРАТЬ Д.Группа КАК Группа, Д.Количество КАК Количество ИЗ СвояА КАК Д
|ИТОГИ СУММА(Количество) ПО Группа КАК Группы
|УПОРЯДОЧИТЬ ПО Группа ВОЗР");
ПроверитьСвоиИсточникиГрамматики(Менеджер, ИсточникА, ИсточникБ, ОжиданияА, ОжиданияБ);
Сообщить("Полная первая форма6строк/две группы5,12; вторая4строки/группы B5,A2; все4исхода сохранены");
Исключение
ЗакрытьСвоиВТ(Менеджер);
ВызватьИсключение;
КонецПопытки;
ЗакрытьСвоиВТ(Менеджер);
ПроверитьСвойПустойСтенд();
КонецПроцедуры
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция СовпадаетСвояСтрока(СтрокаТаблицы, Ожидание, Поля, Колонки)
Для Каждого Имя Из Поля Цикл
Если Не Ожидание.Свойство(Имя, Значение) Тогда
ВызватьИсключение "Нет собственного ожидания поля " + Имя;
КонецЕсли;
Факт = СтрокаТаблицы.Получить(Колонки.Индекс(Колонки.Найти(Имя)));
Если ТипЗнч(Факт) <> ТипЗнч(Значение) Тогда
Возврат Ложь;
КонецЕсли;
Если Факт <> Значение Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Процедура ПроверитьСвоюПолнуюТаблицу(Таблица, Ожидания, Поля, Порядок)
Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Тогда
ВызватьИсключение "Нужна своя полная ТаблицаЗначений";
КонецЕсли;
Если Таблица.Колонки.Количество() <> Поля.Количество() Или Таблица.Количество() <> Ожидания.Количество() Тогда
ВызватьИсключение "Не совпали полные размеры своего результата";
КонецЕсли;
Для Каждого Имя Из Поля Цикл
Если Таблица.Колонки.Найти(Имя) = Неопределено Тогда
ВызватьИсключение "Не найдена своя колонка " + Имя;
КонецЕсли;
КонецЦикла;
Использованные = Новый Массив;
Если Ожидания.Количество() > 0 Тогда
Для Индекс = 0 По Ожидания.Количество() - 1 Цикл
Если Порядок Тогда
Если Не СовпадаетСвояСтрока(Таблица[Индекс], Ожидания[Индекс], Поля, Таблица.Колонки) Тогда
ВызватьИсключение "Не совпали все типы, значения или порядок своей строки";
КонецЕсли;
Иначе
Найден = -1;
Для Кандидат = 0 По Ожидания.Количество() - 1 Цикл
Если Использованные.Найти(Кандидат) = Неопределено Тогда
Если СовпадаетСвояСтрока(Таблица[Индекс], Ожидания[Кандидат], Поля, Таблица.Колонки) Тогда
Найден = Кандидат;
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если Найден = -1 Тогда
ВызватьИсключение "Не совпал полный unordered состав с кратностями";
КонецЕсли;
Использованные.Добавить(Найден);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоеЦелое(Количество)
Если ТипЗнч(Количество) <> Тип("Число") Тогда
ВызватьИсключение "Нужно своё Число, не Null, Неопределено или Булево";
КонецЕсли;
Если Количество < 0 Или Количество > 9999 Или Количество <> Цел(Количество) Тогда
ВызватьИсключение "Нужно собственное целое0..9999";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьОтказСвоегоЦелого(Количество)
Отклонён = Ложь;
Попытка
ПроверитьСвоеЦелое(Количество);
Исключение
Отклонён = Истина;
Сообщить("Ручной опыт: неверное своё число отклонено. " + ОписаниеОшибки());
КонецПопытки;
Если Не Отклонён Тогда
ВызватьИсключение "Ожидался отказ своего числового валидатора";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвойТипКолонки(Таблица, Имя, ТипКолонки)
Колонка = Таблица.Колонки.Найти(Имя);
Если Колонка = Неопределено Тогда
ВызватьИсключение "Не найдена своя колонка " + Имя;
КонецЕсли;
Если Колонка.ТипЗначения.Типы().Количество() <> 1 Или Не Колонка.ТипЗначения.СодержитТип(ТипКолонки) Тогда
ВызватьИсключение "У своей колонки должен быть ровно указанный тип";
КонецЕсли;
КонецПроцедуры
Процедура ЗакрытьСвоиВТ(Менеджер)
Если Менеджер <> Неопределено Тогда
Менеджер.Закрыть();
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвойВводГруппы(Группа, Количество)
Если ТипЗнч(Группа) <> Тип("Строка") Тогда
ВызватьИсключение "Своя группа должна иметь тип Строка";
КонецЕсли;
Если Группа <> "A" И Группа <> "B" Тогда
ВызватьИсключение "В своём fixture нужны только группы A/B";
КонецЕсли;
ПроверитьСвоеЦелое(Количество);
КонецПроцедуры
Процедура ПроверитьОтказСвоейГруппы(Группа)
Отклонён = Ложь;
Попытка
ПроверитьСвойВводГруппы(Группа, 2);
Исключение
Отклонён = Истина;
Сообщить("Ручной опыт: своя неверная группа отклонена. " + ОписаниеОшибки());
КонецПопытки;
Если Не Отклонён Тогда
ВызватьИсключение "Ожидался отказ собственного валидатора группы";
КонецЕсли;
КонецПроцедуры
Функция СоздатьСвойТипизированныйИсточникГрупп()
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Группа", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(1, ДопустимаяДлина.Переменная)));
Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(4, 0, ДопустимыйЗнак.Неотрицательный)));
ПроверитьСвоиКвалификаторыГрупп(Таблица);
Возврат Таблица;
КонецФункции
Процедура ПроверитьСвоиКвалификаторыГрупп(Таблица)
ПроверитьСвойТипКолонки(Таблица, "Группа", Тип("Строка"));
ПроверитьСвойТипКолонки(Таблица, "Количество", Тип("Число"));
Строковый = Таблица.Колонки.Найти("Группа").ТипЗначения.КвалификаторыСтроки;
Числовой = Таблица.Колонки.Найти("Количество").ТипЗначения.КвалификаторыЧисла;
Если Строковый.Длина <> 1 Или Строковый.ДопустимаяДлина <> ДопустимаяДлина.Переменная
Или Числовой.Разрядность <> 4 Или Числовой.РазрядностьДробнойЧасти <> 0
Или Числовой.ДопустимыйЗнак <> ДопустимыйЗнак.Неотрицательный Тогда
ВызватьИсключение "Не совпали собственные Строка(1)/Число(4,0)";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоиИсточникиГрамматики(Менеджер, ИсточникА, ИсточникБ, ОжиданияА, ОжиданияБ)
ПроверитьСвоиКвалификаторыГрупп(ИсточникА);
ПроверитьСвоиКвалификаторыГрупп(ИсточникБ);
Поля = Новый Массив;
Поля.Добавить("Группа");
Поля.Добавить("Количество");
ПроверитьСвоюПолнуюТаблицу(ИсточникА, ОжиданияА, Поля, Ложь);
ПроверитьСвоюПолнуюТаблицу(ИсточникБ, ОжиданияБ, Поля, Ложь);
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Менеджер;
Запрос.Текст = "ВЫБРАТЬ Д.Группа КАК Группа, Д.Количество КАК Количество ИЗ СвояА КАК Д";
ПроверитьСвоюПолнуюТаблицу(Запрос.Выполнить().Выгрузить(), ОжиданияА, Поля, Ложь);
Запрос.Текст = "ВЫБРАТЬ Д.Группа КАК Группа, Д.Количество КАК Количество ИЗ СвояБ КАК Д";
ПроверитьСвоюПолнуюТаблицу(Запрос.Выполнить().Выгрузить(), ОжиданияБ, Поля, Ложь);
КонецПроцедуры
Процедура ПроверитьВидСвоейВыборки(Выборка, ОжидаемыйВид, ОжидаемаяГруппировка)
Вид = Выборка.ТипЗаписи();
Группировка = Выборка.Группировка();
Если ТипЗнч(Вид) <> Тип("ТипЗаписиЗапроса") Или ТипЗнч(Группировка) <> Тип("Строка") Тогда
ВызватьИсключение "Не совпали native enum/Строка фактической записи";
КонецЕсли;
Если Вид <> ОжидаемыйВид Или Группировка <> ОжидаемаяГруппировка Тогда
ВызватьИсключение "Не совпали native вид записи или группировка";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвойПолныйОбход(Результат, ОжиданияГрупп, ОжиданияДеталей)
Если Результат.Колонки.Количество() <> 2 Или Результат.Колонки.Найти("Группа") = Неопределено
Или Результат.Колонки.Найти("Количество") = Неопределено Тогда
ВызватьИсключение "Нужны ровно два собственных поля Группа/Количество";
КонецЕсли;
ТаблицаГрупп = СоздатьСвойТипизированныйИсточникГрупп();
ТаблицаДеталей = СоздатьСвойТипизированныйИсточникГрупп();
Группы = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "Группы");
Пока Группы.Следующий() Цикл
ПроверитьВидСвоейВыборки(Группы, ТипЗаписиЗапроса.ИтогПоГруппировке, "Группы");
ПроверитьСвойВводГруппы(Группы.Группа, Группы.Количество);
Запись = ТаблицаГрупп.Добавить();
Запись.Группа = Группы.Группа;
Запись.Количество = Группы.Количество;
Детали = Группы.Выбрать(ОбходРезультатаЗапроса.Прямой, "");
Пока Детали.Следующий() Цикл
ПроверитьВидСвоейВыборки(Детали, ТипЗаписиЗапроса.ДетальнаяЗапись, "");
ПроверитьСвойВводГруппы(Детали.Группа, Детали.Количество);
Если Детали.Группа <> Группы.Группа Тогда
ВызватьИсключение "Реальная вложенная деталь должна относиться к текущей группе";
КонецЕсли;
Запись = ТаблицаДеталей.Добавить();
Запись.Группа = Детали.Группа;
Запись.Количество = Детали.Количество;
КонецЦикла;
КонецЦикла;
Поля = Новый Массив;
Поля.Добавить("Группа");
Поля.Добавить("Количество");
ПроверитьСвоюПолнуюТаблицу(ТаблицаГрупп, ОжиданияГрупп, Поля, Истина);
ПроверитьСвоюПолнуюТаблицу(ТаблицаДеталей, ОжиданияДеталей, Поля, Истина);
ПроверитьСвоюПолнуюТаблицу(Результат.Выгрузить(ОбходРезультатаЗапроса.Прямой), ОжиданияДеталей, Поля, Истина);
КонецПроцедуры
Процедура ПроверитьОтказСвоегоТекста(Менеджер, Текст)
Неверный = Новый Запрос;
Неверный.МенеджерВременныхТаблиц = Менеджер;
Неверный.Текст = Текст;
Отклонён = Ложь;
Попытка
Неверный.Выполнить();
Исключение
Отклонён = Истина;
Сообщить("Ручной native опыт: неправильный текст запроса отклонён. " + ОписаниеОшибки());
КонецПопытки;
Если Не Отклонён Тогда
ВызватьИсключение "Ожидался отказ неправильного собственного текста запроса";
КонецЕсли;
КонецПроцедурыУчебныйПускПолнойГрамматики85.Форма
Собственная внешняя обработка УчебныйПускПолнойГрамматики85 → управляемая Форма → Модуль
Отдельный полный клиентский/серверный модуль формы; серверный вызов без контекста своего общего модуля. Не смешивать с основным BSL.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
Сообщить("Собственные полные проверки завершены");
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныйЯзык.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
Подготовить новый пустой стенд/общий модуль, сохранить и обновить базу F7; полный launcher дан отдельно. Все данные — только память и две ВТ одного своего менеджера.
root.html описывает запрос как инструкцию: здесь конкретно заданы два источника, поля Группа/Количество, объединение, правила сортировки и итогов. Это план собственного отчёта, не неизвестный исходный объект.
syntax_diagram.html: угловые скобки называют конструкции, квадратные обозначают необязательность, вертикальная черта — выбор альтернативы. Эти символы описания не следует копировать в исполняемый текст.
Типы задаются до значений: Группа только Строка(1), Количество только Число(4,0), неотрицательный. Прочитать qualifiers до Добавить; валидировать каждый ввод. Null/Неопределено/Булево не проходят как Число.
Полный fixture: А(A2,B5), Б(A3,B7). Каждый источник памяти полностью проверяется перед своей отдельной загрузкой ПОМЕСТИТЬ; загрузка не содержит запрещённых для внешней таблицы UNION/соединений/итогов.
ShqueryText задаёт порядок: описание запроса, необязательное объединение, сортировка, необязательный AUTOORDER, затем итоги. Первая форма реально применяет описание+UNION ALL+ORDER BY+TOTALS в этом порядке; AUTOORDER опущен, поскольку здесь строковые группы.
Первая полная форма с КАК/ВОЗР даёт группы A5 и B12 и четыре детали A2,A3,B5,B7. UNION работает до сортировки/итогов; две ветви читают свои ВТ, не склеивают заранее рассчитанный ответ.
Вторая форма без необязательного объединения и без слова КАК у полей/источника сохраняет те же алиасы; выбирает альтернативу УБЫВ. Результат только источникаА: группы B5,A2, вложенные детали B5,A2.
Результат.Выбрать(ПоГруппировкам,"Группы") получает реальные итоги. У каждого Группы.Выбрать(Прямой,"") получает его реальные детали; каждой строке проверяются точный enum ТипЗаписиЗапроса, строковое имя Группировка и все значения/типы.
Полный порядок групп и всех вложенных деталей сравнивается с независимыми структурами ожиданий. Каждая деталь должна принадлежать текущей группе. Прямая выгрузка отдельно возвращает четыре/две детали, а не итоговые строки.
Намеренно плохие тексты: буквальные [КАК] из нотации и ORDER BY после TOTALS. Native диаграмма/правило текста объясняют причины; catch охватывает только Выполнить этих неправильных текстов, не подготовку/успешные проверки.
До, между, после двух положительных и после отрицательных опытов полностью сверить оба источника памяти/ВТ. Семь числовых и пять групповых неправильных вводов — отдельные собственные отказы до присвоения.
На обеих ветвях закрыть только свой единственный менеджер двух ВТ; никаких прикладных записей/транзакций. Python моделирует фиксированные ожидания, не исполняет грамматику1С.
Как проверить результат
Полный первый native состав: A5 итог→A2/A3 детали; B12 итог→B5/B7 детали. Две колонки Строка/Число, виды ИтогПоГруппировке/ДетальнаяЗапись, группировки Группы/пустаяСтрока.
Полный второй состав: B5 итог→B5 деталь; A2 итог→A2 деталь. Порядок УБЫВ по группе и все поля проверены; обе прямые выгрузки совпали с4/2деталями.
Вся память/две ВТ с четырьмя исходами до/между/после неизменны. Неверные inputs/скобки/порядок секций не выдаются за положительный результат.
Точный пустой стенд/версия/F7/launcher подготовлены; закрытие своего менеджера вызывается на обеих ветвях. Если Закрыть завершилось ошибкой, очистка не подтверждена и сообщение об успехе недопустимо; иных менеджеров/прикладных записей нет.
Ожидаемый результат
Прочитанные синтаксические правила применены к двум настоящим полным инструкциям с независимой проверкой каждого итога, детали и порядка.
На что обратить внимание
Только новый собственный пустой стенд. Прикладные объекты и реальные рабочие данные не нужны; здесь никакой BSL/1С/БД/F7 не исполнялись.
Python моделирует только фиксированные данные и собственные ожидания. Статические/native проверки не доказывают исполнение запроса в1С.
Все полные типы/значения/кратности и требуемый порядок проверяются отдельно; количество или одинаковая сумма не заменяют полный состав.
ДЛЯ ИЗМЕНЕНИЯ (FORUPDATEStatement), РАЗРЕШЕННЫЕ (KeyWordsALLOWED) и РазмерХранимыхДанных (StoredDataSize) разобраны в самостоятельных уроках с собственными сеансами, правами и данными. Этот урок общей грамматики не заменяет их отдельные задачи.
Квадратные скобки/вертикальная черта в справке — нотация правил, не символы обязательного текста запроса. Необязательный элемент можно опустить, но порядок оставшихся секций сохраняется.
КАК можно опустить не теряя указанный алиас. Это не разрешает дублировать имена колонок или сортировать итоги до построения объединённого результата.
AUTOORDER/иерархия не используются и не прикрепляются. Урок не обещает иной порядок без явных условий сортировки.
ЗакрытьСвоиВТ в аварийной ветви — попытка очистки, не гарантия. Если вызов Закрыть сам завершится ошибкой до повторного ВызватьИсключение, он может заменить исходную диагностику. В таком случае очистка не подтверждена; не считать этот запуск успешным и не повторять опыт в том же сеансе.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.