diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index ca370ac..98310cc 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -16,10 +16,10 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
oscript_version: ['1.8.3', 'stable']
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Setup Onescript Action
- uses: otymko/setup-onescript@v1.1
+ uses: otymko/setup-onescript@v1.4
with:
version: ${{ matrix.oscript_version }}
@@ -28,22 +28,26 @@ jobs:
opm install opm@1.0.2
opm install -l --dev
+ - name: Prepare macOS env
+ if: matrix.os == 'macos-latest'
+ run: |
+ echo "SIGN_QEMU_BINARY=1" >> "$GITHUB_ENV"
+
- name: Install docker
- if: matrix.os != 'windows-latest'
- uses: crazy-max/ghaction-setup-docker@v1
+ uses: crazy-max/ghaction-setup-docker@v3
timeout-minutes: 12
- name: Setup PostgreSQL
- if: matrix.os != 'windows-latest'
+ shell: bash
run: |
- 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
+ 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
docker ps
while [ "`docker inspect -f {{.State.Health.Status}} postgres`" != "healthy" ]; do docker ps && sleep 2; done
docker ps
- name: Run tests
env:
- TESTRUNNER_RUN_POSTGRES_TESTS: "${{ matrix.os != 'windows-latest' }}"
+ TESTRUNNER_RUN_POSTGRES_TESTS: true
TESTRUNNER_RUN_SQLITE_TESTS: "${{ matrix.os == 'windows-latest' }}"
run: |
oscript ./tasks/test.os
diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml
index a409178..50dd9cc 100644
--- a/.github/workflows/qa.yml
+++ b/.github/workflows/qa.yml
@@ -9,13 +9,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
# Disabling shallow clone is recommended for improving relevancy of reporting
fetch-depth: 0
- name: Setup Onescript Action
- uses: otymko/setup-onescript@v1.1
+ uses: otymko/setup-onescript@v1.4
with:
version: "1.8.3"
@@ -25,7 +25,7 @@ jobs:
opm install -l --dev
- name: Install docker
- uses: crazy-max/ghaction-setup-docker@v1
+ uses: crazy-max/ghaction-setup-docker@v3
timeout-minutes: 12
- name: Setup PostgreSQL
@@ -50,28 +50,30 @@ jobs:
run: |
oscript ./tasks/coverage.os
- - name: SonarCloud Scan on push
- if: github.repository == 'nixel2007/entity' && github.event_name == 'push'
- uses: nixel2007/sonarcloud-github-action@v1.5
+ - name: Setup sonarqube
+ uses: warchant/setup-sonar-scanner@v8
+
+ # Анализ проекта в SonarQube (ветка)
+ - name: Анализ в SonarQube (branch)
+ if: github.event_name == 'push'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- with:
- args: >
- -Dsonar.host.url=https://sonar.openbsl.ru
- -Dsonar.branch.name=${{ env.BRANCH_NAME }}
- -Dsonar.projectVersion=${{ steps.extract_version.outputs.version }}
-
- - name: SonarCloud Scan on PR
- if: github.repository == 'nixel2007/entity' && github.event_name == 'pull_request'
- uses: nixel2007/sonarcloud-github-action@v1.5
+ run: sonar-scanner
+ -Dsonar.host.url=https://sonar.openbsl.ru
+ -Dsonar.branch.name=${{ env.BRANCH_NAME }}
+ -Dsonar.projectVersion=${{ steps.extract_version.outputs.version }}
+
+ # Анализ проекта в SonarQube (PR)
+ # https://docs.sonarqube.org/latest/analysis/pull-request/
+ - name: Анализ в SonarQube (pull-request)
+ if: github.event_name == 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- with:
- args: >
- -Dsonar.host.url=https://sonar.openbsl.ru
- -Dsonar.pullrequest.key=${{ github.event.pull_request.number }}
- -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }}
- -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }}
- -Dsonar.scm.revision=${{ github.event.pull_request.head.sha }}
+ run: sonar-scanner
+ -Dsonar.host.url=https://sonar.openbsl.ru
+ -Dsonar.pullrequest.key=${{ github.event.pull_request.number }}
+ -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }}
+ -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }}
+ -Dsonar.scm.revision=${{ github.event.pull_request.head.sha }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 8299db5..32a5876 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,11 +23,11 @@ jobs:
steps:
# Загрузка проекта
- name: Актуализация
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
# Установка OneScript конкретной версии
- name: Установка OneScript
- uses: otymko/setup-onescript@v1.1
+ uses: otymko/setup-onescript@v1.4
with:
version: ${{ matrix.oscript_version }}
@@ -41,7 +41,7 @@ jobs:
run: opm build .
- name: Заливка артефактов
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: package.zip
path: ./${{ env.PACKAGE_MASK }}
diff --git a/README.md b/README.md
index 54db276..c2f7424 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,7 @@
* КоннекторSQLite
* КоннекторPostgreSQL
* КоннекторJSON
+ * КоннекторInMemory
* Версионирование и обратная совместимость
@@ -522,6 +523,16 @@
Все операциями по записи и удалению сущностей одного типа проводятся **синхронно**, блокируя файл таблицы целиком. Для контроля над синхронным доступом используется библиотека [semaphore](https://github.com/nixel2007/semaphore).
+
+
+### КоннекторInMemory
+
+В состав библиотеки входит референсная реализация интерфейса коннектора в виде упрощенного коннектора к виртуальной базе данных в памяти. База данных состоит из соответствия, где ключ - имя таблицы модели данных, значение таблицы.
+
+В качестве строки соединения произвольная строка, которая будет являться разделителем данных.
+
+Коннектор поддерживает все CRUD-операции над сущностями, простой и сложный поиск, но не поддерживает работу с транзакциями. При вызове операций по работе с транзакциями будут выданы исключения.
+
## Версионирование и обратная совместимость
diff --git a/lib.config b/lib.config
index cc868f2..efbf7b1 100644
--- a/lib.config
+++ b/lib.config
@@ -9,6 +9,7 @@
+
diff --git a/packagedef b/packagedef
index 493da64..88f41cc 100644
--- a/packagedef
+++ b/packagedef
@@ -4,7 +4,7 @@
//
// BSLLS:CodeOutOfRegion-off
Описание.Имя("entity")
- .Версия("2.3.5.0")
+ .Версия("2.3.6.0")
.Автор("Nikita Gryzlov")
.АдресАвтора("nixel2007@gmail.com")
.Описание("entity")
diff --git "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\245\321\200\320\260\320\275\320\270\320\273\320\270\321\211\320\265\320\222\320\237\320\260\320\274\321\217\321\202\320\270.os" "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\245\321\200\320\260\320\275\320\270\320\273\320\270\321\211\320\265\320\222\320\237\320\260\320\274\321\217\321\202\320\270.os"
new file mode 100644
index 0000000..afa3cd9
--- /dev/null
+++ "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\245\321\200\320\260\320\275\320\270\320\273\320\270\321\211\320\265\320\222\320\237\320\260\320\274\321\217\321\202\320\270.os"
@@ -0,0 +1,24 @@
+
+Перем КешиТаблиц;
+
+Функция КешТаблиц(СтрокаПодключения = "default") Экспорт
+ Результат = КешиТаблиц.Получить(СтрокаПодключения);
+
+ Если Результат = Неопределено Тогда
+ Результат = Новый Соответствие();
+ КешиТаблиц.Вставить(СтрокаПодключения, Результат);
+ КонецЕсли;
+
+ Возврат Результат;
+
+КонецФункции
+
+Процедура Очистить(СтрокаПодключения = "default") Экспорт
+ КешиТаблиц.Вставить(СтрокаПодключения, Новый Соответствие());
+КонецПроцедуры
+
+Процедура Инициализация()
+ КешиТаблиц = Новый Соответствие();
+КонецПроцедуры
+
+Инициализация();
\ No newline at end of file
diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200InMemory.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200InMemory.os"
new file mode 100644
index 0000000..8c18847
--- /dev/null
+++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200InMemory.os"
@@ -0,0 +1,261 @@
+#Использовать "../internal"
+
+// Для хранения статуса соединения
+Перем Открыт;
+Перем КешТаблиц;
+Перем Рефлектор;
+
+// Конструктор объекта АбстрактныйКоннектор.
+//
+Процедура ПриСозданииОбъекта()
+ Открыт = Ложь;
+ Рефлектор = Новый Рефлектор;
+КонецПроцедуры
+
+// Открыть соединение с БД.
+//
+// Параметры:
+// СтрокаСоединения - Строка - Строка соединения с БД.
+// ПараметрыКоннектора - Массив - Дополнительные параметры инициализации коннектора.
+//
+Процедура Открыть(СтрокаСоединения, ПараметрыКоннектора) Экспорт
+ КешТаблиц = ХранилищеВПамяти.КешТаблиц(СтрокаСоединения);
+ Открыт = Истина;
+КонецПроцедуры
+
+// Закрыть соединение с БД.
+//
+Процедура Закрыть() Экспорт
+ Открыт = Ложь;
+КонецПроцедуры
+
+// Получить статус соединения с БД.
+//
+// Возвращаемое значение:
+// Булево - Состояние соединения. Истина, если соединение установлено и готово к использованию.
+// В обратном случае - Ложь.
+//
+Функция Открыт() Экспорт
+ Возврат Открыт;
+КонецФункции
+
+// Начинает новую транзакцию в БД.
+//
+Процедура НачатьТранзакцию() Экспорт
+ ВызватьИсключение "Не поддерживается";
+КонецПроцедуры
+
+// Фиксирует открытую транзакцию в БД.
+//
+Процедура ЗафиксироватьТранзакцию() Экспорт
+ ВызватьИсключение "Не поддерживается";
+КонецПроцедуры
+
+// Отменяет открытую транзакцию в БД.
+//
+Процедура ОтменитьТранзакцию() Экспорт
+ ВызватьИсключение "Не поддерживается";
+КонецПроцедуры
+
+// Создает таблицу в БД по данным модели.
+//
+// Параметры:
+// ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД.
+//
+Процедура ИнициализироватьТаблицу(ОбъектМодели) Экспорт
+ ИмяТаблицы = ОбъектМодели.ИмяТаблицы();
+
+ Если КешТаблиц.Получить(ИмяТаблицы) = Неопределено Тогда
+ Таблица = Новый ТаблицаЗначений();
+
+ Таблица.Колонки.Добавить("_Идентификатор");
+ Таблица.Колонки.Добавить("_Сущность");
+
+ Таблица.Индексы.Добавить("_Идентификатор");
+
+ КешТаблиц.Вставить(ИмяТаблицы, Таблица);
+ КонецЕсли;
+
+КонецПроцедуры
+
+// Сохраняет сущность в БД.
+//
+// Параметры:
+// ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД.
+// Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для сохранения в БД.
+//
+Процедура Сохранить(ОбъектМодели, Сущность) Экспорт
+
+ ИмяТаблицы = ОбъектМодели.ИмяТаблицы();
+
+ Таблица = КешТаблиц.Получить(ИмяТаблицы);
+
+ Если Таблица = Неопределено Тогда
+ ВызватьИсключение "Таблица " + ИмяТаблицы + " не найдена";
+ КонецЕсли;
+
+ Идентификатор = ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность);
+ Если НЕ ЗначениеЗаполнено(Идентификатор) Тогда
+
+ Если ОбъектМодели.Идентификатор().ТипКолонки <> ТипыКолонок.Целое Тогда
+ Сообщение = СтрШаблон(
+ "Ошибка при сохранении сущности с типом %1.
+ |Генерация идентификаторов поддерживается только для колонок с типом ""Целое""",
+ ОбъектМодели.ТипСущности()
+ );
+ ВызватьИсключение Сообщение;
+ КонецЕсли;
+
+ МаксимальныйИдентификатор = ПроцессорыКоллекций.ИзКоллекции(Таблица)
+ .Обработать("Результат = Число(Элемент._Идентификатор)")
+ .Максимум();
+
+ Если МаксимальныйИдентификатор = Неопределено Тогда
+ МаксимальныйИдентификатор = 0;
+ КонецЕсли;
+
+ Идентификатор = МаксимальныйИдентификатор + 1;
+
+ ОбъектМодели.УстановитьЗначениеКолонкиВПоле(
+ Сущность,
+ ОбъектМодели.Идентификатор().ИмяКолонки,
+ Идентификатор
+ );
+
+ КонецЕсли;
+ Если ТипЗнч(Идентификатор) = Тип("Число") Тогда
+ Идентификатор = Формат(Идентификатор, "ЧГ=");
+ КонецЕсли;
+
+ СтрокаТЗ = Таблица.Найти(Идентификатор, "_Идентификатор");
+
+ Если СтрокаТЗ = Неопределено Тогда
+ СтрокаТЗ = Таблица.Добавить();
+ КонецЕсли;
+
+ СущностьВБД = Новый (ОбъектМодели.ТипСущности());
+
+ Для Каждого Колонка Из ОбъектМодели.Колонки() Цикл
+ Значение = ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(
+ Сущность,
+ Колонка.ИмяПоля);
+ Рефлектор.УстановитьСвойство(СущностьВБД, Колонка.ИмяПоля, Значение);
+ КонецЦикла;
+
+ СтрокаТЗ._Идентификатор = Идентификатор;
+ СтрокаТЗ._Сущность = СущностьВБД;
+
+КонецПроцедуры
+
+// Удаляет сущность из таблицы БД.
+//
+// Параметры:
+// ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД.
+// Сущность - Произвольный - Объект (экземпляр класса, зарегистрированного в модели) для удаления из БД.
+//
+Процедура Удалить(ОбъектМодели, Сущность) Экспорт
+
+ ИмяТаблицы = ОбъектМодели.ИмяТаблицы();
+
+ Таблица = КешТаблиц.Получить(ИмяТаблицы);
+
+ Если Таблица = Неопределено Тогда
+ ВызватьИсключение "Таблица " + ИмяТаблицы + " не найдена";
+ КонецЕсли;
+
+ Идентификатор = ОбъектМодели.ПолучитьЗначениеИдентификатора(Сущность);
+ Если ТипЗнч(Идентификатор) = Тип("Число") Тогда
+ Идентификатор = Формат(Идентификатор, "ЧГ=");
+ КонецЕсли;
+
+ СтрокаТЗ = Таблица.Найти(Идентификатор, "_Идентификатор");
+
+ Если НЕ СтрокаТЗ = Неопределено Тогда
+ Таблица.Удалить(СтрокаТЗ);
+ КонецЕсли;
+
+КонецПроцедуры
+
+// Осуществляет поиск строк в таблице по указанному отбору.
+//
+// Параметры:
+// ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД.
+// Отбор - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора".
+// Каждый элемент отбора преобразуется к условию поиска. В качестве "ПутьКДанным" указываются имена колонок.
+//
+// Возвращаемое значение:
+// Массив - Массив, элементами которого являются "Соответствия". Ключом элемента соответствия является имя колонки,
+// значением элемента соответствия - значение колонки.
+//
+Функция НайтиСтрокиВТаблице(ОбъектМодели, Отбор = Неопределено) Экспорт
+
+ ИмяТаблицы = ОбъектМодели.ИмяТаблицы();
+
+ Таблица = КешТаблиц.Получить(ИмяТаблицы);
+
+ Если Таблица = Неопределено Тогда
+ ВызватьИсключение "Таблица " + ИмяТаблицы + " не найдена";
+ КонецЕсли;
+
+ ПроцессорКоллекций = ПроцессорыКоллекций.ИзКоллекции(Таблица);
+
+ Для Каждого ЭлементОтбора Из Отбор Цикл
+ СтрокаУсловие = СтрШаблон(
+ "Результат = Элемент._Сущность.%1 %2 ДополнительныеПараметры.Значение",
+ ЭлементОтбора.ПутьКДанным,
+ ЭлементОтбора.ВидСравнения
+ );
+ ДополнительныеПараметры = Новый Структура("Значение", ЭлементОтбора.Значение);
+ ПроцессорКоллекций = ПроцессорКоллекций.Фильтровать(СтрокаУсловие, ДополнительныеПараметры);
+ КонецЦикла;
+
+ ДанныеТаблицы = ПроцессорКоллекций.ВМассив();
+
+ Результат = Новый Массив();
+
+ Колонки = ОбъектМодели.Колонки();
+
+ Для Каждого СтрокаДанныхТаблицы Из ДанныеТаблицы Цикл
+ ЗначенияКолонок = Новый Соответствие;
+ Для Каждого Колонка Из Колонки Цикл
+ Значение = Рефлектор.ПолучитьСвойство(СтрокаДанныхТаблицы._Сущность, Колонка.ИмяПоля);
+ ЗначенияКолонок.Вставить(Колонка.ИмяКолонки, Значение);
+ КонецЦикла;
+ Результат.Добавить(ЗначенияКолонок);
+ КонецЦикла;
+
+ Возврат Результат;
+
+КонецФункции
+
+// Удаляет строки в таблице по указанному отбору.
+//
+// Параметры:
+// ОбъектМодели - ОбъектМодели - Объект, содержащий описание класса-сущности и настроек таблицы БД.
+// Отбор - Массив - Отбор для поиска. Каждый элемент массива должен иметь тип "ЭлементОтбора".
+// Каждый элемент отбора преобразуется к условию поиска. В качестве "ПутьКДанным" указываются имена колонок.
+//
+Процедура УдалитьСтрокиВТаблице(ОбъектМодели, Знач Отбор) Экспорт
+ СтрокиКУдалению = НайтиСтрокиВТаблице(ОбъектМодели, Отбор);
+ Если СтрокиКУдалению.Количество() > 0 Тогда
+
+ ИмяКлонкиИдентификатора = ОбъектМодели.Идентификатор().ИмяКолонки;
+
+ ИмяТаблицы = ОбъектМодели.ИмяТаблицы();
+ Таблица = КешТаблиц.Получить(ИмяТаблицы);
+
+ Для Каждого СтрокаКУдалению Из СтрокиКУдалению Цикл
+ Идентификатор = СтрокаКУдалению.Получить(ИмяКлонкиИдентификатора);
+ Если ТипЗнч(Идентификатор) = Тип("Число") Тогда
+ Идентификатор = Формат(Идентификатор, "ЧГ=");
+ КонецЕсли;
+
+ СтрокаТЗ = Таблица.Найти(Идентификатор, "_Идентификатор");
+
+ Если НЕ СтрокаТЗ = Неопределено Тогда
+ Таблица.Удалить(СтрокаТЗ);
+ КонецЕсли;
+ КонецЦикла;
+
+ КонецЕсли;
+КонецПроцедуры
\ No newline at end of file
diff --git "a/tests/\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200InMemory.os" "b/tests/\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200InMemory.os"
new file mode 100644
index 0000000..28e872f
--- /dev/null
+++ "b/tests/\320\232\320\276\320\275\320\275\320\265\320\272\321\202\320\276\321\200InMemory.os"
@@ -0,0 +1,232 @@
+#Использовать fs
+#Использовать ".."
+
+Перем Коннектор;
+Перем СтрокаСоединения;
+
+Процедура ПередЗапускомТеста() Экспорт
+ ХранилищеВПамяти.Очистить();
+ ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "СущностьСоВсемиТипамиКолонок.os"), "СущностьСоВсемиТипамиКолонок");
+ ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "АвтоинкрементныйКлючБезКолонок.os"), "АвтоинкрементныйКлючБезКолонок");
+
+ Коннектор = Новый КоннекторInMemory();
+ Коннектор.Открыть(СтрокаСоединения, Новый Массив);
+КонецПроцедуры
+
+Процедура ПослеЗапускаТеста() Экспорт
+ Коннектор.Закрыть();
+КонецПроцедуры
+
+&Тест
+Процедура КоннекторInMemoryРеализуетИнтерфейсКоннектора() Экспорт
+ ИнтерфейсОбъекта = Новый ИнтерфейсОбъекта();
+ ИнтерфейсОбъекта.ИзОбъекта(Тип("АбстрактныйКоннектор"));
+
+ РефлекторОбъекта = Новый РефлекторОбъекта(Тип("КоннекторInMemory"));
+ РефлекторОбъекта.РеализуетИнтерфейс(ИнтерфейсОбъекта, Истина);
+КонецПроцедуры
+
+&Тест
+Процедура НайтиСтрокиВТаблице() Экспорт
+ МодельДанных = Новый МодельДанных();
+ ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок"));
+ Коннектор.ИнициализироватьТаблицу(ОбъектМодели);
+
+ ЗависимаяСущность = Новый СущностьСоВсемиТипамиКолонок;
+ ЗависимаяСущность.Целое = 2;
+
+ Сущность = Новый СущностьСоВсемиТипамиКолонок;
+ Сущность.Целое = 1;
+ Сущность.Дробное = 1.2;
+ Сущность.БулевоИстина = Истина;
+ Сущность.БулевоЛожь = Ложь;
+ Сущность.Строка = "Строка";
+ Сущность.Дата = Дата(2018, 1, 1);
+ Сущность.Время = Дата(1, 1, 1, 10, 53, 20);
+ Сущность.ДатаВремя = Дата(2018, 1, 1, 10, 53, 20);
+ Сущность.Ссылка = ЗависимаяСущность;
+ Сущность.ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки("ДвоичныеДанные");
+
+ Коннектор.Сохранить(ОбъектМодели, ЗависимаяСущность);
+ Коннектор.Сохранить(ОбъектМодели, Сущность);
+
+ Отбор = Новый Массив;
+ Отбор.Добавить(Новый ЭлементОтбора("Целое", ВидСравнения.Равно, Сущность.Целое));
+ НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, Отбор);
+ Ожидаем.Что(НайденныеСтроки, "Сущность сохранилась").ИмеетДлину(1);
+
+ ЗначенияКолонок = НайденныеСтроки[0];
+
+ Ожидаем.Что(ЗначенияКолонок.Получить("Целое"), "ЗначенияКолонок.Целое получено корректно").Равно(Сущность.Целое);
+ Ожидаем.Что(ЗначенияКолонок.Получить("Дробное"), "ЗначенияКолонок.Дробное получено корректно").Равно(Сущность.Дробное);
+ Ожидаем.Что(ЗначенияКолонок.Получить("БулевоИстина"), "ЗначенияКолонок.БулевоИстина получено корректно").Равно(Сущность.БулевоИстина);
+ Ожидаем.Что(ЗначенияКолонок.Получить("БулевоЛожь"), "ЗначенияКолонок.БулевоЛожь получено корректно").Равно(Сущность.БулевоЛожь);
+ Ожидаем.Что(ЗначенияКолонок.Получить("Строка"), "ЗначенияКолонок.Строка получено корректно").Равно(Сущность.Строка);
+ Ожидаем.Что(ЗначенияКолонок.Получить("Дата"), "ЗначенияКолонок.Дата получено корректно").Равно(Сущность.Дата);
+ Ожидаем.Что(ЗначенияКолонок.Получить("Время"), "ЗначенияКолонок.Время получено корректно").Равно(Сущность.Время);
+ Ожидаем.Что(ЗначенияКолонок.Получить("ДатаВремя"), "ЗначенияКолонок.ДатаВремя получено корректно").Равно(Сущность.ДатаВремя);
+ Ожидаем.Что(ЗначенияКолонок.Получить("Ссылка"), "ЗначенияКолонок.Ссылка получено корректно").Равно(Сущность.Ссылка.Целое);
+ Ожидаем.Что(ЗначенияКолонок.Получить("ДвоичныеДанные"), "ЗначенияКолонок.ДвоичныеДанные получено корректно").Равно(Сущность.ДвоичныеДанные);
+КонецПроцедуры
+
+&Тест
+Процедура УдалитьСтрокиВТаблице() Экспорт
+ МодельДанных = Новый МодельДанных();
+ ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок"));
+ Коннектор.ИнициализироватьТаблицу(ОбъектМодели);
+
+ Сущность = Новый СущностьСоВсемиТипамиКолонок;
+ Сущность.Целое = 1;
+
+ Коннектор.Сохранить(ОбъектМодели, Сущность);
+
+ Отбор = Новый Массив;
+ Отбор.Добавить(Новый ЭлементОтбора("Целое", ВидСравнения.Равно, Сущность.Целое));
+
+ Коннектор.УдалитьСтрокиВТаблице(ОбъектМодели, Отбор);
+
+ НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, Отбор);
+ Ожидаем.Что(НайденныеСтроки, "Сущность удалилась").ИмеетДлину(0);
+КонецПроцедуры
+
+&Тест
+Процедура УдалениеСущности() Экспорт
+ МодельДанных = Новый МодельДанных();
+ ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("СущностьСоВсемиТипамиКолонок"));
+ Коннектор.ИнициализироватьТаблицу(ОбъектМодели);
+
+ Сущность = Новый СущностьСоВсемиТипамиКолонок();
+ Сущность.Целое = 1;
+ Коннектор.Сохранить(ОбъектМодели, Сущность);
+
+ Коннектор.Удалить(ОбъектМодели, Сущность);
+
+ Отбор = Новый Массив;
+ Отбор.Добавить(Новый ЭлементОтбора("Целое", ВидСравнения.Равно, Сущность.Целое));
+ НайденныеСтроки = Коннектор.НайтиСтрокиВТаблице(ОбъектМодели, Отбор);
+
+ Ожидаем.Что(НайденныеСтроки, "Сущность удалилась").ИмеетДлину(0);
+
+КонецПроцедуры
+
+&Тест
+Процедура Автоинкремент() Экспорт
+ МодельДанных = Новый МодельДанных();
+ ОбъектМодели = МодельДанных.СоздатьОбъектМодели(Тип("АвтоинкрементныйКлючБезКолонок"));
+ Коннектор.ИнициализироватьТаблицу(ОбъектМодели);
+
+ Сущность = Новый АвтоинкрементныйКлючБезКолонок();
+ Коннектор.Сохранить(ОбъектМодели, Сущность);
+
+ Ожидаем.Что(Сущность.Идентификатор).Равно(1);
+
+ Сущность = Новый АвтоинкрементныйКлючБезКолонок();
+ Коннектор.Сохранить(ОбъектМодели, Сущность);
+
+ Ожидаем.Что(Сущность.Идентификатор).Равно(2);
+
+КонецПроцедуры
+
+&Тест
+Процедура СущностьМожетЗаписатьСебя() Экспорт
+ // Дано
+ ПодключитьСценарий("tests/fixtures/ПростойОбъект.os", "ПростойОбъект");
+
+ ТипКоннектора = "КоннекторInMemory";
+ МенеджерСущностей = Новый МенеджерСущностей(Тип(ТипКоннектора));
+ МенеджерСущностей.ДобавитьКлассВМодель(Тип("ПростойОбъект"));
+ МенеджерСущностей.Инициализировать();
+
+ // Когда
+ ПростойОбъект = МенеджерСущностей.СоздатьЭлемент(Тип("ПростойОбъект"));
+ ПростойОбъект.Идентификатор = "1";
+ ПростойОбъект.Поле = "2";
+ ПростойОбъект.Сохранить();
+
+ // Тогда
+ НайденныйПростойОбъект = МенеджерСущностей.ПолучитьОдно(Тип("ПростойОбъект"), "1");
+
+ Ожидаем.Что(НайденныйПростойОбъект).Не_().Равно(Неопределено);
+ Ожидаем.Что(НайденныйПростойОбъект.Идентификатор).Равно("1");
+ Ожидаем.Что(НайденныйПростойОбъект.Поле).Равно("2");
+
+КонецПроцедуры
+
+&Тест
+Процедура СущностьМожетПерезаписатьСебя() Экспорт
+ // Дано
+ ПодключитьСценарий("tests/fixtures/ПростойОбъект.os", "ПростойОбъект");
+ ТипКоннектора = "КоннекторInMemory";
+ МенеджерСущностей = Новый МенеджерСущностей(Тип(ТипКоннектора));
+ МенеджерСущностей.ДобавитьКлассВМодель(Тип("ПростойОбъект"));
+ МенеджерСущностей.Инициализировать();
+
+ // Когда
+ ПростойОбъект = МенеджерСущностей.СоздатьЭлемент(Тип("ПростойОбъект"));
+ ПростойОбъект.Идентификатор = "1";
+ ПростойОбъект.Поле = "2";
+ ПростойОбъект.Сохранить();
+ НайденныйПростойОбъект = МенеджерСущностей.ПолучитьОдно(Тип("ПростойОбъект"), "1");
+ НайденныйПростойОбъект.Поле = "3";
+ НайденныйПростойОбъект.Сохранить();
+
+ // Тогда
+ НайденныйПростойОбъект = МенеджерСущностей.ПолучитьОдно(Тип("ПростойОбъект"), "1");
+
+ Ожидаем.Что(НайденныйПростойОбъект).Не_().Равно(Неопределено);
+ Ожидаем.Что(НайденныйПростойОбъект.Идентификатор).Равно("1");
+ Ожидаем.Что(НайденныйПростойОбъект.Поле).Равно("3");
+
+КонецПроцедуры
+
+&Тест
+Процедура МенеджерСущностейМожетЗаписать() Экспорт
+ // Дано
+ ПодключитьСценарий("tests/fixtures/ПростойОбъект.os", "ПростойОбъект");
+ ТипКоннектора = "КоннекторInMemory";
+ МенеджерСущностей = Новый МенеджерСущностей(Тип(ТипКоннектора));
+ МенеджерСущностей.ДобавитьКлассВМодель(Тип("ПростойОбъект"));
+ МенеджерСущностей.Инициализировать();
+
+ // Когда
+ ПростойОбъект = МенеджерСущностей.СоздатьЭлемент(Тип("ПростойОбъект"));
+ ПростойОбъект.Идентификатор = "1";
+ ПростойОбъект.Поле = "2";
+ МенеджерСущностей.Сохранить(ПростойОбъект);
+
+ // Тогда
+ НайденныйПростойОбъект = МенеджерСущностей.ПолучитьОдно(Тип("ПростойОбъект"), "1");
+
+ Ожидаем.Что(НайденныйПростойОбъект).Не_().Равно(Неопределено);
+ Ожидаем.Что(НайденныйПростойОбъект.Идентификатор).Равно("1");
+ Ожидаем.Что(НайденныйПростойОбъект.Поле).Равно("2");
+
+КонецПроцедуры
+
+&Тест
+Процедура ХранилищеСущностейМожетЗаписать() Экспорт
+
+ // Дано
+ ПодключитьСценарий("tests/fixtures/ПростойОбъект.os", "ПростойОбъект");
+ ТипКоннектора = "КоннекторInMemory";
+ МенеджерСущностей = Новый МенеджерСущностей(Тип(ТипКоннектора));
+ МенеджерСущностей.ДобавитьКлассВМодель(Тип("ПростойОбъект"));
+ МенеджерСущностей.Инициализировать();
+
+ // Когда
+
+ ХранилищеПростойОбъект = МенеджерСущностей.ПолучитьХранилищеСущностей(Тип("ПростойОбъект"));
+
+ ПростойОбъект = ХранилищеПростойОбъект.СоздатьЭлемент();
+ ПростойОбъект.Идентификатор = "1";
+ ПростойОбъект.Поле = "2";
+ ПростойОбъект.Сохранить();
+
+ // Тогда
+ НайденныйПростойОбъект = ХранилищеПростойОбъект.ПолучитьОдно("1");
+
+ Ожидаем.Что(НайденныйПростойОбъект).Не_().Равно(Неопределено);
+ Ожидаем.Что(НайденныйПростойОбъект.Идентификатор).Равно("1");
+ Ожидаем.Что(НайденныйПростойОбъект.Поле).Равно("2");
+
+КонецПроцедуры
\ No newline at end of file