Closed roman-bodavskiy closed 3 weeks ago
Я нашел у тебя пункт по поводу миграций
Before starting the server, please set the cCreateAndFillTable parameter in the /config/db.cfg configuration file as follows::
"cCreateAndFillTable": []
Во первых не очень понятный формат в виде пустого списка []
, это скорей всего так FromJSON
инстанс работает не очень корректно. Лучше уже использовать True/False
Но главное вот:
whenMakeTables config $
Logger.writeLog "Create and fill tables in the database"
>> BB.makeAndFillTables (connectionString config)
whenMakeTables :: (Applicative f) => ConfigDataBase -> f () -> f ()
whenMakeTables = when . isJust . cCreateAndFillTable
Твои миграции удаляют и создают таблицы заново, то есть если мы применяем их к проекту в продакшне. то мы потеряем все данные
Во первых не очень понятный формат в виде пустого списка [], это скорей всего так FromJSON инстанс работает не очень корректно. Лучше уже использовать True/False
Тут я как раз пытался избежать True/False, используя более богатую систему типов. Навеяно "Boolean blindness" (например, https://runtimeverification.com/blog/code-smell-boolean-blindness )
data ConfigDataBase = MkConfigDataBase
{ cHostDB :: T.Text,
cPortDB :: T.Text,
cUserDB :: T.Text,
cNameDB :: T.Text,
cPasswordDB :: T.Text,
cLimitData :: Int,
cPortServer :: Int,
cLogLvl :: Log,
cCreateAndFillTable :: Maybe DoIt
}
deriving stock (Show, Generic)
deriving anyclass (ToJSON, FromJSON)
data DoIt = DoIt
deriving stock (Show, Generic)
deriving anyclass (ToJSON, FromJSON)
Твои миграции удаляют и создают таблицы заново, то есть если мы применяем их к проекту в продакшне. то мы потеряем все данные
Да. Так удобно было все тестировать. Но ведь в документации написано, чтобы миграцию запустили один раз, а далее изменили конфиг, чтобы такого не произошло. Я могу просто убрать удаление таблиц и оставить наполнение, - это будет правильное решение? Или надо что-то иное?
Но она удаляет все таблицы и создает их заново. А как добавить столбец к существующей таблице, не потеряв данные?
Мне нужно написать дополнительную функцию, которая добавляет столбец к существующей таблице? Тут я не до конца понимаю задачу.
Тут я как раз пытался избежать True/False, используя более богатую систему типов. Навеяно "Boolean blindness" (например, https://runtimeverification.com/blog/code-smell-boolean-blindness )
Да, это я понял, но в конфиге у тебя это отбражается как пустой список, что не очень понятно "cCreateAndFillTable": []
Нужно либо добавить второй конструктор DoIt = DoIt | Skip
, либо подправить инстанс, чтобы этот тип корректно отображался
Мне нужно написать дополнительную функцию, которая добавляет столбец к существующей таблице? Тут я не до конца понимаю задачу.
Ну типа того. Миграции это что-то типа системы контроля версий для базы данных. Допустим у тебя проект уже в продакшне и есть несколько тестовых юзеров user1
, user2
, user3
, которых ты задал в своей миграции, и еще несколько реальных юзеров: Вася, Петя, Катя. Мы хотим добавить столбец lastName
в таблицу User
, и для всех существующих пользователей сделать его таким же как и name
. Твоя миграция очевидно для этих целей не подходит, так как она удаляет все таблицы и создает их заново. То есть реальные юзеры Вася, Петя, Катя будут стерты.Она подходит только для начальной инициализации базы данных с нуля
Обычно миграции это пронумерованные sql файлы
Например мы можем в первом файле добавить столбец к нашей таблице, а во втором сделать lastName
таким же как и name
. Можно поместить конечно и в один файл, это просто пример того, что в миграциях важен порядок файлов, мы не можем обновить столбец раньше чем его создали
migrations/0001-user-last-name-create-column.sql
migrations/0002-update-user-last-name.sql
...
При запуске команды, мы проверяем проверяем папку migrations
, допустим мы находим пять миграций. Проверяем, какие из них уже были применены ранее (для этого можно создать отдельную таблицу с номером миграции). Допустим были применены ранее 3 миграции, тогда мы применяем только 4 и 5. Если были применены уже 5 миграций, то вообще ничего не делаем. Таким образом мы добавили новый столбец, обновили его, и все наши юзеры на месте, никакие данные не потеряны.
Можно конечно миграции написать и на хаскеле, а не в sql файле, это не считается ошибкой, но sql проще как по мне. На хаскеле должна быть написана сама команда, которая их применяет, то есть считывает файлы, считывает текущий номер миграций, и применяет оставшиеся миграции если надо
Да. Так удобно было все тестировать. Но ведь в документации написано, чтобы миграцию запустили один раз, а далее изменили конфиг, чтобы такого не произошло. Я могу просто убрать удаление таблиц и оставить наполнение, - это будет правильное решение? Или надо что-то иное?
Можно оставить, это можно использовать для инициализации базы данных, и для процесса разработки, но для продакшна нужно добавить команду которую я описал выше. Ты же не будешь каждый раз удалять и создавать таблицы в продакшне когда нужно добавить один столбец
Вообще как правило для заполнения БД тестовыми данными используются sql файлы, но в принципе можно прописать данные и в хаскеле, это ошибкой не считается. Но это все должно быть оформлено в виде миграций. Допустим, мы хотим добавить столбец
lastName
в таблицуUser
, и для всех существующих пользователей сделать его таким же как иname
. Для этого должна быть простая миграция и простой способ ее применитьВ твоей структуре есть функция
makeAndFillTables
Но она удаляет все таблицы и создает их заново. А как добавить столбец к существующей таблице, не потеряв данные?