Назначение

pgmig - postgresql database migrations

pgmig - это инструмент для управления изменениями схемы БД postgresql, который добавляет изменениям следующие возможности

  • изменения выполняются в одной транзакции загрузкой исходного кода из файлов в алфавитном порядке их имен
  • имена файлов с хранимым кодом и его тестами имеют заданную маску и они выполняются при любом изменении
  • для отката от версии Б к версии А достаточно иметь содержимое БД (версии Б) и исходники версии А
  • номер версии БД определяется по git-атрибутам загружаемого исходного кода
  • история изменений схемы данных и хранимого кода контролируется git

Варианты изменения схемы БД

Обновление (up)

Загрузка в БД изменений и компиляция хранимого кода.

В корневом каталоге и каждом подкаталоге, для каждого файла с маской *.sql

  • если соответствует маске --code_mask - загрузить
  • иначе - проверить наличие файла в БД
    • если нет - загрузить и сохранить в БД контрольную сумму
    • если контрольная сумма совпадает - пропустить
    • иначе - прекратить работу с ошибкой

Дополнения

  • кроме контрольной суммы, для каждого файла в БД сохраняется номер текущей версии каталога (по данным git).
  • корневой каталог для загружаемых файлов задается аргументом --dir.
  • подкаталоги и файлы просматриваются в алфавитном порядке
  • подкаталоги и файлы, имена которых начинаются с точки, игнорируются.
  • если задан аргумент --down-delimiter, часть файла, идущая после его значения, не выполняется, а используется как аргумент функции pgmig.down (для совместимости с goose)

Откат (down)

В терминах pgmig, откат означает отмену обновлений, сделанных после текущей версии, и выполняется так:

  • для всех загруженных в БД файлов с версией больше текущей (в обратном алфавитному порядке) выполнить блок отката
  • по завершении обработки каталога выполнить все соответствующие ему файлы по маске --code_mask

Блоки отката

Размещаются в .sql файлах и содержат команды, отменяющие содержащиеся в них изменения схемы БД.

Пример блока отката:

1
2
3
4
SELECT pgmig.down($_$
   drop index yy;
   drop table xx;
$_$);

Такой вариант позволяет выполнить файл с помощью psql без изменений.

Загрузка текущей версии (build)

Команда представляет собой обновление до текущей версии с её предварительным откатом, предназначена для поддержки процесса разработки и включает следующее:

  • выполнить блоки отката для всех файлов с именем, которое в алфавитном порядке идет после заданного аргументом --target (по умолчанию: 10_schema.sql)
  • выполненить обновление.

Дополнения

  • если версия БД новее версии файлов, выполнение завершается с ошибкой
  • специальные значения аргумента --target
    • last - выполняется только блок отката последнего файла
    • all - блоки отката выполняются для всех файлов в каталоге
    • reset - блоки отката выполняются для всех файлов в каталоге, обновление не выполняется

Другие команды

  • code - выполнить файлы, заданные --code-mask
  • status - вывести реестр загруженных в БД файлов
  • version - вывести версию pgmig

Опции

  • --cmd - команда миграции (если не задано иначе)
  • --dir - каталог, где лежат пакеты
  • --pkg - список пакетов (если не задано - совпадает со списком подкаталогов)
  • --exclude - список игнорируемых пакетов
  • --code_mask - шаблон имени файла с кодом (по умолчанию: *.code.sql)
  • --down-delimiter - разделитель для блока отката
  • --target - целевой файл отката для команды build
  • --version - источник версии файлов в каталоге
  • --verbose - выводить отладочную информацию
  • --nocommit - не выполнять коммит по завершении (exitstatus вернет наличие ошибок)
  • --json - форматировать вывод как список json

Переменные

Перед загрузкой файла в БД и перед выполнением блока отката, в БД устанавливаются значения переменных, доступные через вызовы функций:

  • pgmig.var_file() - имя файла
  • pgmig.var_path() - путь к файлу
  • pgmig.var_version() - версия каталога

Дополнения

Код возврата

Миграция прерывается при одном из условий

  • 01 - ошибка в параметрах конфигурации
  • 02 - команда не входит в число поддерживаемых
  • 03 - команда не входит в число поддерживаемых
  • 04 - после обработки всех файлов каталога зафиксирована ошибка в тестах
  • 05 - при обработке файла зафиксирована ошибка выполнения SQL
  • 06 - попытка выполнить build при версии БД больше текущей

Версии БД

При выполнении миграций используется номер текущей версии. Он может быть свой для каждого каталога и определяется аргументом --version

Специальные значения аргумента --version

  • git - взять версию из .gitinfo (если есть) или метаданных git-репозитория (иначе)
  • gitinfo - взять версию из .gitinfo
  • prefix - взять версию из префикса файла

Если источником задан git, номер текущей версии берется из метаданных git-репозитория, которые могут быть привязаны к текущему каталогу или его предку.

SQL-код поддержки pgmig

  • Дополнение БД сервисным хранимым кодом для документирования, тестов и разграничения доступа

  • pgmig.down - регистрация блока отката

  • pgmig.extra - регистрация запросов вне транзакций

Запросы вне транзакций

Если при выполнении миграции возникает необходимость выполнить SQL-запросы вне транзакции (например CREATE INDEX CONCURRENTLY), код этих запросов регистрируется при обновлении вызовом pgmig.extra(sql) и выполняется в отдельной горутине после выполнения COMMIT.

Параллельные миграции

В текущей версии параддельные миграции не поддерживаются. В начале работы ставится эксключивный лок до завершения

Структура проекта pgmig

  • / - golang-пакет для встраивания в приложения
  • /cmd/pgmig - приложение для управления изменениями (docker)
  • /sql - SQL-код поддержки pgmig (поддерживает встраивание как pgmig/pgmigsql)