Datastore を利用していたときにはスキーマがあってなかったようなものなので、基本的にはエンティティの定義 ≒ スキーマみたいなところがあったが、Spannerは正統派RDB的な振る舞いをするので、 DDL によってスキーマを定義します。
スキーマの設計自体を DDL で行った場合、運用が始まったテーブルに対してはスキーマ自体ではなく、差分のクエリを発行する必要があります。(ALTER TABLE)
RDB を使ってきた人としては「まぁそうだよね」という感じの話ではあるが、毎回差分を把握して ALTER 文を作成するのも面倒なので、そのあたり「いいかんじ」にやってくれるという hammer を試してみます。
hammer をインストールする。
インストールにはバイナリでインストールする方法と、 go get
を利用する方法がありますが、私の環境は go がすでにインストールされてるため、 go get
コマンドを利用してインストールします。
go get -u github.com/daichirata/hammer
インストールが終わるまでちょっと待ちます。
注意 : Spannerライブラリ1.9 で若干構成が変わっているため go get でインストールできない場合があります。その場合はバイナリからのインストールをおすすめします。(2020/09/02現在)
インストールを確認
以下のコマンドで正しくインストールされたか確認してみましょう
hammer
色々それっぽい情報(?)が表示されれば OK です。(-v オプション実装されてない??)
2つのファイルから差分を出してみる
ドキュメントの例の通り、以下のような2つのファイルを用意してみます。
users.sql
CREATE TABLE users ( user_id STRING(36) NOT NULL, ) PRIMARY KEY(user_id);
users2.sql
CREATE TABLE users ( user_id STRING(36) NOT NULL, age INT64, name STRING(MAX) NOT NULL, ) PRIMARY KEY(user_id); CREATE INDEX idx_users_name ON users (name);
これらを用意した上で以下のコマンドを実行してみます
hammer diff users.sql users2.sql
結果は以下のように表示されました。
ALTER TABLE users ADD COLUMN age INT64 ALTER TABLE users ADD COLUMN name STRING(MAX) UPDATE users SET name = '' WHERE name IS NULL ALTER TABLE users ALTER COLUMN name STRING(MAX) NOT NULL CREATE INDEX idx_users_name ON users(name)
良さそうな感じですが、befor/after の2つのファイルを用意するというパターンは Git で DDL を管理している場合にはあまり発生しないパターンだと思うので、 Spanner の DB と直接比較するパターンを試してみます。
DB とファイルの差分を出してみる。
先程の users.sql
を Spanner 側に適用した状態で、 users2.sql
と比較してみます。
hammer diff spanner://projects/{PROJECT_ID}/instances/{INSTANCE_ID/databases/{DB_NAME} users2.sql
コマンドを実行すると以下のような結果が表示されました
ALTER TABLE users ADD COLUMN age INT64 ALTER TABLE users ADD COLUMN name STRING(MAX) UPDATE users SET name = '' WHERE name IS NULL ALTER TABLE users ALTER COLUMN name STRING(MAX) NOT NULL CREATE INDEX idx_users_name ON users(name)
先ほどと同じ感じになりますね。
DBに適用したスキーマをベースに、新しく追加した DDL との差分を得るという運用の場合にはこの感じで利用できそうです。
おまけ : スキーマファイルを Spanner DB に適用する
ファイルを DB に適用する場合には apply コマンドを利用します。
hammer apply spanner://projects/{PROJECT_ID}/instances/{INSTANCE_ID/databases/{DB_NAME} users2.sql
ただ、裏側で何をやっているかあまり把握できていないので、プロダクション環境では利用しない感じでしょうか。
ちょっと不安な点
diff の定義的に、(コマンドでファイル連結するてもあるが) DDL ファイルは1ファイルで管理するイメージになるでしょうか。
テーブルなどが増えてきた際にファイル分割したくなったりするパターンもあるかな?
と思うところもあったので、使ってみて使用感とかまたアウトプットできればと思います。
ではでは。