SQLx にもマイグレーション機能が備わっているので使ってみます。
SQLx CLI でマイグレーション
SQLx のマイグレーションでは、SQLx CLI という CLI ツールを使う必要があります。
sqlx-cli をインストール
Cargo で sql-cli をインストールします。
$ cargo install sqlx-cli
データベースの作成
まずは.env
を作成し、DATABASE_URL
を定義しておきます。
sqlx-cli は、この設定値を読み取ってクエリ等を実行してくれます。
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/todo_db
.env
が存在しない場合は、環境変数のDATABASE_URL
を設定しくおくか、--database-url
オプションを指定することができます。
以下のコマンドでデータベースを作成します。
$ sqlx database create
マイグレーション用SQLファイルの作成
マイグレーションファイルを作成します。
<timestamp>-<name>.sql
というマイグレーションファイルがmigrations
フォルダ直下に作成されます。
$ sqlx migrate add <name>
マイグレーションを実行する
マイグレーションを実行します。
$ sqlx migrate run
データベースを削除する
データベースも簡単に削除できます。
$ sqlx database drop
サンプルで試してみる
Docker で Web サーバーと DB サーバー を起動させてマイグレーションしてみます。
マイグレーションファイルを作成する
以下のマイグレーションをファイルを実行します。
migrations/20221030073018_up.sql
-- Setup tables
create table if not exists todo_statuses (
id varchar(26) not null,
code varchar(255) not null,
name varchar(255) not null,
constraint pk_todo_statuses_id primary key (id)
);
insert into todo_statuses (id, code, name) values ('01GE4ZQCSW8QHKSCA172Q5F358', 'new', '新規') on conflict do nothing;
insert into todo_statuses (id, code, name) values ('01GE4ZQPD3V5AYHZ4WFWHV9Y9S', 'working', '着手中') on conflict do nothing;
insert into todo_statuses (id, code, name) values ('01GE4ZQXGH0S8AWEDFXE5903XR', 'waiting', '未着手') on conflict do nothing;
insert into todo_statuses (id, code, name) values ('01GE50C7RJP4X8WEVWKEATRVKS', 'done', '完了') on conflict do nothing;
insert into todo_statuses (id, code, name) values ('01GE50CDE8K0V9NTPAA6V58XV7', 'discontinued', '中止') on conflict do nothing;
insert into todo_statuses (id, code, name) values ('01GE50CK0PADP4ZH7A7BFHDDH9', 'pending', '保留中') on conflict do nothing;
insert into todo_statuses (id, code, name) values ('01GE50F00G30E08VVZ0PR9QT63', 'deleted', '削除') on conflict do nothing;
create table if not exists todos (
id varchar(26) not null,
title varchar(255) not null,
description text not null,
status_id varchar(26) not null default '01GE4ZQCSW8QHKSCA172Q5F358',
created_at timestamp with time zone not null default current_timestamp,
updated_at timestamp with time zone not null default current_timestamp,
constraint pk_todos_id primary key (id),
constraint fk_todos_status_id_todo_statuses_id foreign key (status_id) references todo_statuses (id)
);
Dockerfile と docker-compose.yaml
データベース用のディレクトリを切ってあります。
FROM postgres:14-alpine AS database
ENV LANG ja_JP.utf8
Axum で Web サーバーでデバッグ実行するための Dockerfile を用意します。
ポイントはRUN cargo install sqlx-cli
です。
FROM rust:1.63.0 as development
WORKDIR /app
COPY ./todo-adapter ./todo-adapter
COPY ./todo-app ./todo-app
COPY ./todo-driver ./todo-driver
COPY ./todo-kernel ./todo-kernel
COPY ./migrations ./migrations
COPY ./Cargo.toml ./Cargo.toml
COPY ./docker-app.env ./.env
RUN cargo install sqlx-cli
Docker Compose でコンテナを起動します。
version: "3.8"
services:
app:
container_name: app
build:
context: .
dockerfile: Dockerfile
target: "development"
ports:
- "8080:8080"
depends_on:
db:
condition: service_healthy
volumes:
- ./todo-adapter:/app/todo-adapter
- ./todo-app:/app/todo-app
- ./todo-driver:/app/todo-driver
- ./todo-kernel:/app/todo-kernel
- ./migrations:/app/migrations
- ./Cargo.toml:/app/Cargo.toml
- ./docker-app.env:/app/.env
stdin_open: true
tty: true
db:
container_name: postgres
build:
context: ./database
dockerfile: Dockerfile
target: "database"
ports:
- "5432:5432"
volumes:
- ./database/pg-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
restart: always
healthcheck:
test: pg_isready -U postgres
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
volumes:
pg-data:
マイグレーションを実行する
実行手順は README にも記載しています。
- コンテナを起動
app
コンテナでbash
を実行- データベースを作成
- マイグレーション
$ docker-compose up --build -d
$ docker-compose exec app bash
$ sqlx database create
$ sqlx migrate run
psql でテーブルを確認
db
コンテナ内でpsql
コマンドを実行してみます。
$ docker-compose exec db bash
データベース一覧、テーブル一覧、todo_statuses
テーブルのレコードを確認します。
bash-5.1# psql -U postgres -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+------------+------------+-----------------------
postgres | postgres | UTF8 | ja_JP.utf8 | ja_JP.utf8 |
template0 | postgres | UTF8 | ja_JP.utf8 | ja_JP.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | ja_JP.utf8 | ja_JP.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
todo_db | postgres | UTF8 | ja_JP.utf8 | ja_JP.utf8 |
(4 rows)
bash-5.1# psql -U postgres -d todo_db
psql (14.5)
Type "help" for help.
todo_db=# \dt
List of relations
Schema | Name | Type | Owner
--------+------------------+-------+----------
public | _sqlx_migrations | table | postgres
public | todo_statuses | table | postgres
public | todos | table | postgres
(3 rows)
todo_db=# select * from todo_statuses;
id | code | name
----------------------------+--------------+--------
01GE4ZQCSW8QHKSCA172Q5F358 | new | 新規
01GE4ZQPD3V5AYHZ4WFWHV9Y9S | working | 着手中
01GE4ZQXGH0S8AWEDFXE5903XR | waiting | 未着手
01GE50C7RJP4X8WEVWKEATRVKS | done | 完了
01GE50CDE8K0V9NTPAA6V58XV7 | discontinued | 中止
01GE50CK0PADP4ZH7A7BFHDDH9 | pending | 保留中
01GE50F00G30E08VVZ0PR9QT63 | deleted | 削除
(7 rows)
まとめ
CLI でマイグレーションを実行できることが確認できました。
SQLx の ORM ではないと割り切っている設計思想も面白いなと思います。
コメント