【PostgreSQL】DBスキーマの差分検出ツールmigraを使ってみた

PostgreSQLのデータベーススキーマの差分を検出するPython製のツールmigraを使ってみました。

インストール

pipでインストールできます。DB接続にはpsycopg2を使用しているので、未インストールであれば一緒にインストールする必要があります。

$ pip install migra
$ pip install psycopg2

動作確認

データベースとテーブル作成

データベースを2つ作成して差分を表示してみます。psqlでローカルのPostgreSQLに接続後に以下のDDLを実行します。

# データベースexample1を作成
$ create database example1;

# example1に接続
$ ¥c example1

# テーブル作成
$ create table price (
    id serial,
    product_id int not null,
    price numeric not null,
    updated_at timestamp with time zone not null,
    constraint pk_price primary key(id)
);

$ create table price_history (
    id serial,
    product_id int not null,
    price numeric not null,
    updated_at timestamp with time zone not null,
    constraint pk_price_history primary key(id)
);

$ ¥c postgres
# データベースexample2を作成
$ create database example2;

# example2に接続
$ ¥c example2

# priceテーブルのみ作成
$ create table price (
    id serial,
    product_id int not null,
    price numeric not null,
    updated_at timestamp with time zone not null,
    constraint pk_price primary key(id)
);

差分検出

作成したデータベースに対してmigraを実行します。1つ目の引数のデータベースから2つ目の引数のデータベースへマイグレーションするために必要なSQLを出力します。

差分が無い場合は何も出力されません。

$ migra --unsafe  postgresql://postgres:xxxxx@localhost:5432/example2 postgresql://postgres:xxxxx@localhost:5432/example1

以下のSQLが出力されました。シーケンスの作成や主キー制約などは個別のSQLになるようです。シーケンスによるIDの採番や主キー制約部分はCREATE TABLEの中に書くことができるので、生成されるSQLは少し冗長に思えます。

create sequence "public"."price_history_id_seq";

create table "public"."price_history" (
    "id" integer not null default nextval('price_history_id_seq'::regclass),
    "product_id" integer not null,
    "price" numeric not null,
    "updated_at" timestamp with time zone not null
);


alter sequence "public"."price_history_id_seq" owned by "public"."price_history"."id";

CREATE UNIQUE INDEX pk_price_history ON public.price_history USING btree (id);

alter table "public"."price_history" add constraint "pk_price_history" PRIMARY KEY using index "pk_price_history";

example2に対して以下のDDLを実行後に再びmigraを実行すると差分は無くなりました。

create table price_history (
    id serial,
    product_id int not null,
    price numeric not null,
    updated_at timestamp with time zone not null,
    constraint pk_price_history primary key(id)
);

テーブル数が多くないのであればマイグレーションするSQLは手作業で作成し、マイグレーションの結果確認にmigraを使うのが良いと思いました。