├── .gitattributes ├── src ├── fake-entrypoint.os ├── oscript.cfg ├── Классы │ ├── ЭлементПорядка.os │ ├── ЭлементОтбора.os │ ├── МодельДанных.os │ ├── ИсточникДанных.os │ ├── ОпцииПоиска.os │ ├── АбстрактныйКоннектор.os │ ├── ХранилищеСущностей.os │ ├── КоннекторSQLite.os │ ├── МенеджерСущностей.os │ ├── АбстрактныйКоннекторSQL.os │ ├── КоннекторInMemory.os │ ├── ОбъектМодели.os │ ├── КоннекторPostgreSQL.os │ └── КоннекторJSON.os ├── Модули │ ├── ТипыПодчиненныхТаблиц.os │ ├── ВидСравнения.os │ └── ТипыКолонок.os ├── internal │ ├── Классы │ │ └── СлужебнаяСущность_ЭлементКоллекцииКлючЗначение.os │ ├── ДинамическиПодключаемыеКлассы │ │ ├── КонструкторКоннектораSQLiteWeb.os │ │ ├── КонструкторКоннектораSQLite.os │ │ ├── КонструкторКоннектораPostgreSQLWeb.os │ │ └── КонструкторКоннектораPostgreSQL.os │ └── Модули │ │ ├── ХранилищеВПамяти.os │ │ ├── ХранилищаСущностей.os │ │ ├── АктивнаяЗапись.os │ │ ├── ОбработкаКоллекций.os │ │ └── РаботаСКоннекторами.os └── Аннотации │ └── Классы │ ├── АннотацияИдентификатор.os │ ├── АннотацияГенерируемоеЗначение.os │ ├── АннотацияСущность.os │ ├── АннотацияПодчиненнаяТаблица.os │ └── АннотацияКолонка.os ├── tasks ├── oscript.cfg ├── coverage.os └── test.os ├── .vscode ├── settings.json └── launch.json ├── .gitignore ├── docs ├── ВидСравнения.md ├── ТипыПодчиненныхТаблиц.md ├── ЭлементПорядка.md ├── ЭлементОтбора.md ├── АктивнаяЗапись.md ├── ТипыКолонок.md ├── МодельДанных.md ├── README.md ├── ОбъектМодели.md ├── ОпцииПоиска.md ├── КоннекторJSON.md ├── АбстрактныйКоннектор.md ├── ХранилищеСущностей.md ├── КоннекторSQLite.md └── МенеджерСущностей.md ├── .bsl-language-server.json ├── tests ├── fixtures │ ├── ПростойОбъект.os │ ├── АвтоинкрементныйКлючБезКолонок.os │ ├── СущностьБезГенерируемогоИдентификатора.os │ ├── СущностьСИменованнымПолем.os │ ├── Автор.os │ └── СущностьСоВсемиТипамиКолонок.os ├── АбстрактныйКоннектор.os ├── utils │ └── Модули │ │ └── ТестовыеУтилиты.os ├── ОпцииПоиска.os ├── ОбъектМодели.os └── КоннекторJSON.os ├── .github ├── dependabot.yml ├── workflows │ ├── copilot-setup-steps.yml │ ├── main.yml │ ├── release.yml │ └── qa.yml └── copilot-instructions.md ├── sonar-project.properties ├── LICENSE.md ├── packagedef └── lib.config /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bsl eol=lf 2 | *.md eol=lf 3 | -------------------------------------------------------------------------------- /src/fake-entrypoint.os: -------------------------------------------------------------------------------- 1 | #Использовать ".." 2 | -------------------------------------------------------------------------------- /src/oscript.cfg: -------------------------------------------------------------------------------- 1 | lib.additional=../oscript_modules 2 | -------------------------------------------------------------------------------- /tasks/oscript.cfg: -------------------------------------------------------------------------------- 1 | lib.system=../oscript_modules 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "language-1c-bsl.linterEntryPoint": "./src/fake-entrypoint.os", 3 | "coverage-gutters.xmlname": "out/coverage.xml" 4 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.db 2 | *.ospx 3 | 4 | tests-reports/ 5 | .scannerwork/ 6 | .sonar/ 7 | .idea/ 8 | out/ 9 | tests/jsondatabase 10 | oscript_modules/ 11 | -------------------------------------------------------------------------------- /docs/ВидСравнения.md: -------------------------------------------------------------------------------- 1 | ## ВидСравнения 2 | 3 | Значения: 4 | 5 | * Равно 6 | * Больше 7 | * БольшеИлиРавно 8 | * Меньше 9 | * МеньшеИлиРавно 10 | * НеРавно 11 | * В 12 | * НеВ 13 | -------------------------------------------------------------------------------- /docs/ТипыПодчиненныхТаблиц.md: -------------------------------------------------------------------------------- 1 | ## ТипыПодчиненныхТаблиц 2 | 3 | ### Значения 4 | 5 | * Массив 6 | * Структура 7 | 8 | ### Типы 9 | 10 | ```bsl 11 | 12 | Функция Типы() Экспорт 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /.bsl-language-server.json: -------------------------------------------------------------------------------- 1 | { 2 | "diagnostics": { 3 | "parameters": { 4 | "IncorrectLineBreak": { 5 | "listOfIncorrectFirstSymbol": ";|,\\s*\\S+" 6 | } 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /tests/fixtures/ПростойОбъект.os: -------------------------------------------------------------------------------- 1 | 2 | &Идентификатор 3 | Перем Идентификатор Экспорт; 4 | 5 | Перем Поле Экспорт; 6 | 7 | &Сущность(ИмяТаблицы = "ПростыеОбъекты") 8 | Процедура ПриСозданииОбъекта() 9 | 10 | КонецПроцедуры -------------------------------------------------------------------------------- /tests/fixtures/АвтоинкрементныйКлючБезКолонок.os: -------------------------------------------------------------------------------- 1 | &Идентификатор 2 | &ГенерируемоеЗначение 3 | &Колонка(Тип = "Целое") 4 | Перем Идентификатор Экспорт; 5 | 6 | &Сущность(ИмяТаблицы = "ВнешниеСущности") 7 | Процедура ПриСозданииОбъекта() 8 | 9 | КонецПроцедуры -------------------------------------------------------------------------------- /tests/АбстрактныйКоннектор.os: -------------------------------------------------------------------------------- 1 | #Использовать ".." 2 | 3 | &Тест 4 | Процедура АбстрактныйКоннекторРеализуетИнтерфейсКоннектора() Экспорт 5 | МенеджерСущностей = Новый МенеджерСущностей(Тип("АбстрактныйКоннектор")); // BSLLS:UnusedLocalVariable-off 6 | КонецПроцедуры 7 | -------------------------------------------------------------------------------- /tests/fixtures/СущностьБезГенерируемогоИдентификатора.os: -------------------------------------------------------------------------------- 1 | &Идентификатор 2 | &Колонка(Имя = "Идентификатор", Тип = "Целое") 3 | Перем ВнутреннийИдентификатор Экспорт; 4 | 5 | &Сущность(ИмяТаблицы = "ВнешниеСущности") 6 | Процедура ПриСозданииОбъекта() 7 | 8 | КонецПроцедуры -------------------------------------------------------------------------------- /src/Классы/ЭлементПорядка.os: -------------------------------------------------------------------------------- 1 | // BSLLS:ExportVariables-off 2 | Перем ПутьКДанным Экспорт; 3 | Перем НаправлениеСортировки Экспорт; 4 | 5 | Процедура ПриСозданииОбъекта(ППутьКДанным, ПНаправлениеСортировки = Неопределено) 6 | ПутьКДанным = ППутьКДанным; 7 | НаправлениеСортировки = ПНаправлениеСортировки; 8 | КонецПроцедуры 9 | -------------------------------------------------------------------------------- /src/Классы/ЭлементОтбора.os: -------------------------------------------------------------------------------- 1 | Перем ПутьКДанным Экспорт; 2 | Перем ВидСравнения Экспорт; 3 | Перем Значение Экспорт; 4 | 5 | Процедура ПриСозданииОбъекта(ППутьКДанным, ПВидСравнения, ПЗначение) 6 | ПутьКДанным = ППутьКДанным ; 7 | ВидСравнения = ПВидСравнения; 8 | Значение = ПЗначение; 9 | КонецПроцедуры 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Модули/ТипыПодчиненныхТаблиц.os: -------------------------------------------------------------------------------- 1 | Перем Массив Экспорт; 2 | Перем Структура Экспорт; 3 | 4 | Перем Типы; 5 | 6 | Функция Типы() Экспорт 7 | Возврат Типы; 8 | КонецФункции 9 | 10 | Массив = "Массив"; 11 | Структура = "Структура"; 12 | 13 | Типы = Новый Массив; 14 | Типы.Добавить(Массив); 15 | Типы.Добавить(Структура); 16 | -------------------------------------------------------------------------------- /docs/ЭлементПорядка.md: -------------------------------------------------------------------------------- 1 | ## ЭлементПорядка 2 | 3 | ### Поля 4 | 5 | | Имя | Тип | 6 | | ------------ | ------------ | 7 | | ПутьКДанным | Строка | 8 | | НаправлениеСортировки | НаправлениеСортировки | 9 | 10 | ### ПриСозданииОбъекта 11 | 12 | ```bsl 13 | 14 | Процедура ПриСозданииОбъекта(ППутьКДанным, ПНаправлениеСортировки = Неопределено) 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /docs/ЭлементОтбора.md: -------------------------------------------------------------------------------- 1 | ## ЭлементОтбора 2 | 3 | ### Поля 4 | 5 | | Имя | Тип | 6 | | ------------ | ------------ | 7 | | ПутьКДанным | Строка | 8 | | ВидСравнения | ВидСравнения | 9 | | Значение | Произвольный | 10 | 11 | ### ПриСозданииОбъекта 12 | 13 | ```bsl 14 | 15 | Процедура ПриСозданииОбъекта(ППутьКДанным, ПВидСравнения, ПЗначение) 16 | ``` 17 | 18 | -------------------------------------------------------------------------------- /tests/fixtures/СущностьСИменованнымПолем.os: -------------------------------------------------------------------------------- 1 | &Идентификатор 2 | &ГенерируемоеЗначение 3 | &Колонка(Имя = "Идентификатор", Тип = "Целое") 4 | Перем ВнутреннийИдентификатор Экспорт; 5 | 6 | Перем Имя Экспорт; 7 | 8 | &Колонка(Имя = "Фамилия") 9 | Перем ВтороеИмя Экспорт; 10 | 11 | &Сущность(ИмяТаблицы = "СущностиСИменованнымПолем") 12 | Процедура ПриСозданииОбъекта() 13 | 14 | КонецПроцедуры 15 | -------------------------------------------------------------------------------- /src/Модули/ВидСравнения.os: -------------------------------------------------------------------------------- 1 | Перем Равно Экспорт; 2 | Перем Больше Экспорт; 3 | Перем БольшеИлиРавно Экспорт; 4 | Перем Меньше Экспорт; 5 | Перем МеньшеИлиРавно Экспорт; 6 | Перем НеРавно Экспорт; 7 | Перем В Экспорт; 8 | Перем НеВ Экспорт; 9 | 10 | Равно = "="; 11 | Больше = ">"; 12 | БольшеИлиРавно = ">="; 13 | Меньше = "<"; 14 | МеньшеИлиРавно = "<="; 15 | НеРавно = "<>"; 16 | В = "IN"; 17 | НеВ = "NOT IN"; 18 | -------------------------------------------------------------------------------- /docs/АктивнаяЗапись.md: -------------------------------------------------------------------------------- 1 | ## АктивнаяЗапись 2 | 3 | ### Сохранить 4 | 5 | ```bsl 6 | // Сохранить текущую сущность. 7 | // 8 | Процедура Сохранить() 9 | ``` 10 | 11 | ### Получить 12 | 13 | ```bsl 14 | // Прочитать текущую сущность. Для чтения в сущностей должно быть заполнено поле, являющееся идентификатором. 15 | // 16 | Процедура Получить() 17 | ``` 18 | 19 | ### Удалить 20 | 21 | ```bsl 22 | // Удалить текущую сущность. 23 | // 24 | Процедура Удалить() 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/ТипыКолонок.md: -------------------------------------------------------------------------------- 1 | ## ТипыКолонок 2 | 3 | ### Значения 4 | 5 | * Целое 6 | * Дробное 7 | * Булево 8 | * Строка 9 | * Дата 10 | * Время 11 | * ДатаВремя 12 | * Ссылка 13 | 14 | ### Типы 15 | 16 | ```bsl 17 | 18 | Функция Типы() Экспорт 19 | ``` 20 | 21 | ### ЭтоПримитивныйТип 22 | 23 | ```bsl 24 | 25 | Функция ЭтоПримитивныйТип(Знач Тип) Экспорт 26 | ``` 27 | 28 | ### ЭтоСсылочныйТип 29 | 30 | ```bsl 31 | 32 | Функция ЭтоСсылочныйТип(Знач Тип) Экспорт 33 | ``` 34 | -------------------------------------------------------------------------------- /src/internal/Классы/СлужебнаяСущность_ЭлементКоллекцииКлючЗначение.os: -------------------------------------------------------------------------------- 1 | &Колонка(Тип = "Целое") 2 | &Идентификатор 3 | &ГенерируемоеЗначение 4 | Перем id Экспорт; 5 | 6 | &Колонка(Тип = "Ссылка", ТипСсылки = "СлужебнаяСущность_ЭлементКоллекцииКлючЗначение") 7 | Перем ref Экспорт; 8 | 9 | &Колонка(Тип = "Целое") 10 | Перем key Экспорт; 11 | 12 | &Колонка 13 | Перем value Экспорт; 14 | 15 | &Сущность 16 | Процедура ПриСозданииОбъекта() 17 | 18 | КонецПроцедуры 19 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /src/Аннотации/Классы/АннотацияИдентификатор.os: -------------------------------------------------------------------------------- 1 | // Каждый класс, подключаемый к менеджеру сущностей, должен иметь поле для хранения 2 | // идентификатора объекта в СУБД - первичного ключа. 3 | // 4 | // Для формирования автоинкрементного первичного ключа можно воспользоваться 5 | // дополнительной аннотацией `&ГенерируемоеЗначение`. 6 | // 7 | // Применяется на поле класса. 8 | // 9 | // Пример: 10 | // 11 | // &Идентификатор 12 | // Перем ИД; 13 | // 14 | &Аннотация("Идентификатор") 15 | Процедура ПриСозданииОбъекта() 16 | КонецПроцедуры 17 | -------------------------------------------------------------------------------- /tests/fixtures/Автор.os: -------------------------------------------------------------------------------- 1 | &Идентификатор 2 | &ГенерируемоеЗначение 3 | &Колонка(Имя = "Идентификатор", Тип = "Целое") 4 | Перем ВнутреннийИдентификатор Экспорт; 5 | 6 | Перем Имя Экспорт; 7 | 8 | &Колонка(Имя = "Фамилия") 9 | Перем ВтороеИмя Экспорт; 10 | 11 | &Колонка(Тип = "Ссылка", ТипСсылки = "СущностьБезГенерируемогоИдентификатора") 12 | Перем ВнешняяСущность Экспорт; 13 | 14 | &Сущность(ИмяТаблицы = "Авторы", ИсточникДанных = "Основной", ИсточникДанных = "Дополнительный") 15 | Процедура ПриСозданииОбъекта() 16 | 17 | КонецПроцедуры 18 | -------------------------------------------------------------------------------- /docs/МодельДанных.md: -------------------------------------------------------------------------------- 1 | ## МодельДанных 2 | 3 | ### ПриСозданииОбъекта 4 | 5 | ```bsl 6 | 7 | Процедура ПриСозданииОбъекта() 8 | ``` 9 | 10 | ### Получить 11 | 12 | ```bsl 13 | 14 | Функция Получить(ТипСущности) Экспорт 15 | ``` 16 | 17 | ### ПолучитьОбъектыМодели 18 | 19 | ```bsl 20 | 21 | Функция ПолучитьОбъектыМодели() Экспорт 22 | ``` 23 | 24 | ### СоздатьОбъектМодели 25 | 26 | ```bsl 27 | 28 | Функция СоздатьОбъектМодели(ТипСущности) Экспорт 29 | ``` 30 | 31 | ### Очистить 32 | 33 | ```bsl 34 | 35 | Процедура Очистить() Экспорт 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /src/Аннотации/Классы/АннотацияГенерируемоеЗначение.os: -------------------------------------------------------------------------------- 1 | // Для части полей допустимо высчитывать значение колонки при вставке записи в таблицу. 2 | // Например, для первичных числовых ключей обычно не требуется явное управление назначаемыми идентификаторами. 3 | // 4 | // Референсная реализация коннекторов на базе SQL поддерживает единственный тип генератора значений - `AUTOINCREMENT`. 5 | // 6 | // Применяется на поле класса. 7 | // 8 | // Пример: 9 | // 10 | // &Идентификатор 11 | // &ГенерируемоеЗначение 12 | // Перем ИД; 13 | // 14 | &Аннотация("ГенерируемоеЗначение") 15 | Процедура ПриСозданииОбъекта() 16 | КонецПроцедуры 17 | -------------------------------------------------------------------------------- /src/internal/ДинамическиПодключаемыеКлассы/КонструкторКоннектораSQLiteWeb.os: -------------------------------------------------------------------------------- 1 | Функция НовыйСоединение() Экспорт 2 | Возврат ИнформационнаяБаза; 3 | КонецФункции 4 | 5 | Процедура Открыть(Соединение, СтрокаСоединения) Экспорт 6 | // no-op 7 | КонецПроцедуры 8 | 9 | Процедура Закрыть(Соединение) Экспорт 10 | // no-op 11 | КонецПроцедуры 12 | 13 | Функция НовыйЗапрос(Соединение) Экспорт 14 | Возврат Соединение.НовыйЗапрос(); 15 | КонецФункции 16 | 17 | Функция ИДПоследнейДобавленнойЗаписи(Соединение, Запрос) Экспорт 18 | Запрос = НовыйЗапрос(Соединение); 19 | Запрос.Текст = "SELECT last_insert_rowid();"; 20 | 21 | Возврат Запрос.ВыполнитьКоманду(); 22 | КонецФункции -------------------------------------------------------------------------------- /src/internal/Модули/ХранилищеВПамяти.os: -------------------------------------------------------------------------------- 1 | 2 | Перем КешиТаблиц; 3 | 4 | Функция КешТаблиц(СтрокаПодключения = "default") Экспорт 5 | Результат = КешиТаблиц.Получить(СтрокаПодключения); 6 | 7 | Если Результат = Неопределено Тогда 8 | Результат = Новый Соответствие(); 9 | КешиТаблиц.Вставить(СтрокаПодключения, Результат); 10 | КонецЕсли; 11 | 12 | Возврат Результат; 13 | 14 | КонецФункции 15 | 16 | Процедура Очистить(СтрокаПодключения = "default") Экспорт 17 | КешиТаблиц.Вставить(СтрокаПодключения, Новый Соответствие()); 18 | КонецПроцедуры 19 | 20 | Процедура Инициализация() 21 | КешиТаблиц = Новый Соответствие(); 22 | КонецПроцедуры 23 | 24 | Инициализация(); -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ## Публичный интерфейс библиотеки entity 2 | 3 | ### Классы 4 | 5 | * [МенеджерСущностей](МенеджерСущностей.md) 6 | * [ХранилищеСущностей](ХранилищеСущностей.md) 7 | * [ОпцииПоиска](ОпцииПоиска.md) 8 | * [АбстрактныйКоннектор](АбстрактныйКоннектор.md) 9 | * [КоннекторSQLite](КоннекторSQLite.md) 10 | * [КоннекторJSON](КоннекторJSON.md) 11 | * [МодельДанных](МодельДанных.md) 12 | * [ОбъектМодели](ОбъектМодели.md) 13 | * [ЭлементОтбора](ЭлементОтбора.md) 14 | * [ЭлементПорядка](ЭлементПорядка.md) 15 | 16 | ### Перечисления 17 | 18 | * [ВидСравнения](ВидСравнения.md) 19 | * [ТипыКолонок](ТипыКолонок.md) 20 | * [ТипыПодчиненныхТаблиц](ТипыПодчиненныхТаблиц.md) 21 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Отладка 1Script", 9 | "type": "oscript", 10 | "request": "launch", 11 | "program": "${file}", 12 | "args": [], 13 | "cwd": "${workspaceRoot}", 14 | "env": {}, 15 | "runtimeExecutable": null, 16 | "runtimeArgs": [], 17 | "debugPort": 2801, 18 | "protocol": "tcp" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /src/internal/ДинамическиПодключаемыеКлассы/КонструкторКоннектораSQLite.os: -------------------------------------------------------------------------------- 1 | #Использовать sql 2 | 3 | Функция НовыйСоединение() Экспорт 4 | Возврат Новый Соединение(); 5 | КонецФункции 6 | 7 | Процедура Открыть(Соединение, СтрокаСоединения) Экспорт 8 | Соединение.ТипСУБД = Соединение.ТипыСУБД.sqlite; 9 | Соединение.СтрокаСоединения = СтрокаСоединения; 10 | Соединение.Открыть(); 11 | КонецПроцедуры 12 | 13 | Процедура Закрыть(Соединение) Экспорт 14 | Соединение.Закрыть(); 15 | КонецПроцедуры 16 | 17 | Функция НовыйЗапрос(Соединение) Экспорт 18 | Возврат Соединение.СоздатьЗапрос(); 19 | КонецФункции 20 | 21 | Функция ИДПоследнейДобавленнойЗаписи(Соединение, Запрос) Экспорт 22 | Возврат Запрос.ИДПоследнейДобавленнойЗаписи(); 23 | КонецФункции 24 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | # must be unique in a given SonarQube instance 2 | sonar.projectKey=entity 3 | 4 | # this is the name displayed in the SonarQube UI 5 | sonar.projectName=entity 6 | 7 | # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. 8 | # Since SonarQube 4.2, this property is optional if sonar.modules is set. 9 | # If not set, SonarQube starts looking for source code from the directory containing 10 | # the sonar-project.properties file. 11 | 12 | sonar.sources=./src 13 | sonar.tests=./tests 14 | 15 | # Encoding of the source code. Default is default system encoding 16 | sonar.sourceEncoding=UTF-8 17 | 18 | sonar.coverageReportPaths=out/genericCoverage.xml 19 | sonar.testExecutionReportPaths=out/tests.xml 20 | -------------------------------------------------------------------------------- /tests/utils/Модули/ТестовыеУтилиты.os: -------------------------------------------------------------------------------- 1 | Функция ПолучитьПеременнуюСредыИлиЗначение(ИмяПеременной, ЗначениеПоУмолчанию) Экспорт 2 | ПеременнаяСреды = ПолучитьПеременнуюСреды(ИмяПеременной); 3 | Если ПеременнаяСреды = Неопределено Тогда 4 | ПеременнаяСреды = ЗначениеПоУмолчанию; 5 | КонецЕсли; 6 | 7 | Возврат ПеременнаяСреды; 8 | КонецФункции 9 | 10 | Процедура УдалитьТаблицыВБазеДанных(Коннектор) Экспорт 11 | ТекстЗапроса = "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"; 12 | Коннектор.ВыполнитьЗапрос(ТекстЗапроса); 13 | КонецПроцедуры 14 | 15 | Процедура СохранитьСущностьСоВсемиТипамиКолонок(Коннектор, ОбъектМодели, Идентификатор) Экспорт 16 | 17 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 18 | Сущность.Целое = Идентификатор; 19 | Коннектор.Сохранить(ОбъектМодели, Сущность); 20 | 21 | КонецПроцедуры 22 | -------------------------------------------------------------------------------- /src/Классы/МодельДанных.os: -------------------------------------------------------------------------------- 1 | Перем ХранилищеМодели; 2 | 3 | Процедура ПриСозданииОбъекта() 4 | ХранилищеМодели = Новый Соответствие; 5 | КонецПроцедуры 6 | 7 | Функция Получить(ТипСущности) Экспорт 8 | Возврат ХранилищеМодели.Получить(ТипСущности); 9 | КонецФункции 10 | 11 | Функция ПолучитьОбъектыМодели() Экспорт 12 | ВсеОбъектыМодели = Новый Массив; 13 | Для Каждого КлючИЗначение Из ХранилищеМодели Цикл 14 | ВсеОбъектыМодели.Добавить(КлючИЗначение.Значение); 15 | КонецЦикла; 16 | 17 | Возврат ВсеОбъектыМодели; 18 | КонецФункции 19 | 20 | Функция СоздатьОбъектМодели(ТипСущности) Экспорт 21 | ОбъектМодели = Новый ОбъектМодели(ТипСущности, ЭтотОбъект); 22 | ХранилищеМодели.Вставить(ТипСущности, ОбъектМодели); 23 | 24 | Возврат ОбъектМодели; 25 | КонецФункции 26 | 27 | Процедура Очистить() Экспорт 28 | ХранилищеМодели.Очистить(); 29 | КонецПроцедуры 30 | -------------------------------------------------------------------------------- /src/Классы/ИсточникДанных.os: -------------------------------------------------------------------------------- 1 | Перем пИмя; 2 | Перем пТипКоннектора; 3 | Перем пСтрокаСоединения; 4 | Перем пПараметрыКоннектора; 5 | 6 | Функция Имя() Экспорт 7 | Возврат пИмя; 8 | КонецФункции 9 | 10 | Функция ТипКоннектора() Экспорт 11 | Возврат пТипКоннектора; 12 | КонецФункции 13 | 14 | Функция СтрокаСоединения() Экспорт 15 | Возврат пСтрокаСоединения; 16 | КонецФункции 17 | 18 | Функция ПараметрыКоннектора() Экспорт 19 | Возврат пПараметрыКоннектора; 20 | КонецФункции 21 | 22 | Процедура ПриСозданииОбъекта( 23 | Знач Имя, 24 | Знач ТипКоннектора, 25 | Знач СтрокаСоединения = "", 26 | Знач ПараметрыКоннектора = Неопределено 27 | ) 28 | 29 | пИмя = Имя; 30 | пТипКоннектора = ТипКоннектора; 31 | пСтрокаСоединения = СтрокаСоединения; 32 | 33 | Если ПараметрыКоннектора = Неопределено Тогда 34 | ПараметрыКоннектора = Новый Массив(); 35 | КонецЕсли; 36 | пПараметрыКоннектора = Новый ФиксированныйМассив(ПараметрыКоннектора); 37 | КонецПроцедуры 38 | -------------------------------------------------------------------------------- /src/internal/ДинамическиПодключаемыеКлассы/КонструкторКоннектораPostgreSQLWeb.os: -------------------------------------------------------------------------------- 1 | Функция НовыйСоединение() Экспорт 2 | Возврат ИнформационнаяБаза; 3 | КонецФункции 4 | 5 | Процедура Открыть(Соединение, СтрокаСоединения) Экспорт 6 | // no-op 7 | КонецПроцедуры 8 | 9 | Процедура Закрыть(Соединение) Экспорт 10 | // no-op 11 | КонецПроцедуры 12 | 13 | Функция НовыйЗапрос(Соединение) Экспорт 14 | Возврат Соединение.НовыйЗапрос(); 15 | // Запрос = Новый Запрос(); 16 | // Запрос.УстановитьСоединение(Соединение); 17 | // Возврат Запрос; 18 | КонецФункции 19 | 20 | Функция ИДПоследнейДобавленнойЗаписи(Соединение, Параметры) Экспорт 21 | 22 | ИДПоследнейДобавленнойЗаписи = -1; 23 | 24 | Запрос = Соединение.НовыйЗапрос(); 25 | Запрос.Текст = СтрШаблон("SELECT max(%1) FROM %2", Параметры.ИмяКолонки, Параметры.ИмяТаблицы); 26 | Рез = Запрос.Выполнить().Выгрузить(); 27 | Если Рез.Количество() > 0 Тогда 28 | ИДПоследнейДобавленнойЗаписи = Рез[0]["max"]; 29 | КонецЕсли; 30 | 31 | Возврат ИДПоследнейДобавленнойЗаписи; 32 | 33 | КонецФункции -------------------------------------------------------------------------------- /src/Аннотации/Классы/АннотацияСущность.os: -------------------------------------------------------------------------------- 1 | // Каждый класс, подключаемый к менеджеру сущностей должен иметь аннотацию `Сущность`, 2 | // расположенную над конструктором объекта. 3 | // 4 | // Параметры: 5 | // ИмяТаблицы - Строка - Имя таблицы, используемой коннектором к СУБД при работе с сущностью. 6 | // Значение по умолчанию - строковое представление имени типа сценария. 7 | // При подключении сценариев стандартным загрузчиком библиотек совпадает с именем файла. 8 | // ИсточникДанных - Строка - Повторяемый. Имя источника данных, используемого коннектором к СУБД при работе с сущностью. 9 | // Если не задано, считается, что сущность может быть использована с любым 10 | // источником данных. 11 | // 12 | // Пример: 13 | // 14 | // &Сущность("ФизическиеЛица") 15 | // Процедура ПриСозданииОбъекта() 16 | // КонецПроцедуры 17 | &Аннотация("Сущность") 18 | Процедура ПриСозданииОбъекта(ИмяТаблицы = Неопределено, &Повторяемый ИсточникДанных = Неопределено) 19 | КонецПроцедуры 20 | -------------------------------------------------------------------------------- /tasks/coverage.os: -------------------------------------------------------------------------------- 1 | #Использовать 1commands 2 | #Использовать fs 3 | #Использовать coverage 4 | 5 | СистемнаяИнформация = Новый СистемнаяИнформация; 6 | ЭтоWindows = Найти(НРег(СистемнаяИнформация.ВерсияОС), "windows") > 0; 7 | 8 | ФС.ОбеспечитьПустойКаталог("out"); 9 | ПутьКСтат = "out/stat.json"; 10 | 11 | Команда = Новый Команда; 12 | Команда.УстановитьКоманду("oscript"); 13 | Если НЕ ЭтоWindows Тогда 14 | Команда.ДобавитьПараметр("-encoding=utf-8"); 15 | КонецЕсли; 16 | Команда.ДобавитьПараметр(СтрШаблон("-codestat=%1", ПутьКСтат)); 17 | Команда.ДобавитьПараметр("tasks/test.os"); // Файла запуска тестов 18 | Команда.ПоказыватьВыводНемедленно(Истина); 19 | 20 | КодВозврата = Команда.Исполнить(); 21 | 22 | Файл_Стат = Новый Файл(ПутьКСтат); 23 | 24 | ПроцессорГенерации = Новый ГенераторОтчетаПокрытия(); 25 | 26 | ПроцессорГенерации.ОтносительныеПути() 27 | .РабочийКаталог("out") 28 | .ИмяФайлаСтатистики() 29 | .GenericCoverage() 30 | .Cobertura() 31 | .Clover("entity") 32 | .Сформировать(); 33 | 34 | ЗавершитьРаботу(КодВозврата); -------------------------------------------------------------------------------- /tests/ОпцииПоиска.os: -------------------------------------------------------------------------------- 1 | #Использовать ".." 2 | 3 | &Тест 4 | Процедура ОтборДобавляется() Экспорт 5 | 6 | // Дано 7 | ОпцииПоиска = Новый ОпцииПоиска(); 8 | Ожидаем.Что(ОпцииПоиска.Отборы().Количество()).Равно(0); 9 | 10 | // Когда 11 | ОпцииПоиска.Отбор("Поле", ВидСравнения.Равно, "Значение"); 12 | 13 | // Тогда 14 | Ожидаем.Что(ОпцииПоиска.Отборы().Количество()).Равно(1); 15 | Ожидаем.Что(ОпцииПоиска.Отборы()[0].ПутьКДанным).Равно("Поле"); 16 | Ожидаем.Что(ОпцииПоиска.Отборы()[0].ВидСравнения).Равно(ВидСравнения.Равно); 17 | Ожидаем.Что(ОпцииПоиска.Отборы()[0].Значение).Равно("Значение"); 18 | 19 | КонецПроцедуры 20 | 21 | &Тест 22 | Процедура СортировкаДобавляется() Экспорт 23 | 24 | // Дано 25 | ОпцииПоиска = Новый ОпцииПоиска(); 26 | Ожидаем.Что(ОпцииПоиска.Сортировки().Количество()).Равно(0); 27 | 28 | // Когда 29 | ОпцииПоиска.СортироватьПо("Поле", НаправлениеСортировки.Возр); 30 | 31 | // Тогда 32 | Ожидаем.Что(ОпцииПоиска.Сортировки().Количество()).Равно(1); 33 | Ожидаем.Что(ОпцииПоиска.Сортировки()[0].ПутьКДанным).Равно("Поле"); 34 | Ожидаем.Что(ОпцииПоиска.Сортировки()[0].НаправлениеСортировки).Равно(НаправлениеСортировки.Возр); 35 | 36 | КонецПроцедуры -------------------------------------------------------------------------------- /src/internal/ДинамическиПодключаемыеКлассы/КонструкторКоннектораPostgreSQL.os: -------------------------------------------------------------------------------- 1 | #Использовать sql 2 | 3 | Функция НовыйСоединение() Экспорт 4 | 5 | Соединение = Новый Соединение(); 6 | Возврат Соединение; 7 | 8 | КонецФункции 9 | 10 | Процедура Открыть(Соединение, СтрокаСоединения) Экспорт 11 | 12 | Соединение.ТипСУБД = Соединение.ТипыСУБД.PostgreSQL; 13 | Соединение.СтрокаСоединения = СтрокаСоединения; 14 | Соединение.Открыть(); 15 | 16 | КонецПроцедуры 17 | 18 | Процедура Закрыть(Соединение) Экспорт 19 | Соединение.Закрыть(); 20 | КонецПроцедуры 21 | 22 | Функция НовыйЗапрос(Соединение) Экспорт 23 | Запрос = Новый Запрос(); 24 | Запрос.УстановитьСоединение(Соединение); 25 | Возврат Запрос; 26 | КонецФункции 27 | 28 | Функция ИДПоследнейДобавленнойЗаписи(Соединение, Параметры) Экспорт 29 | 30 | ИДПоследнейДобавленнойЗаписи = -1; 31 | 32 | Запрос = НовыйЗапрос(Соединение); 33 | Запрос.Текст = СтрШаблон("SELECT max(%1) FROM %2", Параметры.ИмяКолонки, Параметры.ИмяТаблицы); 34 | Рез = Запрос.Выполнить().Выгрузить(); 35 | Если Рез.Количество() > 0 Тогда 36 | ИДПоследнейДобавленнойЗаписи = Рез[0]["max"]; 37 | КонецЕсли; 38 | 39 | Возврат ИДПоследнейДобавленнойЗаписи; 40 | 41 | КонецФункции 42 | 43 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © `2018` `Nikita Gryzlov ` 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /packagedef: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // Описание пакета для сборки и установки 3 | // Полную документацию см. на hub.oscript.io/packaging 4 | // 5 | // BSLLS:CodeOutOfRegion-off 6 | Описание.Имя("entity") 7 | .Версия("3.4.3.1") 8 | .Автор("Nikita Gryzlov") 9 | .АдресАвтора("nixel2007@gmail.com") 10 | .Описание("entity") 11 | .ВерсияСреды("1.9.2") 12 | .ВключитьФайл("src") 13 | .ВключитьФайл("tests") 14 | .ВключитьФайл("lib.config") 15 | .ВключитьФайл("README.md") 16 | .ВключитьФайл("docs") 17 | .ВключитьФайл("LICENSE.md") 18 | .ЗависитОт("annotations", "1.2.0") 19 | .ЗависитОт("asserts", "1.3.0") 20 | .ЗависитОт("fluent", "0.6.1") 21 | .ЗависитОт("fs", "1.0.0") 22 | .ЗависитОт("logos", "1.2.1") 23 | .ЗависитОт("json", "1.1.1") 24 | .ЗависитОт("decorator", "1.5.1") 25 | .ЗависитОт("reflector", "0.6.1") 26 | .ЗависитОт("semaphore", "1.1.0") 27 | .ЗависитОт("sql", "1.3.2") 28 | .ЗависитОт("strings", "0.5.0") 29 | .РазработкаЗависитОт("1commands") 30 | .РазработкаЗависитОт("1testrunner") 31 | .РазработкаЗависитОт("coverage") 32 | .РазработкаЗависитОт("fs") 33 | ; 34 | -------------------------------------------------------------------------------- /tasks/test.os: -------------------------------------------------------------------------------- 1 | #Использовать "../src" 2 | #Использовать 1testrunner 3 | #Использовать fs 4 | 5 | Функция ПрогнатьТесты() 6 | 7 | Тестер = Новый Тестер; 8 | Тестер.УстановитьФорматЛогФайла(Тестер.ФорматыЛогФайла().GenericExec); 9 | 10 | ПутьКТестам = ОбъединитьПути(ТекущийСценарий().Каталог, "..", "tests"); 11 | ПутьКОтчетуJUnit = ОбъединитьПути(ТекущийСценарий().Каталог, "..", "out"); 12 | 13 | ФС.ОбеспечитьПустойКаталог(ПутьКОтчетуJUnit); 14 | 15 | КаталогТестов = Новый Файл(ПутьКТестам); 16 | Если Не КаталогТестов.Существует() Тогда 17 | Сообщить(СтрШаблон("Не найден каталог тестов %1", ПутьКТестам)); 18 | Возврат Истина; 19 | КонецЕсли; 20 | 21 | РезультатТестирования = Тестер.ТестироватьКаталог( 22 | КаталогТестов, 23 | Новый Файл(ПутьКОтчетуJUnit) 24 | ); 25 | 26 | Успешно = РезультатТестирования = 0; 27 | 28 | Возврат Успешно; 29 | КонецФункции // ПрогнатьТесты() 30 | 31 | Попытка 32 | ТестыПрошли = ПрогнатьТесты(); 33 | 34 | Исключение 35 | ТестыПрошли = Ложь; 36 | Сообщить(СтрШаблон("Тесты через 1testrunner выполнены неудачно 37 | |%1", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()))); 38 | КонецПопытки; 39 | 40 | Если Не ТестыПрошли Тогда 41 | ВызватьИсключение "Тестирование завершилось неудачно!"; 42 | Иначе 43 | Сообщить(СтрШаблон("Результат прогона тестов <%1> 44 | |", ТестыПрошли)); 45 | КонецЕсли; 46 | 47 | -------------------------------------------------------------------------------- /src/Аннотации/Классы/АннотацияПодчиненнаяТаблица.os: -------------------------------------------------------------------------------- 1 | // Аннотация `ПодчиненнаяТаблица` используется для хранения коллекций - массивов и структур. 2 | // 3 | // Параметры: 4 | // ИмяТаблицы - Строка - Имя таблицы, используемой коннектором к СУБД при работе с сущностью. 5 | // Значение по умолчанию - строка вида `ИмяТаблицыСущности_ИмяСвойства`. 6 | // Тип - Строка - Тип колонки, используемой для хранения идентификатора. 7 | // Доступные типы подчиненных таблиц: 8 | // - Массив 9 | // - Структура 10 | // ТипЭлемента - Строка - Имя зарегистрированного в модели типа, в который преобразуется значение из колонки. 11 | // Допустимо указывать примитивные типы из перечисления `ТипыКолонок` 12 | // и типы сущностей (например, `"ФизическоеЛицо"`). 13 | // КаскадноеЧтение - Булево - Флаг, отвечающий за инициализацию сущностей в подчиненной таблице 14 | // (если `ТипЭлемента` является ссылочным типом). 15 | // 16 | // Пример: 17 | // &ПодчиненнаяТаблица(Тип = "Массив", ТипЭлемента = "Документ", КаскадноеЧтение = Истина) 18 | // Перем Документы; 19 | &Аннотация("ПодчиненнаяТаблица") 20 | Процедура ПриСозданииОбъекта(ИмяТаблицы = Неопределено, Тип = Неопределено, ТипЭлемента = Неопределено, КаскадноеЧтение = Ложь) 21 | КонецПроцедуры 22 | -------------------------------------------------------------------------------- /tests/fixtures/СущностьСоВсемиТипамиКолонок.os: -------------------------------------------------------------------------------- 1 | &Колонка(Тип = "Целое") 2 | &Идентификатор 3 | Перем Целое Экспорт; 4 | 5 | &Колонка(Тип = "Дробное") 6 | Перем Дробное Экспорт; 7 | 8 | &Колонка(Тип = "Строка") 9 | Перем Строка Экспорт; 10 | 11 | &Колонка(Тип = "Булево") 12 | Перем БулевоИстина Экспорт; 13 | 14 | &Колонка(Тип = "Булево") 15 | Перем БулевоЛожь Экспорт; 16 | 17 | &Колонка(Тип = "Дата") 18 | Перем Дата Экспорт; 19 | 20 | &Колонка(Тип = "Время") 21 | Перем Время Экспорт; 22 | 23 | &Колонка(Тип = "ДатаВремя") 24 | Перем ДатаВремя Экспорт; 25 | 26 | &Колонка(Тип = "ДвоичныеДанные") 27 | Перем ДвоичныеДанные Экспорт; 28 | 29 | &Колонка(Тип = "Ссылка", ТипСсылки = "СущностьСоВсемиТипамиКолонок") 30 | Перем Ссылка Экспорт; 31 | 32 | &ПодчиненнаяТаблица( 33 | Тип = "Массив", 34 | ТипЭлемента = "Строка", 35 | ИмяТаблицы = "ВсеТипыКолонок_Массив" 36 | ) 37 | Перем Массив Экспорт; 38 | 39 | &ПодчиненнаяТаблица( 40 | Тип = "Структура", 41 | ТипЭлемента = "Строка", 42 | ИмяТаблицы = "ВсеТипыКолонок_Структура" 43 | ) 44 | Перем Структура Экспорт; 45 | 46 | &ПодчиненнаяТаблица( 47 | Тип = "Массив", 48 | ТипЭлемента = "СущностьСоВсемиТипамиКолонок", 49 | ИмяТаблицы = "ВсеТипыКолонок_МассивСсылок" 50 | ) 51 | Перем МассивСсылок Экспорт; 52 | 53 | &ПодчиненнаяТаблица( 54 | Тип = "Массив", 55 | ТипЭлемента = "СущностьСоВсемиТипамиКолонок", 56 | ИмяТаблицы = "ВсеТипыКолонок_МассивСсылокКаскад", 57 | КаскадноеЧтение = Истина 58 | ) 59 | Перем МассивСсылокКаскад Экспорт; 60 | 61 | &Сущность 62 | Процедура ПриСозданииОбъекта() 63 | 64 | КонецПроцедуры 65 | -------------------------------------------------------------------------------- /.github/workflows/copilot-setup-steps.yml: -------------------------------------------------------------------------------- 1 | name: "OneScript Development Environment Setup" 2 | 3 | # Allow testing of the setup steps from your repository's "Actions" tab. 4 | on: workflow_dispatch 5 | 6 | jobs: 7 | # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. 8 | copilot-setup-steps: 9 | runs-on: ubuntu-latest 10 | 11 | # Set the permissions to the lowest permissions possible needed for your steps. 12 | # Copilot will be given its own token for its operations. 13 | permissions: 14 | # Clone the repository to install dependencies 15 | contents: read 16 | 17 | # Setup steps for OneScript development environment 18 | steps: 19 | - name: Checkout code 20 | uses: actions/checkout@v6 21 | 22 | - run: git config --global core.quotepath false 23 | 24 | - name: Вычисление версии OneScript 25 | shell: bash 26 | id: extract_oscript_version 27 | run: | 28 | set -ex 29 | if [ -f packagedef ]; then 30 | extracted_version=$(cat packagedef | grep ".ВерсияСреды(" | sed 's|[^"]*"||' | sed -r 's/".+//' || true) 31 | version="${extracted_version:-stable}" 32 | else 33 | version="stable" 34 | fi 35 | echo "version=$version" >> $GITHUB_OUTPUT 36 | 37 | - name: Установка OneScript 38 | uses: otymko/setup-onescript@v1.5 39 | with: 40 | version: ${{ steps.extract_oscript_version.outputs.version }} 41 | 42 | - name: Установка зависимостей 43 | run: | 44 | opm install opm 45 | opm install -l --dev 46 | 47 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | # * is a special character in YAML so you have to quote this string 8 | - cron: '0 0 * * 1' 9 | 10 | jobs: 11 | build: 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | os: [ubuntu-latest, windows-latest] 17 | oscript_version: ['1.9.2', 'stable'] 18 | steps: 19 | - uses: actions/checkout@v6 20 | 21 | - name: Setup Onescript Action 22 | uses: otymko/setup-onescript@v1.5 23 | with: 24 | version: ${{ matrix.oscript_version }} 25 | 26 | - name: Install dependencies 27 | run: | 28 | opm install opm@1.0.2 29 | opm install -l 30 | opm install -l 1commands 1testrunner coverage@0.6.1 31 | 32 | - name: Install docker 33 | uses: docker/setup-docker-action@v4 34 | timeout-minutes: 12 35 | 36 | - name: Setup PostgreSQL 37 | shell: bash 38 | run: | 39 | docker run --rm --name postgres -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_USERNAME=postgres -e POSTGRES_DB=postgres -e POSTGRES_HOST_AUTH_METHOD=password --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 satrapu/postgresql 40 | docker ps 41 | while [ "`docker inspect -f {{.State.Health.Status}} postgres`" != "healthy" ]; do docker ps && sleep 2; done 42 | docker ps 43 | 44 | - name: Run tests 45 | env: 46 | TESTRUNNER_RUN_POSTGRES_TESTS: true 47 | TESTRUNNER_RUN_SQLITE_TESTS: "${{ matrix.os == 'windows-latest' }}" 48 | run: | 49 | oscript ./tasks/test.os 50 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright (C) 2020 Tymko Oleg and contributors 3 | # All rights reserved. 4 | 5 | name: Подготовка релиза и публикация в хабе 6 | # Только события создания и изменения релиза 7 | on: 8 | release: 9 | types: [published] 10 | 11 | env: 12 | PACKAGE_MASK: entity-*.ospx 13 | 14 | jobs: 15 | build: 16 | runs-on: ${{ matrix.os }} 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | os: [ubuntu-latest] 21 | oscript_version: ['1.9.2'] 22 | 23 | steps: 24 | # Загрузка проекта 25 | - name: Актуализация 26 | uses: actions/checkout@v6 27 | 28 | # Установка OneScript конкретной версии 29 | - name: Установка OneScript 30 | uses: otymko/setup-onescript@v1.5 31 | with: 32 | version: ${{ matrix.oscript_version }} 33 | 34 | # Установка зависимостей пакета 35 | - name: Установка зависимостей 36 | run: | 37 | opm install opm 38 | opm install 39 | 40 | - name: Сборка пакета 41 | run: opm build . 42 | 43 | - name: Заливка артефактов 44 | uses: actions/upload-artifact@v6 45 | with: 46 | name: package.zip 47 | path: ./${{ env.PACKAGE_MASK }} 48 | 49 | #- name: Заливка в релиз 50 | # uses: AButler/upload-release-assets@v2.0.2 51 | # with: 52 | # files: ./${{ env.PACKAGE_MASK }} 53 | # repo-token: ${{ secrets.GITHUB_TOKEN }} 54 | 55 | - name: Публикация в hub.oscript.io 56 | shell: bash 57 | run: opm push -f ./${{ env.PACKAGE_MASK }} --token ${{ secrets.PUSH_TOKEN }} -c stable 58 | -------------------------------------------------------------------------------- /src/Модули/ТипыКолонок.os: -------------------------------------------------------------------------------- 1 | Перем Целое Экспорт; 2 | Перем Дробное Экспорт; 3 | Перем Булево Экспорт; 4 | Перем Строка Экспорт; 5 | Перем Дата Экспорт; 6 | Перем Время Экспорт; 7 | Перем ДатаВремя Экспорт; 8 | Перем Ссылка Экспорт; 9 | Перем ДвоичныеДанные Экспорт; 10 | 11 | Перем Типы; 12 | Перем ПримитивныеТипы; 13 | 14 | Функция Типы() Экспорт 15 | Возврат Типы; 16 | КонецФункции 17 | 18 | Функция ЭтоПримитивныйТип(Знач Тип) Экспорт 19 | Если ТипЗнч(Тип) = Тип("Тип") Тогда 20 | Тип = Строка(Тип); 21 | КонецЕсли; 22 | 23 | Возврат ПримитивныеТипы.Найти(Тип) <> Неопределено; 24 | КонецФункции 25 | 26 | Функция ЭтоСсылочныйТип(Знач Тип) Экспорт 27 | Если ТипЗнч(Тип) = Тип("Тип") Тогда 28 | Тип = Строка(Тип); 29 | КонецЕсли; 30 | 31 | Возврат Типы.Найти(Тип) = Неопределено И Не ЭтоПримитивныйТип(Тип); 32 | КонецФункции 33 | 34 | Целое = "Целое"; 35 | Дробное = "Дробное"; 36 | Булево = "Булево"; 37 | Строка = "Строка"; 38 | Дата = "Дата"; 39 | Время = "Время"; 40 | ДатаВремя = "ДатаВремя"; 41 | Ссылка = "Ссылка"; 42 | ДвоичныеДанные = "ДвоичныеДанные"; 43 | 44 | Типы = Новый Массив; 45 | Типы.Добавить(Целое); 46 | Типы.Добавить(Дробное); 47 | Типы.Добавить(Булево); 48 | Типы.Добавить(Строка); 49 | Типы.Добавить(Дата); 50 | Типы.Добавить(Время); 51 | Типы.Добавить(ДатаВремя); 52 | Типы.Добавить(Ссылка); 53 | Типы.Добавить(ДвоичныеДанные); 54 | 55 | ПримитивныеТипы = Новый Массив; 56 | ПримитивныеТипы.Добавить(Целое); 57 | ПримитивныеТипы.Добавить(Дробное); 58 | ПримитивныеТипы.Добавить(Булево); 59 | ПримитивныеТипы.Добавить(Строка); 60 | ПримитивныеТипы.Добавить(Дата); 61 | ПримитивныеТипы.Добавить(Время); 62 | ПримитивныеТипы.Добавить(ДатаВремя); 63 | ПримитивныеТипы.Добавить(ДвоичныеДанные); -------------------------------------------------------------------------------- /src/Аннотации/Классы/АннотацияКолонка.os: -------------------------------------------------------------------------------- 1 | // Все **экспортные** поля класса (за исключением полей, помеченных аннотаций `ПодчиненнаяТаблица`) 2 | // преобразуются в колонки таблицы в СУБД. 3 | // 4 | // Аннотация `Колонка` позволяет тонко настроить параметры колонки таблицы. 5 | // 6 | // Применяется на поле класса. 7 | // 8 | // Параметры: 9 | // Имя - Строка - Имя колонки, используемой коннектором к СУБД при работе с сущностью. 10 | // Значение по умолчанию - имя свойства. 11 | // Тип - Строка - Тип колонки, используемой для хранения идентификатора. Значение по умолчанию - `ТипыКолонок.Строка`. 12 | // Доступные типы колонок: 13 | // - "Целое" 14 | // - "Дробное" 15 | // - "Булево" 16 | // - "Строка" 17 | // - "Дата" 18 | // - "Время" 19 | // - "ДатаВремя" 20 | // - "Ссылка" 21 | // - "ДвоичныеДанные" 22 | // ТипСсылки - Строка - Имя зарегистрированного в модели типа, в который преобразуется значение из колонки. 23 | // Имеет смысл только в паре с параметром `Тип`, равным `Ссылка`. 24 | // Допустимо указывать примитивные типы из перечисления `ТипыКолонок` 25 | // и типы сущностей (например, `"ФизическоеЛицо"`) 26 | // 27 | // Пример: 28 | // 29 | // 1. &Колонка(Тип = Число) 30 | // Перем Возраст; 31 | // 32 | // 2. &Колонка(Имя = "ДУЛ", Тип = Ссылка, ТипСсылки = "Документ") 33 | // Перем ДокументУдостоверяющийЛичность; 34 | // 35 | &Аннотация("Колонка") 36 | Процедура ПриСозданииОбъекта(Имя = Неопределено, Тип = "Строка", ТипСсылки = Неопределено) 37 | КонецПроцедуры 38 | -------------------------------------------------------------------------------- /lib.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/internal/Модули/ХранилищаСущностей.os: -------------------------------------------------------------------------------- 1 | #Использовать semaphore 2 | 3 | Перем Хранилища; 4 | Перем Семафор; 5 | 6 | Функция Получить(ОбъектМодели, Коннектор) Экспорт 7 | 8 | Семафор.Захватить(); 9 | 10 | СвойстваКоннектора = РаботаСКоннекторами.ПолучитьСвойстваКоннектора(Коннектор); 11 | 12 | КлючХранилища = ПолучитьКлючХранилища( 13 | ОбъектМодели.ТипСущности(), 14 | ТипЗнч(Коннектор), 15 | СвойстваКоннектора.СтрокаСоединения 16 | ); 17 | ХранилищеСущностей = Хранилища.Получить(КлючХранилища); 18 | Если ХранилищеСущностей = Неопределено Тогда 19 | ХранилищеСущностей = Новый ХранилищеСущностей( 20 | ОбъектМодели, 21 | ТипЗнч(Коннектор), 22 | СвойстваКоннектора.СтрокаСоединения, 23 | СвойстваКоннектора.Параметры 24 | ); 25 | Хранилища.Вставить(КлючХранилища, ХранилищеСущностей); 26 | КонецЕсли; 27 | 28 | Семафор.Освободить(); 29 | 30 | Возврат ХранилищеСущностей; 31 | 32 | КонецФункции 33 | 34 | Процедура Закрыть(ТипКоннектора, СтрокаСоединения, ПараметрыКоннектора) Экспорт 35 | 36 | Семафор.Захватить(1000); 37 | 38 | ЗакрываемыеХранилища = Новый Массив; 39 | Для Каждого КлючИЗначение Из Хранилища Цикл 40 | Хранилище = КлючИЗначение.Значение; 41 | КоннекторХранилища = Хранилище.ПолучитьКоннектор(); 42 | СвойстваКоннектора = РаботаСКоннекторами.ПолучитьСвойстваКоннектора(КоннекторХранилища); 43 | 44 | Если ТипКоннектора = ТипЗнч(КоннекторХранилища) И СтрокаСоединения = СвойстваКоннектора.СтрокаСоединения Тогда 45 | Хранилище.Закрыть(); 46 | ЗакрываемыеХранилища.Добавить(КлючИЗначение.Ключ); 47 | КонецЕсли; 48 | КонецЦикла; 49 | 50 | Для Каждого ЗакрываемоеХранилище Из ЗакрываемыеХранилища Цикл 51 | Хранилища.Удалить(ЗакрываемоеХранилище); 52 | КонецЦикла; 53 | 54 | Семафор.Освободить(); 55 | 56 | КонецПроцедуры 57 | 58 | Функция ПолучитьКлючХранилища(ТипСущности, ТипКоннектора, СтрокаСоединения) 59 | Возврат СтрШаблон( 60 | "%1 - %2 - %3", 61 | ТипСущности, 62 | ТипКоннектора, 63 | СтрокаСоединения 64 | ); 65 | КонецФункции 66 | 67 | Хранилища = Новый Соответствие(); 68 | Семафор = Новый Семафор(); 69 | -------------------------------------------------------------------------------- /docs/ОбъектМодели.md: -------------------------------------------------------------------------------- 1 | ## ОбъектМодели 2 | 3 | ### ПриСозданииОбъекта 4 | 5 | ```bsl 6 | 7 | Процедура ПриСозданииОбъекта(ПТипСущности, ПМодельДанных) 8 | ``` 9 | 10 | ### ИмяТаблицы 11 | 12 | ```bsl 13 | 14 | Функция ИмяТаблицы() Экспорт 15 | ``` 16 | 17 | ### Колонки 18 | 19 | ```bsl 20 | 21 | Функция Колонки() Экспорт 22 | ``` 23 | 24 | ### ПодчиненныеТаблицы 25 | 26 | ```bsl 27 | 28 | Функция ПодчиненныеТаблицы() Экспорт 29 | ``` 30 | 31 | ### Служебный_Колонки 32 | 33 | ```bsl 34 | // @internal 35 | // TODO: вынести отсюда. Возможно стоит разработать отдельный служебный билдер Объекта модели, 36 | // вытащив заполнение из конструктора в этот билдер, а в конструктор передавать уже готовые для сохранения 37 | // в объект данные. 38 | // 39 | Функция Служебный_Колонки() Экспорт 40 | ``` 41 | 42 | ### Служебный_ИмяТаблицы 43 | 44 | ```bsl 45 | // @internal 46 | Процедура Служебный_ИмяТаблицы(ПИмяТаблицы) Экспорт 47 | ``` 48 | 49 | ### Идентификатор 50 | 51 | ```bsl 52 | 53 | Функция Идентификатор() Экспорт 54 | ``` 55 | 56 | ### МодельДанных 57 | 58 | ```bsl 59 | 60 | Функция МодельДанных() Экспорт 61 | ``` 62 | 63 | ### ТипСущности 64 | 65 | ```bsl 66 | 67 | Функция ТипСущности() Экспорт 68 | ``` 69 | 70 | ### ПолучитьЗначениеИдентификатора 71 | 72 | ```bsl 73 | 74 | Функция ПолучитьЗначениеИдентификатора(Сущность) Экспорт 75 | ``` 76 | 77 | ### ПолучитьПриведенноеЗначениеПоля 78 | 79 | ```bsl 80 | 81 | Функция ПолучитьПриведенноеЗначениеПоля(Сущность, ИмяПоля) Экспорт 82 | ``` 83 | 84 | ### УстановитьЗначениеКолонкиВПоле 85 | 86 | ```bsl 87 | 88 | Процедура УстановитьЗначениеКолонкиВПоле(Сущность, ИмяКолонки, ЗначениеПоля) Экспорт 89 | ``` 90 | 91 | ### УстановитьЗначениеПодчиненнойТаблицыВПоле 92 | 93 | ```bsl 94 | 95 | Процедура УстановитьЗначениеПодчиненнойТаблицыВПоле(Сущность, ИмяПоля, ЗначениеПоля) Экспорт 96 | ``` 97 | 98 | ### ПривестиЗначениеПоля 99 | 100 | ```bsl 101 | 102 | Функция ПривестиЗначениеПоля(ЗначениеПоля, ИмяПоля) Экспорт 103 | ``` 104 | 105 | ### ПолучитьЗначениеПоля 106 | 107 | ```bsl 108 | 109 | Функция ПолучитьЗначениеПоля(Сущность, ИмяПоля) Экспорт 110 | ``` 111 | 112 | -------------------------------------------------------------------------------- /docs/ОпцииПоиска.md: -------------------------------------------------------------------------------- 1 | ## ОпцииПоиска 2 | 3 | ### ПриСозданииОбъекта 4 | 5 | ```bsl 6 | 7 | Процедура ПриСозданииОбъекта() 8 | ``` 9 | 10 | ### Отборы 11 | 12 | ```bsl 13 | // Получить список отборов для выполнения поиска. 14 | // 15 | // Возвращаемое значение: 16 | // ФиксированныйМассив из ЭлементОтбора 17 | // 18 | Функция Отборы() 19 | ``` 20 | 21 | ### Отбор 22 | 23 | ```bsl 24 | // Добавить отбор для выполнения поиска. 25 | // 26 | // Параметры: 27 | // Поле - Строка - Имя поля для отбора. 28 | // ВидСравнения - ВидСравнения - Вид сравнения. 29 | // Значение - Произвольный - Значение для сравнения. 30 | // 31 | // Возвращаемое значение: 32 | // ОпцииПоиска - Текущий объект. 33 | // 34 | Функция Отбор(Поле, ВидСравнения, Значение) 35 | ``` 36 | 37 | ### Сортировки 38 | 39 | ```bsl 40 | // Получить список сортировок для выполнения поиска. 41 | // 42 | // Возвращаемое значение: 43 | // ФиксированныйМассив из ЭлементПорядка 44 | // 45 | Функция Сортировки() 46 | ``` 47 | 48 | ### СортироватьПо 49 | 50 | ```bsl 51 | // Добавить сортировку для выполнения поиска. 52 | // 53 | // Параметры: 54 | // ИмяПоля - Строка - Имя поля для сортировки. 55 | // НаправлениеСортировки - НаправлениеСортировки - Направление сортировки. 56 | // 57 | // Возвращаемое значение: 58 | // ОпцииПоиска - Текущий объект. 59 | // 60 | Функция СортироватьПо(ИмяПоля, НаправлениеСортировки = Неопределено) 61 | ``` 62 | 63 | ### ВыбираютсяПервые 64 | 65 | ```bsl 66 | // Получить количество элементов, которые необходимо выбрать. 67 | // 68 | // Возвращаемое значение: 69 | // Число - Количество элементов. 70 | // 71 | Функция ВыбираютсяПервые() 72 | ``` 73 | 74 | ### Первые 75 | 76 | ```bsl 77 | // Выбрать первые n элементов. 78 | // 79 | // Параметры: 80 | // КоличествоЭлементов - Число - Количество элементов. 81 | // 82 | // Возвращаемое значение: 83 | // ОпцииПоиска - Текущий объект. 84 | // 85 | Функция Первые(КоличествоЭлементов) 86 | ``` 87 | 88 | ### ВыбираетсяСоСмещением 89 | 90 | ```bsl 91 | // Получить количество элементов, которые необходимо пропустить. 92 | // 93 | // Возвращаемое значение: 94 | // Число - Количество элементов. 95 | // 96 | Функция ВыбираетсяСоСмещением() 97 | ``` 98 | 99 | ### Смещение 100 | 101 | ```bsl 102 | // Сместить выборку на n элементов. 103 | // 104 | // Параметры: 105 | // КоличествоЭлементов - Число - Количество элементов. 106 | // 107 | // Возвращаемое значение: 108 | // ОпцииПоиска - Текущий объект. 109 | // 110 | Функция Смещение(КоличествоЭлементов) 111 | ``` 112 | 113 | -------------------------------------------------------------------------------- /src/internal/Модули/АктивнаяЗапись.os: -------------------------------------------------------------------------------- 1 | #Использовать decorator 2 | 3 | Функция ТипСущности(Сущность) Экспорт 4 | ТипСущности = ТипЗнч(Сущность); 5 | Если ТипСущности = Тип("Сценарий") Тогда 6 | ТипСущности = ОбработкаДекоратора.ИсходныйТип(Сущность); 7 | КонецЕсли; 8 | 9 | Возврат ТипСущности; 10 | КонецФункции 11 | 12 | Функция СоздатьИзМенеджера(ОбъектМодели, МенеджерСущностей) Экспорт 13 | Сущность = Новый(ОбъектМодели.ТипСущности()); 14 | 15 | Декоратор = Новый ПостроительДекоратора(Сущность) 16 | .Импорт(Новый Импорт("decorator")) 17 | 18 | .Поле(Новый Поле("_МенеджерСущностей") 19 | .ЗначениеПоУмолчанию(МенеджерСущностей)) 20 | 21 | .Поле(Новый Поле("_ОбъектМодели") 22 | .ЗначениеПоУмолчанию(ОбъектМодели)) 23 | 24 | .Метод(Новый Метод("Прочитать") 25 | .Публичный() 26 | .ТелоМетода("_ТипСущности = ОбработкаДекоратора.ИсходныйТип(ЭтотОбъект); 27 | |_ДанныеСущности = _МенеджерСущностей.ПолучитьОдно( 28 | | _ТипСущности, 29 | | _ОбъектМодели.ПолучитьЗначениеИдентификатора(ЭтотОбъект) 30 | |); 31 | |ОбработкаДекоратора.СинхронизироватьПоля(_ДанныеСущности, ЭтотОбъект);")) 32 | 33 | 34 | .Метод(Новый Метод("Сохранить") 35 | .Публичный() 36 | .ТелоМетода("_МенеджерСущностей.Сохранить(ЭтотОбъект);")) 37 | 38 | .Метод(Новый Метод("Удалить") 39 | .Публичный() 40 | .ТелоМетода("_МенеджерСущностей.Удалить(ЭтотОбъект);")) 41 | 42 | .Построить(); 43 | 44 | Возврат Декоратор; 45 | КонецФункции 46 | 47 | Функция СоздатьИзХранилища(ОбъектМодели, ХранилищеСущностей) Экспорт 48 | Сущность = Новый(ОбъектМодели.ТипСущности()); 49 | 50 | Декоратор = Новый ПостроительДекоратора(Сущность) 51 | .Импорт(Новый Импорт("decorator")) 52 | 53 | .Поле(Новый Поле("_ХранилищеСущностей") 54 | .ЗначениеПоУмолчанию(ХранилищеСущностей)) 55 | 56 | .Поле(Новый Поле("_ОбъектМодели") 57 | .ЗначениеПоУмолчанию(ОбъектМодели)) 58 | 59 | .Метод(Новый Метод("Прочитать") 60 | .Публичный() 61 | .ТелоМетода("_ДанныеСущности = _ХранилищеСущностей.ПолучитьОдно(_ОбъектМодели.ПолучитьЗначениеИдентификатора(ЭтотОбъект)); 62 | |ОбработкаДекоратора.СинхронизироватьПоля(_ДанныеСущности, ЭтотОбъект);")) 63 | 64 | 65 | .Метод(Новый Метод("Сохранить") 66 | .Публичный() 67 | .ТелоМетода("_ХранилищеСущностей.Сохранить(ЭтотОбъект);")) 68 | 69 | .Метод(Новый Метод("Удалить") 70 | .Публичный() 71 | .ТелоМетода("_ХранилищеСущностей.Удалить(ЭтотОбъект);")) 72 | 73 | .Построить(); 74 | 75 | Возврат Декоратор; 76 | КонецФункции -------------------------------------------------------------------------------- /.github/copilot-instructions.md: -------------------------------------------------------------------------------- 1 | ## Общее 2 | 3 | Этот проект написан на языке 1С:Предприятие 8 и выполняется в независимой реализации виртуальной машины под названием OneScript или oscript. Документация доступна на сайте https://oscript.io, исходный код движка - https://github.com/EvilBeaver/OneScript 4 | 5 | Для управления версиями движка OneScript используется OneScript Version Manager (ovm), который уже установлен в окружении Coding Agent. Так же в окружение установлена требуемая версия oscript. Документация по ovm - https://github.com/oscript-library/ovm 6 | 7 | Для работы с зависимостями используется пакетный менеджер OneScript Package Manager (opm), который тоже установлен в окружении. При подготовке окружения автоматически был выполнен шаг установки зависимостей текущего проекта. Они доступны в подкаталоге `oscript_modules`, расположенном в корне проекта. 8 | 9 | Дополнительные пакеты можно установить, выполнив команду `opm install -l имя_пакета` 10 | 11 | Документация о продукте содержится в каталоге docs и README.md. 12 | 13 | ## Тестирование 14 | 15 | Для работы тестов нужно поднять docker-контейрер с postgres: 16 | 17 | ```sh 18 | docker run --rm --name postgres -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_USERNAME=postgres -e POSTGRES_DB=postgres -e POSTGRES_HOST_AUTH_METHOD=password --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 satrapu/postgresql 19 | ``` 20 | 21 | и дождаться его healthy state. 22 | 23 | Для запуска тестов используется команда: 24 | 25 | ```sh 26 | TESTRUNNER_RUN_POSTGRES_TESTS=true TESTRUNNER_RUN_SQLITE_TESTS=false oscript tasks/test.os 27 | ``` 28 | 29 | Для запуска тестов с замером покрытия используется команда: 30 | 31 | ```sh 32 | TESTRUNNER_RUN_POSTGRES_TESTS=true TESTRUNNER_RUN_SQLITE_TEST=false oscript tasks/coverage.os 33 | ``` 34 | 35 | Замеры покрытия доступны в подкаталоге `out`. 36 | 37 | ## Качество кода 38 | 39 | Проект анализируется на сервере SonarQube sonar.openbsl.ru, к которому у тебя есть прямой доступ, в том числе по web-api. Используется плагин для поддержки 1С, основанный на проекте BSL Language Server. 40 | Документация и список диагностик BSL LS доступны на сайте https://1c-syntax.github.io/bsl-language-server 41 | Реализация диагностик доступна по адресу https://github.com/1c-syntax/bsl-language-server 42 | 43 | При необходимости ты можешь скачать из релизов BSL LS исполняемый файл (для Linux или -exec.jar), и запустить bsl ls в режиме analyze с выводом результатов, используя reporter json. 44 | 45 | В корне проекта лежит файл .bsl-language-server.json с дополнительной конфигурацией BSL LS (включая параметры диагностик). 46 | -------------------------------------------------------------------------------- /tests/ОбъектМодели.os: -------------------------------------------------------------------------------- 1 | #Использовать ".." 2 | 3 | #Использовать asserts 4 | 5 | &Тест 6 | Процедура КонструкторОбъектаМоделиКорректноАнализируетКласс() Экспорт 7 | ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "Автор.os"), "Автор"); 8 | ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "СущностьБезГенерируемогоИдентификатора.os"), "СущностьБезГенерируемогоИдентификатора"); 9 | 10 | ОбъектМодели = Новый ОбъектМодели(Тип("Автор"), Неопределено); 11 | 12 | Ожидаем.Что(ОбъектМодели.ИмяТаблицы(), "Имя таблицы определено корректно").Равно("Авторы"); 13 | 14 | Ожидаем.Что(ОбъектМодели.Колонки(), "Сущность имеет четыре колонки").ИмеетДлину(4); 15 | 16 | Идентификатор = ОбъектМодели.Идентификатор(); 17 | Ожидаем.Что(Идентификатор, "Таблица имеет идентификатор").Не_().Равно(Неопределено); 18 | 19 | Ожидаем.Что(Идентификатор.ИмяПоля, "Идентификатор таблицы указывает на корректное поле").Равно("ВнутреннийИдентификатор"); 20 | Ожидаем.Что(Идентификатор.ИмяКолонки, "Идентификатор таблицы имеет корректное имя колонки").Равно("Идентификатор"); 21 | Ожидаем.Что(Идентификатор.ТипКолонки, "Идентификатор таблицы имеет корректный тип колонки").Равно(ТипыКолонок.Целое); 22 | Ожидаем.Что(Идентификатор.ГенерируемоеЗначение, "Идентификатор таблицы имеет флаг автоинкремента").Равно(Истина); 23 | Ожидаем.Что(Идентификатор.ГенерируемоеЗначение, "Идентификатор таблицы имеет флаг идентификатора").Равно(Истина); 24 | 25 | Колонки = ОбъектМодели.Колонки(); 26 | Ожидаем.Что(Колонки[0].ИмяПоля, "Первая колонка - внутренний идентификатор").Равно("ВнутреннийИдентификатор"); 27 | 28 | Ожидаем.Что(Колонки[1].ИмяПоля, "Вторая колонка - Имя").Равно("Имя"); 29 | Ожидаем.Что(Колонки[1].ИмяКолонки, "Имя поля второй колонки корректно").Равно("Имя"); 30 | Ожидаем.Что(Колонки[1].ТипКолонки, "Тип второй колонки корректен").Равно(ТипыКолонок.Строка); 31 | 32 | Ожидаем.Что(Колонки[2].ИмяПоля, "Третья колонка - ВтороеИмя").Равно("ВтороеИмя"); 33 | Ожидаем.Что(Колонки[2].ИмяКолонки, "Имя третье колонки корректно").Равно("Фамилия"); 34 | Ожидаем.Что(Колонки[2].ТипКолонки, "Тип третьей колонки корректен").Равно(ТипыКолонок.Строка); 35 | 36 | Ожидаем.Что(Колонки[3].ИмяКолонки, "Четвертая колонка - ВнешняяСущность").Равно("ВнешняяСущность"); 37 | Ожидаем.Что(Колонки[3].ТипКолонки, "Тип четвертой колонки корректен").Равно(ТипыКолонок.Ссылка); 38 | Ожидаем.Что(Колонки[3].ТипСсылки, "Тип ссылки четвертой колонки определился").Равно(Тип("СущностьБезГенерируемогоИдентификатора")); 39 | 40 | ИсточникиДанных = ОбъектМодели.ИсточникиДанных(); 41 | Ожидаем.Что(ИсточникиДанных, "Объект модели имеет источники данных").ИмеетДлину(2); 42 | Ожидаем.Что(ИсточникиДанных[0], "Первый источник данных имеет корректное имя").Равно("Основной"); 43 | Ожидаем.Что(ИсточникиДанных[1], "Второй источник данных имеет корректное имя").Равно("Дополнительный"); 44 | 45 | КонецПроцедуры 46 | -------------------------------------------------------------------------------- /.github/workflows/qa.yml: -------------------------------------------------------------------------------- 1 | name: QA 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v6 13 | with: 14 | # Disabling shallow clone is recommended for improving relevancy of reporting 15 | fetch-depth: 0 16 | 17 | - name: Setup Onescript Action 18 | uses: otymko/setup-onescript@v1.5 19 | with: 20 | version: "1.9.2" 21 | 22 | - name: Install dependencies 23 | run: | 24 | opm install opm@1.0.2 25 | opm install -l 26 | opm install -l 1commands 1testrunner coverage@0.6.1 27 | 28 | - name: Install docker 29 | uses: docker/setup-docker-action@v4 30 | timeout-minutes: 12 31 | 32 | - name: Setup PostgreSQL 33 | run: | 34 | docker run --rm --name postgres -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_USERNAME=postgres -e POSTGRES_DB=postgres -e POSTGRES_HOST_AUTH_METHOD=password --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 postgres 35 | docker ps 36 | while [ "`docker inspect -f {{.State.Health.Status}} postgres`" != "healthy" ]; do docker ps && sleep 2; done 37 | docker ps 38 | 39 | - name: Compute branch name 40 | uses: nelonoel/branch-name@v1.0.1 41 | 42 | - name: Извлечение версии пакета 43 | shell: bash 44 | run: echo "##[set-output name=version;]`cat packagedef | grep ".Версия(" | sed 's|[^"]*"||' | sed -r 's/".+//'`" 45 | id: extract_version 46 | 47 | - name: Run coverage tests 48 | env: 49 | TESTRUNNER_RUN_POSTGRES_TESTS: true 50 | TESTRUNNER_RUN_SQLITE_TESTS: false 51 | run: | 52 | oscript ./tasks/coverage.os 53 | 54 | - name: Setup sonarqube 55 | uses: warchant/setup-sonar-scanner@v9 56 | 57 | # Анализ проекта в SonarQube (ветка) 58 | - name: Анализ в SonarQube (branch) 59 | if: github.event_name == 'push' 60 | env: 61 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 62 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 63 | run: sonar-scanner 64 | -Dsonar.host.url=https://sonar.openbsl.ru 65 | -Dsonar.branch.name=${{ env.BRANCH_NAME }} 66 | -Dsonar.projectVersion=${{ steps.extract_version.outputs.version }} 67 | 68 | # Анализ проекта в SonarQube (PR) 69 | # https://docs.sonarqube.org/latest/analysis/pull-request/ 70 | - name: Анализ в SonarQube (pull-request) 71 | if: github.event_name == 'pull_request' 72 | env: 73 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 74 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 75 | run: sonar-scanner 76 | -Dsonar.host.url=https://sonar.openbsl.ru 77 | -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} 78 | -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} 79 | -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }} 80 | -Dsonar.scm.revision=${{ github.event.pull_request.head.sha }} 81 | -------------------------------------------------------------------------------- /src/Классы/ОпцииПоиска.os: -------------------------------------------------------------------------------- 1 | Перем Отборы; 2 | Перем Сортировки; 3 | Перем Первые; 4 | Перем Смещение; 5 | 6 | // Получить список отборов для выполнения поиска. 7 | // 8 | // Возвращаемое значение: 9 | // ФиксированныйМассив из ЭлементОтбора 10 | // 11 | Функция Отборы() Экспорт 12 | Возврат Новый ФиксированныйМассив(Отборы); 13 | КонецФункции 14 | 15 | // Добавить отбор для выполнения поиска. 16 | // 17 | // Параметры: 18 | // Поле - Строка - Имя поля для отбора. 19 | // ВидСравнения - ВидСравнения - Вид сравнения. 20 | // Значение - Произвольный - Значение для сравнения. 21 | // 22 | // Возвращаемое значение: 23 | // ОпцииПоиска - Текущий объект. 24 | // 25 | Функция Отбор(Поле, ВидСравнения, Значение) Экспорт 26 | 27 | ЭлементОтбора = Новый ЭлементОтбора(Поле, ВидСравнения, Значение); 28 | Отборы.Добавить(ЭлементОтбора); 29 | 30 | Возврат ЭтотОбъект; 31 | 32 | КонецФункции 33 | 34 | // Получить список сортировок для выполнения поиска. 35 | // 36 | // Возвращаемое значение: 37 | // ФиксированныйМассив из ЭлементПорядка 38 | // 39 | Функция Сортировки() Экспорт 40 | Возврат Новый ФиксированныйМассив(Сортировки); 41 | КонецФункции 42 | 43 | // Добавить сортировку для выполнения поиска. 44 | // 45 | // Параметры: 46 | // ИмяПоля - Строка - Имя поля для сортировки. 47 | // НаправлениеСортировки - НаправлениеСортировки - Направление сортировки. 48 | // 49 | // Возвращаемое значение: 50 | // ОпцииПоиска - Текущий объект. 51 | // 52 | Функция СортироватьПо(ИмяПоля, НаправлениеСортировки = Неопределено) Экспорт 53 | 54 | ЭлементПорядка = Новый ЭлементПорядка(ИмяПоля, НаправлениеСортировки); 55 | Сортировки.Добавить(ЭлементПорядка); 56 | 57 | Возврат ЭтотОбъект; 58 | 59 | КонецФункции 60 | 61 | // Получить количество элементов, которые необходимо выбрать. 62 | // 63 | // Возвращаемое значение: 64 | // Число - Количество элементов. 65 | // 66 | Функция ВыбираютсяПервые() Экспорт 67 | Возврат Первые; 68 | КонецФункции 69 | 70 | // Выбрать первые n элементов. 71 | // 72 | // Параметры: 73 | // КоличествоЭлементов - Число - Количество элементов. 74 | // 75 | // Возвращаемое значение: 76 | // ОпцииПоиска - Текущий объект. 77 | // 78 | Функция Первые(КоличествоЭлементов) Экспорт 79 | 80 | Первые = КоличествоЭлементов; 81 | 82 | Возврат ЭтотОбъект; 83 | КонецФункции 84 | 85 | // Получить количество элементов, которые необходимо пропустить. 86 | // 87 | // Возвращаемое значение: 88 | // Число - Количество элементов. 89 | // 90 | Функция ВыбираетсяСоСмещением() Экспорт 91 | Возврат Смещение; 92 | КонецФункции 93 | 94 | // Сместить выборку на n элементов. 95 | // 96 | // Параметры: 97 | // КоличествоЭлементов - Число - Количество элементов. 98 | // 99 | // Возвращаемое значение: 100 | // ОпцииПоиска - Текущий объект. 101 | // 102 | Функция Смещение(КоличествоЭлементов) Экспорт 103 | 104 | Смещение = КоличествоЭлементов; 105 | 106 | Возврат ЭтотОбъект; 107 | 108 | КонецФункции 109 | 110 | Процедура ПриСозданииОбъекта() 111 | Отборы = Новый Массив(); 112 | Сортировки = Новый Массив(); 113 | Первые = Неопределено; 114 | КонецПроцедуры 115 | -------------------------------------------------------------------------------- /src/Классы/АбстрактныйКоннектор.os: -------------------------------------------------------------------------------- 1 | // BSLLS:UnusedParameters-off 2 | // Для хранения статуса соединения 3 | Перем Открыт; 4 | 5 | // Конструктор объекта АбстрактныйКоннектор. 6 | // 7 | Процедура ПриСозданииОбъекта() 8 | Открыт = Ложь; 9 | КонецПроцедуры 10 | 11 | // Открыть соединение с БД. 12 | // 13 | // Параметры: 14 | // СтрокаСоединения - Строка - Строка соединения с БД. 15 | // ПараметрыКоннектора - Массив - Дополнительные параметры инициализации коннектора. 16 | // 17 | Процедура Открыть(СтрокаСоединения, ПараметрыКоннектора) Экспорт 18 | Открыт = Истина; 19 | КонецПроцедуры 20 | 21 | // Закрыть соединение с БД. 22 | // 23 | Процедура Закрыть() Экспорт 24 | Открыт = Ложь; 25 | КонецПроцедуры 26 | 27 | // Получить статус соединения с БД. 28 | // 29 | // Возвращаемое значение: 30 | // Булево - Состояние соединения. Истина, если соединение установлено и готово к использованию. 31 | // В обратном случае - Ложь. 32 | // 33 | Функция Открыт() Экспорт 34 | Возврат Открыт; 35 | КонецФункции 36 | 37 | // Начинает новую транзакцию в БД. 38 | // 39 | Процедура НачатьТранзакцию() Экспорт 40 | 41 | КонецПроцедуры 42 | 43 | // Фиксирует открытую транзакцию в БД. 44 | // 45 | Процедура ЗафиксироватьТранзакцию() Экспорт 46 | 47 | КонецПроцедуры 48 | 49 | // Отменяет открытую транзакцию в БД. 50 | // 51 | Процедура ОтменитьТранзакцию() Экспорт 52 | 53 | КонецПроцедуры 54 | 55 | // Создает таблицу в БД по данным модели. 56 | // 57 | // Параметры: 58 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 59 | // 60 | Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт 61 | 62 | КонецПроцедуры 63 | 64 | // Сохраняет сущность в БД. 65 | // 66 | // Параметры: 67 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 68 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 69 | // 70 | Процедура Сохранить(ОбъектМодели, Сущность) Экспорт 71 | 72 | КонецПроцедуры 73 | 74 | // Удаляет сущность из таблицы БД. 75 | // 76 | // Параметры: 77 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 78 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД. 79 | // 80 | Процедура Удалить(ОбъектМодели, Сущность) Экспорт 81 | 82 | КонецПроцедуры 83 | 84 | // Осуществляет поиск строк в таблице по указанному отбору. 85 | // 86 | // Параметры: 87 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 88 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 89 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 90 | // Каждый элемент отбора преобразуется к условию поиска. 91 | // В качестве "ПутьКДанным" указываются имена колонок. 92 | // * Сортировки - Массив - Сортировка для результата поиска. 93 | // Каждый элемент массива должен иметь тип "ЭлементПорядка". 94 | // В качестве "ПутьКДанным" указываются имена колонок. 95 | // 96 | // Возвращаемое значение: 97 | // Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки, 98 | // значением элемента соответствия - значение колонки. 99 | // 100 | Функция НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 101 | 102 | МассивЗначений = Новый Массив; 103 | Возврат МассивЗначений; 104 | 105 | КонецФункции 106 | 107 | // Удаляет строки в таблице по указанному отбору. 108 | // 109 | // Параметры: 110 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 111 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 112 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 113 | // Каждый элемент отбора преобразуется к условию поиска. 114 | // В качестве "ПутьКДанным" указываются имена колонок. 115 | // 116 | Процедура УдалитьСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 117 | 118 | КонецПроцедуры 119 | -------------------------------------------------------------------------------- /docs/КоннекторJSON.md: -------------------------------------------------------------------------------- 1 | ## КоннекторJSON 2 | 3 | ### ПриСозданииОбъекта 4 | 5 | ```bsl 6 | // Конструктор объекта АбстрактныйКоннектор. 7 | // 8 | Процедура ПриСозданииОбъекта() 9 | ``` 10 | 11 | ### Открыть 12 | 13 | ```bsl 14 | // Открыть соединение с БД. 15 | // 16 | // Параметры: 17 | // СтрокаСоединения - Строка - Строка соединения с БД. 18 | // ПараметрыКоннектора - Массив - Дополнительные параметры инициализиации коннектора. 19 | // 20 | Процедура Открыть(СтрокаСоединения, ПараметрыКоннектора) Экспорт 21 | ``` 22 | 23 | ### Закрыть 24 | 25 | ```bsl 26 | // Закрыть соединение с БД. 27 | // 28 | Процедура Закрыть() Экспорт 29 | ``` 30 | 31 | ### Открыт 32 | 33 | ```bsl 34 | // Получить статус соединения с БД. 35 | // 36 | // Возвращаемое значение: 37 | // Булево - Состояние соединения. Истина, если соединение установлено и готово к использованию. 38 | // В обратном случае - Ложь. 39 | // 40 | Функция Открыт() Экспорт 41 | ``` 42 | 43 | ### НачатьТранзакцию 44 | 45 | ```bsl 46 | // Начинает новую транзакцию в БД. 47 | // 48 | Процедура НачатьТранзакцию() Экспорт 49 | ``` 50 | 51 | ### ЗафиксироватьТранзакцию 52 | 53 | ```bsl 54 | // Фиксирует открытую транзакцию в БД. 55 | // 56 | Процедура ЗафиксироватьТранзакцию() Экспорт 57 | ``` 58 | 59 | ### ОтменитьТранзакцию 60 | 61 | ```bsl 62 | // Отменяет открытую транзакцию в БД. 63 | // 64 | Процедура ОтменитьТранзакцию() Экспорт 65 | ``` 66 | 67 | ### ИнициализироватьТаблицу 68 | 69 | ```bsl 70 | // Создает таблицу в БД по данным модели. 71 | // 72 | // Параметры: 73 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 74 | // 75 | Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт 76 | ``` 77 | 78 | ### Сохранить 79 | 80 | ```bsl 81 | // Сохраняет сущность в БД. 82 | // 83 | // Параметры: 84 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 85 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 86 | // 87 | Процедура Сохранить(ОбъектМодели, Сущность) Экспорт 88 | ``` 89 | 90 | ### Удалить 91 | 92 | ```bsl 93 | // Удаляет сущность из таблицы БД. 94 | // 95 | // Параметры: 96 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 97 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД. 98 | // 99 | Процедура Удалить(ОбъектМодели, Сущность) Экспорт 100 | ``` 101 | 102 | ### НайтиСтрокиВТаблице 103 | 104 | ```bsl 105 | // Осуществляет поиск строк в таблице по указанному отбору. 106 | // 107 | // Параметры: 108 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 109 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 110 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 111 | // Каждый элемент отбора преобразуется к условию поиска. 112 | // В качестве "ПутьКДанным" указываются имена колонок. 113 | // * Сортировки - Массив - Сортировка для результата поиска. 114 | // Каждый элемент массива должен иметь тип "ЭлементПорядка". 115 | // В качестве "ПутьКДанным" указываются имена колонок. 116 | // 117 | // Возвращаемое значение: 118 | // Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки, 119 | // значением элемента соответствия - значение колонки. 120 | // 121 | Функция НайтиСтрокиВТаблице(ОбъектМодели, Знач Отбор) Экспорт 122 | ``` 123 | 124 | ### УдалитьСтрокиВТаблице 125 | 126 | ```bsl 127 | // Удаляет строки в таблице по указанному отбору. 128 | // 129 | // Параметры: 130 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 131 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 132 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 133 | // Каждый элемент отбора преобразуется к условию поиска. 134 | // В качестве "ПутьКДанным" указываются имена колонок. 135 | // 136 | Процедура УдалитьСтрокиВТаблице(ОбъектМодели, Знач Отбор) Экспорт 137 | ``` 138 | 139 | -------------------------------------------------------------------------------- /docs/АбстрактныйКоннектор.md: -------------------------------------------------------------------------------- 1 | ## АбстрактныйКоннектор 2 | 3 | ### ПриСозданииОбъекта 4 | 5 | ```bsl 6 | // Конструктор объекта АбстрактныйКоннектор. 7 | // 8 | Процедура ПриСозданииОбъекта() 9 | ``` 10 | 11 | ### Открыть 12 | 13 | ```bsl 14 | // Открыть соединение с БД. 15 | // 16 | // Параметры: 17 | // СтрокаСоединения - Строка - Строка соединения с БД. 18 | // ПараметрыКоннектора - Массив - Дополнительные параметры инициализации коннектора. 19 | // 20 | Процедура Открыть(СтрокаСоединения, ПараметрыКоннектора) Экспорт 21 | ``` 22 | 23 | ### Закрыть 24 | 25 | ```bsl 26 | // Закрыть соединение с БД. 27 | // 28 | Процедура Закрыть() Экспорт 29 | ``` 30 | 31 | ### Открыт 32 | 33 | ```bsl 34 | // Получить статус соединения с БД. 35 | // 36 | // Возвращаемое значение: 37 | // Булево - Состояние соединения. Истина, если соединение установлено и готово к использованию. 38 | // В обратном случае - Ложь. 39 | // 40 | Функция Открыт() Экспорт 41 | ``` 42 | 43 | ### НачатьТранзакцию 44 | 45 | ```bsl 46 | // Начинает новую транзакцию в БД. 47 | // 48 | Процедура НачатьТранзакцию() Экспорт 49 | ``` 50 | 51 | ### ЗафиксироватьТранзакцию 52 | 53 | ```bsl 54 | // Фиксирует открытую транзакцию в БД. 55 | // 56 | Процедура ЗафиксироватьТранзакцию() Экспорт 57 | ``` 58 | 59 | ### ОтменитьТранзакцию 60 | 61 | ```bsl 62 | // Отменяет открытую транзакцию в БД. 63 | // 64 | Процедура ОтменитьТранзакцию() Экспорт 65 | ``` 66 | 67 | ### ИнициализироватьТаблицу 68 | 69 | ```bsl 70 | // Создает таблицу в БД по данным модели. 71 | // 72 | // Параметры: 73 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 74 | // 75 | Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт 76 | ``` 77 | 78 | ### Сохранить 79 | 80 | ```bsl 81 | // Сохраняет сущность в БД. 82 | // 83 | // Параметры: 84 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 85 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 86 | // 87 | Процедура Сохранить(ОбъектМодели, Сущность) Экспорт 88 | ``` 89 | 90 | ### Удалить 91 | 92 | ```bsl 93 | // Удаляет сущность из таблицы БД. 94 | // 95 | // Параметры: 96 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 97 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД. 98 | // 99 | Процедура Удалить(ОбъектМодели, Сущность) Экспорт 100 | ``` 101 | 102 | ### НайтиСтрокиВТаблице 103 | 104 | ```bsl 105 | // Осуществляет поиск строк в таблице по указанному отбору. 106 | // 107 | // Параметры: 108 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 109 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 110 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 111 | // Каждый элемент отбора преобразуется к условию поиска. 112 | // В качестве "ПутьКДанным" указываются имена колонок. 113 | // * Сортировки - Массив - Сортировка для результата поиска. 114 | // Каждый элемент массива должен иметь тип "ЭлементПорядка". 115 | // В качестве "ПутьКДанным" указываются имена колонок. 116 | // 117 | // Возвращаемое значение: 118 | // Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки, 119 | // значением элемента соответствия - значение колонки. 120 | // 121 | Функция НайтиСтрокиВТаблице(ОбъектМодели, Отбор = Неопределено) Экспорт 122 | ``` 123 | 124 | ### УдалитьСтрокиВТаблице 125 | 126 | ```bsl 127 | // Удаляет строки в таблице по указанному отбору. 128 | // 129 | // Параметры: 130 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 131 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 132 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 133 | // Каждый элемент отбора преобразуется к условию поиска. 134 | // В качестве "ПутьКДанным" указываются имена колонок. 135 | // 136 | Процедура УдалитьСтрокиВТаблице(ОбъектМодели, Знач Отбор) Экспорт 137 | ``` 138 | -------------------------------------------------------------------------------- /docs/ХранилищеСущностей.md: -------------------------------------------------------------------------------- 1 | ## ХранилищеСущностей 2 | 3 | ### ПриСозданииОбъекта 4 | 5 | ```bsl 6 | 7 | Процедура ПриСозданииОбъекта(Знач ПОбъектМодели, Знач ТипКоннектора, Знач СтрокаСоединения, ПараметрыКоннектора) 8 | ``` 9 | 10 | ### СоздатьЭлемент 11 | 12 | ```bsl 13 | // Создает экземпляр сущности, расширенный методами паттерна Active Record. 14 | // 15 | // Возвращаемое значение: 16 | // Произвольный - экземпляр класса сущности с типом, привязанным к ХранилищуСущностей, 17 | // с дополнительными методами паттерна Active Record. 18 | // 19 | Функция СоздатьЭлемент() Экспорт 20 | ``` 21 | 22 | ### Сохранить 23 | 24 | ```bsl 25 | // Сохраняет сущность в БД. 26 | // 27 | // Параметры: 28 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 29 | // 30 | Процедура Сохранить(Сущность) Экспорт 31 | ``` 32 | 33 | ### Получить 34 | 35 | ```bsl 36 | // Осуществляет поиск сущностей типа, привязанного к ХранилищуСущностей, по идентификатору. 37 | // 38 | // Параметры: 39 | // ОпцииПоиска - Произвольный - Опции поиска. 40 | // Если параметр не задан или равен "Неопределено", то возвращаются все найденные сущности указанного типа. 41 | // Если параметр имеет тип "Соответствие", то каждое значение соответствия преобразуется к условию поиска 42 | // ИмяПоля = ЗначениеПоля, где ИмяПоля - ключ элемента соответствия, ЗначениеПоля - значение элемента соответствия. 43 | // Если параметр имеет тип "ОпцииПоиска", то опции передаются как есть. 44 | // 45 | // Возвращаемое значение: 46 | // Массив - Массив найденных сущностей. В качестве элементов массива выступают 47 | // экземпляры класса с типом, привязанным к ХранилищуСущностей, с заполненными значениями полей. 48 | // 49 | Функция Получить(Знач ОпцииПоиска = Неопределено) Экспорт 50 | ``` 51 | 52 | ### ПолучитьОдно 53 | 54 | ```bsl 55 | // Осуществляет поиск сущности типа, привязанного к ХранилищуСущностей, по идентификатору. 56 | // 57 | // Параметры: 58 | // ОпцииПоиска - Произвольный - Опции поиска. 59 | // Если параметр не задан или равен "Неопределено", то возвращаются все найденные сущности указанного типа. 60 | // Если параметр имеет тип "Соответствие", то каждое значение соответствия преобразуется к условию поиска 61 | // ИмяПоля = ЗначениеПоля, где ИмяПоля - ключ элемента соответствия, ЗначениеПоля - значение элемента соответствия. 62 | // Если параметр имеет тип "ОпцииПоиска", то опции передаются как есть. 63 | // Любой другой тип интерпретируется как поиск по &Идентификатору. 64 | // 65 | // Возвращаемое значение: 66 | // Произвольный - Если сущность была найдена, то возвращается экземпляр класса с типом, 67 | // привязанным к ХранилищуСущностей, с заполненными значениями полей. Иначе возвращается "Неопределено". 68 | // 69 | Функция ПолучитьОдно(Знач ОпцииПоиска = Неопределено) Экспорт 70 | ``` 71 | 72 | ### Удалить 73 | 74 | ```bsl 75 | // Выполняет удаление сущности из базы данных. 76 | // Сущность должна иметь заполненный идентификатор. 77 | // 78 | // Параметры: 79 | // Сущность - Произвольный - Удаляемая сущность 80 | // 81 | Процедура Удалить(Сущность) Экспорт 82 | ``` 83 | 84 | ### Закрыть 85 | 86 | ```bsl 87 | // Выполняет очистку текущего Хранилища сущностей. 88 | // Дополнительно посылает коннектору запрос на закрытие соединения. 89 | // 90 | Процедура Закрыть() Экспорт 91 | ``` 92 | 93 | ### НачатьТранзакцию 94 | 95 | ```bsl 96 | // Посылает коннектору запрос на начало транзакции. 97 | // 98 | Процедура НачатьТранзакцию() Экспорт 99 | ``` 100 | 101 | ### ЗафиксироватьТранзакцию 102 | 103 | ```bsl 104 | // Посылает коннектору запрос на фиксацию транзакции. 105 | // 106 | Процедура ЗафиксироватьТранзакцию() Экспорт 107 | ``` 108 | 109 | ### ОтменитьТранзакцию 110 | 111 | ```bsl 112 | // Посылает коннектору запрос на отмену транзакции. 113 | // 114 | Процедура ОтменитьТранзакцию() Экспорт 115 | ``` 116 | 117 | ### ПолучитьКоннектор 118 | 119 | ```bsl 120 | // Возвращает текущий активный коннектор. 121 | // 122 | // Возвращаемое значение: 123 | // АбстрактныйКоннектор - Возвращает экземпляр коннектора. Конкретная реализация определяется параметром 124 | // ТипКоннектора при вызове конструктора МенеджерСущностей. 125 | // 126 | Функция ПолучитьКоннектор() Экспорт 127 | ``` 128 | 129 | ### ПолучитьОбъектМодели 130 | 131 | ```bsl 132 | // Возвращает объект модели, связанный с текущим хранилищем сущностей. 133 | // 134 | // Возвращаемое значение: 135 | // ОбъектМодели 136 | // 137 | Функция ПолучитьОбъектМодели() Экспорт 138 | ``` 139 | 140 | ### ПолучитьПулСущностей 141 | 142 | ```bsl 143 | // @internal 144 | // Для служебного пользования. 145 | // 146 | // Возвращает пул сущностей текущего объекта. 147 | // 148 | // Возвращаемое значение: 149 | // Соответствие - Пул сущностей. 150 | // 151 | Функция ПолучитьПулСущностей() Экспорт 152 | ``` 153 | 154 | -------------------------------------------------------------------------------- /docs/КоннекторSQLite.md: -------------------------------------------------------------------------------- 1 | ## КоннекторSQLite 2 | 3 | ### ПриСозданииОбъекта 4 | 5 | ```bsl 6 | // Конструктор объекта КоннекторSQLite. 7 | // 8 | Процедура ПриСозданииОбъекта() 9 | ``` 10 | 11 | ### Открыть 12 | 13 | ```bsl 14 | // Открыть соединение с БД. 15 | // 16 | // Параметры: 17 | // СтрокаСоединения - Строка - Строка соединения с БД. 18 | // ПараметрыКоннектора - Массив - Дополнительные параметры инициализации коннектора. 19 | // 20 | Процедура Открыть(СтрокаСоединения, ПараметрыКоннектора) Экспорт 21 | ``` 22 | 23 | ### Закрыть 24 | 25 | ```bsl 26 | // Закрыть соединение с БД. 27 | // 28 | Процедура Закрыть() Экспорт 29 | ``` 30 | 31 | ### Открыт 32 | 33 | ```bsl 34 | // Получить статус соединения с БД. 35 | // 36 | // Возвращаемое значение: 37 | // Булево - Состояние соединения. Истина, если соединение установлено и готово к использованию. 38 | // В обратном случае - Ложь. 39 | // 40 | Функция Открыт() Экспорт 41 | ``` 42 | 43 | ### НачатьТранзакцию 44 | 45 | ```bsl 46 | // Начинает новую транзакцию в БД. 47 | // 48 | Процедура НачатьТранзакцию() Экспорт 49 | ``` 50 | 51 | ### ЗафиксироватьТранзакцию 52 | 53 | ```bsl 54 | // Фиксирует открытую транзакцию в БД. 55 | // 56 | Процедура ЗафиксироватьТранзакцию() Экспорт 57 | ``` 58 | 59 | ### ОтменитьТранзакцию 60 | 61 | ```bsl 62 | // Отменяет открытую транзакцию в БД. 63 | // 64 | Процедура ОтменитьТранзакцию() Экспорт 65 | ``` 66 | 67 | ### ИнициализироватьТаблицу 68 | 69 | ```bsl 70 | // Создает таблицу в БД по данным модели. 71 | // 72 | // Параметры: 73 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 74 | // 75 | Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт 76 | ``` 77 | 78 | ### Сохранить 79 | 80 | ```bsl 81 | // Сохраняет сущность в БД. 82 | // 83 | // Параметры: 84 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 85 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 86 | // 87 | Процедура Сохранить(ОбъектМодели, Сущность) Экспорт 88 | ``` 89 | 90 | ### Удалить 91 | 92 | ```bsl 93 | // Удаляет сущность из таблицы БД. 94 | // 95 | // Параметры: 96 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 97 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД. 98 | // 99 | Процедура Удалить(ОбъектМодели, Сущность) Экспорт 100 | ``` 101 | 102 | ### НайтиСтрокиВТаблице 103 | 104 | ```bsl 105 | // Осуществляет поиск строк в таблице по указанному отбору. 106 | // 107 | // Параметры: 108 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 109 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 110 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 111 | // Каждый элемент отбора преобразуется к условию поиска. 112 | // В качестве "ПутьКДанным" указываются имена колонок. 113 | // * Сортировки - Массив - Сортировка для результата поиска. 114 | // Каждый элемент массива должен иметь тип "ЭлементПорядка". 115 | // В качестве "ПутьКДанным" указываются имена колонок. 116 | // 117 | // Возвращаемое значение: 118 | // Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки, 119 | // значением элемента соответствия - значение колонки. 120 | // 121 | Функция НайтиСтрокиВТаблице(ОбъектМодели, Знач Отбор) Экспорт 122 | ``` 123 | 124 | ### УдалитьСтрокиВТаблице 125 | 126 | ```bsl 127 | // Удаляет строки в таблице по указанному отбору. 128 | // 129 | // Параметры: 130 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 131 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 132 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 133 | // Каждый элемент отбора преобразуется к условию поиска. 134 | // В качестве "ПутьКДанным" указываются имена колонок. 135 | // 136 | Процедура УдалитьСтрокиВТаблице(ОбъектМодели, Знач Отбор) Экспорт 137 | ``` 138 | 139 | ### ВыполнитьЗапрос 140 | 141 | ```bsl 142 | // @Unstable 143 | // Выполнить произвольный запрос и получить результат. 144 | // 145 | // Данный метод не входит в основной интерфейс "Коннектор". 146 | // Не рекомендуется использовать этот метод в прикладном коде, сигнатура метода может измениться. 147 | // 148 | // Параметры: 149 | // ТекстЗапроса - Строка - Текст выполняемого запроса 150 | // 151 | // Возвращаемое значение: 152 | // ТаблицаЗначений - Результат выполнения запроса. 153 | // 154 | Функция ВыполнитьЗапрос(ТекстЗапроса) Экспорт 155 | ``` 156 | 157 | -------------------------------------------------------------------------------- /src/internal/Модули/ОбработкаКоллекций.os: -------------------------------------------------------------------------------- 1 | // <Описание функции> 2 | // 3 | // Параметры: 4 | // ИсходнаяКоллекция - Структура, Массив - Коллекция, которую нужно преобразовать к коллекции сущностей. 5 | // РодительскаяСущность - Произвольный - Владелец коллекции 6 | // 7 | // Возвращаемое значение: 8 | // Массив - Массив сущностей, полученных из элементов изначальной коллекции. 9 | // 10 | Функция ПреобразоватьКоллекциюККоллекцииСущностей( 11 | ИсходнаяКоллекция, 12 | РодительскаяСущность, 13 | РодительскийОбъектМодели, 14 | ПодчиненнаяТаблица) Экспорт 15 | 16 | КоллекцияСущностей = Новый Массив; 17 | ТипКоллекции = ТипЗнч(ИсходнаяКоллекция); 18 | 19 | ОбъектМоделиЭлементКоллекции = ОбработкаКоллекций.ПолучитьОбъектМоделиДляПодчиненнойТаблицы( 20 | РодительскийОбъектМодели, 21 | ПодчиненнаяТаблица 22 | ); 23 | 24 | Если ТипКоллекции = Тип("Массив") Тогда 25 | 26 | Для сч = 0 По ИсходнаяКоллекция.ВГраница() Цикл 27 | Значение = ИсходнаяКоллекция[сч]; 28 | 29 | СущностьЭлемент = Новый СлужебнаяСущность_ЭлементКоллекцииКлючЗначение(); 30 | 31 | ОбъектМоделиЭлементКоллекции.УстановитьЗначениеКолонкиВПоле(СущностьЭлемент, "ref", РодительскаяСущность); 32 | ОбъектМоделиЭлементКоллекции.УстановитьЗначениеКолонкиВПоле(СущностьЭлемент, "key", сч); 33 | ОбъектМоделиЭлементКоллекции.УстановитьЗначениеКолонкиВПоле(СущностьЭлемент, "value", Значение); 34 | 35 | КоллекцияСущностей.Добавить(СущностьЭлемент); 36 | КонецЦикла; 37 | 38 | ИначеЕсли ТипКоллекции = Тип("Структура") Тогда 39 | 40 | Для Каждого ЭлементКоллекции Из ИсходнаяКоллекция Цикл 41 | СущностьЭлемент = Новый СлужебнаяСущность_ЭлементКоллекцииКлючЗначение(); 42 | 43 | ОбъектМоделиЭлементКоллекции.УстановитьЗначениеКолонкиВПоле(СущностьЭлемент, "ref", РодительскаяСущность); 44 | ОбъектМоделиЭлементКоллекции.УстановитьЗначениеКолонкиВПоле(СущностьЭлемент, "key", ЭлементКоллекции.Ключ); 45 | ОбъектМоделиЭлементКоллекции.УстановитьЗначениеКолонкиВПоле(СущностьЭлемент, "value", ЭлементКоллекции.Значение); 46 | 47 | КоллекцияСущностей.Добавить(СущностьЭлемент); 48 | КонецЦикла; 49 | 50 | Иначе 51 | ВызватьИсключение "Неизвестный тип коллекции " + ТипКоллекции; 52 | КонецЕсли; 53 | 54 | Возврат КоллекцияСущностей; 55 | 56 | КонецФункции 57 | 58 | Функция ПреобразоватьКоллекциюСтрокККоллекции(КоллекцияСущностей, ПодчиненнаяТаблица) Экспорт 59 | 60 | Если ПодчиненнаяТаблица.ТипТаблицы = ТипыПодчиненныхТаблиц.Массив Тогда 61 | Коллекция = Новый Массив; 62 | 63 | Для Каждого СущностьЭлемент Из КоллекцияСущностей Цикл 64 | Коллекция.Добавить(СущностьЭлемент.Получить("value")); 65 | КонецЦикла; 66 | ИначеЕсли ПодчиненнаяТаблица.ТипТаблицы = ТипыПодчиненныхТаблиц.Структура Тогда 67 | Коллекция = Новый Структура; 68 | 69 | Для Каждого СущностьЭлемент Из КоллекцияСущностей Цикл 70 | Коллекция.Вставить(СущностьЭлемент.Получить("key"), СущностьЭлемент.Получить("value")); 71 | КонецЦикла; 72 | Иначе 73 | ВызватьИсключение "Неизвестный тип коллекции " + ПодчиненнаяТаблица.ТипТаблицы; 74 | КонецЕсли; 75 | 76 | Возврат Коллекция; 77 | 78 | КонецФункции 79 | 80 | Функция ПолучитьОбъектМоделиДляПодчиненнойТаблицы(РодительскийОбъектМодели, ПодчиненнаяТаблица) Экспорт 81 | 82 | Если ПодчиненнаяТаблица.ТипТаблицы = ТипыПодчиненныхТаблиц.Массив Тогда 83 | ТипКолонкиКлюч = ТипыКолонок.Целое; 84 | ИначеЕсли ПодчиненнаяТаблица.ТипТаблицы = ТипыПодчиненныхТаблиц.Структура Тогда 85 | ТипКолонкиКлюч = ТипыКолонок.Строка; 86 | Иначе 87 | ВызватьИсключение "Неизвестный тип элемента " + ПодчиненнаяТаблица.ТипЭлемента; 88 | КонецЕсли; 89 | 90 | ОбъектМоделиЭлементКоллекции = Новый ОбъектМодели( 91 | Тип("СлужебнаяСущность_ЭлементКоллекцииКлючЗначение"), 92 | РодительскийОбъектМодели.МодельДанных() 93 | ); 94 | 95 | ОбъектМоделиЭлементКоллекции.Служебный_ИмяТаблицы(ПодчиненнаяТаблица.ИмяТаблицы); 96 | КолонкиОбъектаМодели = ОбъектМоделиЭлементКоллекции.Служебный_Колонки(); 97 | 98 | КолонкаKey = КолонкиОбъектаМодели.Найти("key", "ИмяКолонки"); 99 | КолонкаKey.ТипКолонки = ТипКолонкиКлюч; 100 | 101 | КолонкаRef = КолонкиОбъектаМодели.Найти("ref", "ИмяКолонки"); 102 | КолонкаRef.ТипСсылки = РодительскийОбъектМодели.ТипСущности(); 103 | 104 | КолонкаValue = КолонкиОбъектаМодели.Найти("value", "ИмяКолонки"); 105 | Если ТипыКолонок.ЭтоПримитивныйТип(ПодчиненнаяТаблица.ТипЭлемента) Тогда 106 | КолонкаValue.ТипКолонки = ПодчиненнаяТаблица.ТипЭлемента; 107 | ИначеЕсли ТипыПодчиненныхТаблиц.Типы().Найти(ПодчиненнаяТаблица.ТипЭлемента) <> Неопределено Тогда 108 | ВызватьИсключение "Коллекция коллекций не поддерживается."; 109 | Иначе 110 | ОбъектМоделиТипЭлемента = РодительскийОбъектМодели.МодельДанных().Получить(ПодчиненнаяТаблица.ТипЭлемента); 111 | КолонкаValue.ТипКолонки = ТипыКолонок.Ссылка; 112 | КолонкаValue.ТипСсылки = ПодчиненнаяТаблица.ТипЭлемента; 113 | КонецЕсли; 114 | 115 | Возврат ОбъектМоделиЭлементКоллекции; 116 | 117 | КонецФункции 118 | -------------------------------------------------------------------------------- /src/Классы/ХранилищеСущностей.os: -------------------------------------------------------------------------------- 1 | #Использовать "../internal" 2 | 3 | Перем ОбъектМодели; 4 | Перем Коннектор; 5 | Перем ПулСущностей; 6 | 7 | Процедура ПриСозданииОбъекта(Знач ПОбъектМодели, Знач ТипКоннектора, Знач СтрокаСоединения, ПараметрыКоннектора) 8 | ОбъектМодели = ПОбъектМодели; 9 | Коннектор = РаботаСКоннекторами.СоздатьКоннектор(ТипКоннектора); 10 | 11 | РаботаСКоннекторами.ОткрытьКоннектор(Коннектор, СтрокаСоединения, ПараметрыКоннектора); 12 | ПулСущностей = Новый Соответствие(); 13 | КонецПроцедуры 14 | 15 | // Создает экземпляр сущности, расширенный методами паттерна Active Record. 16 | // 17 | // Возвращаемое значение: 18 | // Произвольный - экземпляр класса сущности с типом, привязанным к ХранилищуСущностей, 19 | // с дополнительными методами паттерна Active Record. 20 | // 21 | Функция СоздатьЭлемент() Экспорт 22 | Возврат АктивнаяЗапись.СоздатьИзХранилища(ОбъектМодели, ЭтотОбъект); 23 | КонецФункции 24 | 25 | // Сохраняет сущность в БД. 26 | // 27 | // Параметры: 28 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 29 | // 30 | Процедура Сохранить(Сущность) Экспорт 31 | РаботаСКоннекторами.Сохранить(Коннектор, ОбъектМодели, ПулСущностей, Сущность); 32 | КонецПроцедуры 33 | 34 | 35 | // Осуществляет поиск сущностей типа, привязанного к ХранилищуСущностей, по идентификатору. 36 | // 37 | // Параметры: 38 | // ОпцииПоиска - Произвольный - Опции поиска. 39 | // Если параметр не задан или равен "Неопределено", то возвращаются все найденные сущности указанного типа. 40 | // Если параметр имеет тип "Соответствие", то каждое значение соответствия преобразуется к условию поиска 41 | // ИмяПоля = ЗначениеПоля, где ИмяПоля - ключ элемента соответствия, ЗначениеПоля - значение элемента соответствия. 42 | // Если параметр имеет тип "ОпцииПоиска", то опции передаются как есть. 43 | // 44 | // Возвращаемое значение: 45 | // Массив - Массив найденных сущностей. В качестве элементов массива выступают 46 | // экземпляры класса с типом, привязанным к ХранилищуСущностей, с заполненными значениями полей. 47 | // 48 | Функция Получить(Знач ОпцииПоиска = Неопределено) Экспорт 49 | Если ОпцииПоиска = Неопределено Тогда 50 | ОпцииПоиска = Новый ОпцииПоиска(); 51 | КонецЕсли; 52 | 53 | Возврат РаботаСКоннекторами.Получить(Коннектор, ОбъектМодели, ПулСущностей, ОпцииПоиска); 54 | КонецФункции 55 | 56 | // Осуществляет поиск сущности типа, привязанного к ХранилищуСущностей, по идентификатору. 57 | // 58 | // Параметры: 59 | // ОпцииПоиска - Произвольный - Опции поиска. 60 | // Если параметр не задан или равен "Неопределено", то возвращаются все найденные сущности указанного типа. 61 | // Если параметр имеет тип "Соответствие", то каждое значение соответствия преобразуется к условию поиска 62 | // ИмяПоля = ЗначениеПоля, где ИмяПоля - ключ элемента соответствия, ЗначениеПоля - значение элемента соответствия. 63 | // Если параметр имеет тип "ОпцииПоиска", то опции передаются как есть. 64 | // Любой другой тип интерпретируется как поиск по &Идентификатору. 65 | // 66 | // Возвращаемое значение: 67 | // Произвольный - Если сущность была найдена, то возвращается экземпляр класса с типом, 68 | // привязанным к ХранилищуСущностей, с заполненными значениями полей. Иначе возвращается "Неопределено". 69 | // 70 | Функция ПолучитьОдно(Знач ОпцииПоиска = Неопределено) Экспорт 71 | Если ОпцииПоиска = Неопределено Тогда 72 | ОпцииПоиска = Новый ОпцииПоиска(); 73 | КонецЕсли; 74 | 75 | Возврат РаботаСКоннекторами.ПолучитьОдно(Коннектор, ОбъектМодели, ПулСущностей, ОпцииПоиска); 76 | КонецФункции 77 | 78 | // Выполняет удаление сущности из базы данных. 79 | // Сущность должна иметь заполненный идентификатор. 80 | // 81 | // Параметры: 82 | // Сущность - Произвольный - Удаляемая сущность 83 | // 84 | Процедура Удалить(Сущность) Экспорт 85 | РаботаСКоннекторами.Удалить(Коннектор, ОбъектМодели, ПулСущностей, Сущность); 86 | КонецПроцедуры 87 | 88 | // Выполняет очистку текущего Хранилища сущностей. 89 | // Дополнительно посылает коннектору запрос на закрытие соединения. 90 | // 91 | Процедура Закрыть() Экспорт 92 | РаботаСКоннекторами.ЗакрытьКоннектор(Коннектор); 93 | ПулСущностей.Очистить(); 94 | КонецПроцедуры 95 | 96 | // Посылает коннектору запрос на начало транзакции. 97 | // 98 | Процедура НачатьТранзакцию() Экспорт 99 | РаботаСКоннекторами.НачатьТранзакцию(Коннектор); 100 | КонецПроцедуры 101 | 102 | // Посылает коннектору запрос на фиксацию транзакции. 103 | // 104 | Процедура ЗафиксироватьТранзакцию() Экспорт 105 | РаботаСКоннекторами.ЗафиксироватьТранзакцию(Коннектор); 106 | КонецПроцедуры 107 | 108 | // Посылает коннектору запрос на отмену транзакции. 109 | // 110 | Процедура ОтменитьТранзакцию() Экспорт 111 | РаботаСКоннекторами.ОтменитьТранзакцию(Коннектор); 112 | КонецПроцедуры 113 | 114 | // Возвращает текущий активный коннектор. 115 | // 116 | // Возвращаемое значение: 117 | // АбстрактныйКоннектор - Возвращает экземпляр коннектора. Конкретная реализация определяется параметром 118 | // ТипКоннектора при вызове конструктора МенеджерСущностей. 119 | // 120 | Функция ПолучитьКоннектор() Экспорт 121 | Возврат Коннектор; 122 | КонецФункции 123 | 124 | // Возвращает объект модели, связанный с текущим хранилищем сущностей. 125 | // 126 | // Возвращаемое значение: 127 | // ОбъектМодели 128 | // 129 | Функция ПолучитьОбъектМодели() Экспорт 130 | Возврат ОбъектМодели; 131 | КонецФункции 132 | 133 | // @internal 134 | // Для служебного пользования. 135 | // 136 | // Возвращает пул сущностей текущего объекта. 137 | // 138 | // Возвращаемое значение: 139 | // Соответствие - Пул сущностей. 140 | // 141 | Функция ПолучитьПулСущностей() Экспорт 142 | Возврат ПулСущностей; 143 | КонецФункции 144 | -------------------------------------------------------------------------------- /docs/МенеджерСущностей.md: -------------------------------------------------------------------------------- 1 | ## МенеджерСущностей 2 | 3 | ### ПриСозданииОбъекта 4 | 5 | ```bsl 6 | // Конструктор объекта МенеджерСущностей. 7 | // 8 | // Параметры: 9 | // ТипКоннектора - Тип - Тип класса, реализующего интерфейс Коннектор. 10 | // СтрокаСоединения - Строка - Строка соединения к БД, к которой подключается коннектор. 11 | // ППараметрыКоннектора - Массив - Массив дополнительных параметров коннектора. Содержимое произвольное. 12 | // 13 | Процедура ПриСозданииОбъекта(Знач ТипКоннектора, Знач СтрокаСоединения = "", Знач ППараметрыКоннектора = Неопределено) 14 | ``` 15 | 16 | ### ДобавитьКлассВМодель 17 | 18 | ```bsl 19 | // Регистрирует переданный тип класса-сценария в модели данных. 20 | // 21 | // Параметры: 22 | // ТипСущности - Тип - Тип для добавления в модель 23 | // 24 | Процедура ДобавитьКлассВМодель(ТипСущности) 25 | ``` 26 | 27 | ### ПолучитьМодельДанных 28 | 29 | ```bsl 30 | // Получить модель данных - хранилище информации о типах полей, колонок, таблиц для типов сущостей. 31 | // 32 | // Возвращаемое значение: 33 | // МодельДанных 34 | // 35 | Функция ПолучитьМодельДанных() Экспорт 36 | ``` 37 | 38 | ### Инициализировать 39 | 40 | ```bsl 41 | // Запускает процессы инициализации коннектора и таблиц БД. 42 | // 43 | Процедура Инициализировать() 44 | ``` 45 | 46 | ### СоздатьЭлемент 47 | 48 | ```bsl 49 | // Создает экземпляр сущности, расширенный методами паттерна Active Record. 50 | // 51 | // Параметры: 52 | // ТипСущности - Тип - Тип создаваемой сущности. 53 | // 54 | // Возвращаемое значение: 55 | // Произвольный - экземпляр класса сущности с типом, привязанным к переданному "ТипуСущности", 56 | // с дополнительными методами паттерна Active Record. 57 | // 58 | Функция СоздатьЭлемент(ТипСущности) 59 | ``` 60 | 61 | ### Сохранить 62 | 63 | ```bsl 64 | // Сохраняет сущность в БД. 65 | // 66 | // Параметры: 67 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 68 | // 69 | Процедура Сохранить(Сущность) 70 | ``` 71 | 72 | ### Получить 73 | 74 | ```bsl 75 | // Осуществляет поиск сущностей переданного типа по идентификатору. 76 | // 77 | // Параметры: 78 | // ТипСущности - Тип - Тип искомой сущности. 79 | // ОпцииПоиска - Произвольный - Опции поиска. 80 | // Если параметр не задан или равен "Неопределено", то возвращаются все найденные сущности указанного типа. 81 | // Если параметр имеет тип "Соответствие", то каждое значение соответствия преобразуется к условию поиска 82 | // ИмяПоля = ЗначениеПоля, где ИмяПоля - ключ элемента соответствия, ЗначениеПоля - значение элемента соответствия. 83 | // Если параметр имеет тип "ОпцииПоиска", то опции передаются как есть. 84 | // 85 | // Возвращаемое значение: 86 | // Массив - Массив найденных сущностей. В качестве элементов массива выступают 87 | // экземпляры класса с типом, равным переданному "ТипуСущности", с заполненными значениями полей. 88 | // 89 | Функция Получить(ТипСущности, Знач ОпцииПоиска = Неопределено) 90 | ``` 91 | 92 | ### ПолучитьОдно 93 | 94 | ```bsl 95 | // Осуществляет поиск сущности переданного типа по идентификатору. 96 | // 97 | // Параметры: 98 | // ТипСущности - Тип - Тип искомой сущности. 99 | // ОпцииПоиска - Произвольный - Опции поиска. 100 | // Если параметр не задан или равен "Неопределено", то возвращаются все найденные сущности указанного типа. 101 | // Если параметр имеет тип "Соответствие", то каждое значение соответствия преобразуется к условию поиска 102 | // ИмяПоля = ЗначениеПоля, где ИмяПоля - ключ элемента соответствия, ЗначениеПоля - значение элемента соответствия. 103 | // Если параметр имеет тип "ОпцииПоиска", то опции передаются как есть. 104 | // Любой другой тип интерпретируется как поиск по &Идентификатору. 105 | // 106 | // Возвращаемое значение: 107 | // Произвольный - Если сущность была найдена, то возвращается экземпляр класса с типом, равным переданному 108 | // "ТипуСущности", с заполненными значениями полей. Иначе возвращается "Неопределено". 109 | // 110 | Функция ПолучитьОдно(ТипСущности, Знач ОпцииПоиска = Неопределено) 111 | ``` 112 | 113 | ### Удалить 114 | 115 | ```bsl 116 | // Выполняет удаление сущности из базы данных. 117 | // Сущность должна иметь заполненный идентификатор. 118 | // 119 | // Параметры: 120 | // Сущность - Произвольный - Удаляемая сущность 121 | // 122 | Процедура Удалить(Сущность) 123 | ``` 124 | 125 | ### Закрыть 126 | 127 | ```bsl 128 | // Выполняет очистку полную данных библиотеки. 129 | // Дополнительно посылает всем используемым коннекторам запросы на закрытие соединения. 130 | // 131 | Процедура Закрыть() 132 | ``` 133 | 134 | ### НачатьТранзакцию 135 | 136 | ```bsl 137 | // Посылает коннектору запрос на начало транзакции. 138 | // 139 | Процедура НачатьТранзакцию() 140 | ``` 141 | 142 | ### ЗафиксироватьТранзакцию 143 | 144 | ```bsl 145 | // Посылает коннектору запрос на фиксацию транзакции. 146 | // 147 | Процедура ЗафиксироватьТранзакцию() 148 | ``` 149 | 150 | ### ОтменитьТранзакцию 151 | 152 | ```bsl 153 | // Посылает коннектору запрос на отмену транзакции. 154 | // 155 | Процедура ОтменитьТранзакцию() 156 | ``` 157 | 158 | ### ПолучитьКоннектор 159 | 160 | ```bsl 161 | // Возвращает текущий активный коннектор. 162 | // 163 | // Возвращаемое значение: 164 | // АбстрактныйКоннектор - Возвращает экземпляр коннектора. Конкретная реализация определяется параметром 165 | // ТипКоннектора при вызове конструктора МенеджерСущностей. 166 | // 167 | Функция ПолучитьКоннектор() 168 | ``` 169 | 170 | ### ПолучитьХранилищеСущностей 171 | 172 | ```bsl 173 | // Получает ХранилищеСущностей, привязанное к переданному типу сущности. 174 | // 175 | // Параметры: 176 | // ТипСущности - Тип - Тип сущности, зарегистрированный в Модели 177 | // 178 | // Возвращаемое значение: 179 | // ХранилищеСущностей - Хранилище сущностей, привязанное к переданному типу сущности. 180 | // 181 | Функция ПолучитьХранилищеСущностей(ТипСущности) 182 | ``` 183 | 184 | ### ПолучитьПулСущностей 185 | 186 | ```bsl 187 | // @internal 188 | // Для служебного пользования. 189 | // 190 | // Возвращает пул сущностей из хранилища сущностей, привязанного к переданному типу сущности. 191 | // 192 | // Параметры: 193 | // ТипСущности - Тип - Тип сущности, зарегистрированный в Модели. 194 | // 195 | // Возвращаемое значение: 196 | // Соответствие - Пул сущностей. 197 | // 198 | Функция ПолучитьПулСущностей(ТипСущности) 199 | ``` 200 | 201 | -------------------------------------------------------------------------------- /src/Классы/КоннекторSQLite.os: -------------------------------------------------------------------------------- 1 | #Использовать asserts 2 | #Использовать logos 3 | #Использовать reflector 4 | #Использовать semaphore 5 | #Использовать strings 6 | 7 | Перем КоннекторSQL; 8 | Перем КонструкторКоннектора Экспорт; 9 | Перем Соединение Экспорт; 10 | Перем КартаТипов; 11 | 12 | Перем Лог; 13 | 14 | // Конструктор объекта КоннекторSQLite. 15 | // 16 | Процедура ПриСозданииОбъекта() 17 | 18 | Лог = Логирование.ПолучитьЛог("oscript.lib.entity.connector.sqlite"); 19 | КоннекторSQL = Новый АбстрактныйКоннекторSQL(ЭтотОбъект, Лог); 20 | 21 | КонструкторКоннектора = ПолучитьКонструкторКоннектора(); 22 | Соединение = КонструкторКоннектора.НовыйСоединение(); 23 | КартаТипов = СоответствиеТиповМоделиИТиповКолонок(); 24 | 25 | КонецПроцедуры 26 | 27 | // Открыть соединение с БД. 28 | // 29 | // Параметры: 30 | // СтрокаСоединения - Строка - Строка соединения с БД. 31 | // ПараметрыКоннектора - Массив - Дополнительные параметры инициализации коннектора. 32 | // 33 | Процедура Открыть(СтрокаСоединения, ПараметрыКоннектора) Экспорт 34 | КонструкторКоннектора.Открыть(Соединение, СтрокаСоединения); 35 | КонецПроцедуры 36 | 37 | // Закрыть соединение с БД. 38 | // 39 | Процедура Закрыть() Экспорт 40 | КонструкторКоннектора.Закрыть(Соединение); 41 | КонецПроцедуры 42 | 43 | // Получить статус соединения с БД. 44 | // 45 | // Возвращаемое значение: 46 | // Булево - Состояние соединения. Истина, если соединение установлено и готово к использованию. 47 | // В обратном случае - Ложь. 48 | // 49 | Функция Открыт() Экспорт 50 | Возврат Соединение.Открыто; 51 | КонецФункции 52 | 53 | // Начинает новую транзакцию в БД. 54 | // 55 | Процедура НачатьТранзакцию() Экспорт 56 | Запрос = КонструкторКоннектора.НовыйЗапрос(Соединение); 57 | Запрос.Текст = "BEGIN TRANSACTION;"; 58 | Запрос.ВыполнитьКоманду(); 59 | КонецПроцедуры 60 | 61 | // Фиксирует открытую транзакцию в БД. 62 | // 63 | Процедура ЗафиксироватьТранзакцию() Экспорт 64 | Запрос = КонструкторКоннектора.НовыйЗапрос(Соединение); 65 | Запрос.Текст = "COMMIT TRANSACTION;"; 66 | Запрос.ВыполнитьКоманду(); 67 | КонецПроцедуры 68 | 69 | // Отменяет открытую транзакцию в БД. 70 | // 71 | Процедура ОтменитьТранзакцию() Экспорт 72 | Запрос = КонструкторКоннектора.НовыйЗапрос(Соединение); 73 | Запрос.Текст = "ROLLBACK TRANSACTION;"; 74 | Запрос.ВыполнитьКоманду(); 75 | КонецПроцедуры 76 | 77 | // Создает таблицу в БД по данным модели. 78 | // 79 | // Параметры: 80 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 81 | // 82 | Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт 83 | 84 | КоннекторSQL.ИнициализироватьТаблицу(ОбъектМодели); 85 | 86 | КонецПроцедуры 87 | 88 | // Сохраняет сущность в БД. 89 | // 90 | // Параметры: 91 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 92 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 93 | // 94 | Процедура Сохранить(ОбъектМодели, Сущность) Экспорт 95 | 96 | ИмяТаблицы = ОбъектМодели.ИмяТаблицы(); 97 | КолонкиТаблицы = ОбъектМодели.Колонки(); 98 | 99 | Запрос = КонструкторКоннектора.НовыйЗапрос(Соединение); 100 | 101 | ИменаКолонок = ""; 102 | ЗначенияКолонок = ""; 103 | 104 | Если КолонкиТаблицы.Количество() = 1 И ОбъектМодели.Идентификатор().ГенерируемоеЗначение Тогда 105 | ИменаКолонок = Символы.Таб + ОбъектМодели.Идентификатор().ИмяКолонки; 106 | ЗначенияКолонок = Символы.Таб + "null"; 107 | Иначе 108 | Для Каждого ДанныеОКолонке Из КолонкиТаблицы Цикл 109 | ЗначениеПараметра = ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(Сущность, ДанныеОКолонке.ИмяПоля); 110 | 111 | Если ДанныеОКолонке.ГенерируемоеЗначение И НЕ ЗначениеЗаполнено(ЗначениеПараметра) Тогда 112 | // TODO: Поддержка чего-то кроме автоинкремента 113 | Продолжить; 114 | КонецЕсли; 115 | ИменаКолонок = ИменаКолонок + Символы.Таб + ДанныеОКолонке.ИмяКолонки + "," + Символы.ПС; 116 | ЗначенияКолонок = ЗначенияКолонок + Символы.Таб + "@" + ДанныеОКолонке.ИмяКолонки + "," + Символы.ПС; 117 | 118 | Запрос.УстановитьПараметр(ДанныеОКолонке.ИмяКолонки, ЗначениеПараметра); 119 | КонецЦикла; 120 | 121 | СтроковыеФункции.УдалитьПоследнийСимволВСтроке(ИменаКолонок, 2); 122 | СтроковыеФункции.УдалитьПоследнийСимволВСтроке(ЗначенияКолонок, 2); 123 | КонецЕсли; 124 | 125 | ТекстЗапроса = "INSERT OR REPLACE INTO %1 ( 126 | |%2 127 | |) VALUES ( 128 | |%3 129 | |);"; 130 | 131 | ТекстЗапроса = СтрШаблон(ТекстЗапроса, ИмяТаблицы, ИменаКолонок, ЗначенияКолонок); 132 | Лог.Отладка("Сохранение сущности с типом %1:%2%3", ОбъектМодели.ТипСущности(), Символы.ПС, ТекстЗапроса); 133 | 134 | Семафор = Семафоры.Получить(Строка(ОбъектМодели.ТипСущности())); 135 | Семафор.Захватить(); 136 | Запрос.Текст = ТекстЗапроса; 137 | 138 | Попытка 139 | 140 | Запрос.ВыполнитьКоманду(); 141 | 142 | Если ОбъектМодели.Идентификатор().ГенерируемоеЗначение Тогда 143 | ИДПоследнейДобавленнойЗаписи = КонструкторКоннектора.ИДПоследнейДобавленнойЗаписи(Соединение, Запрос); 144 | ОбъектМодели.УстановитьЗначениеКолонкиВПоле( 145 | Сущность, 146 | ОбъектМодели.Идентификатор().ИмяКолонки, 147 | ИДПоследнейДобавленнойЗаписи 148 | ); 149 | КонецЕсли; 150 | 151 | Исключение 152 | 153 | Семафор.Освободить(); 154 | 155 | ВызватьИсключение; 156 | 157 | КонецПопытки; 158 | 159 | Семафор.Освободить(); 160 | 161 | // TODO: Для полей с автоинкрементом - получить значения из базы. 162 | // по факту - просто переинициализировать класс значениями полей из СУБД. 163 | // ЗаполнитьСущность(Сущность, ОбъектМодели); 164 | 165 | КонецПроцедуры 166 | 167 | // Удаляет сущность из таблицы БД. 168 | // 169 | // Параметры: 170 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 171 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД. 172 | // 173 | Процедура Удалить(ОбъектМодели, Сущность) Экспорт 174 | 175 | КоннекторSQL.Удалить(ОбъектМодели, Сущность); 176 | 177 | КонецПроцедуры 178 | 179 | // Осуществляет поиск строк в таблице по указанному отбору. 180 | // 181 | // Параметры: 182 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 183 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 184 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 185 | // Каждый элемент отбора преобразуется к условию поиска. 186 | // В качестве "ПутьКДанным" указываются имена колонок. 187 | // * Сортировки - Массив - Сортировка для результата поиска. 188 | // Каждый элемент массива должен иметь тип "ЭлементПорядка". 189 | // В качестве "ПутьКДанным" указываются имена колонок. 190 | // 191 | // Возвращаемое значение: 192 | // Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки, 193 | // значением элемента соответствия - значение колонки. 194 | // 195 | Функция НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 196 | 197 | Возврат КоннекторSQL.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 198 | 199 | КонецФункции 200 | 201 | // Удаляет строки в таблице по указанному отбору. 202 | // 203 | // Параметры: 204 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 205 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 206 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 207 | // Каждый элемент отбора преобразуется к условию поиска. 208 | // В качестве "ПутьКДанным" указываются имена колонок. 209 | // 210 | Процедура УдалитьСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 211 | 212 | КоннекторSQL.УдалитьСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 213 | 214 | КонецПроцедуры 215 | 216 | // @Unstable 217 | // Выполнить произвольный запрос и получить результат. 218 | // 219 | // Данный метод не входит в основной интерфейс "Коннектор". 220 | // Не рекомендуется использовать этот метод в прикладном коде, сигнатура метода может измениться. 221 | // 222 | // Параметры: 223 | // ТекстЗапроса - Строка - Текст выполняемого запроса 224 | // 225 | // Возвращаемое значение: 226 | // ТаблицаЗначений - Результат выполнения запроса. 227 | // 228 | Функция ВыполнитьЗапрос(ТекстЗапроса) Экспорт 229 | 230 | Возврат КоннекторSQL.ВыполнитьЗапрос(ТекстЗапроса); 231 | 232 | КонецФункции 233 | 234 | Функция СоответствиеТиповМоделиИТиповКолонок() 235 | 236 | Перем Карта; 237 | 238 | Карта = Новый Соответствие; 239 | Карта.Вставить(ТипыКолонок.Целое, "INTEGER"); 240 | Карта.Вставить(ТипыКолонок.Дробное, "DECIMAL"); 241 | Карта.Вставить(ТипыКолонок.Булево, "BOOLEAN"); 242 | Карта.Вставить(ТипыКолонок.Строка, "TEXT"); 243 | Карта.Вставить(ТипыКолонок.Дата, "DATE"); 244 | Карта.Вставить(ТипыКолонок.Время, "TIME"); 245 | Карта.Вставить(ТипыКолонок.ДатаВремя, "DATETIME"); 246 | Карта.Вставить(ТипыКолонок.ДвоичныеДанные, "BLOB"); 247 | 248 | Возврат Карта; 249 | 250 | КонецФункции 251 | 252 | Функция ПолучитьТипКолонкиСУБД(ОбъектМодели, КолонкаМодели) Экспорт 253 | ТипКолонкиСУБД = Неопределено; 254 | 255 | Если КолонкаМодели.ТипКолонки = ТипыКолонок.Ссылка Тогда 256 | ОбъектМоделиСсылка = ОбъектМодели.МодельДанных().Получить(КолонкаМодели.ТипСсылки); 257 | ТипКолонкиСУБД = КартаТипов.Получить(ОбъектМоделиСсылка.Идентификатор().ТипКолонки); 258 | ИначеЕсли ТипыКолонок.ЭтоПримитивныйТип(КолонкаМодели.ТипКолонки) Тогда 259 | ТипКолонкиСУБД = КартаТипов.Получить(КолонкаМодели.ТипКолонки); 260 | Иначе 261 | ВызватьИсключение "Неизвестный тип колонки " + КолонкаМодели.ТипКолонки; 262 | КонецЕсли; 263 | 264 | Возврат ТипКолонкиСУБД; 265 | КонецФункции 266 | 267 | Функция ПолучитьОписаниеВнешнегоКлюча(ОбъектМодели, КолонкаМодели) Экспорт 268 | 269 | Возврат КоннекторSQL.ПолучитьОписаниеВнешнегоКлюча(ОбъектМодели, КолонкаМодели); 270 | 271 | КонецФункции 272 | 273 | #Область Подключение_коннектора_СУБД 274 | 275 | Функция ПолучитьКонструкторКоннектора() 276 | 277 | ПутьККлассам = ОбъединитьПути( 278 | ТекущийСценарий().Каталог, 279 | "..", 280 | "internal", 281 | "ДинамическиПодключаемыеКлассы" 282 | ); 283 | 284 | Попытка 285 | А = Вычислить("ПользователиИнформационнойБазы"); 286 | ПутьККоннектору = ОбъединитьПути( 287 | ПутьККлассам, 288 | "КонструкторКоннектораSQLiteWeb.os" 289 | ); 290 | Исключение 291 | ПутьККоннектору = ОбъединитьПути( 292 | ПутьККлассам, 293 | "КонструкторКоннектораSQLite.os" 294 | ); 295 | КонецПопытки; 296 | 297 | Возврат ЗагрузитьСценарий(ПутьККоннектору); 298 | 299 | КонецФункции 300 | 301 | #КонецОбласти 302 | -------------------------------------------------------------------------------- /src/Классы/МенеджерСущностей.os: -------------------------------------------------------------------------------- 1 | #Использовать "../Аннотации" 2 | #Использовать "../internal" 3 | 4 | #Использовать asserts 5 | #Использовать logos 6 | #Использовать reflector 7 | 8 | // Хранит данные о типах полей, колонках, настроек таблиц для типов сущностей 9 | Перем МодельДанных; 10 | 11 | // Хранит коннектор к БД, транслирующий команды менеджера сущностей в запросы к БД 12 | Перем Коннектор; 13 | Перем СтрокаСоединенияКоннектора; 14 | Перем ПараметрыКоннектора; 15 | 16 | Перем Лог; 17 | 18 | // Конструктор объекта МенеджерСущностей. 19 | // 20 | // Параметры: 21 | // ТипКоннектора - Тип - Тип класса, реализующего интерфейс Коннектор. 22 | // СтрокаСоединения - Строка - Строка соединения к БД, к которой подключается коннектор. 23 | // ППараметрыКоннектора - Массив - Массив дополнительных параметров коннектора. Содержимое произвольное. 24 | // 25 | Процедура ПриСозданииОбъекта(Знач ТипКоннектора, Знач СтрокаСоединения = "", Знач ППараметрыКоннектора = Неопределено) 26 | Лог = Логирование.ПолучитьЛог("oscript.lib.entity.manager"); 27 | Лог.Отладка("Инициализация менеджера сущностей с коннектором %1", ТипКоннектора); 28 | ПроверитьПоддержкуИнтерфейсаКоннектора(ТипКоннектора); 29 | 30 | МодельДанных = Новый МодельДанных; 31 | 32 | Коннектор = РаботаСКоннекторами.СоздатьКоннектор(ТипКоннектора); 33 | 34 | СтрокаСоединенияКоннектора = СтрокаСоединения; 35 | Если ППараметрыКоннектора = Неопределено Тогда 36 | ПараметрыКоннектора = Новый Массив; 37 | Иначе 38 | ПараметрыКоннектора = ППараметрыКоннектора; 39 | КонецЕсли; 40 | КонецПроцедуры 41 | 42 | // Регистрирует переданный тип класса-сценария в модели данных. 43 | // 44 | // Параметры: 45 | // ТипСущности - Тип - Тип для добавления в модель 46 | // 47 | Процедура ДобавитьКлассВМодель(ТипСущности) Экспорт 48 | ПроверитьЧтоКлассЯвляетсяСущностью(ТипСущности); 49 | 50 | МодельДанных.СоздатьОбъектМодели(ТипСущности); 51 | КонецПроцедуры 52 | 53 | // Получить модель данных - хранилище информации о типах полей, колонок, таблиц для типов сущостей. 54 | // 55 | // Возвращаемое значение: 56 | // МодельДанных 57 | // 58 | Функция ПолучитьМодельДанных() Экспорт 59 | Возврат МодельДанных; 60 | КонецФункции 61 | 62 | // Запускает процессы инициализации коннектора и таблиц БД. 63 | // 64 | Процедура Инициализировать() Экспорт 65 | 66 | РаботаСКоннекторами.ОткрытьКоннектор(Коннектор, СтрокаСоединенияКоннектора, ПараметрыКоннектора); 67 | 68 | ОбъектыМодели = МодельДанных.ПолучитьОбъектыМодели(); 69 | 70 | Для Каждого ОбъектМодели Из ОбъектыМодели Цикл 71 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 72 | 73 | ПодчиненныеТаблицы = ОбъектМодели.ПодчиненныеТаблицы(); 74 | Для Каждого ПодчиненнаяТаблица Из ПодчиненныеТаблицы Цикл 75 | 76 | ОбъектМоделиЭлементКоллекции = ОбработкаКоллекций.ПолучитьОбъектМоделиДляПодчиненнойТаблицы( 77 | ОбъектМодели, 78 | ПодчиненнаяТаблица 79 | ); 80 | 81 | Коннектор.ИнициализироватьТаблицу(ОбъектМоделиЭлементКоллекции); 82 | КонецЦикла; 83 | КонецЦикла; 84 | 85 | КонецПроцедуры 86 | 87 | // Создает экземпляр сущности, расширенный методами паттерна Active Record. 88 | // 89 | // Параметры: 90 | // ТипСущности - Тип - Тип создаваемой сущности. 91 | // 92 | // Возвращаемое значение: 93 | // Произвольный - экземпляр класса сущности с типом, привязанным к переданному "ТипуСущности", 94 | // с дополнительными методами паттерна Active Record. 95 | // 96 | Функция СоздатьЭлемент(ТипСущности) Экспорт 97 | ОбъектМодели = МодельДанных.Получить(ТипСущности); 98 | 99 | Возврат АктивнаяЗапись.СоздатьИзМенеджера(ОбъектМодели, ЭтотОбъект); 100 | КонецФункции 101 | 102 | // Сохраняет сущность в БД. 103 | // 104 | // Параметры: 105 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 106 | // 107 | Процедура Сохранить(Сущность) Экспорт 108 | ТипСущности = АктивнаяЗапись.ТипСущности(Сущность); 109 | ОбъектМодели = МодельДанных.Получить(ТипСущности); 110 | ПулСущностей = ПолучитьПулСущностей(ТипСущности); 111 | РаботаСКоннекторами.Сохранить(Коннектор, ОбъектМодели, ПулСущностей, Сущность); 112 | КонецПроцедуры 113 | 114 | // Осуществляет поиск сущностей переданного типа по идентификатору. 115 | // 116 | // Параметры: 117 | // ТипСущности - Тип - Тип искомой сущности. 118 | // ОпцииПоиска - Произвольный - Опции поиска. 119 | // Если параметр не задан или равен "Неопределено", то возвращаются все найденные сущности указанного типа. 120 | // Если параметр имеет тип "Соответствие", то каждое значение соответствия преобразуется к условию поиска 121 | // ИмяПоля = ЗначениеПоля, где ИмяПоля - ключ элемента соответствия, ЗначениеПоля - значение элемента соответствия. 122 | // Если параметр имеет тип "ОпцииПоиска", то опции передаются как есть. 123 | // 124 | // Возвращаемое значение: 125 | // Массив - Массив найденных сущностей. В качестве элементов массива выступают 126 | // экземпляры класса с типом, равным переданному параметру "ТипСущности", с заполненными значениями полей. 127 | // 128 | Функция Получить(ТипСущности, Знач ОпцииПоиска = Неопределено) Экспорт 129 | ОбъектМодели = МодельДанных.Получить(ТипСущности); 130 | ПулСущностей = ПолучитьПулСущностей(ТипСущности); 131 | Если ОпцииПоиска = Неопределено Тогда 132 | ОпцииПоиска = Новый ОпцииПоиска; 133 | КонецЕсли; 134 | Возврат РаботаСКоннекторами.Получить(Коннектор, ОбъектМодели, ПулСущностей, ОпцииПоиска); 135 | КонецФункции 136 | 137 | // Осуществляет поиск сущности переданного типа по идентификатору. 138 | // 139 | // Параметры: 140 | // ТипСущности - Тип - Тип искомой сущности. 141 | // ОпцииПоиска - Произвольный - Опции поиска. 142 | // Если параметр не задан или равен "Неопределено", то возвращаются все найденные сущности указанного типа. 143 | // Если параметр имеет тип "Соответствие", то каждое значение соответствия преобразуется к условию поиска 144 | // ИмяПоля = ЗначениеПоля, где ИмяПоля - ключ элемента соответствия, ЗначениеПоля - значение элемента соответствия. 145 | // Если параметр имеет тип "ОпцииПоиска", то опции передаются как есть. 146 | // Любой другой тип интерпретируется как поиск по &Идентификатору. 147 | // 148 | // Возвращаемое значение: 149 | // Произвольный - Если сущность была найдена, то возвращается экземпляр класса с типом, равным переданному параметру 150 | // "ТипСущности", с заполненными значениями полей. Иначе возвращается "Неопределено". 151 | // 152 | Функция ПолучитьОдно(ТипСущности, Знач ОпцииПоиска = Неопределено) Экспорт 153 | ОбъектМодели = МодельДанных.Получить(ТипСущности); 154 | ПулСущностей = ПолучитьПулСущностей(ТипСущности); 155 | Если ОпцииПоиска = Неопределено Тогда 156 | ОпцииПоиска = Новый ОпцииПоиска; 157 | КонецЕсли; 158 | Возврат РаботаСКоннекторами.ПолучитьОдно(Коннектор, ОбъектМодели, ПулСущностей, ОпцииПоиска); 159 | КонецФункции 160 | 161 | // Выполняет удаление сущности из базы данных. 162 | // Сущность должна иметь заполненный идентификатор. 163 | // 164 | // Параметры: 165 | // Сущность - Произвольный - Удаляемая сущность 166 | // 167 | Процедура Удалить(Сущность) Экспорт 168 | ТипСущности = АктивнаяЗапись.ТипСущности(Сущность); 169 | ОбъектМодели = МодельДанных.Получить(ТипСущности); 170 | ПулСущностей = ПолучитьПулСущностей(ТипСущности); 171 | РаботаСКоннекторами.Удалить(Коннектор, ОбъектМодели, ПулСущностей, Сущность); 172 | КонецПроцедуры 173 | 174 | // Выполняет очистку полную данных библиотеки. 175 | // Дополнительно посылает всем используемым коннекторам запросы на закрытие соединения. 176 | // 177 | Процедура Закрыть() Экспорт 178 | РаботаСКоннекторами.ЗакрытьКоннектор(Коннектор); 179 | МодельДанных.Очистить(); 180 | СвойстваКоннектора = РаботаСКоннекторами.ПолучитьСвойстваКоннектора(Коннектор); 181 | ХранилищаСущностей.Закрыть(ТипЗнч(Коннектор), СвойстваКоннектора.СтрокаСоединения, СвойстваКоннектора.Параметры); 182 | // Для освобожения ссылок на все коннекторы и соединения с СУБД 183 | ВыполнитьСборкуМусора(); 184 | КонецПроцедуры 185 | 186 | // Посылает коннектору запрос на начало транзакции. 187 | // 188 | Процедура НачатьТранзакцию() Экспорт 189 | РаботаСКоннекторами.НачатьТранзакцию(Коннектор); 190 | КонецПроцедуры 191 | 192 | // Посылает коннектору запрос на фиксацию транзакции. 193 | // 194 | Процедура ЗафиксироватьТранзакцию() Экспорт 195 | РаботаСКоннекторами.ЗафиксироватьТранзакцию(Коннектор); 196 | КонецПроцедуры 197 | 198 | // Посылает коннектору запрос на отмену транзакции. 199 | // 200 | Процедура ОтменитьТранзакцию() Экспорт 201 | РаботаСКоннекторами.ОтменитьТранзакцию(Коннектор); 202 | КонецПроцедуры 203 | 204 | // Возвращает текущий активный коннектор. 205 | // 206 | // Возвращаемое значение: 207 | // АбстрактныйКоннектор - Возвращает экземпляр коннектора. Конкретная реализация определяется параметром 208 | // ТипКоннектора при вызове конструктора МенеджерСущностей. 209 | // 210 | Функция ПолучитьКоннектор() Экспорт 211 | Возврат Коннектор; 212 | КонецФункции 213 | 214 | // Получает ХранилищеСущностей, привязанное к переданному типу сущности. 215 | // 216 | // Параметры: 217 | // ТипСущности - Тип - Тип сущности, зарегистрированный в Модели 218 | // 219 | // Возвращаемое значение: 220 | // ХранилищеСущностей - Хранилище сущностей, привязанное к переданному типу сущности. 221 | // 222 | Функция ПолучитьХранилищеСущностей(ТипСущности) Экспорт 223 | ОбъектМодели = МодельДанных.Получить(ТипСущности); 224 | ХранилищеСущностей = ХранилищаСущностей.Получить( 225 | ОбъектМодели, 226 | Коннектор 227 | ); 228 | Возврат ХранилищеСущностей; 229 | КонецФункции 230 | 231 | // @internal 232 | // Для служебного пользования. 233 | // 234 | // Возвращает пул сущностей из хранилища сущностей, привязанного к переданному типу сущности. 235 | // 236 | // Параметры: 237 | // ТипСущности - Тип - Тип сущности, зарегистрированный в Модели. 238 | // 239 | // Возвращаемое значение: 240 | // Соответствие - Пул сущностей. 241 | // 242 | Функция ПолучитьПулСущностей(ТипСущности) Экспорт 243 | Возврат ПолучитьХранилищеСущностей(ТипСущности).ПолучитьПулСущностей(); 244 | КонецФункции 245 | 246 | // <Описание процедуры> 247 | // 248 | // Параметры: 249 | // ТипКоннектора - Тип - Тип, проверяемый на реализацию интерфейса 250 | // 251 | Процедура ПроверитьПоддержкуИнтерфейсаКоннектора(ТипКоннектора) 252 | 253 | ИнтерфейсКоннектор = Новый ИнтерфейсОбъекта; 254 | ИнтерфейсКоннектор.ИзОбъекта(Тип("АбстрактныйКоннектор")); 255 | 256 | РефлекторОбъекта = Новый РефлекторОбъекта(ТипКоннектора); 257 | ПоддерживаетсяИнтерфейсКоннектора = РефлекторОбъекта.РеализуетИнтерфейс(ИнтерфейсКоннектор); 258 | 259 | Ожидаем.Что( 260 | ПоддерживаетсяИнтерфейсКоннектора, 261 | СтрШаблон("Тип <%1> не реализует интерфейс коннектора", ТипКоннектора) 262 | ).ЭтоИстина(); 263 | 264 | КонецПроцедуры 265 | 266 | // <Описание процедуры> 267 | // 268 | // Параметры: 269 | // ТипКласса - Тип - Тип, в котором проверяется наличие необходимых аннотаций. 270 | // 271 | Процедура ПроверитьЧтоКлассЯвляетсяСущностью(ТипКласса) 272 | 273 | РефлекторОбъекта = Новый РефлекторОбъекта(ТипКласса); 274 | ТаблицаМетодов = РефлекторОбъекта.ПолучитьТаблицуМетодов("Сущность", Ложь); 275 | Ожидаем.Что(ТаблицаМетодов, СтрШаблон("Класс %1 не имеет аннотации &Сущность", ТипКласса)).ИмеетДлину(1); 276 | 277 | ТаблицаСвойств = РефлекторОбъекта.ПолучитьТаблицуСвойств("Идентификатор"); 278 | Ожидаем.Что(ТаблицаСвойств, СтрШаблон("Класс %1 не имеет поля с аннотацией &Идентификатор", ТипКласса)).ИмеетДлину(1); 279 | 280 | КонецПроцедуры 281 | -------------------------------------------------------------------------------- /src/internal/Модули/РаботаСКоннекторами.os: -------------------------------------------------------------------------------- 1 | #Использовать asserts 2 | 3 | Перем СвойстваКоннекторов; 4 | 5 | Функция СоздатьКоннектор(ТипКоннектора) Экспорт 6 | Коннектор = Новый(ТипКоннектора); 7 | СвойстваКоннектора = Конструктор_СвойстваКоннектора(); 8 | СвойстваКоннекторов.Вставить(Коннектор, СвойстваКоннектора); 9 | 10 | Возврат Коннектор; 11 | КонецФункции 12 | 13 | Процедура ОткрытьКоннектор(Коннектор, СтрокаСоединения, ПараметрыКоннектора) Экспорт 14 | СвойстваКоннектора = СвойстваКоннекторов.Получить(Коннектор); 15 | СвойстваКоннектора.СтрокаСоединения = СтрокаСоединения; 16 | СвойстваКоннектора.Параметры = ПараметрыКоннектора; 17 | 18 | Коннектор.Открыть(СтрокаСоединения, ПараметрыКоннектора); 19 | КонецПроцедуры 20 | 21 | Процедура ЗакрытьКоннектор(Коннектор) Экспорт 22 | Если Коннектор.Открыт() Тогда 23 | Коннектор.Закрыть(); 24 | КонецЕсли; 25 | КонецПроцедуры 26 | 27 | Процедура Сохранить(Коннектор, ОбъектМодели, ПулСущностей, Сущность) Экспорт 28 | ТипСущности = АктивнаяЗапись.ТипСущности(Сущность); 29 | 30 | ПроверитьЧтоКлассЯвляетсяСущностью(ТипСущности); 31 | ПроверитьЧтоТипСущностиЗарегистрированВМодели(ОбъектМодели); 32 | ПроверитьНеобходимостьЗаполненияИдентификатора(ОбъектМодели, Сущность); 33 | 34 | Коннектор.Сохранить(ОбъектМодели, Сущность); 35 | 36 | // Сохранение полей, расширяемых таблицами 37 | ПодчиненныеТаблицы = ОбъектМодели.ПодчиненныеТаблицы(); 38 | Для Каждого ПодчиненнаяТаблица Из ПодчиненныеТаблицы Цикл 39 | 40 | ОбъектМоделиЭлементКоллекции = ОбработкаКоллекций.ПолучитьОбъектМоделиДляПодчиненнойТаблицы( 41 | ОбъектМодели, 42 | ПодчиненнаяТаблица 43 | ); 44 | 45 | // Очистка подчиненной таблицы 46 | ОпцииПоиска = Новый ОпцииПоиска(); 47 | ОпцииПоиска.Отбор("ref", ВидСравнения.Равно, ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность)); 48 | Коннектор.УдалитьСтрокиВТаблице(ОбъектМоделиЭлементКоллекции, ОпцииПоиска); 49 | 50 | РасширяемоеПоле = ОбъектМодели.ПолучитьЗначениеПоля(Сущность, ПодчиненнаяТаблица.ИмяПоля); 51 | 52 | Если НЕ ЗначениеЗаполнено(РасширяемоеПоле) Тогда 53 | Продолжить; 54 | КонецЕсли; 55 | 56 | КоллекцияСущностей = ОбработкаКоллекций.ПреобразоватьКоллекциюККоллекцииСущностей( 57 | РасширяемоеПоле, 58 | Сущность, 59 | ОбъектМодели, 60 | ПодчиненнаяТаблица 61 | ); 62 | 63 | Для Каждого ЭлементКоллекции Из КоллекцияСущностей Цикл 64 | Коннектор.Сохранить(ОбъектМоделиЭлементКоллекции, ЭлементКоллекции); 65 | КонецЦикла; 66 | 67 | КонецЦикла; 68 | 69 | ПулСущностей.Вставить(ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность), Сущность); 70 | КонецПроцедуры 71 | 72 | Функция Получить(Коннектор, ОбъектМодели, ПулСущностей, ОпцииПоиска) Экспорт 73 | Колонки = ОбъектМодели.Колонки(); 74 | ПодчиненныеТаблицы = ОбъектМодели.ПодчиненныеТаблицы(); 75 | 76 | ПередаваемыеОпцииПоиска = Новый ОпцииПоиска(); 77 | 78 | Если ТипЗнч(ОпцииПоиска) = Тип("Соответствие") Тогда 79 | // Переформируем ключи отбора из имен полей в имена колонок 80 | Для Каждого КлючИЗначение Из ОпцииПоиска Цикл 81 | Колонка = Колонки.Найти(КлючИЗначение.Ключ, "ИмяПоля"); 82 | Ожидаем.Что( 83 | Колонка, 84 | СтрШаблон("Не удалось найти данные о колонке по имени поля %1", КлючИЗначение.Ключ) 85 | ).Не_().Равно(Неопределено); 86 | 87 | ПередаваемыеОпцииПоиска.Отбор(Колонка.ИмяКолонки, ВидСравнения.Равно, КлючИЗначение.Значение); 88 | КонецЦикла; 89 | ИначеЕсли ТипЗнч(ОпцииПоиска) = Тип("ОпцииПоиска") Тогда 90 | Для Каждого ЭлементОтбора Из ОпцииПоиска.Отборы() Цикл 91 | Колонка = Колонки.Найти(ЭлементОтбора.ПутьКДанным, "ИмяПоля"); 92 | Ожидаем.Что( 93 | Колонка, 94 | СтрШаблон("Не удалось найти данные о колонке по имени поля %1", ЭлементОтбора.ПутьКДанным) 95 | ).Не_().Равно(Неопределено); 96 | 97 | ПередаваемыеОпцииПоиска.Отбор(Колонка.ИмяКолонки, ЭлементОтбора.ВидСравнения, ЭлементОтбора.Значение); 98 | КонецЦикла; 99 | 100 | Для Каждого ЭлементПорядка Из ОпцииПоиска.Сортировки() Цикл 101 | Колонка = Колонки.Найти(ЭлементПорядка.ПутьКДанным, "ИмяПоля"); 102 | Ожидаем.Что( 103 | Колонка, 104 | СтрШаблон("Не удалось найти данные о колонке по имени поля %1", ЭлементПорядка.ПутьКДанным) 105 | ).Не_().Равно(Неопределено); 106 | 107 | ПередаваемыеОпцииПоиска.СортироватьПо(Колонка.ИмяКолонки, ЭлементПорядка.НаправлениеСортировки); 108 | КонецЦикла; 109 | 110 | ПередаваемыеОпцииПоиска.Смещение(ОпцииПоиска.ВыбираетсяСоСмещением()); 111 | ПередаваемыеОпцииПоиска.Первые(ОпцииПоиска.ВыбираютсяПервые()); 112 | Иначе 113 | ВызватьИсключение "В метод получения данных передан неожиданный тип опций поиска: " + ТипЗнч(ОпцииПоиска); 114 | КонецЕсли; 115 | 116 | НайденныеСущности = Новый Массив; 117 | 118 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ПередаваемыеОпцииПоиска); 119 | Если НайденныеСтроки.Количество() = 0 Тогда 120 | Возврат НайденныеСущности; 121 | КонецЕсли; 122 | 123 | Для Каждого НайденнаяСтрока Из НайденныеСтроки Цикл 124 | ЗначениеИдентификатора = НайденнаяСтрока.Получить(ОбъектМодели.Идентификатор().ИмяКолонки); 125 | ЗначениеИдентификатора = ОбъектМодели.ПривестиЗначениеПоля( 126 | ЗначениеИдентификатора, 127 | ОбъектМодели.Идентификатор().ИмяПоля 128 | ); 129 | Сущность = ПулСущностей.Получить(ЗначениеИдентификатора); 130 | Если Сущность = Неопределено Тогда 131 | ХранилищеСущностей = ХранилищаСущностей.Получить(ОбъектМодели, Коннектор); 132 | Сущность = АктивнаяЗапись.СоздатьИзХранилища(ОбъектМодели, ХранилищеСущностей); 133 | ПулСущностей.Вставить(ЗначениеИдентификатора, Сущность); 134 | КонецЕсли; 135 | 136 | Для Каждого Колонка Из Колонки Цикл 137 | 138 | ЗначениеКолонки = НайденнаяСтрока.Получить(Колонка.ИмяКолонки); 139 | Если Колонка.ТипКолонки = ТипыКолонок.Ссылка И ЗначениеЗаполнено(ЗначениеКолонки) Тогда 140 | 141 | Если Колонка.ТипСсылки = ОбъектМодели.ТипСущности() И ЗначениеКолонки = ЗначениеИдентификатора Тогда 142 | ЗначениеКолонки = Сущность; 143 | Иначе 144 | ХранилищеСущностейСсылки = ХранилищаСущностей.Получить( 145 | ОбъектМодели.МодельДанных().Получить(Колонка.ТипСсылки), 146 | Коннектор 147 | ); 148 | ЗначениеКолонки = ХранилищеСущностейСсылки.ПолучитьОдно(ЗначениеКолонки); 149 | КонецЕсли; 150 | КонецЕсли; 151 | 152 | ОбъектМодели.УстановитьЗначениеКолонкиВПоле(Сущность, Колонка.ИмяКолонки, ЗначениеКолонки); 153 | КонецЦикла; 154 | 155 | Для Каждого ПодчиненнаяТаблица Из ПодчиненныеТаблицы Цикл 156 | ОбъектМоделиЭлементКоллекции = ОбработкаКоллекций.ПолучитьОбъектМоделиДляПодчиненнойТаблицы( 157 | ОбъектМодели, 158 | ПодчиненнаяТаблица 159 | ); 160 | 161 | ВнутренниеОпцииПоиска = Новый ОпцииПоиска(); 162 | ВнутренниеОпцииПоиска.Отбор("ref", ВидСравнения.Равно, ЗначениеИдентификатора); 163 | 164 | ЗначениеКолонки = Коннектор.НайтиСтрокиВТаблице(ОбъектМоделиЭлементКоллекции, ВнутренниеОпцииПоиска); 165 | 166 | ЗначениеКолонки = ОбработкаКоллекций.ПреобразоватьКоллекциюСтрокККоллекции(ЗначениеКолонки, ПодчиненнаяТаблица); 167 | 168 | Если ПодчиненнаяТаблица.КаскадноеЧтение 169 | И ТипыКолонок.ЭтоСсылочныйТип(ПодчиненнаяТаблица.ТипЭлемента) Тогда 170 | 171 | ХранилищеСущностейСсылки = ХранилищаСущностей.Получить( 172 | ОбъектМодели.МодельДанных().Получить(ПодчиненнаяТаблица.ТипЭлемента), 173 | Коннектор 174 | ); 175 | 176 | Для НомерИндекса = 0 По ЗначениеКолонки.ВГраница() Цикл 177 | ЗначениеКолонки[НомерИндекса] = ХранилищеСущностейСсылки.ПолучитьОдно(ЗначениеКолонки[НомерИндекса]); 178 | КонецЦикла; 179 | 180 | КонецЕсли; 181 | 182 | ОбъектМодели.УстановитьЗначениеПодчиненнойТаблицыВПоле(Сущность, ПодчиненнаяТаблица.ИмяПоля, ЗначениеКолонки); 183 | КонецЦикла; 184 | 185 | НайденныеСущности.Добавить(Сущность); 186 | КонецЦикла; 187 | 188 | Возврат НайденныеСущности; 189 | КонецФункции 190 | 191 | Функция ПолучитьОдно(Коннектор, ОбъектМодели, ПулСущностей, ОпцииПоиска) Экспорт 192 | 193 | Если ТипЗнч(ОпцииПоиска) = Тип("Соответствие") Тогда 194 | ПередаваемыеОпцииПоиска = ОпцииПоиска; 195 | ИначеЕсли ТипЗнч(ОпцииПоиска) = Тип("ОпцииПоиска") Тогда 196 | ПередаваемыеОпцииПоиска = ОпцииПоиска; 197 | Иначе 198 | ПередаваемыеОпцииПоиска = Новый ОпцииПоиска(); 199 | ПередаваемыеОпцииПоиска.Отбор(ОбъектМодели.Идентификатор().ИмяПоля, ВидСравнения.Равно, ОпцииПоиска); 200 | КонецЕсли; 201 | 202 | НайденныеСущности = Получить(Коннектор, ОбъектМодели, ПулСущностей, ПередаваемыеОпцииПоиска); 203 | 204 | Если НайденныеСущности.Количество() = 0 Тогда 205 | Возврат Неопределено; 206 | Иначе 207 | Возврат НайденныеСущности[0]; 208 | КонецЕсли; 209 | 210 | КонецФункции 211 | 212 | // Удаляет удаление сущности из базы данных. 213 | // Сущность должна иметь заполненный идентификатор. 214 | // 215 | // Параметры: 216 | // Сущность - Произвольный - Удаляемая сущность 217 | // 218 | Процедура Удалить(Коннектор, ОбъектМодели, ПулСущностей, Сущность) Экспорт 219 | Коннектор.Удалить(ОбъектМодели, Сущность); 220 | ПулСущностей.Удалить(Сущность); 221 | КонецПроцедуры 222 | 223 | // Посылает коннектору запрос на начало транзакции. 224 | // 225 | Процедура НачатьТранзакцию(Коннектор) Экспорт 226 | Коннектор.НачатьТранзакцию(); 227 | КонецПроцедуры 228 | 229 | // Посылает коннектору запрос на фиксацию транзакции. 230 | // 231 | Процедура ЗафиксироватьТранзакцию(Коннектор) Экспорт 232 | Коннектор.ЗафиксироватьТранзакцию(); 233 | КонецПроцедуры 234 | 235 | // Посылает коннектору запрос на отмену транзакции. 236 | // 237 | Процедура ОтменитьТранзакцию(Коннектор) Экспорт 238 | Коннектор.ОтменитьТранзакцию(); 239 | КонецПроцедуры 240 | 241 | // Возвращает дополнительные свойства коннектора 242 | // 243 | // Параметры: 244 | // Коннектор - АбстрактныйКоннектор - Коннектор, свойства которого необходимо получить. 245 | // 246 | // Возвращаемое значение: 247 | // Структура - Дополнительные свойства коннектора. см. Конструктор_СвойстваКоннектора() 248 | // 249 | Функция ПолучитьСвойстваКоннектора(Коннектор) Экспорт 250 | Возврат СвойстваКоннекторов.Получить(Коннектор); 251 | КонецФункции 252 | 253 | // <Описание процедуры> 254 | // 255 | // Параметры: 256 | // ТипКласса - Тип - Тип, в котором проверяется наличие необходимых аннотаций. 257 | // 258 | Процедура ПроверитьЧтоКлассЯвляетсяСущностью(ТипКласса) 259 | 260 | РефлекторОбъекта = Новый РефлекторОбъекта(ТипКласса); 261 | ТаблицаМетодов = РефлекторОбъекта.ПолучитьТаблицуМетодов("Сущность", Ложь); 262 | Ожидаем.Что(ТаблицаМетодов, СтрШаблон("Класс %1 не имеет аннотации &Сущность", ТипКласса)).ИмеетДлину(1); 263 | 264 | ТаблицаСвойств = РефлекторОбъекта.ПолучитьТаблицуСвойств("Идентификатор"); 265 | Ожидаем.Что(ТаблицаСвойств, СтрШаблон("Класс %1 не имеет поля с аннотацией &Идентификатор", ТипКласса)).ИмеетДлину(1); 266 | 267 | КонецПроцедуры 268 | 269 | Процедура ПроверитьЧтоТипСущностиЗарегистрированВМодели(ОбъектМодели) 270 | // TODO: проверка должна быть в момент получения репозитория 271 | Ожидаем.Что(ОбъектМодели, "Тип сущности не зарегистрирован в модели данных").Не_().Равно(Неопределено); 272 | КонецПроцедуры 273 | 274 | Процедура ПроверитьНеобходимостьЗаполненияИдентификатора(ОбъектМодели, Сущность) 275 | Если ОбъектМодели.Идентификатор().ГенерируемоеЗначение Тогда 276 | Возврат; 277 | КонецЕсли; 278 | 279 | ЗначениеИдентификатора = ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность); 280 | Ожидаем.Что( 281 | ЗначениеИдентификатора, СтрШаблон("Сущность с типом %1 должна иметь заполненный идентификатор", Тип(Сущность)) 282 | ).Заполнено(); 283 | 284 | КонецПроцедуры 285 | 286 | Функция Конструктор_СвойстваКоннектора() 287 | СвойстваКоннектора = Новый Структура; 288 | СвойстваКоннектора.Вставить("СтрокаСоединения"); 289 | СвойстваКоннектора.Вставить("Параметры"); 290 | 291 | Возврат СвойстваКоннектора; 292 | КонецФункции 293 | 294 | СвойстваКоннекторов = Новый Соответствие(); 295 | -------------------------------------------------------------------------------- /src/Классы/АбстрактныйКоннекторSQL.os: -------------------------------------------------------------------------------- 1 | #Использовать logos 2 | #Использовать strings 3 | 4 | Перем Лог; 5 | Перем Коннектор; 6 | 7 | Процедура ПриСозданииОбъекта(пКоннектор, пЛог = Неопределено) 8 | 9 | Коннектор = пКоннектор; 10 | Если ЗначениеЗаполнено(пЛог) Тогда 11 | Лог = пЛог; 12 | Иначе 13 | Лог = Логирование.ПолучитьЛог("oscript.lib.entity.connector.abstractsql"); 14 | КонецЕсли; 15 | 16 | КонецПроцедуры 17 | 18 | // @Unstable 19 | // Выполнить произвольный запрос и получить результат. 20 | // 21 | // Данный метод не входит в основной интерфейс "Коннектор". 22 | // Не рекомендуется использовать этот метод в прикладном коде, сигнатура метода может измениться. 23 | // 24 | // Параметры: 25 | // ТекстЗапроса - Строка - Текст выполняемого запроса 26 | // 27 | // Возвращаемое значение: 28 | // ТаблицаЗначений - Результат выполнения запроса. 29 | // 30 | Функция ВыполнитьЗапрос(ТекстЗапроса) Экспорт 31 | 32 | Лог.Отладка("Выполнение запроса:%1%2", Символы.ПС, ТекстЗапроса); 33 | 34 | Запрос = Коннектор.КонструкторКоннектора.НовыйЗапрос(Коннектор.Соединение); 35 | Запрос.Текст = ТекстЗапроса; 36 | Результат = Запрос.Выполнить().Выгрузить(); 37 | 38 | Возврат Результат; 39 | 40 | КонецФункции 41 | 42 | // Удаляет строки в таблице по указанному отбору. 43 | // 44 | // Параметры: 45 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 46 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 47 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 48 | // Каждый элемент отбора преобразуется к условию поиска. 49 | // В качестве "ПутьКДанным" указываются имена колонок. 50 | // 51 | Процедура УдалитьСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 52 | 53 | Запрос = Коннектор.КонструкторКоннектора.НовыйЗапрос(Коннектор.Соединение); 54 | 55 | ТекстЗапроса = СтрШаблон( 56 | "DELETE FROM %1", 57 | ОбъектМодели.ИмяТаблицы() 58 | ); 59 | 60 | СтрокаУсловий = ПолучитьСтрокуУсловий(Запрос, ОпцииПоиска.Отборы()); 61 | 62 | Если ЗначениеЗаполнено(СтрокаУсловий) Тогда 63 | ТекстЗапроса = ТекстЗапроса + Символы.ПС + "WHERE " + СтрокаУсловий; 64 | КонецЕсли; 65 | 66 | Лог.Отладка("Удаление сущностей в таблице %1:%2%3", ОбъектМодели.ИмяТаблицы(), Символы.ПС, ТекстЗапроса); 67 | 68 | Запрос.Текст = ТекстЗапроса; 69 | Запрос.ВыполнитьКоманду(); 70 | 71 | КонецПроцедуры 72 | 73 | // Осуществляет поиск строк в таблице по указанному отбору. 74 | // 75 | // Параметры: 76 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 77 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 78 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 79 | // Каждый элемент отбора преобразуется к условию поиска. 80 | // В качестве "ПутьКДанным" указываются имена колонок. 81 | // * Сортировки - Массив - Сортировка для результата поиска. 82 | // Каждый элемент массива должен иметь тип "ЭлементПорядка". 83 | // В качестве "ПутьКДанным" указываются имена колонок. 84 | // 85 | // Возвращаемое значение: 86 | // Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки, 87 | // значением элемента соответствия - значение колонки. 88 | // 89 | Функция НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 90 | 91 | НайденныеСтроки = Новый Массив; 92 | Колонки = ОбъектМодели.Колонки(); 93 | 94 | Запрос = Коннектор.КонструкторКоннектора.НовыйЗапрос(Коннектор.Соединение); 95 | 96 | ТекстЗапроса = СтрШаблон( 97 | "SELECT * FROM %1", 98 | ОбъектМодели.ИмяТаблицы() 99 | ); 100 | 101 | СтрокаУсловий = ПолучитьСтрокуУсловий(Запрос, ОпцииПоиска.Отборы()); 102 | 103 | Если ЗначениеЗаполнено(СтрокаУсловий) Тогда 104 | ТекстЗапроса = ТекстЗапроса + Символы.ПС + "WHERE " + СтрокаУсловий; 105 | КонецЕсли; 106 | 107 | СтрокаСортировки = ПолучитьСтрокуСортировки(ОпцииПоиска.Сортировки()); 108 | 109 | Если ЗначениеЗаполнено(СтрокаСортировки) Тогда 110 | ТекстЗапроса = ТекстЗапроса + Символы.ПС + "ORDER BY " + СтрокаСортировки; 111 | КонецЕсли; 112 | 113 | Если ОпцииПоиска.ВыбираютсяПервые() <> Неопределено Тогда 114 | ТекстЗапроса = ТекстЗапроса + Символы.ПС + "LIMIT " + ОпцииПоиска.ВыбираютсяПервые(); 115 | КонецЕсли; 116 | 117 | Если ОпцииПоиска.ВыбираетсяСоСмещением() <> Неопределено Тогда 118 | ТекстЗапроса = ТекстЗапроса + Символы.ПС + "OFFSET " + ОпцииПоиска.ВыбираетсяСоСмещением(); 119 | КонецЕсли; 120 | 121 | Лог.Отладка("Поиск сущности в таблице %1:%2%3", ОбъектМодели.ИмяТаблицы(), Символы.ПС, ТекстЗапроса); 122 | 123 | Запрос.Текст = ТекстЗапроса; 124 | Результат = Запрос.Выполнить().Выгрузить(); 125 | 126 | Если Результат.Количество() = 0 Тогда 127 | Лог.Отладка("Сущность с типом %1 не найдена", ОбъектМодели.ТипСущности()); 128 | Возврат НайденныеСтроки; 129 | КонецЕсли; 130 | 131 | Для Каждого СтрокаИзБазы Из Результат Цикл 132 | ЗначенияКолонок = Новый Соответствие; 133 | 134 | Для Каждого Колонка Из Колонки Цикл 135 | 136 | ЗначениеКолонки = СтрокаИзБазы[Колонка.ИмяКолонки]; 137 | ЗначенияКолонок.Вставить(Колонка.ИмяКолонки, ЗначениеКолонки); 138 | 139 | КонецЦикла; 140 | 141 | НайденныеСтроки.Добавить(ЗначенияКолонок); 142 | КонецЦикла; 143 | 144 | Возврат НайденныеСтроки; 145 | 146 | КонецФункции 147 | 148 | // Удаляет сущность из таблицы БД. 149 | // 150 | // Параметры: 151 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 152 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД. 153 | // 154 | Процедура Удалить(ОбъектМодели, Сущность) Экспорт 155 | 156 | ИмяТаблицы = ОбъектМодели.ИмяТаблицы(); 157 | 158 | ТекстЗапроса = "DELETE FROM %1 159 | |WHERE %2 = @Идентификатор;"; 160 | 161 | ТекстЗапроса = СтрШаблон(ТекстЗапроса, ИмяТаблицы, ОбъектМодели.Идентификатор().ИмяКолонки); 162 | Лог.Отладка( 163 | "Удаление сущности с типом %1 и идентификатором %2:%3%4", 164 | ОбъектМодели.ТипСущности(), 165 | ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность), 166 | Символы.ПС, 167 | ТекстЗапроса 168 | ); 169 | 170 | Запрос = Коннектор.КонструкторКоннектора.НовыйЗапрос(Коннектор.Соединение); 171 | Запрос.Текст = ТекстЗапроса; 172 | Запрос.УстановитьПараметр("Идентификатор", ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность)); 173 | Запрос.ВыполнитьКоманду(); 174 | 175 | КонецПроцедуры 176 | 177 | Функция ПолучитьОписаниеВнешнегоКлюча(ОбъектМодели, КолонкаМодели) Экспорт 178 | 179 | СтрокаВнешнийКлюч = ""; 180 | 181 | Если КолонкаМодели.ТипКолонки = ТипыКолонок.Ссылка Тогда 182 | ОбъектМоделиСсылка = ОбъектМодели.МодельДанных().Получить(КолонкаМодели.ТипСсылки); 183 | 184 | СтрокаВнешнийКлюч = Символы.Таб + СтрШаблон( 185 | "FOREIGN KEY (%1) REFERENCES %2(%3),%4", 186 | КолонкаМодели.ИмяКолонки, 187 | ОбъектМоделиСсылка.ИмяТаблицы(), 188 | ОбъектМоделиСсылка.Идентификатор().ИмяКолонки, 189 | Символы.ПС 190 | ); 191 | КонецЕсли; 192 | 193 | Возврат СтрокаВнешнийКлюч; 194 | 195 | КонецФункции 196 | 197 | // Создает таблицу в БД по данным модели. 198 | // 199 | // Параметры: 200 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 201 | // 202 | Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт 203 | 204 | ИмяТаблицы = ОбъектМодели.ИмяТаблицы(); 205 | 206 | ШаблонСозданияТаблицы = "CREATE TABLE IF NOT EXISTS %1 ( 207 | |%2 208 | |);"; 209 | 210 | ТекстЗапроса = ШаблонСозданияТаблицы; 211 | 212 | КолонкиТаблицы = ОбъектМодели.Колонки(); 213 | Идентификатор = ОбъектМодели.Идентификатор(); 214 | СтрокаОпределенийКолонок = ""; 215 | СтрокаВнешнихКлючей = ""; 216 | Для Каждого Колонка Из КолонкиТаблицы Цикл 217 | 218 | ТипКолонкиСУБД = Коннектор.ПолучитьТипКолонкиСУБД(ОбъектМодели, Колонка); 219 | ОписаниеВнешнегоКлюча = Коннектор.ПолучитьОписаниеВнешнегоКлюча(ОбъектМодели, Колонка); 220 | 221 | // Формирование строки-колонки 222 | СтрокаКолонка = Символы.Таб + Колонка.ИмяКолонки; 223 | 224 | СтрокаКолонка = СтрокаКолонка + " " + ТипКолонкиСУБД; 225 | Если Колонка.ИмяПоля = Идентификатор.ИмяПоля Тогда 226 | СтрокаКолонка = СтрокаКолонка + " PRIMARY KEY"; 227 | КонецЕсли; 228 | Если Колонка.ГенерируемоеЗначение И Не ТипКолонкиСУБД = "serial" Тогда 229 | СтрокаКолонка = СтрокаКолонка + " AUTOINCREMENT"; 230 | КонецЕсли; 231 | СтрокаКолонка = СтрокаКолонка + "," + Символы.ПС; 232 | 233 | СтрокаОпределенийКолонок = СтрокаОпределенийКолонок + СтрокаКолонка; 234 | Если ЗначениеЗаполнено(ОписаниеВнешнегоКлюча) Тогда 235 | СтрокаВнешнихКлючей = СтрокаВнешнихКлючей + ОписаниеВнешнегоКлюча; 236 | КонецЕсли; 237 | КонецЦикла; 238 | 239 | СтрокаОпределенийКолонок = СтрокаОпределенийКолонок + СтрокаВнешнихКлючей; 240 | 241 | СтроковыеФункции.УдалитьПоследнийСимволВСтроке(СтрокаОпределенийКолонок, 2); 242 | 243 | ТекстЗапроса = СтрШаблон(ТекстЗапроса, ИмяТаблицы, СтрокаОпределенийКолонок); 244 | Лог.Отладка("Инициализация таблицы %1:%2%3", ИмяТаблицы, Символы.ПС, ТекстЗапроса); 245 | 246 | Запрос = Коннектор.КонструкторКоннектора.НовыйЗапрос(Коннектор.Соединение); 247 | Запрос.Текст = ТекстЗапроса; 248 | 249 | Запрос.ВыполнитьКоманду(); 250 | 251 | КонецПроцедуры 252 | 253 | Функция ПолучитьСтрокуУсловий(Запрос, Отбор) Экспорт 254 | 255 | СтрокаУсловий = ""; 256 | 257 | сч = 0; 258 | Для Каждого ЭлементОтбора Из Отбор Цикл 259 | ПредставлениеСчетчика = "п" + Формат(сч + 1, "ЧН=0; ЧГ="); 260 | Если ЗначениеЗаполнено(СтрокаУсловий) Тогда 261 | СтрокаУсловий = СтрокаУсловий + Символы.ПС + Символы.Таб + "AND "; 262 | КонецЕсли; 263 | Если ЭлементОтбора.ВидСравнения = ВидСравнения.В ИЛИ ЭлементОтбора.ВидСравнения = ВидСравнения.НеВ Тогда 264 | ПараметрыВ = Новый Массив; 265 | Для Каждого Элемент Из ЭлементОтбора.Значение Цикл 266 | ПредставлениеСчетчика = "п" + Формат(сч + 1, "ЧН=0; ЧГ="); 267 | ПараметрыВ.Добавить(ПредставлениеСчетчика); 268 | 269 | Запрос.УстановитьПараметр(ПредставлениеСчетчика, Элемент); 270 | 271 | сч = сч + 1; 272 | КонецЦикла; 273 | 274 | Если ПараметрыВ.Количество() = 0 Тогда 275 | СтрокаУсловий = СтрокаУсловий + "FALSE"; 276 | Иначе 277 | 278 | ПодстрокаНе = ?(ЭлементОтбора.ВидСравнения = ВидСравнения.НеВ, "NOT ", ""); 279 | 280 | СтрокаУсловий = СтрокаУсловий + СтрШаблон( 281 | "%1 %2 IN (@%3)", 282 | ЭлементОтбора.ПутьКДанным, 283 | ПодстрокаНе, 284 | СтрСоединить(ПараметрыВ, ", @") 285 | ); 286 | КонецЕсли; 287 | 288 | Иначе 289 | СтрокаУсловий = СтрокаУсловий + СтрШаблон( 290 | "%1 %2 @%3", 291 | ЭлементОтбора.ПутьКДанным, 292 | ЭлементОтбора.ВидСравнения, 293 | ПредставлениеСчетчика 294 | ); 295 | 296 | Запрос.УстановитьПараметр(ПредставлениеСчетчика, ЭлементОтбора.Значение); 297 | 298 | КонецЕсли; 299 | 300 | сч = сч + 1; 301 | КонецЦикла; 302 | 303 | Возврат СтрокаУсловий; 304 | 305 | КонецФункции 306 | 307 | Функция ПолучитьСтрокуСортировки(Сортировка) 308 | 309 | СтрокаСортировки = ""; 310 | 311 | Для сч = 0 По Сортировка.ВГраница() Цикл 312 | ЭлементСортировки = Сортировка[сч]; 313 | 314 | Если ЗначениеЗаполнено(СтрокаСортировки) Тогда 315 | СтрокаСортировки = СтрокаСортировки + ", " + Символы.ПС + Символы.Таб; 316 | КонецЕсли; 317 | 318 | ИмяКолонки = ЭлементСортировки.ПутьКДанным; 319 | Направление = ?(ЭлементСортировки.НаправлениеСортировки = НаправлениеСортировки.Возр, "ASC", "DESC"); 320 | 321 | СтрокаСортировки = СтрокаСортировки + СтрШаблон( 322 | "%1 %2", 323 | ИмяКолонки, 324 | Направление 325 | ); 326 | КонецЦикла; 327 | 328 | Возврат СтрокаСортировки; 329 | 330 | КонецФункции 331 | -------------------------------------------------------------------------------- /src/Классы/КоннекторInMemory.os: -------------------------------------------------------------------------------- 1 | #Использовать "../internal" 2 | #Использовать fluent 3 | 4 | // Для хранения статуса соединения 5 | Перем Открыт; 6 | Перем КешТаблиц; 7 | Перем Рефлектор; 8 | 9 | // Конструктор объекта АбстрактныйКоннектор. 10 | // 11 | Процедура ПриСозданииОбъекта() 12 | Открыт = Ложь; 13 | Рефлектор = Новый Рефлектор; 14 | КонецПроцедуры 15 | 16 | // Открыть соединение с БД. 17 | // 18 | // Параметры: 19 | // СтрокаСоединения - Строка - Строка соединения с БД. 20 | // ПараметрыКоннектора - Массив - Дополнительные параметры инициализации коннектора. 21 | // 22 | Процедура Открыть(СтрокаСоединения, ПараметрыКоннектора) Экспорт // BSLLS:UnusedParameters-off 23 | КешТаблиц = ХранилищеВПамяти.КешТаблиц(СтрокаСоединения); 24 | Открыт = Истина; 25 | КонецПроцедуры 26 | 27 | // Закрыть соединение с БД. 28 | // 29 | Процедура Закрыть() Экспорт 30 | Открыт = Ложь; 31 | КонецПроцедуры 32 | 33 | // Получить статус соединения с БД. 34 | // 35 | // Возвращаемое значение: 36 | // Булево - Состояние соединения. Истина, если соединение установлено и готово к использованию. 37 | // В обратном случае - Ложь. 38 | // 39 | Функция Открыт() Экспорт 40 | Возврат Открыт; 41 | КонецФункции 42 | 43 | // Начинает новую транзакцию в БД. 44 | // 45 | Процедура НачатьТранзакцию() Экспорт 46 | ВызватьИсключение "Не поддерживается"; 47 | КонецПроцедуры 48 | 49 | // Фиксирует открытую транзакцию в БД. 50 | // 51 | Процедура ЗафиксироватьТранзакцию() Экспорт 52 | ВызватьИсключение "Не поддерживается"; 53 | КонецПроцедуры 54 | 55 | // Отменяет открытую транзакцию в БД. 56 | // 57 | Процедура ОтменитьТранзакцию() Экспорт 58 | ВызватьИсключение "Не поддерживается"; 59 | КонецПроцедуры 60 | 61 | // Создает таблицу в БД по данным модели. 62 | // 63 | // Параметры: 64 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 65 | // 66 | Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт 67 | ИмяТаблицы = ОбъектМодели.ИмяТаблицы(); 68 | 69 | Если КешТаблиц.Получить(ИмяТаблицы) = Неопределено Тогда 70 | Таблица = Новый ТаблицаЗначений(); 71 | 72 | Таблица.Колонки.Добавить("_Идентификатор"); 73 | Таблица.Колонки.Добавить("_Сущность"); 74 | 75 | Таблица.Индексы.Добавить("_Идентификатор"); 76 | 77 | КешТаблиц.Вставить(ИмяТаблицы, Таблица); 78 | КонецЕсли; 79 | 80 | КонецПроцедуры 81 | 82 | // Сохраняет сущность в БД. 83 | // 84 | // Параметры: 85 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 86 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 87 | // 88 | Процедура Сохранить(ОбъектМодели, Сущность) Экспорт 89 | 90 | ИмяТаблицы = ОбъектМодели.ИмяТаблицы(); 91 | 92 | Таблица = КешТаблиц.Получить(ИмяТаблицы); 93 | 94 | Если Таблица = Неопределено Тогда 95 | ВызватьИсключение "Таблица " + ИмяТаблицы + " не найдена"; 96 | КонецЕсли; 97 | 98 | Идентификатор = ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность); 99 | Если НЕ ЗначениеЗаполнено(Идентификатор) Тогда 100 | 101 | Если ОбъектМодели.Идентификатор().ТипКолонки <> ТипыКолонок.Целое Тогда 102 | Сообщение = СтрШаблон( 103 | "Ошибка при сохранении сущности с типом %1. 104 | |Генерация идентификаторов поддерживается только для колонок с типом ""Целое""", 105 | ОбъектМодели.ТипСущности() 106 | ); 107 | ВызватьИсключение Сообщение; 108 | КонецЕсли; 109 | 110 | МаксимальныйИдентификатор = ПроцессорыКоллекций.ИзКоллекции(Таблица) 111 | .Обработать("Элемент -> Число(Элемент._Идентификатор)") 112 | .Максимум(); 113 | 114 | Если МаксимальныйИдентификатор = Неопределено Тогда 115 | МаксимальныйИдентификатор = 0; 116 | КонецЕсли; 117 | 118 | Идентификатор = МаксимальныйИдентификатор + 1; 119 | 120 | ОбъектМодели.УстановитьЗначениеКолонкиВПоле( 121 | Сущность, 122 | ОбъектМодели.Идентификатор().ИмяКолонки, 123 | Идентификатор 124 | ); 125 | 126 | КонецЕсли; 127 | Если ТипЗнч(Идентификатор) = Тип("Число") Тогда 128 | Идентификатор = Формат(Идентификатор, "ЧГ="); 129 | КонецЕсли; 130 | 131 | СтрокаТЗ = Таблица.Найти(Идентификатор, "_Идентификатор"); 132 | 133 | Если СтрокаТЗ = Неопределено Тогда 134 | СтрокаТЗ = Таблица.Добавить(); 135 | КонецЕсли; 136 | 137 | СущностьВБД = Новый (ОбъектМодели.ТипСущности()); 138 | 139 | Для Каждого Колонка Из ОбъектМодели.Колонки() Цикл 140 | Значение = ОбъектМодели.ПолучитьПриведенноеЗначениеПоля( 141 | Сущность, 142 | Колонка.ИмяПоля); 143 | Рефлектор.УстановитьСвойство(СущностьВБД, Колонка.ИмяПоля, Значение); 144 | КонецЦикла; 145 | 146 | СтрокаТЗ._Идентификатор = Идентификатор; 147 | СтрокаТЗ._Сущность = СущностьВБД; 148 | 149 | КонецПроцедуры 150 | 151 | // Удаляет сущность из таблицы БД. 152 | // 153 | // Параметры: 154 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 155 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД. 156 | // 157 | Процедура Удалить(ОбъектМодели, Сущность) Экспорт 158 | 159 | ИмяТаблицы = ОбъектМодели.ИмяТаблицы(); 160 | 161 | Таблица = КешТаблиц.Получить(ИмяТаблицы); 162 | 163 | Если Таблица = Неопределено Тогда 164 | ВызватьИсключение "Таблица " + ИмяТаблицы + " не найдена"; 165 | КонецЕсли; 166 | 167 | Идентификатор = ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность); 168 | Если ТипЗнч(Идентификатор) = Тип("Число") Тогда 169 | Идентификатор = Формат(Идентификатор, "ЧГ="); 170 | КонецЕсли; 171 | 172 | СтрокаТЗ = Таблица.Найти(Идентификатор, "_Идентификатор"); 173 | 174 | Если НЕ СтрокаТЗ = Неопределено Тогда 175 | Таблица.Удалить(СтрокаТЗ); 176 | КонецЕсли; 177 | 178 | КонецПроцедуры 179 | 180 | // Осуществляет поиск строк в таблице по указанному отбору. 181 | // 182 | // Параметры: 183 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 184 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 185 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 186 | // Каждый элемент отбора преобразуется к условию поиска. 187 | // В качестве "ПутьКДанным" указываются имена колонок. 188 | // * Сортировки - Массив - Сортировка для результата поиска. 189 | // Каждый элемент массива должен иметь тип "ЭлементПорядка". 190 | // В качестве "ПутьКДанным" указываются имена колонок. 191 | // 192 | // Возвращаемое значение: 193 | // Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки, 194 | // значением элемента соответствия - значение колонки. 195 | // 196 | Функция НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 197 | 198 | ИмяТаблицы = ОбъектМодели.ИмяТаблицы(); 199 | Отборы = ОпцииПоиска.Отборы(); 200 | Сортировки = ОпцииПоиска.Сортировки(); 201 | 202 | Таблица = КешТаблиц.Получить(ИмяТаблицы); 203 | 204 | Если Таблица = Неопределено Тогда 205 | ВызватьИсключение "Таблица " + ИмяТаблицы + " не найдена"; 206 | КонецЕсли; 207 | 208 | ПроцессорКоллекций = ПроцессорыКоллекций.ИзКоллекции(Таблица); 209 | 210 | Колонки = ОбъектМодели.Колонки(); 211 | 212 | Для Каждого ЭлементОтбора Из Отборы Цикл 213 | 214 | НайденныеКолонки = Колонки.НайтиСтроки(Новый Структура("ИмяКолонки", ЭлементОтбора.ПутьКДанным)); 215 | 216 | Если НайденныеКолонки.Количество() = 0 Тогда 217 | ИмяПоля = ЭлементОтбора.ПутьКДанным; 218 | Иначе 219 | ИмяПоля = НайденныеКолонки[0].ИмяПоля; 220 | КонецЕсли; 221 | 222 | Если ЭлементОтбора.ВидСравнения = ВидСравнения.В Тогда 223 | СтрокаУсловие = СтрШаблон( 224 | "Элемент -> Значение.Найти(Элемент._Сущность.%1) <> Неопределено", 225 | ЭлементОтбора.ПутьКДанным 226 | ); 227 | ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравнения.НеВ Тогда 228 | СтрокаУсловие = СтрШаблон( 229 | "Элемент -> Значение.Найти(Элемент._Сущность.%1) = Неопределено", 230 | ЭлементОтбора.ПутьКДанным 231 | ); 232 | Иначе 233 | СтрокаУсловие = СтрШаблон( 234 | "Элемент -> Элемент._Сущность.%1 %2 Значение", 235 | ИмяПоля, 236 | ЭлементОтбора.ВидСравнения 237 | ); 238 | КонецЕсли; 239 | 240 | ДополнительныеПараметры = Новый Структура("Значение", ЭлементОтбора.Значение); 241 | ПроцессорКоллекций = ПроцессорКоллекций.Фильтровать(СтрокаУсловие, ДополнительныеПараметры); 242 | КонецЦикла; 243 | 244 | СтрокаСортировка = ""; 245 | Для Каждого ЭлементПорядка Из Сортировки Цикл 246 | 247 | НайденныеКолонки = Колонки.НайтиСтроки(Новый Структура("ИмяКолонки", ЭлементПорядка.ПутьКДанным)); 248 | 249 | Если НайденныеКолонки.Количество() = 0 Тогда 250 | ИмяПоля = ЭлементПорядка.ПутьКДанным; 251 | Иначе 252 | ИмяПоля = НайденныеКолонки[0].ИмяПоля; 253 | КонецЕсли; 254 | ПорядокСортировки = ?(ЭлементПорядка.НаправлениеСортировки = НаправлениеСортировки.Возр, 255 | "ПрямойПорядок", 256 | "ОбратныйПорядок" 257 | ); 258 | 259 | // формирование текста лямбды для сравнения элементов по нескольким полям 260 | СтрокаСортировка = СтрокаСортировка + СтрШаблон( 261 | "Сравнение = ПроцессорыКоллекцийСлужебный.СравнениеЗначений%1(Элемент1._Сущность.%2, Элемент2._Сущность.%2); 262 | |Если Сравнение <> 0 Тогда 263 | | Возврат Сравнение; 264 | |КонецЕсли; 265 | | 266 | |", 267 | ПорядокСортировки, 268 | ИмяПоля 269 | ); 270 | 271 | КонецЦикла; 272 | 273 | Если СтрокаСортировка <> "" Тогда 274 | СтрокаСортировка = "(Элемент1, Элемент2) -> " + Символы.ПС + СтрокаСортировка + "Возврат Сравнение;"; 275 | 276 | ПроцессорКоллекций = ПроцессорКоллекций.Сортировать(СтрокаСортировка); 277 | КонецЕсли; 278 | 279 | Если ОпцииПоиска.ВыбираетсяСоСмещением() <> Неопределено Тогда 280 | ПроцессорКоллекций = ПроцессорКоллекций.Пропустить(ОпцииПоиска.ВыбираетсяСоСмещением()); 281 | КонецЕсли; 282 | 283 | Если ОпцииПоиска.ВыбираютсяПервые() <> Неопределено Тогда 284 | ПроцессорКоллекций = ПроцессорКоллекций.Первые(ОпцииПоиска.ВыбираютсяПервые()); 285 | КонецЕсли; 286 | 287 | ДанныеТаблицы = ПроцессорКоллекций.ВМассив(); 288 | 289 | Результат = Новый Массив(); 290 | 291 | Колонки = ОбъектМодели.Колонки(); 292 | 293 | Для Каждого СтрокаДанныхТаблицы Из ДанныеТаблицы Цикл 294 | ЗначенияКолонок = Новый Соответствие; 295 | Для Каждого Колонка Из Колонки Цикл 296 | Значение = Рефлектор.ПолучитьСвойство(СтрокаДанныхТаблицы._Сущность, Колонка.ИмяПоля); 297 | ЗначенияКолонок.Вставить(Колонка.ИмяКолонки, Значение); 298 | КонецЦикла; 299 | Результат.Добавить(ЗначенияКолонок); 300 | КонецЦикла; 301 | 302 | Возврат Результат; 303 | 304 | КонецФункции 305 | 306 | // Удаляет строки в таблице по указанному отбору. 307 | // 308 | // Параметры: 309 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 310 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 311 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 312 | // Каждый элемент отбора преобразуется к условию поиска. 313 | // В качестве "ПутьКДанным" указываются имена колонок. 314 | // 315 | Процедура УдалитьСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 316 | 317 | СтрокиКУдалению = НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 318 | Если СтрокиКУдалению.Количество() > 0 Тогда 319 | 320 | ИмяКолонкиИдентификатора = ОбъектМодели.Идентификатор().ИмяКолонки; 321 | 322 | ИмяТаблицы = ОбъектМодели.ИмяТаблицы(); 323 | Таблица = КешТаблиц.Получить(ИмяТаблицы); 324 | 325 | Для Каждого СтрокаКУдалению Из СтрокиКУдалению Цикл 326 | Идентификатор = СтрокаКУдалению.Получить(ИмяКолонкиИдентификатора); 327 | Если ТипЗнч(Идентификатор) = Тип("Число") Тогда 328 | Идентификатор = Формат(Идентификатор, "ЧГ="); 329 | КонецЕсли; 330 | 331 | СтрокаТЗ = Таблица.Найти(Идентификатор, "_Идентификатор"); 332 | 333 | Если НЕ СтрокаТЗ = Неопределено Тогда 334 | Таблица.Удалить(СтрокаТЗ); 335 | КонецЕсли; 336 | КонецЦикла; 337 | 338 | КонецЕсли; 339 | КонецПроцедуры 340 | -------------------------------------------------------------------------------- /src/Классы/ОбъектМодели.os: -------------------------------------------------------------------------------- 1 | #Использовать annotations 2 | #Использовать reflector 3 | #Использовать strings 4 | 5 | Перем ТипСущности; 6 | Перем ИмяТаблицы; 7 | Перем ИсточникиДанных; 8 | Перем Колонки; 9 | Перем ПодчиненныеТаблицы; 10 | // TODO: Первичный ключ из нескольких полей? 11 | Перем Идентификатор; 12 | 13 | Перем МодельДанных; 14 | 15 | Перем Рефлектор; 16 | 17 | Процедура ПриСозданииОбъекта(ПТипСущности, ПМодельДанных) 18 | 19 | МодельДанных = ПМодельДанных; 20 | ТипСущности = ПТипСущности; 21 | ЗаполнитьКолонки(); 22 | ЗаполнитьПодчиненныеТаблицы(); 23 | Рефлектор = Новый Рефлектор; 24 | 25 | КонецПроцедуры 26 | 27 | Функция ИмяТаблицы() Экспорт 28 | Возврат ИмяТаблицы; 29 | КонецФункции 30 | 31 | Функция ИсточникиДанных() Экспорт 32 | Возврат ИсточникиДанных; 33 | КонецФункции 34 | 35 | Функция Колонки() Экспорт 36 | Возврат Колонки.Скопировать(); 37 | КонецФункции 38 | 39 | Функция ПодчиненныеТаблицы() Экспорт 40 | Возврат ПодчиненныеТаблицы.Скопировать(); 41 | КонецФункции 42 | 43 | // @internal 44 | // TODO: вынести отсюда. Возможно стоит разработать отдельный служебный билдер Объекта модели, 45 | // вытащив заполнение из конструктора в этот билдер, а в конструктор передавать уже готовые для сохранения 46 | // в объект данные. 47 | // 48 | Функция Служебный_Колонки() Экспорт 49 | Возврат Колонки; 50 | КонецФункции 51 | 52 | // @internal 53 | Процедура Служебный_ИмяТаблицы(ПИмяТаблицы) Экспорт 54 | ИмяТаблицы = ПИмяТаблицы; 55 | КонецПроцедуры 56 | 57 | Функция Идентификатор() Экспорт 58 | Возврат Новый ФиксированнаяСтруктура(Идентификатор); 59 | КонецФункции 60 | 61 | Функция МодельДанных() Экспорт 62 | Возврат МодельДанных; 63 | КонецФункции 64 | 65 | Функция ТипСущности() Экспорт 66 | Возврат ТипСущности; 67 | КонецФункции 68 | 69 | Функция ПолучитьЗначениеИдентификатора(Сущность) Экспорт 70 | ЗначениеИдентификатора = ПолучитьЗначениеПоля(Сущность, Идентификатор().ИмяПоля); 71 | Возврат ЗначениеИдентификатора; 72 | КонецФункции 73 | 74 | Функция ПолучитьПриведенноеЗначениеПоля(Сущность, ИмяПоля) Экспорт 75 | ЗначениеПоля = ПолучитьЗначениеПоля(Сущность, ИмяПоля); 76 | 77 | Колонка = Колонки().Найти(ИмяПоля, "ИмяПоля"); 78 | 79 | Если Колонка.ТипКолонки = ТипыКолонок.Ссылка Тогда 80 | ОбъектМоделиСсылки = МодельДанных.Получить(Колонка.ТипСсылки); 81 | Если ЗначениеПоля = Неопределено Тогда 82 | ЗначениеПоля = ОбъектМоделиСсылки.ПривестиЗначениеПоля(ЗначениеПоля, ОбъектМоделиСсылки.Идентификатор().ИмяПоля); 83 | Иначе 84 | ЗначениеПоля = ОбъектМоделиСсылки.ПолучитьЗначениеИдентификатора(ЗначениеПоля); 85 | КонецЕсли; 86 | ИначеЕсли Колонка.ТипКолонки = ТипыКолонок.ДвоичныеДанные Тогда 87 | // Просто ничего не делаем, все работает само 88 | Иначе 89 | ЗначениеПоля = ПривестиЗначениеПоля(ЗначениеПоля, ИмяПоля); 90 | КонецЕсли; 91 | 92 | Возврат ЗначениеПоля; 93 | КонецФункции 94 | 95 | Процедура УстановитьЗначениеКолонкиВПоле(Сущность, ИмяКолонки, ЗначениеПоля) Экспорт 96 | 97 | Колонка = Колонки().Найти(ИмяКолонки, "ИмяКолонки"); 98 | 99 | Если Колонка.ТипКолонки = ТипыКолонок.Ссылка Тогда 100 | УстанавливаемоеЗначениеПоля = ЗначениеПоля; 101 | Иначе 102 | УстанавливаемоеЗначениеПоля = ВыполнитьПриведениеЗначения(Колонка, ЗначениеПоля); 103 | КонецЕсли; 104 | 105 | Рефлектор.УстановитьСвойство(Сущность, Колонка.ИмяПоля, УстанавливаемоеЗначениеПоля); 106 | 107 | КонецПроцедуры 108 | 109 | Процедура УстановитьЗначениеПодчиненнойТаблицыВПоле(Сущность, ИмяПоля, ЗначениеПоля) Экспорт 110 | Рефлектор.УстановитьСвойство(Сущность, ИмяПоля, ЗначениеПоля); 111 | КонецПроцедуры 112 | 113 | Функция ПривестиЗначениеПоля(ЗначениеПоля, ИмяПоля) Экспорт 114 | 115 | Колонка = Колонки().Найти(ИмяПоля, "ИмяПоля"); 116 | Возврат ВыполнитьПриведениеЗначения(Колонка, ЗначениеПоля); 117 | 118 | КонецФункции 119 | 120 | Функция ПолучитьЗначениеПоля(Сущность, ИмяПоля) Экспорт 121 | ЗначениеПоля = Рефлектор.ПолучитьСвойство(Сущность, ИмяПоля); 122 | Возврат ЗначениеПоля; 123 | КонецФункции 124 | 125 | Процедура ЗаполнитьКолонки() 126 | 127 | ОписаниеТиповСтрока = Новый ОписаниеТипов("Строка"); 128 | ОписаниеТиповБулево = Новый ОписаниеТипов("Булево"); 129 | 130 | Колонки = Новый ТаблицаЗначений; 131 | Колонки.Колонки.Добавить("ИмяПоля", ОписаниеТиповСтрока); 132 | Колонки.Колонки.Добавить("ИмяКолонки", ОписаниеТиповСтрока); 133 | Колонки.Колонки.Добавить("ТипКолонки", ОписаниеТиповСтрока); 134 | Колонки.Колонки.Добавить("ГенерируемоеЗначение", ОписаниеТиповБулево); 135 | Колонки.Колонки.Добавить("Идентификатор", ОписаниеТиповБулево); 136 | Колонки.Колонки.Добавить("ТипСсылки"); 137 | 138 | РефлекторОбъекта = Новый РефлекторОбъекта(ТипСущности); 139 | МетодСущность = РефлекторОбъекта.ПолучитьТаблицуМетодов("Сущность", Ложь)[0]; 140 | 141 | АннотацияСущность = РаботаСАннотациями.НайтиАннотацию(МетодСущность.Аннотации, "Сущность"); 142 | ИмяТаблицы = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияСущность, "ИмяТаблицы", Строка(ТипСущности)); 143 | ИсточникиДанных = Новый ФиксированныйМассив( 144 | РаботаСАннотациями.ПолучитьЗначенияПараметровАннотации(АннотацияСущность, "ИсточникДанных") 145 | ); 146 | 147 | ТаблицаСвойств = РефлекторОбъекта.ПолучитьТаблицуСвойств(); 148 | Для Каждого Свойство Из ТаблицаСвойств Цикл 149 | Аннотации = Свойство.Аннотации; 150 | АннотацияПодчиненнаяТаблица = РаботаСАннотациями.НайтиАннотацию(Аннотации, "ПодчиненнаяТаблица"); 151 | Если АннотацияПодчиненнаяТаблица <> Неопределено Тогда 152 | Продолжить; 153 | КонецЕсли; 154 | 155 | ДанныеОКолонке = НовыйДанныеОКолонке(); 156 | ДанныеОКолонке.ИмяПоля = Свойство.Имя; 157 | 158 | АннотацияКолонка = РаботаСАннотациями.НайтиАннотацию(Аннотации, "Колонка"); 159 | ДанныеОКолонке.ИмяКолонки = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияКолонка, "Имя", ДанныеОКолонке.ИмяПоля); 160 | ДанныеОКолонке.ТипКолонки = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияКолонка, "Тип", ТипыКолонок.Строка); 161 | ТипСсылки = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияКолонка, "ТипСсылки", Неопределено, Истина); 162 | ДанныеОКолонке.ТипСсылки = ?(ТипСсылки = Неопределено, Неопределено, Тип(ТипСсылки)); 163 | 164 | Если РаботаСАннотациями.НайтиАннотацию(Аннотации, "Идентификатор") <> Неопределено Тогда 165 | ДанныеОКолонке.Идентификатор = Истина; 166 | Идентификатор = ДанныеОКолонке; 167 | КонецЕсли; 168 | 169 | Если РаботаСАннотациями.НайтиАннотацию(Аннотации, "ГенерируемоеЗначение") <> Неопределено Тогда 170 | ДанныеОКолонке.ГенерируемоеЗначение = Истина; 171 | КонецЕсли; 172 | 173 | ЗаполнитьЗначенияСвойств(Колонки.Добавить(), ДанныеОКолонке); 174 | КонецЦикла; 175 | 176 | КонецПроцедуры 177 | 178 | Процедура ЗаполнитьПодчиненныеТаблицы() 179 | 180 | ОписаниеТиповСтрока = Новый ОписаниеТипов("Строка"); 181 | ОписаниеТиповБулево = Новый ОписаниеТипов("Булево"); 182 | 183 | ПодчиненныеТаблицы = Новый ТаблицаЗначений; 184 | ПодчиненныеТаблицы.Колонки.Добавить("ИмяПоля", ОписаниеТиповСтрока); 185 | ПодчиненныеТаблицы.Колонки.Добавить("ИмяТаблицы", ОписаниеТиповСтрока); 186 | ПодчиненныеТаблицы.Колонки.Добавить("ТипТаблицы", ОписаниеТиповСтрока); 187 | ПодчиненныеТаблицы.Колонки.Добавить("ТипЭлемента"); 188 | ПодчиненныеТаблицы.Колонки.Добавить("КаскадноеЧтение", ОписаниеТиповБулево); 189 | 190 | РефлекторОбъекта = Новый РефлекторОбъекта(ТипСущности); 191 | ТаблицаСвойств = РефлекторОбъекта.ПолучитьТаблицуСвойств("ПодчиненнаяТаблица"); 192 | 193 | Для Каждого Свойство Из ТаблицаСвойств Цикл 194 | ДанныеОПодчиненнойТаблице = НовыйДанныеОПодчиненнойТаблице(); 195 | ДанныеОПодчиненнойТаблице.ИмяПоля = Свойство.Имя; 196 | 197 | Аннотации = Свойство.Аннотации; 198 | АннотацияПодчиненнаяТаблица = РаботаСАннотациями.НайтиАннотацию(Аннотации, "ПодчиненнаяТаблица"); 199 | 200 | ИмяТаблицыПоУмолчанию = СтрШаблон( 201 | "%1_%2", 202 | Строка(ТипСущности), 203 | ДанныеОПодчиненнойТаблице.ИмяПоля 204 | ); 205 | ДанныеОПодчиненнойТаблице.ИмяТаблицы = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияПодчиненнаяТаблица, "ИмяТаблицы", ИмяТаблицыПоУмолчанию); 206 | ДанныеОПодчиненнойТаблице.ТипТаблицы = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияПодчиненнаяТаблица, "Тип", Неопределено, Истина); 207 | 208 | ТипЭлемента = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияПодчиненнаяТаблица, "ТипЭлемента", Неопределено, Истина); 209 | ДанныеОПодчиненнойТаблице.ТипЭлемента = ?(ТипЭлемента = Неопределено, Неопределено, Тип(ТипЭлемента)); 210 | 211 | ДанныеОПодчиненнойТаблице.КаскадноеЧтение = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияПодчиненнаяТаблица, "КаскадноеЧтение", Ложь); 212 | 213 | ЗаполнитьЗначенияСвойств(ПодчиненныеТаблицы.Добавить(), ДанныеОПодчиненнойТаблице); 214 | КонецЦикла; 215 | 216 | КонецПроцедуры 217 | 218 | Функция НовыйДанныеОКолонке() 219 | ДанныеОКолонке = Новый Структура; 220 | ДанныеОКолонке.Вставить("ИмяПоля", ""); 221 | ДанныеОКолонке.Вставить("ИмяКолонки", ""); 222 | ДанныеОКолонке.Вставить("ТипКолонки", ""); 223 | ДанныеОКолонке.Вставить("ГенерируемоеЗначение", Ложь); 224 | ДанныеОКолонке.Вставить("Идентификатор", Ложь); 225 | ДанныеОКолонке.Вставить("ТипСсылки"); 226 | Возврат ДанныеОКолонке; 227 | КонецФункции 228 | 229 | Функция НовыйДанныеОПодчиненнойТаблице() 230 | ДанныеОПодчиненнойТаблице = Новый Структура; 231 | ДанныеОПодчиненнойТаблице.Вставить("ИмяПоля", ""); 232 | ДанныеОПодчиненнойТаблице.Вставить("ИмяТаблицы", ""); 233 | ДанныеОПодчиненнойТаблице.Вставить("ТипТаблицы"); 234 | ДанныеОПодчиненнойТаблице.Вставить("ТипЭлемента"); 235 | ДанныеОПодчиненнойТаблице.Вставить("КаскадноеЧтение", Ложь); 236 | 237 | Возврат ДанныеОПодчиненнойТаблице; 238 | КонецФункции 239 | 240 | Функция СоответствиеТиповМоделиОписанийТипов() 241 | 242 | Перем Карта; 243 | 244 | Карта = Новый Соответствие; 245 | Карта.Вставить(ТипыКолонок.Целое, Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла( , 0))); 246 | Карта.Вставить(ТипыКолонок.Дробное, Новый ОписаниеТипов("Число")); 247 | Карта.Вставить(ТипыКолонок.Булево, Новый ОписаниеТипов("Булево")); 248 | Карта.Вставить(ТипыКолонок.Строка, Новый ОписаниеТипов("Строка")); 249 | Карта.Вставить(ТипыКолонок.Дата, Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Дата))); 250 | Карта.Вставить(ТипыКолонок.Время, Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Время))); 251 | Карта.Вставить(ТипыКолонок.ДатаВремя, Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя))); 252 | Карта.Вставить(ТипыКолонок.ДвоичныеДанные, Новый ОписаниеТипов("ДвоичныеДанные")); 253 | 254 | Возврат Карта; 255 | 256 | КонецФункции 257 | 258 | Функция ВыполнитьПриведениеЗначения(Колонка, Значение) 259 | // Если тип колонки и значение - двоичные данные, то приводить не нужно. 260 | // по крайней мере пока oscript не научится приводить тип двоичных данных 261 | // https://github.com/EvilBeaver/OneScript/issues/1327 262 | Если Колонка.ТипКолонки = ТипыКолонок.ДвоичныеДанные 263 | И ТипЗнч(Значение) = Тип("ДвоичныеДанные") Тогда 264 | Возврат Значение; 265 | КонецЕсли; 266 | 267 | ОбработанноеЗначение = Значение; 268 | 269 | КартаОписанийТипов = СоответствиеТиповМоделиОписанийТипов(); 270 | 271 | ОписаниеТипов = КартаОписанийТипов.Получить(Колонка.ТипКолонки); 272 | Если ОписаниеТипов = Неопределено Тогда 273 | ВызватьИсключение "Неизвестный тип колонки " + Колонка.ИмяКолонки; 274 | КонецЕсли; 275 | 276 | // Некоторые коннекторы возвращают дату/время в виде строки в формате ISO. 277 | Если ТипЗнч(ОбработанноеЗначение) = Тип("Строка") Тогда 278 | Если Колонка.ТипКолонки = ТипыКолонок.Дата Тогда 279 | ОбработанноеЗначение = СтроковыеФункции.СтрокаВДату(ОбработанноеЗначение, ЧастиДаты.Дата); 280 | ИначеЕсли Колонка.ТипКолонки = ТипыКолонок.ДатаВремя Тогда 281 | ОбработанноеЗначение = СтроковыеФункции.СтрокаВДату(ОбработанноеЗначение, ЧастиДаты.ДатаВремя); 282 | ИначеЕсли Колонка.ТипКолонки = ТипыКолонок.Время Тогда 283 | ОбработанноеЗначение = СтроковыеФункции.СтрокаВДату(ОбработанноеЗначение, ЧастиДаты.Время); 284 | Иначе 285 | // no-op 286 | КонецЕсли; 287 | КонецЕсли; 288 | 289 | Возврат ОписаниеТипов.ПривестиЗначение(ОбработанноеЗначение); 290 | КонецФункции 291 | -------------------------------------------------------------------------------- /src/Классы/КоннекторPostgreSQL.os: -------------------------------------------------------------------------------- 1 | #Использовать logos 2 | #Использовать strings 3 | #Использовать semaphore 4 | 5 | Перем КоннекторSQL; 6 | Перем КонструкторКоннектора Экспорт; 7 | Перем Соединение Экспорт; 8 | Перем КартаТипов; 9 | 10 | Перем Лог Экспорт; 11 | 12 | // Конструктор объекта КоннекторPostgreSQL. 13 | // 14 | Процедура ПриСозданииОбъекта() 15 | 16 | Лог = Логирование.ПолучитьЛог("oscript.lib.entity.connector.postgresql"); 17 | КоннекторSQL = Новый АбстрактныйКоннекторSQL(ЭтотОбъект, Лог); 18 | 19 | КонструкторКоннектора = ПолучитьКонструкторКоннектора(); 20 | Соединение = КонструкторКоннектора.НовыйСоединение(); 21 | КартаТипов = СоответствиеТиповМоделиИТиповКолонок(); 22 | 23 | КонецПроцедуры 24 | 25 | // Открыть соединение с БД. 26 | // 27 | // Параметры: 28 | // СтрокаСоединения - Строка - Строка соединения с БД. 29 | // ПараметрыКоннектора - Массив - Дополнительные параметры инициализации коннектора. 30 | // 31 | Процедура Открыть(СтрокаСоединения, ПараметрыКоннектора) Экспорт 32 | КонструкторКоннектора.Открыть(Соединение, СтрокаСоединения); 33 | КонецПроцедуры 34 | 35 | // Закрыть соединение с БД. 36 | // 37 | Процедура Закрыть() Экспорт 38 | КонструкторКоннектора.Закрыть(Соединение); 39 | КонецПроцедуры 40 | 41 | // Получить статус соединения с БД. 42 | // 43 | // Возвращаемое значение: 44 | // Булево - Состояние соединения. Истина, если соединение установлено и готово к использованию. 45 | // В обратном случае - Ложь. 46 | // 47 | Функция Открыт() Экспорт 48 | Возврат Соединение.Открыто; 49 | КонецФункции 50 | 51 | // Начинает новую транзакцию в БД. 52 | // 53 | Процедура НачатьТранзакцию() Экспорт 54 | Запрос = КонструкторКоннектора.НовыйЗапрос(Соединение); 55 | Запрос.Текст = "START TRANSACTION;"; 56 | Запрос.ВыполнитьКоманду(); 57 | КонецПроцедуры 58 | 59 | // Фиксирует открытую транзакцию в БД. 60 | // 61 | Процедура ЗафиксироватьТранзакцию() Экспорт 62 | Запрос = КонструкторКоннектора.НовыйЗапрос(Соединение); 63 | Запрос.Текст = "COMMIT;"; 64 | Запрос.ВыполнитьКоманду(); 65 | КонецПроцедуры 66 | 67 | // Отменяет открытую транзакцию в БД. 68 | // 69 | Процедура ОтменитьТранзакцию() Экспорт 70 | Запрос = КонструкторКоннектора.НовыйЗапрос(Соединение); 71 | Запрос.Текст = "ROLLBACK;"; 72 | Запрос.ВыполнитьКоманду(); 73 | КонецПроцедуры 74 | 75 | 76 | // Создает таблицу в БД по данным модели. 77 | // 78 | // Параметры: 79 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 80 | // 81 | Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт 82 | 83 | КоннекторSQL.ИнициализироватьТаблицу(ОбъектМодели); 84 | 85 | КонецПроцедуры 86 | 87 | // Сохраняет сущность в БД. 88 | // 89 | // Параметры: 90 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 91 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 92 | // 93 | Процедура Сохранить(ОбъектМодели, Сущность) Экспорт 94 | 95 | ИмяТаблицы = ОбъектМодели.ИмяТаблицы(); 96 | КолонкиТаблицы = ОбъектМодели.Колонки(); 97 | 98 | Запрос = КонструкторКоннектора.НовыйЗапрос(Соединение); 99 | 100 | КолонкаИдентификатор = ОбъектМодели.Идентификатор().ИмяКолонки; 101 | ЭтоВставкаОбъекта = Ложь; 102 | СоздаватьНовыйИдентификатор = Ложь; 103 | 104 | ИменаКолонок = ""; 105 | ЗначенияКолонок = ""; 106 | СтрокаОбновления = ""; 107 | 108 | Если КолонкиТаблицы.Количество() = 1 И ОбъектМодели.Идентификатор().ГенерируемоеЗначение Тогда 109 | 110 | ИменаКолонок = Символы.Таб + ОбъектМодели.Идентификатор().ИмяКолонки; 111 | ЗначенияКолонок = Символы.Таб + "null"; 112 | 113 | ЗначениеПараметра = ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(Сущность, ОбъектМодели.Идентификатор().ИмяКолонки); 114 | Если Не ЗначениеЗаполнено(ЗначениеПараметра) Тогда 115 | СоздаватьНовыйИдентификатор = Истина; 116 | КонецЕсли; 117 | Иначе 118 | Для Каждого ДанныеОКолонке Из КолонкиТаблицы Цикл 119 | ЗначениеПараметра = ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(Сущность, ДанныеОКолонке.ИмяПоля); 120 | 121 | Если ДанныеОКолонке.ГенерируемоеЗначение И НЕ ЗначениеЗаполнено(ЗначениеПараметра) Тогда 122 | 123 | ЭтоВставкаОбъекта = Истина; 124 | СоздаватьНовыйИдентификатор = Истина; 125 | Продолжить; 126 | 127 | КонецЕсли; 128 | 129 | Если ДанныеОКолонке.Идентификатор И ЗначениеЗаполнено(ЗначениеПараметра) Тогда 130 | ЭтоВставкаОбъекта = Истина; 131 | КонецЕсли; 132 | 133 | ЭтоПустаяСсылка = ДанныеОКолонке.ТипКолонки = ТипыКолонок.Ссылка 134 | И (ЗначениеПараметра = 0 Или ЗначениеПараметра = Неопределено); 135 | 136 | ИменаКолонок = ИменаКолонок + Символы.Таб + ДанныеОКолонке.ИмяКолонки + "," + Символы.ПС; 137 | 138 | ЗначенияКолонок = ЗначенияКолонок 139 | + Символы.Таб 140 | + ?(ЭтоПустаяСсылка, "null", "@" + ДанныеОКолонке.ИмяКолонки) 141 | + "," + Символы.ПС; 142 | 143 | Если Не ДанныеОКолонке.Идентификатор Тогда 144 | 145 | ЗначениеОбновления = ?(ЭтоПустаяСсылка, "null", "@" + ДанныеОКолонке.ИмяКолонки); 146 | СтрокаОбновления = СтрокаОбновления + СтрШаблон(" %1 = %2,", ДанныеОКолонке.ИмяКолонки, ЗначениеОбновления); 147 | КонецЕсли; 148 | 149 | Если Не ЭтоПустаяСсылка Тогда 150 | Запрос.УстановитьПараметр(ДанныеОКолонке.ИмяКолонки, ЗначениеПараметра); 151 | КонецЕсли; 152 | 153 | КонецЦикла; 154 | 155 | СтроковыеФункции.УдалитьПоследнийСимволВСтроке(ИменаКолонок, 2); 156 | СтроковыеФункции.УдалитьПоследнийСимволВСтроке(ЗначенияКолонок, 2); 157 | КонецЕсли; 158 | 159 | СтрокаОбновления = Лев(СтрокаОбновления, СтрДлина(СтрокаОбновления) - 1); 160 | 161 | Если КолонкиТаблицы.Количество() = 1 И СоздаватьНовыйИдентификатор Тогда 162 | 163 | ТекстЗапроса = СтрШаблон("INSERT INTO ""%1"" DEFAULT VALUES;", ИмяТаблицы); 164 | ЭтоВставкаОбъекта = Истина; 165 | 166 | Иначе 167 | ТекстЗапроса = 168 | "INSERT INTO %1 ( 169 | |%2 170 | |) VALUES ( 171 | |%3 172 | |)%4;"; 173 | 174 | ТекстОбновления = ?( 175 | ПустаяСтрока(СтрокаОбновления), 176 | "", 177 | СтрШаблон("ON CONFLICT (%1) DO UPDATE SET %2", КолонкаИдентификатор, СтрокаОбновления)); 178 | 179 | ТекстЗапроса = СтрШаблон( 180 | ТекстЗапроса, 181 | ИмяТаблицы, 182 | ИменаКолонок, 183 | ЗначенияКолонок, 184 | ТекстОбновления 185 | ); 186 | 187 | КонецЕсли; 188 | 189 | Лог.Отладка("Сохранение сущности с типом %1:%2%3", ОбъектМодели.ТипСущности(), Символы.ПС, ТекстЗапроса); 190 | 191 | Семафор = Семафоры.Получить(Строка(ОбъектМодели.ТипСущности())); 192 | Семафор.Захватить(); 193 | Запрос.Текст = ТекстЗапроса; 194 | 195 | Запрос.ВыполнитьКоманду(); 196 | 197 | Если ОбъектМодели.Идентификатор().ГенерируемоеЗначение Тогда 198 | 199 | Если ЭтоВставкаОбъекта Тогда 200 | ПараметрыЗапросаИдентификатора = Новый Структура("ИмяТаблицы, ИмяКолонки", ИмяТаблицы, КолонкаИдентификатор); 201 | ИДПоследнейДобавленнойЗаписи = 202 | КонструкторКоннектора.ИДПоследнейДобавленнойЗаписи(Соединение, ПараметрыЗапросаИдентификатора); 203 | Иначе 204 | ИДПоследнейДобавленнойЗаписи = ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(Сущность, КолонкаИдентификатор); 205 | КонецЕсли; 206 | 207 | ОбъектМодели.УстановитьЗначениеКолонкиВПоле( 208 | Сущность, 209 | ОбъектМодели.Идентификатор().ИмяКолонки, 210 | ИДПоследнейДобавленнойЗаписи 211 | ); 212 | КонецЕсли; 213 | Семафор.Освободить(); 214 | 215 | КонецПроцедуры 216 | 217 | // Удаляет сущность из таблицы БД. 218 | // 219 | // Параметры: 220 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 221 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД. 222 | // 223 | Процедура Удалить(ОбъектМодели, Сущность) Экспорт 224 | 225 | КоннекторSQL.Удалить(ОбъектМодели, Сущность); 226 | 227 | КонецПроцедуры 228 | 229 | 230 | // Осуществляет поиск строк в таблице по указанному отбору. 231 | // 232 | // Параметры: 233 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 234 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 235 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 236 | // Каждый элемент отбора преобразуется к условию поиска. 237 | // В качестве "ПутьКДанным" указываются имена колонок. 238 | // * Сортировки - Массив - Сортировка для результата поиска. 239 | // Каждый элемент массива должен иметь тип "ЭлементПорядка". 240 | // В качестве "ПутьКДанным" указываются имена колонок. 241 | // 242 | // Возвращаемое значение: 243 | // Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки, 244 | // значением элемента соответствия - значение колонки. 245 | // 246 | Функция НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 247 | 248 | Возврат КоннекторSQL.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 249 | 250 | КонецФункции 251 | 252 | // Удаляет строки в таблице по указанному отбору. 253 | // 254 | // Параметры: 255 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 256 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 257 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 258 | // Каждый элемент отбора преобразуется к условию поиска. 259 | // В качестве "ПутьКДанным" указываются имена колонок. 260 | // 261 | Процедура УдалитьСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 262 | 263 | КоннекторSQL.УдалитьСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 264 | 265 | КонецПроцедуры 266 | 267 | // @Unstable 268 | // Выполнить произвольный запрос и получить результат. 269 | // 270 | // Данный метод не входит в основной интерфейс "Коннектор". 271 | // Не рекомендуется использовать этот метод в прикладном коде, сигнатура метода может измениться. 272 | // 273 | // Параметры: 274 | // ТекстЗапроса - Строка - Текст выполняемого запроса 275 | // 276 | // Возвращаемое значение: 277 | // ТаблицаЗначений - Результат выполнения запроса. 278 | // 279 | Функция ВыполнитьЗапрос(ТекстЗапроса) Экспорт 280 | 281 | Возврат КоннекторSQL.ВыполнитьЗапрос(ТекстЗапроса); 282 | 283 | КонецФункции 284 | 285 | Функция СоответствиеТиповМоделиИТиповКолонок() 286 | 287 | Перем Карта; 288 | 289 | Карта = Новый Соответствие; 290 | Карта.Вставить(ТипыКолонок.Целое, "integer"); 291 | Карта.Вставить(ТипыКолонок.Дробное, "decimal"); 292 | Карта.Вставить(ТипыКолонок.Булево, "boolean"); 293 | Карта.Вставить(ТипыКолонок.Строка, "text"); 294 | Карта.Вставить(ТипыКолонок.Дата, "date"); 295 | Карта.Вставить(ТипыКолонок.Время, "time"); 296 | Карта.Вставить(ТипыКолонок.ДатаВремя, "timestamp"); 297 | Карта.Вставить(ТипыКолонок.ДвоичныеДанные, "bytea"); 298 | 299 | Возврат Карта; 300 | 301 | КонецФункции 302 | 303 | Функция ПолучитьТипКолонкиСУБД(ОбъектМодели, КолонкаМодели) Экспорт 304 | 305 | ТипКолонкиСУБД = Неопределено; 306 | 307 | Если КолонкаМодели.ТипКолонки = ТипыКолонок.Ссылка Тогда 308 | ОбъектМоделиСсылка = ОбъектМодели.МодельДанных().Получить(КолонкаМодели.ТипСсылки); 309 | ТипКолонкиСУБД = КартаТипов.Получить(ОбъектМоделиСсылка.Идентификатор().ТипКолонки); 310 | ИначеЕсли ТипыКолонок.ЭтоПримитивныйТип(КолонкаМодели.ТипКолонки) Тогда 311 | ТипКолонкиСУБД = КартаТипов.Получить(КолонкаМодели.ТипКолонки); 312 | Если КолонкаМодели.ГенерируемоеЗначение Тогда 313 | ТипКолонкиСУБД = "serial"; 314 | КонецЕсли; 315 | Иначе 316 | ВызватьИсключение "Неизвестный тип колонки " + КолонкаМодели.ТипКолонки; 317 | КонецЕсли; 318 | 319 | Возврат ТипКолонкиСУБД; 320 | 321 | КонецФункции 322 | 323 | Функция ПолучитьОписаниеВнешнегоКлюча(ОбъектМодели, КолонкаМодели) Экспорт 324 | 325 | Возврат КоннекторSQL.ПолучитьОписаниеВнешнегоКлюча(ОбъектМодели, КолонкаМодели); 326 | 327 | КонецФункции 328 | 329 | #Область Подключение_коннектора_СУБД 330 | 331 | Функция ПолучитьКонструкторКоннектора() 332 | 333 | ПутьККлассам = ОбъединитьПути( 334 | ТекущийСценарий().Каталог, 335 | "..", 336 | "internal", 337 | "ДинамическиПодключаемыеКлассы" 338 | ); 339 | 340 | Попытка 341 | А = Вычислить("ПользователиИнформационнойБазы"); 342 | ПутьККоннектору = ОбъединитьПути( 343 | ПутьККлассам, 344 | "КонструкторКоннектораPostgreSQLWeb.os" 345 | ); 346 | Исключение 347 | ПутьККоннектору = ОбъединитьПути( 348 | ПутьККлассам, 349 | "КонструкторКоннектораPostgreSQL.os" 350 | ); 351 | КонецПопытки; 352 | 353 | Возврат ЗагрузитьСценарий(ПутьККоннектору); 354 | 355 | КонецФункции 356 | 357 | #КонецОбласти 358 | -------------------------------------------------------------------------------- /src/Классы/КоннекторJSON.os: -------------------------------------------------------------------------------- 1 | #Использовать asserts 2 | #Использовать fluent 3 | #Использовать fs 4 | #Использовать json 5 | #Использовать logos 6 | #Использовать semaphore 7 | 8 | // Для хранения статуса соединения 9 | Перем Открыт; 10 | 11 | Перем ПарсерJSON; 12 | Перем БазовыйКаталог; 13 | 14 | Перем Лог; 15 | 16 | // Конструктор объекта АбстрактныйКоннектор. 17 | // 18 | Процедура ПриСозданииОбъекта() 19 | 20 | Открыт = Ложь; 21 | Лог = Логирование.ПолучитьЛог("oscript.lib.entity.connector.json"); 22 | ПарсерJSON = Новый ПарсерJSON; 23 | 24 | КонецПроцедуры 25 | 26 | // Открыть соединение с БД. 27 | // 28 | // Параметры: 29 | // СтрокаСоединения - Строка - Строка соединения с БД. 30 | // ПараметрыКоннектора - Массив - Дополнительные параметры инициализиации коннектора. 31 | // 32 | Процедура Открыть(СтрокаСоединения, ПараметрыКоннектора) Экспорт // BSLLS:UnusedParameters-off 33 | Открыт = Истина; 34 | Лог.Отладка("Открытие коннектора со строкой соединения %1", СтрокаСоединения); 35 | Ожидаем.Что(ФС.КаталогСуществует(СтрокаСоединения), "Существует каталог для выгрузки данных сущностей"); 36 | БазовыйКаталог = СтрокаСоединения; 37 | КонецПроцедуры 38 | 39 | // Закрыть соединение с БД. 40 | // 41 | Процедура Закрыть() Экспорт 42 | Открыт = Ложь; 43 | КонецПроцедуры 44 | 45 | // Получить статус соединения с БД. 46 | // 47 | // Возвращаемое значение: 48 | // Булево - Состояние соединения. Истина, если соединение установлено и готово к использованию. 49 | // В обратном случае - Ложь. 50 | // 51 | Функция Открыт() Экспорт 52 | Возврат Открыт; 53 | КонецФункции 54 | 55 | // Начинает новую транзакцию в БД. 56 | // 57 | Процедура НачатьТранзакцию() Экспорт 58 | ВызватьИсключение "Не поддерживается"; 59 | КонецПроцедуры 60 | 61 | // Фиксирует открытую транзакцию в БД. 62 | // 63 | Процедура ЗафиксироватьТранзакцию() Экспорт 64 | ВызватьИсключение "Не поддерживается"; 65 | КонецПроцедуры 66 | 67 | // Отменяет открытую транзакцию в БД. 68 | // 69 | Процедура ОтменитьТранзакцию() Экспорт 70 | ВызватьИсключение "Не поддерживается"; 71 | КонецПроцедуры 72 | 73 | // Создает таблицу в БД по данным модели. 74 | // 75 | // Параметры: 76 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 77 | // 78 | Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт 79 | ИмяФайла = ОбъединитьПути(БазовыйКаталог, ОбъектМодели.ИмяТаблицы()) + ".json"; 80 | Если НЕ ФС.Существует(ИмяФайла) Тогда 81 | Лог.Отладка("Инициализация таблицы %1 в файле %1", ОбъектМодели.ИмяТаблицы(), ИмяФайла); 82 | Таблица = Новый Соответствие; 83 | ЗаписатьОбъектВФайл(Таблица, ИмяФайла); 84 | КонецЕсли; 85 | КонецПроцедуры 86 | 87 | // Сохраняет сущность в БД. 88 | // 89 | // Параметры: 90 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 91 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД. 92 | // 93 | Процедура Сохранить(ОбъектМодели, Сущность) Экспорт 94 | ИмяФайла = ОбъединитьПути(БазовыйКаталог, ОбъектМодели.ИмяТаблицы()) + ".json"; 95 | Семафор = Семафоры.Получить(ИмяФайла); 96 | Семафор.Захватить(); 97 | 98 | Таблица = ПрочитатьОбъектИзФайла(ИмяФайла); 99 | 100 | Идентификатор = ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность); 101 | Если НЕ ЗначениеЗаполнено(Идентификатор) Тогда 102 | 103 | Если ОбъектМодели.Идентификатор().ТипКолонки <> ТипыКолонок.Целое Тогда 104 | Сообщение = СтрШаблон( 105 | "Ошибка при сохранении сущности с типом %1. 106 | |Генерация идентификаторов поддерживается только для колонок с типом ""Целое""", 107 | ОбъектМодели.ТипСущности() 108 | ); 109 | ВызватьИсключение Сообщение; 110 | КонецЕсли; 111 | 112 | МаксимальныйИдентификатор = ПроцессорыКоллекций.ИзКоллекции(Таблица) 113 | .Обработать("Элемент -> Число(Элемент.Ключ)") 114 | .Максимум(); 115 | 116 | Если МаксимальныйИдентификатор = Неопределено Тогда 117 | МаксимальныйИдентификатор = 0; 118 | КонецЕсли; 119 | 120 | Идентификатор = МаксимальныйИдентификатор + 1; 121 | 122 | ОбъектМодели.УстановитьЗначениеКолонкиВПоле( 123 | Сущность, 124 | ОбъектМодели.Идентификатор().ИмяКолонки, 125 | Идентификатор 126 | ); 127 | 128 | КонецЕсли; 129 | Если ТипЗнч(Идентификатор) = Тип("Число") Тогда 130 | Идентификатор = Формат(Идентификатор, "ЧГ="); 131 | КонецЕсли; 132 | 133 | Лог.Отладка("Сохранение сущности с типом %1 и идентификатором %2", ОбъектМодели.ТипСущности(), Идентификатор); 134 | 135 | Таблица.Вставить(Идентификатор, РазложитьОбъектВСоответствие(Сущность, ОбъектМодели)); 136 | ЗаписатьОбъектВФайл(Таблица, ИмяФайла, ОбъектМодели); 137 | 138 | Семафор.Освободить(); 139 | 140 | КонецПроцедуры 141 | 142 | // Удаляет сущность из таблицы БД. 143 | // 144 | // Параметры: 145 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 146 | // Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД. 147 | // 148 | Процедура Удалить(ОбъектМодели, Сущность) Экспорт 149 | 150 | ИмяФайла = ОбъединитьПути(БазовыйКаталог, ОбъектМодели.ИмяТаблицы()) + ".json"; 151 | Семафор = Семафоры.Получить(ИмяФайла); 152 | Семафор.Захватить(); 153 | 154 | Таблица = ПрочитатьОбъектИзФайла(ИмяФайла); 155 | 156 | Идентификатор = ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность); 157 | Если ТипЗнч(Идентификатор) = Тип("Число") Тогда 158 | Идентификатор = Формат(Идентификатор, "ЧГ="); 159 | КонецЕсли; 160 | 161 | Лог.Отладка( 162 | "Удаление сущности с типом %1 и идентификатором %2", 163 | ОбъектМодели.ТипСущности(), 164 | Идентификатор 165 | ); 166 | 167 | Таблица.Удалить(Идентификатор); 168 | 169 | ЗаписатьОбъектВФайл(Таблица, ИмяФайла, ОбъектМодели); 170 | 171 | Семафор.Освободить(); 172 | 173 | КонецПроцедуры 174 | 175 | // Осуществляет поиск строк в таблице по указанному отбору. 176 | // 177 | // Параметры: 178 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 179 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 180 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 181 | // Каждый элемент отбора преобразуется к условию поиска. 182 | // В качестве "ПутьКДанным" указываются имена колонок. 183 | // * Сортировки - Массив - Сортировка для результата поиска. 184 | // Каждый элемент массива должен иметь тип "ЭлементПорядка". 185 | // В качестве "ПутьКДанным" указываются имена колонок. 186 | // 187 | // Возвращаемое значение: 188 | // Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки, 189 | // значением элемента соответствия - значение колонки. 190 | // 191 | Функция НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 192 | 193 | НайденныеСтроки = Новый Массив; 194 | 195 | ИмяФайла = ОбъединитьПути(БазовыйКаталог, ОбъектМодели.ИмяТаблицы()) + ".json"; 196 | Таблица = ПрочитатьОбъектИзФайла(ИмяФайла); 197 | 198 | Лог.Отладка("Поиск сущностей в таблице %1", ОбъектМодели.ИмяТаблицы()); 199 | 200 | ПроцессорКоллекций = ПроцессорыКоллекций.ИзКоллекции(Таблица); 201 | 202 | Для Каждого ЭлементОтбора Из ОпцииПоиска.Отборы() Цикл 203 | Если ЭлементОтбора.ВидСравнения = ВидСравнения.В Тогда 204 | СтрокаУсловие = СтрШаблон( 205 | "Элемент -> Значение.Найти(Элемент.Значение.Получить(""%1"")) <> Неопределено", 206 | ЭлементОтбора.ПутьКДанным 207 | ); 208 | ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравнения.НеВ Тогда 209 | СтрокаУсловие = СтрШаблон( 210 | "Элемент -> Значение.Найти(Элемент.Значение.Получить(""%1"")) = Неопределено", 211 | ЭлементОтбора.ПутьКДанным 212 | ); 213 | Иначе 214 | СтрокаУсловие = СтрШаблон( 215 | "Элемент -> Элемент.Значение.Получить(""%1"") %2 Значение", 216 | ЭлементОтбора.ПутьКДанным, 217 | ЭлементОтбора.ВидСравнения 218 | ); 219 | КонецЕсли; 220 | ДополнительныеПараметры = Новый Структура("Значение", ЭлементОтбора.Значение); 221 | ПроцессорКоллекций = ПроцессорКоллекций.Фильтровать(СтрокаУсловие, ДополнительныеПараметры); 222 | КонецЦикла; 223 | 224 | Колонки = ОбъектМодели.Колонки(); 225 | СтрокаСортировка = ""; 226 | Для Каждого ЭлементПорядка Из ОпцииПоиска.Сортировки() Цикл 227 | 228 | НайденныеКолонки = Колонки.НайтиСтроки(Новый Структура("ИмяКолонки", ЭлементПорядка.ПутьКДанным)); 229 | 230 | Если НайденныеКолонки.Количество() = 0 Тогда 231 | ИмяПоля = ЭлементПорядка.ПутьКДанным; 232 | Иначе 233 | ИмяПоля = НайденныеКолонки[0].ИмяПоля; 234 | КонецЕсли; 235 | ПорядокСортировки = ?(ЭлементПорядка.НаправлениеСортировки = НаправлениеСортировки.Возр, "ПрямойПорядок", "ОбратныйПорядок"); 236 | 237 | // формирование текста лямбды для сравнения элементов по нескольким полям 238 | СтрокаСортировка = СтрокаСортировка + СтрШаблон( 239 | "Сравнение = ПроцессорыКоллекцийСлужебный.СравнениеЗначений%1(Элемент1.Значение.Получить(""%2""), Элемент2.Значение.Получить(""%2"")); 240 | |Если Сравнение <> 0 Тогда 241 | | Возврат Сравнение; 242 | |КонецЕсли; 243 | | 244 | |", 245 | ПорядокСортировки, 246 | ИмяПоля 247 | ); 248 | 249 | КонецЦикла; 250 | 251 | Если СтрокаСортировка <> "" Тогда 252 | СтрокаСортировка = "(Элемент1, Элемент2) -> " + Символы.ПС + СтрокаСортировка + "Возврат Сравнение;"; 253 | 254 | ПроцессорКоллекций = ПроцессорКоллекций.Сортировать(СтрокаСортировка); 255 | КонецЕсли; 256 | 257 | Если ОпцииПоиска.ВыбираетсяСоСмещением() <> Неопределено Тогда 258 | ПроцессорКоллекций = ПроцессорКоллекций.Пропустить(ОпцииПоиска.ВыбираетсяСоСмещением()); 259 | КонецЕсли; 260 | 261 | Если ОпцииПоиска.ВыбираютсяПервые() <> Неопределено Тогда 262 | ПроцессорКоллекций = ПроцессорКоллекций.Первые(ОпцииПоиска.ВыбираютсяПервые()); 263 | КонецЕсли; 264 | 265 | ДанныеТаблицы = ПроцессорКоллекций.ВМассив(); 266 | 267 | Для Каждого СтрокаДанныхТаблицы Из ДанныеТаблицы Цикл 268 | ЗначенияКолонок = Новый Соответствие; 269 | Для Каждого Колонка Из ОбъектМодели.Колонки() Цикл 270 | Значение = СтрокаДанныхТаблицы.Значение.Получить(Колонка.ИмяКолонки); 271 | Если Колонка.ТипКолонки = ТипыКолонок.ДвоичныеДанные Тогда 272 | Значение = ПолучитьДвоичныеДанныеИзBase64Строки(Значение); 273 | КонецЕсли; 274 | ЗначенияКолонок.Вставить(Колонка.ИмяКолонки, Значение); 275 | КонецЦикла; 276 | НайденныеСтроки.Добавить(ЗначенияКолонок); 277 | КонецЦикла; 278 | 279 | Возврат НайденныеСтроки; 280 | КонецФункции 281 | 282 | // Удаляет строки в таблице по указанному отбору. 283 | // 284 | // Параметры: 285 | // ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД. 286 | // ОпцииПоиска - ОпцииПоиска - Опции поиска. Содержит следующие параметры: 287 | // * Отборы - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора". 288 | // Каждый элемент отбора преобразуется к условию поиска. 289 | // В качестве "ПутьКДанным" указываются имена колонок. 290 | // 291 | Процедура УдалитьСтрокиВТаблице(ОбъектМодели, ОпцииПоиска) Экспорт 292 | 293 | Лог.Отладка("Удаление сущностей в таблице %1", ОбъектМодели.ИмяТаблицы()); 294 | 295 | ИмяФайла = ОбъединитьПути(БазовыйКаталог, ОбъектМодели.ИмяТаблицы()) + ".json"; 296 | Семафор = Семафоры.Получить(ИмяФайла); 297 | Семафор.Захватить(); 298 | 299 | НайденныеСтроки = НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 300 | 301 | Лог.Отладка("К удалению сущностей: %1 шт.", НайденныеСтроки.Количество()); 302 | 303 | Таблица = ПрочитатьОбъектИзФайла(ИмяФайла); 304 | 305 | Для Каждого НайденнаяСтрока Из НайденныеСтроки Цикл 306 | Идентификатор = НайденнаяСтрока.Получить(ОбъектМодели.Идентификатор().ИмяКолонки); 307 | Если ТипЗнч(Идентификатор) = Тип("Число") Тогда 308 | Идентификатор = Формат(Идентификатор, "ЧГ="); 309 | КонецЕсли; 310 | 311 | Таблица.Удалить(Идентификатор); 312 | КонецЦикла; 313 | 314 | ЗаписатьОбъектВФайл(Таблица, ИмяФайла, ОбъектМодели); 315 | 316 | Семафор.Освободить(); 317 | 318 | КонецПроцедуры 319 | 320 | Процедура ЗаписатьОбъектВФайл(Значение, ИмяФайла, ОбъектМодели = Неопределено) 321 | ТекстJSON = ПарсерJSON.ЗаписатьJSON(Значение); 322 | ЗаписьТекста = Новый ЗаписьТекста(ИмяФайла, "UTF-8"); 323 | ЗаписьТекста.Записать(ТекстJSON); 324 | ЗаписьТекста.Закрыть(); 325 | КонецПроцедуры 326 | 327 | Функция РазложитьОбъектВСоответствие(Значение, ОбъектМодели) 328 | Соответствие = Новый Соответствие; 329 | Для Каждого Колонка Из ОбъектМодели.Колонки() Цикл 330 | ЗначениеПараметра = ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(Значение, Колонка.ИмяПоля); 331 | Соответствие.Вставить(Колонка.ИмяКолонки, ЗначениеПараметра); 332 | КонецЦикла; 333 | 334 | Возврат Соответствие; 335 | КонецФункции 336 | 337 | Функция ПрочитатьОбъектИзФайла(ИмяФайла) 338 | ЧтениеТекста = Новый ЧтениеТекста(ИмяФайла, "UTF-8"); 339 | ТекстJSON = ЧтениеТекста.Прочитать(); 340 | Объект = ПарсерJSON.ПрочитатьJSON(ТекстJSON); 341 | ЧтениеТекста.Закрыть(); 342 | Возврат Объект; 343 | КонецФункции 344 | -------------------------------------------------------------------------------- /tests/КоннекторJSON.os: -------------------------------------------------------------------------------- 1 | // BSLLS:MagicNumber-off 2 | // BSLLS:LatinAndCyrillicSymbolInWord-off 3 | // BSLLS:DuplicateStringLiteral-off 4 | // BSLLS:LineLength-off 5 | 6 | #Использовать fs 7 | #Использовать ".." 8 | #Использовать "utils" 9 | 10 | Перем Коннектор; 11 | Перем СтрокаСоединения; 12 | 13 | Процедура ПередЗапускомТеста() Экспорт 14 | ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "СущностьСоВсемиТипамиКолонок.os"), "СущностьСоВсемиТипамиКолонок"); 15 | ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "АвтоинкрементныйКлючБезКолонок.os"), "АвтоинкрементныйКлючБезКолонок"); 16 | 17 | СтрокаСоединения = ОбъединитьПути(ТекущийКаталог(), "tests", "jsontestdata"); 18 | СоздатьКаталог(СтрокаСоединения); 19 | 20 | Коннектор = Новый КоннекторJSON(); 21 | Коннектор.Открыть(СтрокаСоединения, Новый Массив); 22 | КонецПроцедуры 23 | 24 | Процедура ПослеЗапускаТеста() Экспорт 25 | Коннектор.Закрыть(); 26 | УдалитьФайлы(СтрокаСоединения); 27 | КонецПроцедуры 28 | 29 | &Тест 30 | Процедура КоннекторJSONРеализуетИнтерфейсКоннектора() Экспорт 31 | ИнтерфейсОбъекта = Новый ИнтерфейсОбъекта(); 32 | ИнтерфейсОбъекта.ИзОбъекта(Тип("АбстрактныйКоннектор")); 33 | 34 | РефлекторОбъекта = Новый РефлекторОбъекта(Тип("КоннекторJSON")); 35 | РефлекторОбъекта.РеализуетИнтерфейс(ИнтерфейсОбъекта, Истина); 36 | КонецПроцедуры 37 | 38 | &Тест 39 | Процедура НайтиСтрокиВТаблице() Экспорт 40 | МодельДанных = Новый МодельДанных(); 41 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок")); 42 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 43 | 44 | ЗависимаяСущность = Новый СущностьСоВсемиТипамиКолонок; 45 | ЗависимаяСущность.Целое = 2; 46 | 47 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 48 | Сущность.Целое = 1; 49 | Сущность.Дробное = 1.2; 50 | Сущность.БулевоИстина = Истина; 51 | Сущность.БулевоЛожь = Ложь; 52 | Сущность.Строка = "Строка"; 53 | Сущность.Дата = Дата(2018, 1, 1); 54 | Сущность.Время = Дата(1, 1, 1, 10, 53, 20); 55 | Сущность.ДатаВремя = Дата(2018, 1, 1, 10, 53, 20); 56 | Сущность.Ссылка = ЗависимаяСущность; 57 | Сущность.ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки("ДвоичныеДанные"); 58 | 59 | Коннектор.Сохранить(ОбъектМодели, ЗависимаяСущность); 60 | Коннектор.Сохранить(ОбъектМодели, Сущность); 61 | 62 | ОпцииПоиска = Новый ОпцииПоиска(); 63 | ОпцииПоиска.Отбор("Целое", ВидСравнения.Равно, Сущность.Целое); 64 | 65 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 66 | Ожидаем.Что(НайденныеСтроки, "Сущность сохранилась").ИмеетДлину(1); 67 | 68 | ЗначенияКолонок = НайденныеСтроки[0]; 69 | 70 | Ожидаем.Что(ЗначенияКолонок.Получить("Целое"), "ЗначенияКолонок.Целое получено корректно").Равно(Сущность.Целое); 71 | Ожидаем.Что(ЗначенияКолонок.Получить("Дробное"), "ЗначенияКолонок.Дробное получено корректно").Равно(Сущность.Дробное); 72 | Ожидаем.Что(ЗначенияКолонок.Получить("БулевоИстина"), "ЗначенияКолонок.БулевоИстина получено корректно").Равно(Сущность.БулевоИстина); 73 | Ожидаем.Что(ЗначенияКолонок.Получить("БулевоЛожь"), "ЗначенияКолонок.БулевоЛожь получено корректно").Равно(Сущность.БулевоЛожь); 74 | Ожидаем.Что(ЗначенияКолонок.Получить("Строка"), "ЗначенияКолонок.Строка получено корректно").Равно(Сущность.Строка); 75 | Ожидаем.Что(ЗначенияКолонок.Получить("Дата"), "ЗначенияКолонок.Дата получено корректно").Равно(Сущность.Дата); 76 | Ожидаем.Что(ЗначенияКолонок.Получить("Время"), "ЗначенияКолонок.Время получено корректно").Равно(Сущность.Время); 77 | Ожидаем.Что(ЗначенияКолонок.Получить("ДатаВремя"), "ЗначенияКолонок.ДатаВремя получено корректно").Равно(Сущность.ДатаВремя); 78 | Ожидаем.Что(ЗначенияКолонок.Получить("Ссылка"), "ЗначенияКолонок.Ссылка получено корректно").Равно(Сущность.Ссылка.Целое); 79 | Ожидаем.Что(ЗначенияКолонок.Получить("ДвоичныеДанные"), "ЗначенияКолонок.ДвоичныеДанные получено корректно").Равно(Сущность.ДвоичныеДанные); 80 | КонецПроцедуры 81 | 82 | &Тест 83 | Процедура ПоискВСписке() Экспорт 84 | 85 | // Дано 86 | МодельДанных = Новый МодельДанных(); 87 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок")); 88 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 89 | 90 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 91 | Сущность.Целое = 1; 92 | Коннектор.Сохранить(ОбъектМодели, Сущность); 93 | 94 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 95 | Сущность.Целое = 2; 96 | Коннектор.Сохранить(ОбъектМодели, Сущность); 97 | 98 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 99 | Сущность.Целое = 3; 100 | Коннектор.Сохранить(ОбъектМодели, Сущность); 101 | 102 | // Когда 103 | МассивПоиска = Новый Массив; 104 | МассивПоиска.Добавить(1); 105 | МассивПоиска.Добавить(3); 106 | 107 | ОпцииПоиска = Новый ОпцииПоиска(); 108 | ОпцииПоиска.Отбор("Целое", ВидСравнения.В, МассивПоиска); 109 | 110 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 111 | 112 | // Тогда 113 | Ожидаем.Что(НайденныеСтроки, "Все строки получены").ИмеетДлину(2); 114 | Ожидаем.Что(НайденныеСтроки[0].Получить("Целое"), "Строки найдены").Равно(1); 115 | Ожидаем.Что(НайденныеСтроки[1].Получить("Целое"), "Строки найдены").Равно(3); 116 | 117 | КонецПроцедуры 118 | 119 | &Тест 120 | Процедура ПоискНеВСписке() Экспорт 121 | 122 | // Дано 123 | МодельДанных = Новый МодельДанных(); 124 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок")); 125 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 126 | 127 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 128 | Сущность.Целое = 1; 129 | Коннектор.Сохранить(ОбъектМодели, Сущность); 130 | 131 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 132 | Сущность.Целое = 2; 133 | Коннектор.Сохранить(ОбъектМодели, Сущность); 134 | 135 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 136 | Сущность.Целое = 3; 137 | Коннектор.Сохранить(ОбъектМодели, Сущность); 138 | 139 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 140 | Сущность.Целое = 4; 141 | Коннектор.Сохранить(ОбъектМодели, Сущность); 142 | 143 | // Когда 144 | МассивПоиска = Новый Массив; 145 | МассивПоиска.Добавить(1); 146 | МассивПоиска.Добавить(3); 147 | 148 | ОпцииПоиска = Новый ОпцииПоиска(); 149 | ОпцииПоиска.Отбор("Целое", ВидСравнения.НеВ, МассивПоиска); 150 | 151 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 152 | 153 | // Тогда 154 | Ожидаем.Что(НайденныеСтроки, "Все строки получены").ИмеетДлину(2); 155 | Ожидаем.Что(НайденныеСтроки[0].Получить("Целое"), "Строки найдены").Равно(2); 156 | Ожидаем.Что(НайденныеСтроки[1].Получить("Целое"), "Строки найдены").Равно(4); 157 | 158 | КонецПроцедуры 159 | 160 | &Тест 161 | Процедура ПоискВПустомСписке() Экспорт 162 | 163 | // Дано 164 | МодельДанных = Новый МодельДанных(); 165 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок")); 166 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 167 | 168 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 169 | Сущность.Целое = 1; 170 | Коннектор.Сохранить(ОбъектМодели, Сущность); 171 | 172 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 173 | Сущность.Целое = 2; 174 | Коннектор.Сохранить(ОбъектМодели, Сущность); 175 | 176 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 177 | Сущность.Целое = 3; 178 | Коннектор.Сохранить(ОбъектМодели, Сущность); 179 | 180 | // Когда 181 | МассивПоиска = Новый Массив; 182 | 183 | ОпцииПоиска = Новый ОпцииПоиска(); 184 | ОпцииПоиска.Отбор("Целое", ВидСравнения.В, МассивПоиска); 185 | 186 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 187 | 188 | // Тогда 189 | Ожидаем.Что(НайденныеСтроки, "Строки не найдены").ИмеетДлину(0); 190 | 191 | КонецПроцедуры 192 | 193 | &Тест 194 | Процедура ВыбратьПервые() Экспорт 195 | 196 | // Дано 197 | МодельДанных = Новый МодельДанных(); 198 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок")); 199 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 200 | 201 | ТестовыеУтилиты.СохранитьСущностьСоВсемиТипамиКолонок(Коннектор, ОбъектМодели, 1); 202 | ТестовыеУтилиты.СохранитьСущностьСоВсемиТипамиКолонок(Коннектор, ОбъектМодели, 2); 203 | ТестовыеУтилиты.СохранитьСущностьСоВсемиТипамиКолонок(Коннектор, ОбъектМодели, 3); 204 | 205 | // Когда 206 | ОпцииПоиска = Новый ОпцииПоиска; 207 | ОпцииПоиска.Первые(2); 208 | 209 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 210 | 211 | // Тогда 212 | Ожидаем.Что(НайденныеСтроки, "Все строки получены").ИмеетДлину(2); 213 | Ожидаем.Что(НайденныеСтроки[0].Получить("Целое"), "Первая строка").Равно(1); 214 | Ожидаем.Что(НайденныеСтроки[1].Получить("Целое"), "Вторая строка").Равно(2); 215 | 216 | КонецПроцедуры 217 | 218 | &Тест 219 | Процедура ВыбратьПервыеСоСмещением() Экспорт 220 | 221 | // Дано 222 | МодельДанных = Новый МодельДанных(); 223 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок")); 224 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 225 | 226 | ТестовыеУтилиты.СохранитьСущностьСоВсемиТипамиКолонок(Коннектор, ОбъектМодели, 1); 227 | ТестовыеУтилиты.СохранитьСущностьСоВсемиТипамиКолонок(Коннектор, ОбъектМодели, 2); 228 | ТестовыеУтилиты.СохранитьСущностьСоВсемиТипамиКолонок(Коннектор, ОбъектМодели, 3); 229 | ТестовыеУтилиты.СохранитьСущностьСоВсемиТипамиКолонок(Коннектор, ОбъектМодели, 4); 230 | 231 | // Когда 232 | ОпцииПоиска = Новый ОпцииПоиска; 233 | ОпцииПоиска 234 | .Первые(2) 235 | .Смещение(1) 236 | .СортироватьПо("Целое", НаправлениеСортировки.Возр); 237 | 238 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 239 | 240 | // Тогда 241 | Ожидаем.Что(НайденныеСтроки, "Все строки получены").ИмеетДлину(2); 242 | Ожидаем.Что(НайденныеСтроки[0].Получить("Целое"), "Первая строка").Равно(2); 243 | Ожидаем.Что(НайденныеСтроки[1].Получить("Целое"), "Вторая строка").Равно(3); 244 | 245 | КонецПроцедуры 246 | 247 | &Тест 248 | Процедура УдалитьСтрокиВТаблице() Экспорт 249 | МодельДанных = Новый МодельДанных(); 250 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок")); 251 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 252 | 253 | Сущность = Новый СущностьСоВсемиТипамиКолонок; 254 | Сущность.Целое = 1; 255 | 256 | Коннектор.Сохранить(ОбъектМодели, Сущность); 257 | 258 | ОпцииПоиска = Новый ОпцииПоиска(); 259 | ОпцииПоиска.Отбор("Целое", ВидСравнения.Равно, Сущность.Целое); 260 | 261 | Коннектор.УдалитьСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 262 | 263 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 264 | Ожидаем.Что(НайденныеСтроки, "Сущность удалилась").ИмеетДлину(0); 265 | КонецПроцедуры 266 | 267 | &Тест 268 | Процедура УдалениеСущности() Экспорт 269 | МодельДанных = Новый МодельДанных(); 270 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок")); 271 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 272 | 273 | Сущность = Новый СущностьСоВсемиТипамиКолонок(); 274 | Сущность.Целое = 1; 275 | Коннектор.Сохранить(ОбъектМодели, Сущность); 276 | 277 | Коннектор.Удалить(ОбъектМодели, Сущность); 278 | 279 | ОпцииПоиска = Новый ОпцииПоиска(); 280 | ОпцииПоиска.Отбор("Целое", ВидСравнения.Равно, Сущность.Целое); 281 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 282 | 283 | Ожидаем.Что(НайденныеСтроки, "Сущность удалилась").ИмеетДлину(0); 284 | 285 | КонецПроцедуры 286 | 287 | &Тест 288 | Процедура Автоинкремент() Экспорт 289 | МодельДанных = Новый МодельДанных(); 290 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("АвтоинкрементныйКлючБезКолонок")); 291 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 292 | 293 | Сущность = Новый АвтоинкрементныйКлючБезКолонок(); 294 | Коннектор.Сохранить(ОбъектМодели, Сущность); 295 | 296 | Ожидаем.Что(Сущность.Идентификатор).Равно(1); 297 | 298 | Сущность = Новый АвтоинкрементныйКлючБезКолонок(); 299 | Коннектор.Сохранить(ОбъектМодели, Сущность); 300 | 301 | Ожидаем.Что(Сущность.Идентификатор).Равно(2); 302 | 303 | КонецПроцедуры 304 | 305 | &Тест 306 | Процедура СущностьМожетЗаписатьСебя() Экспорт 307 | // Дано 308 | ПодключитьСценарий("tests/fixtures/ПростойОбъект.os", "ПростойОбъект"); 309 | КаталогБД = "./tests/jsondatabase"; 310 | ФС.ОбеспечитьПустойКаталог(КаталогБД); 311 | ТипКоннектора = "КоннекторJSON"; 312 | МенеджерСущностей = Новый МенеджерСущностей(Тип(ТипКоннектора), КаталогБД); 313 | МенеджерСущностей.ДобавитьКлассВМодель(Тип("ПростойОбъект")); 314 | МенеджерСущностей.Инициализировать(); 315 | 316 | // Когда 317 | ПростойОбъект = МенеджерСущностей.СоздатьЭлемент(Тип("ПростойОбъект")); 318 | ПростойОбъект.Идентификатор = "1"; 319 | ПростойОбъект.Поле = "2"; 320 | ПростойОбъект.Сохранить(); 321 | 322 | // Тогда 323 | НайденныйПростойОбъект = МенеджерСущностей.ПолучитьОдно(Тип("ПростойОбъект"), "1"); 324 | 325 | Ожидаем.Что(НайденныйПростойОбъект).Не_().Равно(Неопределено); 326 | Ожидаем.Что(НайденныйПростойОбъект.Идентификатор).Равно("1"); 327 | Ожидаем.Что(НайденныйПростойОбъект.Поле).Равно("2"); 328 | 329 | КонецПроцедуры 330 | 331 | &Тест 332 | Процедура СущностьМожетПерезаписатьСебя() Экспорт 333 | // Дано 334 | ПодключитьСценарий("tests/fixtures/ПростойОбъект.os", "ПростойОбъект"); 335 | КаталогБД = "./tests/jsondatabase"; 336 | ФС.ОбеспечитьПустойКаталог(КаталогБД); 337 | ТипКоннектора = "КоннекторJSON"; 338 | МенеджерСущностей = Новый МенеджерСущностей(Тип(ТипКоннектора), КаталогБД); 339 | МенеджерСущностей.ДобавитьКлассВМодель(Тип("ПростойОбъект")); 340 | МенеджерСущностей.Инициализировать(); 341 | 342 | // Когда 343 | ПростойОбъект = МенеджерСущностей.СоздатьЭлемент(Тип("ПростойОбъект")); 344 | ПростойОбъект.Идентификатор = "1"; 345 | ПростойОбъект.Поле = "2"; 346 | ПростойОбъект.Сохранить(); 347 | НайденныйПростойОбъект = МенеджерСущностей.ПолучитьОдно(Тип("ПростойОбъект"), "1"); 348 | НайденныйПростойОбъект.Поле = "3"; 349 | НайденныйПростойОбъект.Сохранить(); 350 | 351 | // Тогда 352 | НайденныйПростойОбъект = МенеджерСущностей.ПолучитьОдно(Тип("ПростойОбъект"), "1"); 353 | 354 | Ожидаем.Что(НайденныйПростойОбъект).Не_().Равно(Неопределено); 355 | Ожидаем.Что(НайденныйПростойОбъект.Идентификатор).Равно("1"); 356 | Ожидаем.Что(НайденныйПростойОбъект.Поле).Равно("3"); 357 | 358 | КонецПроцедуры 359 | 360 | &Тест 361 | Процедура МенеджерСущностейМожетЗаписать() Экспорт 362 | // Дано 363 | ПодключитьСценарий("tests/fixtures/ПростойОбъект.os", "ПростойОбъект"); 364 | КаталогБД = "./tests/jsondatabase"; 365 | ФС.ОбеспечитьПустойКаталог(КаталогБД); 366 | ТипКоннектора = "КоннекторJSON"; 367 | МенеджерСущностей = Новый МенеджерСущностей(Тип(ТипКоннектора), КаталогБД); 368 | МенеджерСущностей.ДобавитьКлассВМодель(Тип("ПростойОбъект")); 369 | МенеджерСущностей.Инициализировать(); 370 | 371 | // Когда 372 | ПростойОбъект = МенеджерСущностей.СоздатьЭлемент(Тип("ПростойОбъект")); 373 | ПростойОбъект.Идентификатор = "1"; 374 | ПростойОбъект.Поле = "2"; 375 | МенеджерСущностей.Сохранить(ПростойОбъект); 376 | 377 | // Тогда 378 | НайденныйПростойОбъект = МенеджерСущностей.ПолучитьОдно(Тип("ПростойОбъект"), "1"); 379 | 380 | Ожидаем.Что(НайденныйПростойОбъект).Не_().Равно(Неопределено); 381 | Ожидаем.Что(НайденныйПростойОбъект.Идентификатор).Равно("1"); 382 | Ожидаем.Что(НайденныйПростойОбъект.Поле).Равно("2"); 383 | 384 | КонецПроцедуры 385 | 386 | &Тест 387 | Процедура ХранилищеСущностейМожетЗаписать() Экспорт 388 | 389 | // Дано 390 | ПодключитьСценарий("tests/fixtures/ПростойОбъект.os", "ПростойОбъект"); 391 | КаталогБД = "./tests/jsondatabase"; 392 | ФС.ОбеспечитьПустойКаталог(КаталогБД); 393 | ТипКоннектора = "КоннекторJSON"; 394 | МенеджерСущностей = Новый МенеджерСущностей(Тип(ТипКоннектора), КаталогБД); 395 | МенеджерСущностей.ДобавитьКлассВМодель(Тип("ПростойОбъект")); 396 | МенеджерСущностей.Инициализировать(); 397 | 398 | // Когда 399 | 400 | ХранилищеПростойОбъект = МенеджерСущностей.ПолучитьХранилищеСущностей(Тип("ПростойОбъект")); 401 | 402 | ПростойОбъект = ХранилищеПростойОбъект.СоздатьЭлемент(); 403 | ПростойОбъект.Идентификатор = "1"; 404 | ПростойОбъект.Поле = "2"; 405 | ПростойОбъект.Сохранить(); 406 | 407 | // Тогда 408 | НайденныйПростойОбъект = ХранилищеПростойОбъект.ПолучитьОдно("1"); 409 | 410 | Ожидаем.Что(НайденныйПростойОбъект).Не_().Равно(Неопределено); 411 | Ожидаем.Что(НайденныйПростойОбъект.Идентификатор).Равно("1"); 412 | Ожидаем.Что(НайденныйПростойОбъект.Поле).Равно("2"); 413 | 414 | КонецПроцедуры 415 | 416 | &Тест 417 | Процедура СортировкаПоДвумКолонкам() Экспорт 418 | 419 | // Дано 420 | МодельДанных = Новый МодельДанных(); 421 | ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок")); 422 | Коннектор.ИнициализироватьТаблицу(ОбъектМодели); 423 | 424 | Сущность1 = Новый СущностьСоВсемиТипамиКолонок; 425 | Сущность1.Целое = 1; 426 | Сущность1.ДатаВремя = Дата(2018, 1, 1, 0, 0, 0); 427 | Коннектор.Сохранить(ОбъектМодели, Сущность1); 428 | 429 | Сущность2 = Новый СущностьСоВсемиТипамиКолонок; 430 | Сущность2.Целое = 2; 431 | Сущность2.ДатаВремя = Дата(2018, 1, 1, 0, 0, 0); 432 | Коннектор.Сохранить(ОбъектМодели, Сущность2); 433 | 434 | Сущность3 = Новый СущностьСоВсемиТипамиКолонок; 435 | Сущность3.Целое = 3; 436 | Сущность3.ДатаВремя = Дата(2019, 1, 1, 0, 0, 0); 437 | Коннектор.Сохранить(ОбъектМодели, Сущность3); 438 | 439 | // Когда 440 | ОпцииПоиска = Новый ОпцииПоиска(); 441 | ОпцииПоиска 442 | .СортироватьПо("ДатаВремя", НаправлениеСортировки.Возр) 443 | .СортироватьПо("Целое", НаправлениеСортировки.Убыв); 444 | 445 | НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, ОпцииПоиска); 446 | 447 | // Тогда 448 | Ожидаем.Что(НайденныеСтроки, "Все строки получены").ИмеетДлину(3); 449 | Ожидаем.Что(НайденныеСтроки[0].Получить("Целое"), "Строки отсортированы по полю").Равно(2); 450 | Ожидаем.Что(НайденныеСтроки[1].Получить("Целое"), "Строки отсортированы по полю").Равно(1); 451 | Ожидаем.Что(НайденныеСтроки[2].Получить("Целое"), "Строки отсортированы по полю").Равно(3); 452 | 453 | КонецПроцедуры 454 | --------------------------------------------------------------------------------