заведён канон общих конвенций для личных проектов
- 13 конвенций по осям arch / lang / stack / common; репозитории берут оттуда копии в свой docs/conventions/ и коммитят их у себя - conv — синхронизация копий: add / status / diff / pull / push, локальные регионы исключены из сравнения, поэтому расхождение не даёт шума
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
---
|
||||
status: рекомендуемая
|
||||
---
|
||||
|
||||
# Схема и миграции (SQLite, Go)
|
||||
|
||||
Область действия — **новые миграции**. Существующая схема не переписывается;
|
||||
линтер проверяет то, что добавляется, а не то, что уже лежит.
|
||||
|
||||
## Миграции
|
||||
|
||||
- Инструмент — goose, файлы миграций лежат рядом со store-слоем.
|
||||
- **SQL-файл** для DDL: создание таблиц, индексы, изменение структуры.
|
||||
- **Go-миграция** (`goose.AddMigrationContext`) — когда нужен код:
|
||||
генерация идентификаторов, backfill, перенос данных между формами.
|
||||
Не пытаемся выразить это SQL-ом ради единообразия.
|
||||
- **В деплое движение только вперёд.** Down-миграция — инструмент
|
||||
разработки, а не отката на сервере.
|
||||
- **Down пишется, когда он честно обращает up**: убрать то, что up добавил.
|
||||
Не пишется, когда up необратимо трансформирует данные, — тогда его
|
||||
отсутствие честнее имитации, которая молча теряет колонку.
|
||||
- При изменении структуры ER-схема в спеках обновляется **в том же
|
||||
изменении**, а не «потом»: разошедшаяся схема хуже отсутствующей.
|
||||
|
||||
## Типы колонок
|
||||
|
||||
- **Enum-поля** (`state`, `kind`, …) — обычный `TEXT` **без `CHECK`**.
|
||||
Допустимые значения держит код. `ALTER TABLE` в SQLite не умеет менять
|
||||
ограничения ни в одной версии, поэтому каждое новое значение в
|
||||
`CHECK(... IN (...))` означает пересоздание таблицы по 12-шаговой
|
||||
процедуре; защита от невалидного значения всё равно нужна на уровне типов
|
||||
Go.
|
||||
- **Метки времени** — `TEXT` в формате из `arch/time.md`. Без
|
||||
`DEFAULT (datetime('now'))`: помимо того, что время ставит приложение,
|
||||
эта функция даёт `YYYY-MM-DD HH:MM:SS` — без `T` и без `Z`, то есть не
|
||||
тот формат.
|
||||
- **Булевы** — `INTEGER` 0/1. Отдельного типа в SQLite нет, а строка
|
||||
`'true'` в булевом контексте приводится к **0** — то есть тихо
|
||||
инвертирует смысл, а не просто ломает фильтрацию.
|
||||
- **Первичные ключи** — если репозиторий взял `arch/db-identifiers.md`, то
|
||||
по ней (без `AUTOINCREMENT`); иначе автоинкремент допустим.
|
||||
|
||||
<!-- local:механизировано -->
|
||||
<!-- /local -->
|
||||
|
||||
<!-- local:отступления -->
|
||||
<!-- /local -->
|
||||
|
||||
## Связано
|
||||
|
||||
- `arch/time.md` — формат меток времени.
|
||||
- `arch/db-identifiers.md` — выбор первичных ключей.
|
||||
- `lang/go/errors.md` — граничные ошибки `database/sql` транслируются в
|
||||
доменные у источника, в слое store.
|
||||
|
||||
<!-- local:связано -->
|
||||
<!-- /local -->
|
||||
Reference in New Issue
Block a user