Два настоящих собственных реквизита ХранилищеЗначения записываются только внутри своей отменяемой транзакции. Запрос измеряет поле базы, а независимое чтение проверяет все данные целиком; длина строки и занимаемые байты не смешиваются.
Где и как запускать
Полный серверный общий модуль УчебныйЯзык только новой собственной конфигурации УчебноеХранение85 на8.5.1.1343. Все helpers включены; записи только свои и отменяемые. Запуск в 1С не проверялся.
Подготовка
Создайте НОВУЮ отдельную пустую учебную информационную базу, никогда не копию рабочей базы, на платформе точно8.5.1.1343. Имя конфигурации УчебноеХранение85; режим совместимости Не использовать; единственный учебный сеанс. Других прикладных метаданных, ролей, подписок/заданий, общих реквизитов, внешних источников и расширений базы/сеанса нет. Не подставляйте справочник из КА2/УНФ/УТ/БП.
В Конфигураторе → Справочники → УчебныеХранилища85: Иерархический=Нет; владельцы пусты; код только Строка длина3, Автонумерация=Нет; наименование длина40; нет табличных частей и предопределённых элементов. Реквизиты → Данные: только единственный тип ХранилищеЗначения, не составной. Стандартные поля платформы остаются. Ничего заранее вручную не записывайте.
Все объектные/менеджерские модули, формы справочника, модули приложения/сеанса и обработчики вручную полностью пусты. Native МодульОбъекта/МодульМенеджера возвращают Неопределено и не дают проверить текст: guard не использует это значение как доказательство. Единственные непустые модули — полный общий модуль и полный отдельный модуль собственной формы ниже.
Общие → Общие модули → УчебныйЯзык: Сервер=Истина; Глобальный=Ложь; ВызовСервера=Ложь; Привилегированный=Ложь; клиентские/внешнее соединение отключены; повторное использование выключено. Вставьте весь основной модуль, включая все процедуры/функции на уровне модуля; не вкладывайте полный код в чужую процедуру.
Создайте собственную новую внешнюю обработку УчебныйРазмерПоля85, управляемую Форма, команду Выполнить и её кнопку/действие. Других реквизитов формы не нужно, прочие модули обработки пусты. Отдельный полный модуль формы дан как поддерживающий модуль; серверная процедура БезКонтекста вызывает серверный общий модуль, а хранилища не передаются клиенту.
После ВСЕХ настроек метаданных/флагов и вставки обоих полных модулей сохраните свою конфигурацию. Завершите предыдущий учебный сеанс: активной транзакции/опыта быть не должно. Только ДО будущего запуска выполните Конфигурация → Обновить конфигурацию базы данных (F7), подтвердите только свою новую конфигурацию, дождитесь успешного завершения и запустите свежий сеанс. F7 не выполняется внутри опыта или после Записать в остановленной активной транзакции.
Подготовка и будущий запуск — исключительно ручная работа читателя в собственном стенде. Здесь не запускался Конфигуратор/1С, не созданы записи, не изменены конфигурации пользователя и не выполнен rollback; статические проверки не означают успешного исполнения в1С.
Процедура ВыполнитьПример() Экспорт
ПроверитьСвойСтендХранения();
ПроверитьСвойПустойКаталог();
КороткийТекст = "Азбука: книга ""Мир""";
ДлинныйТекст = "";
Для Индекс = 1 По 400 Цикл
ДлинныйТекст = ДлинныйТекст + "Свой текст: 0123456789;";
КонецЦикла;
Если СтрДлина(КороткийТекст) <> 19 Или СтрДлина(ДлинныйТекст) <> 9200 Тогда
ВызватьИсключение "Не совпали собственные фиксированные исходные строки";
КонецЕсли;
НачатьТранзакцию();
Попытка
Ожидания = Новый Массив;
Ожидания.Добавить(СоздатьСвоёХранилище("001", "Короткий свой текст", КороткийТекст));
Ожидания.Добавить(СоздатьСвоёХранилище("002", "Длинный свой текст", ДлинныйТекст));
ПроверитьСвоиСохранённыеЗначения(Ожидания);
Измерение = Новый Запрос;
Измерение.Текст = "ВЫБРАТЬ Кат.Ссылка КАК Ссылка, Кат.Код КАК Код,
|Кат.Наименование КАК Наименование, Кат.ПометкаУдаления КАК ПометкаУдаления,
|РазмерХранимыхДанных(Кат.Данные) КАК БайтыПоля
|ИЗ Справочник.УчебныеХранилища85 КАК Кат
|УПОРЯДОЧИТЬ ПО Кат.Код ВОЗР";
Первое = Измерение.Выполнить().Выгрузить();
ПроверитьСвоёИзмерение(Первое, Ожидания, 1);
ПроверитьСвоиСохранённыеЗначения(Ожидания);
Второе = Измерение.Выполнить().Выгрузить();
ПроверитьСвоёИзмерение(Второе, Ожидания, 2);
ПроверитьСвоиСохранённыеЗначения(Ожидания);
Исключение
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию();
КонецЕсли;
ПроверитьСвойПустойКаталог();
ВызватьИсключение;
КонецПопытки;
ОтменитьТранзакцию();
ПроверитьСвойПустойКаталог();
Сообщить("Своя транзакция завершена; собственный каталог снова пуст");
КонецПроцедуры
Процедура ПроверитьСвойСтендХранения()
Если Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Или Метаданные.Роли.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый минимальный стенд хранения";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Или ПривилегированныйРежим() Тогда
ВызватьИсключение "Изменения расширениями и привилегированный режим запрещены";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Нужен массив расширений";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "Свой стенд должен быть без расширений базы и сеанса";
КонецЕсли;
КонецЦикла;
МетаКат = Метаданные.Справочники.Найти("УчебныеХранилища85");
Если МетаКат = Неопределено Тогда
ВызватьИсключение "Не найден собственный справочник";
КонецЕсли;
Если МетаКат.Иерархический Или МетаКат.Владельцы.Количество() <> 0
Или МетаКат.ТипКода <> Метаданные.СвойстваОбъектов.ТипКодаСправочника.Строка
Или МетаКат.ДлинаКода <> 3 Или МетаКат.ДлинаНаименования <> 40 Или МетаКат.Автонумерация
Или МетаКат.Реквизиты.Количество() <> 1 Или МетаКат.ТабличныеЧасти.Количество() <> 0 Тогда
ВызватьИсключение "Не совпала собственная схема хранения";
КонецЕсли;
МетаРеквизит = МетаКат.Реквизиты.Найти("Данные");
Если МетаРеквизит = Неопределено Тогда
ВызватьИсключение "Нет собственного реквизита Данные";
КонецЕсли;
ТипыДанных = МетаРеквизит.Тип.Типы();
Если ТипыДанных.Количество() <> 1 Тогда
ВызватьИсключение "Составной тип собственного реквизита запрещён";
КонецЕсли;
Если ТипыДанных[0] <> Тип("ХранилищеЗначения") Тогда
ВызватьИсключение "Данные должны иметь только тип ХранилищеЗначения";
КонецЕсли;
Имена = МетаКат.ПолучитьИменаПредопределенных();
Если ТипЗнч(Имена) <> Тип("ФиксированныйМассив") Тогда
ВызватьИсключение "Нужен фиксированный массив предопределённых имён";
КонецЕсли;
Если Имена.Количество() <> 0 Тогда
ВызватьИсключение "Предопределённые записи запрещены";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвойПустойКаталог()
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Проверка пустоты должна быть вне активной транзакции";
КонецЕсли;
Проверка = Новый Запрос;
Проверка.Текст = "ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Количество ИЗ Справочник.УчебныеХранилища85";
Таблица = Проверка.Выполнить().Выгрузить();
Если Таблица.Количество() <> 1 Или Таблица.Колонки.Количество() <> 1
Или Таблица.Колонки.Найти("Количество") = Неопределено Тогда
ВызватьИсключение "Не получен полный результат проверки пустоты";
КонецЕсли;
Если ТипЗнч(Таблица[0].Количество) <> Тип("Число") Тогда
ВызватьИсключение "Счётчик собственного каталога должен быть числом";
КонецЕсли;
Если Таблица[0].Количество <> 0 Тогда
ВызватьИсключение "Свой справочник не пуст; существующие записи не удалять";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвойВвод(Код, Наименование, Текст)
Если ТипЗнч(Код) <> Тип("Строка") Или ТипЗнч(Наименование) <> Тип("Строка")
Или ТипЗнч(Текст) <> Тип("Строка") Тогда
ВызватьИсключение "Свой код, название и содержимое должны быть строками";
КонецЕсли;
Если (Код <> "001" И Код <> "002") Или СтрДлина(Наименование) < 1
Или СтрДлина(Наименование) > 40 Или СтрДлина(Текст) < 1 Или СтрДлина(Текст) > 10000 Тогда
ВызватьИсключение "Нарушены собственные границы учебного ввода";
КонецЕсли;
КонецПроцедуры
Функция СоздатьСвоёХранилище(Код, Наименование, Текст)
ПроверитьСвойВвод(Код, Наименование, Текст);
СвойОбъект = Справочники.УчебныеХранилища85.СоздатьЭлемент();
СвойОбъект.Код = Код;
СвойОбъект.Наименование = Наименование;
СвойОбъект.ПометкаУдаления = Ложь;
СвойОбъект.Данные = Новый ХранилищеЗначения(Текст);
СвойОбъект.Записать();
Ссылка = СвойОбъект.Ссылка;
Если ТипЗнч(Ссылка) <> Тип("СправочникСсылка.УчебныеХранилища85") Тогда
ВызватьИсключение "Не получена собственная ссылка нужного типа";
КонецЕсли;
Если Ссылка.Пустая() Тогда
ВызватьИсключение "Своя записанная ссылка не должна быть пустой";
КонецЕсли;
Возврат Новый Структура("Ссылка,Код,Наименование,ПометкаУдаления,Текст", Ссылка, Код, Наименование, Ложь, Текст);
КонецФункции
Процедура ПроверитьСвоиСохранённыеЗначения(Ожидания)
Если Ожидания.Количество() <> 2 Или Ожидания[0].Ссылка = Ожидания[1].Ссылка Тогда
ВызватьИсключение "Нужны две различные собственные записи";
КонецЕсли;
Для Каждого Ожидание Из Ожидания Цикл
СвойОбъект = Ожидание.Ссылка.ПолучитьОбъект();
Если СвойОбъект = Неопределено Тогда
ВызватьИсключение "Собственная запись отсутствует";
КонецЕсли;
Если ТипЗнч(СвойОбъект) <> Тип("СправочникОбъект.УчебныеХранилища85") Тогда
ВызватьИсключение "Прочитан объект не своего типа";
КонецЕсли;
Если ТипЗнч(СвойОбъект.Код) <> Тип("Строка") Или ТипЗнч(СвойОбъект.Наименование) <> Тип("Строка")
Или ТипЗнч(СвойОбъект.ПометкаУдаления) <> Тип("Булево") Тогда
ВызватьИсключение "Не совпали типы стандартных собственных полей";
КонецЕсли;
Если СвойОбъект.Ссылка <> Ожидание.Ссылка Или СвойОбъект.Код <> Ожидание.Код
Или СвойОбъект.Наименование <> Ожидание.Наименование Или СвойОбъект.ПометкаУдаления <> Ложь Тогда
ВызватьИсключение "Не совпали все стандартные собственные поля";
КонецЕсли;
Если ТипЗнч(СвойОбъект.Данные) <> Тип("ХранилищеЗначения") Тогда
ВызватьИсключение "Сохранённое поле должно быть хранилищем";
КонецЕсли;
Факт = СвойОбъект.Данные.Получить();
Если ТипЗнч(Факт) <> Тип("Строка") Тогда
ВызватьИсключение "Хранилище не вернуло собственную строку";
КонецЕсли;
Если Факт <> Ожидание.Текст Тогда
ВызватьИсключение "Не совпало полное собственное содержимое, а не только его длина";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ПроверитьНаблюдаемыеБайты(Значение)
Если ТипЗнч(Значение) <> Тип("Число") Тогда
ВызватьИсключение "РазмерХранимыхДанных должен вернуть число";
КонецЕсли;
Если Значение < 0 Или Значение > 999999999999 Или Значение <> Цел(Значение) Тогда
ВызватьИсключение "Измерение должно быть целым неотрицательным числом длины не более12";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоёИзмерение(Таблица, Ожидания, Номер)
Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Тогда
ВызватьИсключение "Не получена собственная таблица измерений";
КонецЕсли;
Если Таблица.Количество() <> 2 Или Таблица.Колонки.Количество() <> 5 Тогда
ВызватьИсключение "Нужны ровно две строки и пять колонок измерений";
КонецЕсли;
ИменаПолей = Новый Массив;
ИменаПолей.Добавить("Ссылка");
ИменаПолей.Добавить("Код");
ИменаПолей.Добавить("Наименование");
ИменаПолей.Добавить("ПометкаУдаления");
ИменаПолей.Добавить("БайтыПоля");
Для Каждого ИмяПоля Из ИменаПолей Цикл
Если Таблица.Колонки.Найти(ИмяПоля) = Неопределено Тогда
ВызватьИсключение "Не найдена полная колонка " + ИмяПоля;
КонецЕсли;
КонецЦикла;
Для Индекс = 0 По 1 Цикл
СтрокаРезультата = Таблица[Индекс];
Ожидание = Ожидания[Индекс];
Если ТипЗнч(СтрокаРезультата.Ссылка) <> Тип("СправочникСсылка.УчебныеХранилища85")
Или ТипЗнч(СтрокаРезультата.Код) <> Тип("Строка") Или ТипЗнч(СтрокаРезультата.Наименование) <> Тип("Строка")
Или ТипЗнч(СтрокаРезультата.ПометкаУдаления) <> Тип("Булево") Тогда
ВызватьИсключение "Не совпали типы всех идентифицирующих полей результата";
КонецЕсли;
Если СтрокаРезультата.Ссылка <> Ожидание.Ссылка Или СтрокаРезультата.Код <> Ожидание.Код
Или СтрокаРезультата.Наименование <> Ожидание.Наименование Или СтрокаРезультата.ПометкаУдаления <> Ложь Тогда
ВызватьИсключение "Не совпали полный состав и порядок собственных строк";
КонецЕсли;
ПроверитьНаблюдаемыеБайты(СтрокаРезультата.БайтыПоля);
Сообщить("Замер" + Строка(Номер) + "; свой код" + Ожидание.Код + "; наблюдалось байтов поля: " + Строка(СтрокаРезультата.БайтыПоля));
КонецЦикла;
КонецПроцедурыУчебныйРазмерПоля85.Форма
Своя новая внешняя обработка УчебныйРазмерПоля85 → управляемая Форма → Модуль
Полный отдельный модуль своей формы с клиентским действием и серверным вызовом БезКонтекста; не смешивать с общим модулем.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
Сообщить("Содержимое проверено; измерения наблюдались; свои записи отменены");
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныйЯзык.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
Сначала guard проверяет новый собственный стенд, точную платформу, схему и отсутствие расширений/ролей/привилегированного режима. До НачатьТранзакцию нет чтения содержимого чужих записей и нет удаления: только строгая проверка Число0 своих записей вне активной транзакции.
Подготовить полностью известные строки: Азбука: книга "Мир" —19символов; Свой текст: 0123456789; повторить400раз —9200символов. СтрДлина служит только проверкой фиксированного входа, а не заменяет измерение базы.
Начать свою транзакцию, создать два разных настоящих элемента с кодами001/002 и полными названиями. Данные=Новый ХранилищеЗначения(Текст) использует только один аргумент: согласно установленному ctor1 сжатие не задано и не используется. Записать не означает ЗафиксироватьТранзакцию.
Своя квитанция Ожидания хранит фактические ссылки двух созданных здесь объектов и весь ожидаемый текст. ПолучитьОбъект сначала проверяется на Неопределено, затем на правильный собственный тип; проверяются ссылка, код, название, Булево Ложь пометки и ХранилищеЗначения.
Получить() возвращает произвольное значение, поэтому сначала проверяется именно Строка, затем равенство ВСЕГО текста. Одной длины недостаточно: содержимое той же длины, но с другим символом, должно быть отклонено.
В запросе функция получает именно Кат.Данные из Справочник.УчебныеХранилища85, не строку из памяти и не параметр &Текст. Выборка содержит пять уникальных колонок: фактическая ссылка, код, название, пометка и наблюдаемое число байтов поля.
УПОРЯДОЧИТЬ ПО Кат.Код ВОЗР устанавливает ожидаемый порядок001/002. Сверяются обе строки целиком, точные пять имён и все типы; число байтов проверяется как неотрицательное целое не более999999999999. Булево, Null, отрицательное/дробное значение не принимаются.
Повторить реальный измерительный запрос, независимо проверить обе новые строки и снова перечитать полное содержимое обеих записей. Не сравнивать размеры с19/9200, не требовать размер002>размер001 и не задавать ложную константу ожидаемых байтов.
На успешном пути и при ошибке завершить только собственную транзакцию отменой и доказать в своём стенде отсутствие активной транзакции, полный результат COUNT(*) с одной строкой/колонкой и Число0. Нет фиксации, удаления, записи файлов или вызова сети.
Как проверить результат
Будущий ручной положительный опыт: четыре сообщения замеров, по два собственных кода001/002 для каждого замера; конкретные числа берутся из вашей СУБД. Три независимых полных readback обеих строк должны совпасть с19- и9200-символьными исходниками. Сообщения о завершении выводятся только после rollback и проверки Число0.
В отладчике до отмены проверить Первое/Второе: ровно2строки,5колонок, разные собственные ссылки, коды001/002 по порядку, полные свои названия, Булево Ложь и допустимые фактические Число-байты. После отмены своя проверка COUNT(*) показывает0, ТранзакцияАктивна() возвращаетЛожь.
Для отдельной будущей проверки отказа, только вне активной транзакции, временно заменить последний символ ожидаемого Ожидания[0].Текст на другой символ той же длины перед первым ПроверитьСвоиСохранённыеЗначения. Сохранить/обновить свою конфигурацию (F7), запустить свежий сеанс: должно быть исключение полного содержимого и аварийный rollback; положительного финального сообщения быть не должно. Затем убрать временную правку и повторить F7 до нового сеанса.
Контроль аварийного отката отдельно: после завершённого положительного опыта и Число0 завершить сеанс; в полном общем модуле сразу ПОСЛЕ Ожидания.Добавить(СоздатьСвоёХранилище("002", "Длинный свой текст", ДлинныйТекст)); временно вставить ВызватьИсключение "Учебный отказ после двух собственных записей";. Только затем, вне активной транзакции, сохранить/F7/свежий сеанс. После ошибки в catch проверить Ложь транзакции и Число0, без финального успеха. Удалить временную строку и снова обновить/F7 до свежего сеанса; здесь ни один ручной опыт не запускался.
Ожидаемый результат
Будущий ручной результат — реальные наблюдаемые байты двух собственных полей, полностью сохранённое содержимое и пустой каталог после отмены. Заранее обещать конкретное количество байтов нельзя.
На что обратить внимание
Это размер указанных полей по функции запроса, не точный физический размер базы, файла, таблицы, индексов или её свободного пространства. Native прямо допускает отличие фактического размера и разные значения на разных СУБД для одних данных.
СтрДлина измеряет символы, а РазмерХранимыхДанных возвращает байты хранения поля. Не умножайте19или9200на фиксированное число байтов и не делайте из двух измерений вывод о степени сжатия: второй параметр конструктора в этом уроке вообще не передан.
По установленной справке запрос с этой функцией не передаётся в Дата акселератор. Это ограничение контракта, не выполненное здесь измерение маршрута или скорости; здесь нет настройки акселератора и времени исполнения.
ПолучитьОбъект может вернуть Неопределено; неверный тип реквизита, недостаточные права, ошибка запроса или записи — отказ подготовки/опыта, а не успешное измерение. Такой отказ не следует заменять размером0.
Если отмена или контроль пустоты сами завершатся ошибкой, вторичная ошибка может заменить исходную и очистка не доказана. Не сообщать об успехе и не удалять записи вслепую; разбирать только свой новый стенд. Проверка версии/метаданных не доказывает пустоту текста модулей: их необходимо вручную проверить в Конфигураторе.
BSL, запросы, запись и rollback в 1С здесь не исполнялись. Python моделирует только наши фиксированные входы и валидаторы, direct HBK — только установленный контракт. ДЛЯ ИЗМЕНЕНИЯ и РАЗРЕШЕННЫЕ разобраны в самостоятельных уроках с собственными сеансами/правами; измерение размера поля не заменяет эти задачи.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.