百名山 API を開発しました | mountix APICLICK !

Rust | SQLx の sqlx-cli でマイグレーションを実行する

Rust SQLx Migration
  • URLをコピーしました!

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 は ORM ではないので、テーブル作成などのSQLを自分で記述する必要があります。

マイグレーションを実行する

マイグレーションを実行します。

$ 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

データベース用のディレクトリを切ってあります。

database/Dockerfile

FROM postgres:14-alpine AS database
ENV LANG ja_JP.utf8

Axum で Web サーバーでデバッグ実行するための Dockerfile を用意します。

ポイントはRUN cargo install sqlx-cliです。

Dockerfile

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 でコンテナを起動します。

docker-compose.yaml

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 にも記載しています。

  1. コンテナを起動
  2. appコンテナでbashを実行
  3. データベースを作成
  4. マイグレーション
$ 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 ではないと割り切っている設計思想も面白いなと思います。

秀和システム
¥1,980 (2022/11/28 10:40時点 | Amazon調べ)
Rust SQLx Migration

この記事が気に入ったら
フォローしてね!

  • URLをコピーしました!

コメント

コメントする

目次