やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rust自習(diesel 6 SQLite3 ORM)

 マイグレーションにてテーブルに列を追加する。

成果物

テーブルにカラムを追加

 日付データ列を追加したい。

 ただ、SQLite3の列追加SQLコマンドには、かなりの制限がある。

  • テーブル名の変更とカラムの追加
    • 列を削除するコマンドはない
    • 列を追加するコマンドはある(alter table some_table add column new_column;
      • 制約はほぼ設定できない
        • PRIMARY KEYUNIQUEを設定できない
        • DEFAULTを設定する時はCURRENT_TIME,CURRENT_DATE,CURRENT_TIMESTAMPを指定できない
        • NOT NULLを設定する時はNULL以外のデフォルト値が必要

 alterコマンドを使うことにする。追加する日付データ列の値はすべてNULLになる。本当はNOT NULL制約を与えたいが……。

マイグレーションの単位を新設する

 マイグレーションの単位を新設する。

diesel migration generate add_column_pushed_to_posts
Creating migrations/2019-07-27-093533_add_column_pushed_to_posts/up.sql
Creating migrations/2019-07-27-093533_add_column_pushed_to_posts/down.sql

 SQLを書いていく。

up.sql

alter table posts add column published text;

 SQLite3は列の削除に対応するSQLコマンドがない。仕方なく一時テーブルを作成しコピーしてから削除する。

down.sql

-- 既存のテーブルをリネーム
ALTER TABLE posts RENAME TO tmp_posts;
-- 新しいテーブルを作成(元々のテーブル名と同じ名前で)
create table posts (
    id integer primary key,
    title text not null,
    body text not null,
    is_published text not null default 'f'
);
-- レコードを全て移す
INSERT INTO posts(id, title, body, is_published) SELECT id, title, body, is_published FROM tmp_posts;
-- 元のテーブルを削除
DROP TABLE tmp_posts;

 ダウングレードするときのコードだからpublished列を削除してある。

マイグレーション確認

$ sqlite3 ./db.sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> .headers on
sqlite> select * from posts;
id|title|body|is_published
1|記事のタイトル|記事の本文。
複数行を書く。
Ctrl+dキーで終了。
最終行。
|1
2|ドラフトだから表示されない|見せられないよ!
|f
sqlite> select * from sqlite_master;
type|name|tbl_name|rootpage|sql
...
table|posts|posts|4|CREATE TABLE posts (
    id integer primary key,
    title text not null,
    body text not null,
    is_published text not null default 'f'
)

 では、published列を追加するマイグレーションを実行する。

diesel migration run
Running migration 2019-07-27-093533_add_column_pushed_to_posts

 DBファイル確認。成功。published列が追加されている。値はNULLなので何も表示されていない。

$ sqlite3 /tmp/work/Rust.Diesel.Chrono.20190727181847/src/0/diesel_hello/db.sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> .headers on
sqlite> select * from posts;
id|title|body|is_published|published
1|記事のタイトル|記事の本文。
複数行を書く。
Ctrl+dキーで終了。
最終行。
|1|
2|ドラフトだから表示されない|見せられないよ!
|f|
sqlite> select * from sqlite_master;
type|name|tbl_name|rootpage|sql
...
table|posts|posts|4|CREATE TABLE posts (
    id integer primary key,
    title text not null,
    body text not null,
    is_published text not null default 'f'
, published text)

 ダウングレードする。

diesel migration redo
Rolling back migration 2019-07-27-093533_add_column_pushed_to_posts
Running migration 2019-07-27-093533_add_column_pushed_to_posts

 DBファイルを確認する。あれ、何の変化もない……。

$ sqlite3 ./db.sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> .headers on
sqlite> select * from posts;
id|title|body|is_published|published
1|記事のタイトル|記事の本文。
複数行を書く。
Ctrl+dキーで終了。
最終行。
|1|
2|ドラフトだから表示されない|見せられないよ!
|f|
sqlite> select * from sqlite_master;
type|name|tbl_name|rootpage|sql
table|__diesel_schema_migrations|__diesel_schema_migrations|2|CREATE TABLE __diesel_schema_migrations (version VARCHAR(50) PRIMARY KEY NOT NULL,run_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)
index|sqlite_autoindex___diesel_schema_migrations_1|__diesel_schema_migrations|3|
table|posts|posts|5|CREATE TABLE posts (
    id integer primary key,
    title text not null,
    body text not null,
    is_published text not null default 'f'
, published text)

 なぜだ。まあいいや。一旦無視して進もう。途中だけど今日はここまで。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで