1
0
forked from BRT/arc
arc/docs/database.md

80 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# База данных — схема и миграции
SQLite-база, путь задаётся в `config.ini` (`db/dbPath`). Управляется через `DatabaseManager` (singleton) + DAO-слой.
---
## Инициализация схемы
При каждом запуске приложения вызывается `DatabaseManager::initSchema()` (`database/DatabaseManager.cpp`).
Именно здесь происходят все миграции — до открытия главного окна.
При **обновлении из меню** приложение скачивает новый `.exe`, применяет его и перезапускается, поэтому `initSchema()` тоже выполняется заново на новой версии.
---
## Что применяется автоматически при обновлении
| Изменение | Применяется? | Как |
|-----------|-------------|-----|
| Новая таблица | Да | `CREATE TABLE IF NOT EXISTS` |
| Новая колонка | Да | `ALTER TABLE ... ADD COLUMN` |
| Удаление таблицы | Да | `DROP TABLE IF EXISTS` |
| Удаление колонки | Нет | SQLite не поддерживает |
| Переименование колонки | Нет | Нужна пересборка таблицы |
| Изменение типа колонки | Нет | Нужна пересборка таблицы |
| Изменение DEFAULT у существующей колонки | Нет | `CREATE TABLE IF NOT EXISTS` не выполняется повторно |
---
## Паттерн добавления колонки
```cpp
// 1. Добавить колонку в CREATE TABLE IF NOT EXISTS (для новых установок)
q.exec(R"(CREATE TABLE IF NOT EXISTS my_table (
...
new_col TEXT DEFAULT ''
))");
// 2. Добавить ALTER TABLE для существующих БД (ошибка "column already exists" игнорируется)
q.exec("ALTER TABLE my_table ADD COLUMN new_col TEXT DEFAULT ''");
```
Оба шага обязательны: `CREATE TABLE` покрывает свежие установки, `ALTER TABLE` — обновление существующей БД.
---
## Сложные миграции (изменение типа, переименование)
Для изменений, которые SQLite не поддерживает напрямую, используется ручная миграция с пересозданием таблицы и `PRAGMA user_version` для версионирования:
```cpp
QSqlQuery q(db);
q.exec("PRAGMA user_version");
q.next();
int version = q.value(0).toInt();
if (version < 2) {
// пересоздаём таблицу
q.exec("ALTER TABLE my_table RENAME TO my_table_old");
q.exec("CREATE TABLE my_table (...)");
q.exec("INSERT INTO my_table SELECT ... FROM my_table_old");
q.exec("DROP TABLE my_table_old");
q.exec("PRAGMA user_version = 2");
}
```
---
## Таблицы
| Таблица | Описание |
|---------|----------|
| `devices` | Android-устройства, подключённые по ADB |
| `bank_profiles` | Банковские профили (приложение + устройство) |
| `materials` | Карты/счета профиля |
| `transactions` | Транзакции по картам |
| `events` | Задачи из очереди API |
| `banks` | Справочник банков (alias, name, nspk_name) |
| `general_logs` | Общий лог приложения |
| `settings` | Настройки key-value |