From 3c3c7110e0149a1b9fe6e2cf2b2ea116066f673b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 09:20:32 +0000 Subject: [PATCH 1/6] =?UTF-8?q?test(model):=20=D0=BF=D0=BE=D0=B8=D1=81?= =?UTF-8?q?=D0=BA=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD=D0=BE=D0=BA,=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BF=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=BB=D0=BE?= =?UTF-8?q?=D0=BD=D0=BE=D0=BA=20=D0=9E=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=9C?= =?UTF-8?q?=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Охрана перед кэшированием: копия Колонки() не влияет на модель, правка служебных колонок видна приведению, поле и колонка ищутся каждый по своему имени, неизвестные поле и колонка дают исключение, идентификатор неизменяем. Исключения проверяются явной попыткой: ВыбрасываетИсключение() из asserts без фрагмента текста проходит и без исключения. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017UYvrFghKi7WmhoF3vvpyp --- ...20\276\320\264\320\265\320\273\320\270.os" | 116 +++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index 1426b4b3..cdeabbe4 100644 --- "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -41,5 +41,119 @@ Ожидаем.Что(ИсточникиДанных, "Объект модели имеет источники данных").ИмеетДлину(2); Ожидаем.Что(ИсточникиДанных[0], "Первый источник данных имеет корректное имя").Равно("Основной"); Ожидаем.Что(ИсточникиДанных[1], "Второй источник данных имеет корректное имя").Равно("Дополнительный"); - + +КонецПроцедуры + +// Колонки() отдает копию: правка результата не меняет ни модель, ни приведение значений по ней. +&Тест +Процедура ИзменениеКопииКолонокНеМеняетПриведение() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Колонки = ОбъектМодели.Колонки(); + Колонки.Найти("Имя", "ИмяПоля").ТипКолонки = ТипыКолонок.Целое; + + Ожидаем.Что(ОбъектМодели.Колонки().Найти("Имя", "ИмяПоля").ТипКолонки, "Модель не видит правку копии") + .Равно(ТипыКолонок.Строка); + Ожидаем.Что(ОбъектМодели.ПривестиЗначениеПоля("12", "Имя"), "Поле приводится по типу модели") + .Равно("12"); + + Автор = Новый Автор; + ОбъектМодели.УстановитьЗначениеКолонкиВПоле(Автор, "Имя", "12"); + Ожидаем.Что(Автор.Имя, "Колонка устанавливается по типу модели").Равно("12"); + +КонецПроцедуры + +// Служебные колонки - сама таблица модели: так ОбработкаКоллекций донастраивает типы колонок +// объекта модели элемента коллекции. Правка видна и поиску колонки, и приведению значения. +&Тест +Процедура ИзменениеСлужебныхКолонокМеняетПриведение() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + ОбъектМодели.Служебный_Колонки().Найти("Имя", "ИмяПоля").ТипКолонки = ТипыКолонок.Целое; + + Ожидаем.Что(ОбъектМодели.Колонки().Найти("Имя", "ИмяПоля").ТипКолонки, "Модель видит правку") + .Равно(ТипыКолонок.Целое); + Ожидаем.Что(ОбъектМодели.ПривестиЗначениеПоля("12", "Имя"), "Поле приводится по новому типу") + .Равно(12); + + Автор = Новый Автор; + ОбъектМодели.УстановитьЗначениеКолонкиВПоле(Автор, "Имя", "12"); + Ожидаем.Что(Автор.Имя, "Колонка устанавливается по новому типу").Равно(12); + + Автор.Имя = "34"; + Ожидаем.Что(ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(Автор, "Имя"), "Значение поля приводится по новому типу") + .Равно(34); + +КонецПроцедуры + +// Поле ищется по имени поля, колонка - по имени колонки: у поля ВтороеИмя колонка Фамилия. +&Тест +Процедура ПолеИКолонкаИщутсяКаждыйПоСвоемуИмени() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Автор = Новый Автор; + ОбъектМодели.УстановитьЗначениеКолонкиВПоле(Автор, "Фамилия", "Иванов"); + Ожидаем.Что(Автор.ВтороеИмя, "Колонка Фамилия пишется в поле ВтороеИмя").Равно("Иванов"); + + Ожидаем.Что(ОбъектМодели.ПривестиЗначениеПоля(5, "ВтороеИмя"), "Поле ВтороеИмя приводится к строке") + .Равно("5"); + Ожидаем.Что(ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(Автор, "ВтороеИмя"), "Поле ВтороеИмя читается") + .Равно("Иванов"); + КонецПроцедуры + +// Исключение проверяется явной попыткой: ВыбрасываетИсключение() из asserts без фрагмента текста +// проходит и тогда, когда исключения не было, а текст этой ошибки зависит от локали. +&Тест +Процедура НеизвестноеПолеНеПриводится() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + ИсключениеВозникло = Ложь; + Попытка + ОбъектМодели.ПривестиЗначениеПоля(1, "НетТакогоПоля"); + Исключение + ИсключениеВозникло = Истина; + КонецПопытки; + + Ожидаем.Что(ИсключениеВозникло, "Неизвестное поле не приводится").ЭтоИстина(); + +КонецПроцедуры + +&Тест +Процедура НеизвестнаяКолонкаНеУстанавливается() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + ИсключениеВозникло = Ложь; + Попытка + ОбъектМодели.УстановитьЗначениеКолонкиВПоле(Новый Автор, "НетТакойКолонки", 1); + Исключение + ИсключениеВозникло = Истина; + КонецПопытки; + + Ожидаем.Что(ИсключениеВозникло, "Неизвестная колонка не устанавливается").ЭтоИстина(); + +КонецПроцедуры + +// Идентификатор отдается неизменяемым: правка результата невозможна и модель не меняет. +&Тест +Процедура ИдентификаторНеизменяем() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Ожидаем.Что(ТипЗнч(ОбъектМодели.Идентификатор()), "Идентификатор - фиксированная структура") + .Равно(Тип("ФиксированнаяСтруктура")); + Ожидаем.Что(ОбъектМодели.Идентификатор().ИмяКолонки, "Идентификатор тот же при повторном обращении") + .Равно("Идентификатор"); + +КонецПроцедуры + +Функция НовыйОбъектМоделиАвтора() + ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "Автор.os"), "Автор"); + ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "СущностьБезГенерируемогоИдентификатора.os"), "СущностьБезГенерируемогоИдентификатора"); + Возврат Новый ОбъектМодели(Тип("Автор"), Неопределено); +КонецФункции From a5b6108d2f074d6fc3320c258b5029f2f996753f Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 09:20:32 +0000 Subject: [PATCH 2/6] =?UTF-8?q?perf(model):=20=D1=81=D0=B1=D0=BE=D1=80?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=81=D1=83=D1=89=D0=BD=D0=BE=D1=81=D1=82=D0=B8?= =?UTF-8?q?=20=D0=B1=D0=B5=D0=B7=20=D0=BA=D0=BE=D0=BF=D0=B8=D0=B9=20=D1=82?= =?UTF-8?q?=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D1=8B=20=D0=BA=D0=BE=D0=BB=D0=BE?= =?UTF-8?q?=D0=BD=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ОбъектМодели строит в конструкторе соответствия колонок по имени поля и по имени колонки, карту описаний типов и неизменяемый идентификатор; дальше они только читаются. Раньше на каждое значение каждой строки копировалась таблица колонок и заново строилась карта из восьми ОписаниеТипов. Соответствия ссылаются на строки самой таблицы, поэтому правка через Служебный_Колонки() видна и им. Публичный Колонки() по-прежнему отдает копию. РаботаСКоннекторами.ЗаполнитьКолонки обходит таблицу модели без копии. Замер, 219 строк, 12 колонок, пул сущностей заполнен: PostgreSQL 863 -> 407 мкс на строку, SQLite 859 -> 292. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017UYvrFghKi7WmhoF3vvpyp --- ...20\276\321\200\320\260\320\274\320\270.os" | 4 +- ...20\276\320\264\320\265\320\273\320\270.os" | 54 ++++++++++++++----- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\240\320\260\320\261\320\276\321\202\320\260\320\241\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200\320\260\320\274\320\270.os" "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\240\320\260\320\261\320\276\321\202\320\260\320\241\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200\320\260\320\274\320\270.os" index 5cd1bc2c..a07dc014 100644 --- "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\240\320\260\320\261\320\276\321\202\320\260\320\241\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200\320\260\320\274\320\270.os" +++ "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\240\320\260\320\261\320\276\321\202\320\260\320\241\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200\320\260\320\274\320\270.os" @@ -539,7 +539,9 @@ // Процедура ЗаполнитьКолонки(Сущность, НайденнаяСтрока, Менеджер, ОбъектМодели, Знач ЗначениеИдентификатора) - Для Каждого Колонка Из ОбъектМодели.Колонки() Цикл + // Таблица модели без копии: здесь она только читается, а копия на каждую строку результата + // стоила бы дороже самого заполнения. + Для Каждого Колонка Из ОбъектМодели.Служебный_Колонки() Цикл ЗначениеКолонки = НайденнаяСтрока.Получить(Колонка.ИмяКолонки); diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index ec6c2cdc..eca5d15d 100644 --- "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -9,19 +9,30 @@ Перем ПодчиненныеТаблицы; // TODO: Первичный ключ из нескольких полей? Перем Идентификатор; +Перем ФиксированныйИдентификатор; + +// Строки таблицы Колонки по имени поля и по имени колонки. Строятся в конструкторе и дальше только +// читаются, в том числе из многих потоков. Ссылаются на сами строки таблицы, поэтому правка строки +// через Служебный_Колонки() видна и через них; строки после конструктора не добавляются. +Перем КолонкиПоИмениПоля; +Перем КолонкиПоИмениКолонки; + +// Соответствие типа колонки модели его ОписаниюТипов. Строится в конструкторе и дальше только читается. +Перем ОписанияТиповКолонок; Перем МодельДанных; Перем Рефлектор; Процедура ПриСозданииОбъекта(ПТипСущности, ПМодельДанных) - + МодельДанных = ПМодельДанных; ТипСущности = ПТипСущности; + ОписанияТиповКолонок = СоответствиеТиповМоделиОписанийТипов(); ЗаполнитьКолонки(); ЗаполнитьПодчиненныеТаблицы(); Рефлектор = Новый Рефлектор; - + КонецПроцедуры Функция ИмяТаблицы() Экспорт @@ -55,7 +66,10 @@ КонецПроцедуры Функция Идентификатор() Экспорт - Возврат Новый ФиксированнаяСтруктура(Идентификатор); + Если ФиксированныйИдентификатор = Неопределено Тогда + Возврат Новый ФиксированнаяСтруктура(Идентификатор); + КонецЕсли; + Возврат ФиксированныйИдентификатор; КонецФункции Функция МодельДанных() Экспорт @@ -73,9 +87,9 @@ Функция ПолучитьПриведенноеЗначениеПоля(Сущность, ИмяПоля) Экспорт ЗначениеПоля = ПолучитьЗначениеПоля(Сущность, ИмяПоля); - - Колонка = Колонки().Найти(ИмяПоля, "ИмяПоля"); - + + Колонка = КолонкиПоИмениПоля.Получить(ИмяПоля); + Если Колонка.ТипКолонки = ТипыКолонок.Ссылка Тогда ОбъектМоделиСсылки = МодельДанных.Получить(Колонка.ТипСсылки); Если ЗначениеПоля = Неопределено Тогда @@ -94,8 +108,8 @@ Процедура УстановитьЗначениеКолонкиВПоле(Сущность, ИмяКолонки, ЗначениеПоля) Экспорт - Колонка = Колонки().Найти(ИмяКолонки, "ИмяКолонки"); - + Колонка = КолонкиПоИмениКолонки.Получить(ИмяКолонки); + Если Колонка.ТипКолонки = ТипыКолонок.Ссылка Тогда УстанавливаемоеЗначениеПоля = ЗначениеПоля; Иначе @@ -112,7 +126,7 @@ Функция ПривестиЗначениеПоля(ЗначениеПоля, ИмяПоля) Экспорт - Колонка = Колонки().Найти(ИмяПоля, "ИмяПоля"); + Колонка = КолонкиПоИмениПоля.Получить(ИмяПоля); Возврат ВыполнитьПриведениеЗначения(Колонка, ЗначениеПоля); КонецФункции @@ -173,6 +187,22 @@ ЗаполнитьЗначенияСвойств(Колонки.Добавить(), ДанныеОКолонке); КонецЦикла; + // Как Колонки.Найти: при совпадении имен находится первая строка. + КолонкиПоИмениПоля = Новый Соответствие; + КолонкиПоИмениКолонки = Новый Соответствие; + Для Каждого Колонка Из Колонки Цикл + Если КолонкиПоИмениПоля.Получить(Колонка.ИмяПоля) = Неопределено Тогда + КолонкиПоИмениПоля.Вставить(Колонка.ИмяПоля, Колонка); + КонецЕсли; + Если КолонкиПоИмениКолонки.Получить(Колонка.ИмяКолонки) = Неопределено Тогда + КолонкиПоИмениКолонки.Вставить(Колонка.ИмяКолонки, Колонка); + КонецЕсли; + КонецЦикла; + + Если Идентификатор <> Неопределено Тогда + ФиксированныйИдентификатор = Новый ФиксированнаяСтруктура(Идентификатор); + КонецЕсли; + КонецПроцедуры Процедура ЗаполнитьПодчиненныеТаблицы() @@ -300,10 +330,8 @@ КонецЕсли; ОбработанноеЗначение = Значение; - - КартаОписанийТипов = СоответствиеТиповМоделиОписанийТипов(); - - ОписаниеТипов = КартаОписанийТипов.Получить(Колонка.ТипКолонки); + + ОписаниеТипов = ОписанияТиповКолонок.Получить(Колонка.ТипКолонки); Если ОписаниеТипов = Неопределено Тогда ВызватьИсключение "Неизвестный тип колонки " + Колонка.ИмяКолонки; КонецЕсли; From 0fd9436dc51e1794b7606c8c77d71c36734934ad Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 09:28:55 +0000 Subject: [PATCH 3/6] =?UTF-8?q?fix(model):=20=D0=BF=D0=BE=D0=BD=D1=8F?= =?UTF-8?q?=D1=82=D0=BD=D0=B0=D1=8F=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BD=D0=B5=D0=B8=D0=B7=D0=B2=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BF=D0=BE=D0=BB=D1=8F?= =?UTF-8?q?=20=D0=B8=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ПривестиЗначениеПоля, ПолучитьПриведенноеЗначениеПоля и УстановитьЗначениеКолонкиВПоле с именем, которого нет в модели, бросают «В модели сущности <Тип> нет поля|колонки <Имя>» вместо ошибки обращения к полю Неопределено, текст которой зависит от локали. Тесты проверяют текст через ВыбрасываетИсключение. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017UYvrFghKi7WmhoF3vvpyp --- ...20\276\320\264\320\265\320\273\320\270.os" | 23 ++++++++-- ...20\276\320\264\320\265\320\273\320\270.os" | 44 ++++++++++++------- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index eca5d15d..9e8ab057 100644 --- "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -86,10 +86,9 @@ КонецФункции Функция ПолучитьПриведенноеЗначениеПоля(Сущность, ИмяПоля) Экспорт + Колонка = КолонкаПоИмениПоля(ИмяПоля); ЗначениеПоля = ПолучитьЗначениеПоля(Сущность, ИмяПоля); - Колонка = КолонкиПоИмениПоля.Получить(ИмяПоля); - Если Колонка.ТипКолонки = ТипыКолонок.Ссылка Тогда ОбъектМоделиСсылки = МодельДанных.Получить(Колонка.ТипСсылки); Если ЗначениеПоля = Неопределено Тогда @@ -108,7 +107,7 @@ Процедура УстановитьЗначениеКолонкиВПоле(Сущность, ИмяКолонки, ЗначениеПоля) Экспорт - Колонка = КолонкиПоИмениКолонки.Получить(ИмяКолонки); + Колонка = КолонкаПоИмениКолонки(ИмяКолонки); Если Колонка.ТипКолонки = ТипыКолонок.Ссылка Тогда УстанавливаемоеЗначениеПоля = ЗначениеПоля; @@ -126,11 +125,27 @@ Функция ПривестиЗначениеПоля(ЗначениеПоля, ИмяПоля) Экспорт - Колонка = КолонкиПоИмениПоля.Получить(ИмяПоля); + Колонка = КолонкаПоИмениПоля(ИмяПоля); Возврат ВыполнитьПриведениеЗначения(Колонка, ЗначениеПоля); КонецФункции +Функция КолонкаПоИмениПоля(Знач ИмяПоля) + Колонка = КолонкиПоИмениПоля.Получить(ИмяПоля); + Если Колонка = Неопределено Тогда + ВызватьИсключение СтрШаблон("В модели сущности %1 нет поля %2", ТипСущности, ИмяПоля); + КонецЕсли; + Возврат Колонка; +КонецФункции + +Функция КолонкаПоИмениКолонки(Знач ИмяКолонки) + Колонка = КолонкиПоИмениКолонки.Получить(ИмяКолонки); + Если Колонка = Неопределено Тогда + ВызватьИсключение СтрШаблон("В модели сущности %1 нет колонки %2", ТипСущности, ИмяКолонки); + КонецЕсли; + Возврат Колонка; +КонецФункции + Функция ПолучитьЗначениеПоля(Сущность, ИмяПоля) Экспорт ЗначениеПоля = Рефлектор.ПолучитьСвойство(Сущность, ИмяПоля); Возврат ЗначениеПоля; diff --git "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index cdeabbe4..9e83c300 100644 --- "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -105,21 +105,18 @@ КонецПроцедуры -// Исключение проверяется явной попыткой: ВыбрасываетИсключение() из asserts без фрагмента текста -// проходит и тогда, когда исключения не было, а текст этой ошибки зависит от локали. &Тест Процедура НеизвестноеПолеНеПриводится() Экспорт ОбъектМодели = НовыйОбъектМоделиАвтора(); - ИсключениеВозникло = Ложь; - Попытка - ОбъектМодели.ПривестиЗначениеПоля(1, "НетТакогоПоля"); - Исключение - ИсключениеВозникло = Истина; - КонецПопытки; + Параметры = Новый Массив; + Параметры.Добавить(1); + Параметры.Добавить("НетТакогоПоля"); - Ожидаем.Что(ИсключениеВозникло, "Неизвестное поле не приводится").ЭтоИстина(); + Ожидаем.Что(ОбъектМодели) + .Метод("ПривестиЗначениеПоля", Параметры) + .ВыбрасываетИсключение("В модели сущности Автор нет поля НетТакогоПоля"); КонецПроцедуры @@ -128,14 +125,29 @@ ОбъектМодели = НовыйОбъектМоделиАвтора(); - ИсключениеВозникло = Ложь; - Попытка - ОбъектМодели.УстановитьЗначениеКолонкиВПоле(Новый Автор, "НетТакойКолонки", 1); - Исключение - ИсключениеВозникло = Истина; - КонецПопытки; + Параметры = Новый Массив; + Параметры.Добавить(Новый Автор); + Параметры.Добавить("НетТакойКолонки"); + Параметры.Добавить(1); - Ожидаем.Что(ИсключениеВозникло, "Неизвестная колонка не устанавливается").ЭтоИстина(); + Ожидаем.Что(ОбъектМодели) + .Метод("УстановитьЗначениеКолонкиВПоле", Параметры) + .ВыбрасываетИсключение("В модели сущности Автор нет колонки НетТакойКолонки"); + +КонецПроцедуры + +&Тест +Процедура НеизвестноеПолеНеЧитается() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Параметры = Новый Массив; + Параметры.Добавить(Новый Автор); + Параметры.Добавить("НетТакогоПоля"); + + Ожидаем.Что(ОбъектМодели) + .Метод("ПолучитьПриведенноеЗначениеПоля", Параметры) + .ВыбрасываетИсключение("В модели сущности Автор нет поля НетТакогоПоля"); КонецПроцедуры From f0bc2e22b3bd0750c3f98222f1a684557f435cee Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 09:43:32 +0000 Subject: [PATCH 4/6] =?UTF-8?q?refactor(model):=20=D0=9A=D0=BE=D0=BB=D0=BE?= =?UTF-8?q?=D0=BD=D0=BA=D0=B8()=20=D0=B1=D0=B5=D0=B7=20=D0=BA=D0=BE=D0=BF?= =?UTF-8?q?=D0=B8=D0=B8,=20=D0=B8=D0=B4=D0=B5=D0=BD=D1=82=D0=B8=D1=84?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D1=80=20=D1=81=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D1=83=20=D1=84=D0=B8=D0=BA=D1=81=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Колонки() отдает саму таблицу модели, только для чтения; служебный Служебный_Колонки() удален - ОбработкаКоллекций и ЗаполнитьКолонки берут Колонки(). Поиск колонки - Найти по таблице модели вместо двух соответствий. Поле Идентификатор хранит ФиксированнуюСтруктуру, отдельное поле под нее не нужно. Замер, 219 строк, 12 колонок, пул сущностей заполнен: PostgreSQL 378 мкс на строку, SQLite 358 - на уровне варианта с соответствиями. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017UYvrFghKi7WmhoF3vvpyp --- ...20\276\320\264\320\265\320\273\320\270.md" | 21 ++++---- ...20\265\320\272\321\206\320\270\320\271.os" | 2 +- ...20\276\321\200\320\260\320\274\320\270.os" | 4 +- ...20\276\320\264\320\265\320\273\320\270.os" | 51 ++++++------------- ...20\276\320\264\320\265\320\273\320\270.os" | 29 ++++------- 5 files changed, 36 insertions(+), 71 deletions(-) diff --git "a/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" "b/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" index b42e3d7f..cfedfbcf 100644 --- "a/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" +++ "b/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" @@ -17,7 +17,15 @@ ### Колонки ```bsl - +// Возвращает таблицу колонок модели - саму таблицу, а не копию. +// +// Объект модели читают многие потоки, поэтому таблица только для чтения. Меняет ее лишь +// ОбработкаКоллекций, донастраивая только что созданный объект модели элемента коллекции, +// который другим потокам еще не виден. +// +// Возвращаемое значение: +// ТаблицаЗначений - Колонки модели. +// Функция Колонки() Экспорт ``` @@ -28,17 +36,6 @@ Функция ПодчиненныеТаблицы() Экспорт ``` -### Служебный_Колонки - -```bsl -// @internal -// TODO: вынести отсюда. Возможно стоит разработать отдельный служебный билдер Объекта модели, -// вытащив заполнение из конструктора в этот билдер, а в конструктор передавать уже готовые для сохранения -// в объект данные. -// -Функция Служебный_Колонки() Экспорт -``` - ### Служебный_ИмяТаблицы ```bsl diff --git "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" index 1eee6066..6ada385a 100644 --- "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" +++ "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" @@ -93,7 +93,7 @@ ); ОбъектМоделиЭлементКоллекции.Служебный_ИмяТаблицы(ПодчиненнаяТаблица.ИмяТаблицы); - КолонкиОбъектаМодели = ОбъектМоделиЭлементКоллекции.Служебный_Колонки(); + КолонкиОбъектаМодели = ОбъектМоделиЭлементКоллекции.Колонки(); КолонкаKey = КолонкиОбъектаМодели.Найти("key", "ИмяКолонки"); КолонкаKey.ТипКолонки = ТипКолонкиКлюч; diff --git "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\240\320\260\320\261\320\276\321\202\320\260\320\241\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200\320\260\320\274\320\270.os" "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\240\320\260\320\261\320\276\321\202\320\260\320\241\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200\320\260\320\274\320\270.os" index a07dc014..5cd1bc2c 100644 --- "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\240\320\260\320\261\320\276\321\202\320\260\320\241\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200\320\260\320\274\320\270.os" +++ "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\240\320\260\320\261\320\276\321\202\320\260\320\241\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200\320\260\320\274\320\270.os" @@ -539,9 +539,7 @@ // Процедура ЗаполнитьКолонки(Сущность, НайденнаяСтрока, Менеджер, ОбъектМодели, Знач ЗначениеИдентификатора) - // Таблица модели без копии: здесь она только читается, а копия на каждую строку результата - // стоила бы дороже самого заполнения. - Для Каждого Колонка Из ОбъектМодели.Служебный_Колонки() Цикл + Для Каждого Колонка Из ОбъектМодели.Колонки() Цикл ЗначениеКолонки = НайденнаяСтрока.Получить(Колонка.ИмяКолонки); diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index 9e8ab057..20e6a8f6 100644 --- "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -8,14 +8,8 @@ Перем Колонки; Перем ПодчиненныеТаблицы; // TODO: Первичный ключ из нескольких полей? +// ФиксированнаяСтруктура. Перем Идентификатор; -Перем ФиксированныйИдентификатор; - -// Строки таблицы Колонки по имени поля и по имени колонки. Строятся в конструкторе и дальше только -// читаются, в том числе из многих потоков. Ссылаются на сами строки таблицы, поэтому правка строки -// через Служебный_Колонки() видна и через них; строки после конструктора не добавляются. -Перем КолонкиПоИмениПоля; -Перем КолонкиПоИмениКолонки; // Соответствие типа колонки модели его ОписаниюТипов. Строится в конструкторе и дальше только читается. Перем ОписанияТиповКолонок; @@ -43,33 +37,30 @@ Возврат ИсточникиДанных; КонецФункции +// Возвращает таблицу колонок модели - саму таблицу, а не копию. +// +// Объект модели читают многие потоки, поэтому таблица только для чтения. Меняет ее лишь +// ОбработкаКоллекций, донастраивая только что созданный объект модели элемента коллекции, +// который другим потокам еще не виден. +// +// Возвращаемое значение: +// ТаблицаЗначений - Колонки модели. +// Функция Колонки() Экспорт - Возврат Колонки.Скопировать(); + Возврат Колонки; КонецФункции Функция ПодчиненныеТаблицы() Экспорт Возврат ПодчиненныеТаблицы.Скопировать(); КонецФункции -// @internal -// TODO: вынести отсюда. Возможно стоит разработать отдельный служебный билдер Объекта модели, -// вытащив заполнение из конструктора в этот билдер, а в конструктор передавать уже готовые для сохранения -// в объект данные. -// -Функция Служебный_Колонки() Экспорт - Возврат Колонки; -КонецФункции - // @internal Процедура Служебный_ИмяТаблицы(ПИмяТаблицы) Экспорт ИмяТаблицы = ПИмяТаблицы; КонецПроцедуры Функция Идентификатор() Экспорт - Если ФиксированныйИдентификатор = Неопределено Тогда - Возврат Новый ФиксированнаяСтруктура(Идентификатор); - КонецЕсли; - Возврат ФиксированныйИдентификатор; + Возврат Идентификатор; КонецФункции Функция МодельДанных() Экспорт @@ -131,7 +122,7 @@ КонецФункции Функция КолонкаПоИмениПоля(Знач ИмяПоля) - Колонка = КолонкиПоИмениПоля.Получить(ИмяПоля); + Колонка = Колонки.Найти(ИмяПоля, "ИмяПоля"); Если Колонка = Неопределено Тогда ВызватьИсключение СтрШаблон("В модели сущности %1 нет поля %2", ТипСущности, ИмяПоля); КонецЕсли; @@ -139,7 +130,7 @@ КонецФункции Функция КолонкаПоИмениКолонки(Знач ИмяКолонки) - Колонка = КолонкиПоИмениКолонки.Получить(ИмяКолонки); + Колонка = Колонки.Найти(ИмяКолонки, "ИмяКолонки"); Если Колонка = Неопределено Тогда ВызватьИсключение СтрШаблон("В модели сущности %1 нет колонки %2", ТипСущности, ИмяКолонки); КонецЕсли; @@ -202,20 +193,8 @@ ЗаполнитьЗначенияСвойств(Колонки.Добавить(), ДанныеОКолонке); КонецЦикла; - // Как Колонки.Найти: при совпадении имен находится первая строка. - КолонкиПоИмениПоля = Новый Соответствие; - КолонкиПоИмениКолонки = Новый Соответствие; - Для Каждого Колонка Из Колонки Цикл - Если КолонкиПоИмениПоля.Получить(Колонка.ИмяПоля) = Неопределено Тогда - КолонкиПоИмениПоля.Вставить(Колонка.ИмяПоля, Колонка); - КонецЕсли; - Если КолонкиПоИмениКолонки.Получить(Колонка.ИмяКолонки) = Неопределено Тогда - КолонкиПоИмениКолонки.Вставить(Колонка.ИмяКолонки, Колонка); - КонецЕсли; - КонецЦикла; - Если Идентификатор <> Неопределено Тогда - ФиксированныйИдентификатор = Новый ФиксированнаяСтруктура(Идентификатор); + Идентификатор = Новый ФиксированнаяСтруктура(Идентификатор); КонецЕсли; КонецПроцедуры diff --git "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index 9e83c300..23f08c00 100644 --- "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -44,34 +44,25 @@ КонецПроцедуры -// Колонки() отдает копию: правка результата не меняет ни модель, ни приведение значений по ней. +// Колонки() отдает саму таблицу модели, без копии на каждое обращение. &Тест -Процедура ИзменениеКопииКолонокНеМеняетПриведение() Экспорт +Процедура КолонкиОтдаютТаблицуМодели() Экспорт ОбъектМодели = НовыйОбъектМоделиАвтора(); - Колонки = ОбъектМодели.Колонки(); - Колонки.Найти("Имя", "ИмяПоля").ТипКолонки = ТипыКолонок.Целое; - - Ожидаем.Что(ОбъектМодели.Колонки().Найти("Имя", "ИмяПоля").ТипКолонки, "Модель не видит правку копии") - .Равно(ТипыКолонок.Строка); - Ожидаем.Что(ОбъектМодели.ПривестиЗначениеПоля("12", "Имя"), "Поле приводится по типу модели") - .Равно("12"); - - Автор = Новый Автор; - ОбъектМодели.УстановитьЗначениеКолонкиВПоле(Автор, "Имя", "12"); - Ожидаем.Что(Автор.Имя, "Колонка устанавливается по типу модели").Равно("12"); + Ожидаем.Что(ОбъектМодели.Колонки(), "Повторное обращение отдает ту же таблицу") + .Равно(ОбъектМодели.Колонки()); КонецПроцедуры -// Служебные колонки - сама таблица модели: так ОбработкаКоллекций донастраивает типы колонок -// объекта модели элемента коллекции. Правка видна и поиску колонки, и приведению значения. +// Так ОбработкаКоллекций донастраивает типы колонок объекта модели элемента коллекции: правка +// таблицы колонок видна и поиску колонки, и приведению значения. &Тест -Процедура ИзменениеСлужебныхКолонокМеняетПриведение() Экспорт +Процедура ИзменениеКолонокМеняетПриведение() Экспорт ОбъектМодели = НовыйОбъектМоделиАвтора(); - ОбъектМодели.Служебный_Колонки().Найти("Имя", "ИмяПоля").ТипКолонки = ТипыКолонок.Целое; + ОбъектМодели.Колонки().Найти("Имя", "ИмяПоля").ТипКолонки = ТипыКолонок.Целое; Ожидаем.Что(ОбъектМодели.Колонки().Найти("Имя", "ИмяПоля").ТипКолонки, "Модель видит правку") .Равно(ТипыКолонок.Целое); @@ -159,8 +150,8 @@ Ожидаем.Что(ТипЗнч(ОбъектМодели.Идентификатор()), "Идентификатор - фиксированная структура") .Равно(Тип("ФиксированнаяСтруктура")); - Ожидаем.Что(ОбъектМодели.Идентификатор().ИмяКолонки, "Идентификатор тот же при повторном обращении") - .Равно("Идентификатор"); + Ожидаем.Что(ОбъектМодели.Идентификатор(), "Повторное обращение отдает тот же идентификатор") + .Равно(ОбъектМодели.Идентификатор()); КонецПроцедуры From 005e7536247d6779cf61df9b5d9f1dcb613fcc1a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 09:44:48 +0000 Subject: [PATCH 5/6] =?UTF-8?q?docs(model):=20=D0=B2=20=D0=BE=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B8=D0=B8=20=D0=9A=D0=BE=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=D0=BA=D0=B8()=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Описание метода говорит, что таблица колонок только для чтения, без подробностей реализации. Почему ОбработкаКоллекций ее все же меняет - в комментарии на месте изменения. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017UYvrFghKi7WmhoF3vvpyp --- ...02\320\234\320\276\320\264\320\265\320\273\320\270.md" | 8 ++------ ...73\320\273\320\265\320\272\321\206\320\270\320\271.os" | 1 + ...02\320\234\320\276\320\264\320\265\320\273\320\270.os" | 8 ++------ 3 files changed, 5 insertions(+), 12 deletions(-) diff --git "a/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" "b/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" index cfedfbcf..3c3d21b7 100644 --- "a/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" +++ "b/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" @@ -17,14 +17,10 @@ ### Колонки ```bsl -// Возвращает таблицу колонок модели - саму таблицу, а не копию. -// -// Объект модели читают многие потоки, поэтому таблица только для чтения. Меняет ее лишь -// ОбработкаКоллекций, донастраивая только что созданный объект модели элемента коллекции, -// который другим потокам еще не виден. +// Возвращает таблицу колонок модели. // // Возвращаемое значение: -// ТаблицаЗначений - Колонки модели. +// ТаблицаЗначений - Колонки модели, только для чтения. // Функция Колонки() Экспорт ``` diff --git "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" index 6ada385a..e2af1cf6 100644 --- "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" +++ "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" @@ -93,6 +93,7 @@ ); ОбъектМоделиЭлементКоллекции.Служебный_ИмяТаблицы(ПодчиненнаяТаблица.ИмяТаблицы); + // Колонки модели только для чтения, но этот объект модели только что создан и еще никому не отдан. КолонкиОбъектаМодели = ОбъектМоделиЭлементКоллекции.Колонки(); КолонкаKey = КолонкиОбъектаМодели.Найти("key", "ИмяКолонки"); diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index 20e6a8f6..fa450fc5 100644 --- "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -37,14 +37,10 @@ Возврат ИсточникиДанных; КонецФункции -// Возвращает таблицу колонок модели - саму таблицу, а не копию. -// -// Объект модели читают многие потоки, поэтому таблица только для чтения. Меняет ее лишь -// ОбработкаКоллекций, донастраивая только что созданный объект модели элемента коллекции, -// который другим потокам еще не виден. +// Возвращает таблицу колонок модели. // // Возвращаемое значение: -// ТаблицаЗначений - Колонки модели. +// ТаблицаЗначений - Колонки модели, только для чтения. // Функция Колонки() Экспорт Возврат Колонки; From 6414b68645cfb3658eb0048b8af41358d46e84cb Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 09:48:01 +0000 Subject: [PATCH 6/6] =?UTF-8?q?perf(model):=20=D0=B8=D0=BD=D0=B4=D0=B5?= =?UTF-8?q?=D0=BA=D1=81=D1=8B=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD=D0=BE=D0=BA?= =?UTF-8?q?=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8=20=D0=BF=D0=BE=20=D0=B8?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=8F=20=D0=B8=20?= =?UTF-8?q?=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Индексы строятся в конструкторе, после заполнения таблицы; поиск колонки в ОбъектМодели идет по ним. ОбработкаКоллекций меняет у строк только тип колонки и тип ссылки, индексированные имена не трогает. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017UYvrFghKi7WmhoF3vvpyp --- ...4\320\276\320\264\320\265\320\273\320\270.os" | 3 +++ ...4\320\276\320\264\320\265\320\273\320\270.os" | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index fa450fc5..c5704879 100644 --- "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -189,6 +189,9 @@ ЗаполнитьЗначенияСвойств(Колонки.Добавить(), ДанныеОКолонке); КонецЦикла; + Колонки.Индексы.Добавить("ИмяПоля"); + Колонки.Индексы.Добавить("ИмяКолонки"); + Если Идентификатор <> Неопределено Тогда Идентификатор = Новый ФиксированнаяСтруктура(Идентификатор); КонецЕсли; diff --git "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index 23f08c00..619d6764 100644 --- "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -55,6 +55,22 @@ КонецПроцедуры +// Колонка ищется по имени поля и по имени колонки - по каждому из них есть индекс. +&Тест +Процедура КолонкиИндексированыПоИменам() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Индексы = Новый Массив; + Для Каждого Индекс Из ОбъектМодели.Колонки().Индексы Цикл + Индексы.Добавить(Строка(Индекс)); + КонецЦикла; + + Ожидаем.Что(Индексы, "Есть индекс по имени поля").Содержит("ИмяПоля"); + Ожидаем.Что(Индексы, "Есть индекс по имени колонки").Содержит("ИмяКолонки"); + +КонецПроцедуры + // Так ОбработкаКоллекций донастраивает типы колонок объекта модели элемента коллекции: правка // таблицы колонок видна и поиску колонки, и приведению значения. &Тест