自動生成されたDDLをsedで調整
macOS 10.12 Sierra, MariaDB 10.1, ERMaster 1.0.0.v20150619-0219
ER図を手軽に書くにはEclipseプラグインのERMasterがとっても便利。
ここ数年、愛用している。
ところで、MariaDBのテーブル定義というのは、他の一般的なDBMSと比べてかなり特殊である。特に私がいつも気にすることが2つある。1つはVARCHAR列がデフォルトでignore case(大文字小文字区別無し)なのと、もう1つはTIMESTAMP列が2つ以上ある時に1つの列にしかDEFAULT CURRENT_TIMESTAMPを指定できないことだ。
私の場合は、varchar列は全てBINARYにしてしまう。それが良いかはさておき、sedで変換するには例えば以下のようにする。
sed -E '/BINARY/!s/(varchar\([0-9]+\))/\1 BINARY/g' create_table.sql
もう1つのTIMESTAMP問題については、たとえば、以下のような要件を仮定する。
- 全テーブルに生成日時と更新日時を持たせる
- 生成日時を create_ts とする
- 更新日時を update_ts とする
- create_ts は default current_timestamp にしたい
- update_ts は default current_timestamp にして、かつ、on update current_timestamp にしたい
これはMariaDBの仕様上できないので、create_ts の方は default 0 にする。そして、update_ts は default current_timestamp にしておく。
ERMasterでDDLを自動生成すると、
CREATE TABLE some_table ( -- create_ts timestamp DEFAULT 0 NOT NULL, update_ts timestamp DEFAULT current_timestamp NOT NULL );
こうなるわけだ。
create_ts については、INSERT 時に NULL を指定することによって、現在日時を登録するようにする。((ここで、insert into some_table(create_ts) values(current_timestamp);
としてしまうと、timestamp(3) のようにミリ秒まで保持させている場合に、create_ts と update_ts の値が微妙にずれる))
insert into some_table(create_ts) values(null);
update_ts の ON UPDATEについては、sed でつけ足してしまおう。
sed -E '/ON UPDATE/!s/(update_ts timestamp DEFAULT current_timestamp NOT NULL)/\1 ON UPDATE current_timestamp/g' create_table.sql
んー。
あんまりスマートじゃない気がするけども、まあ、1個ずつ手で直すよりは遥かにマシだろうて。
#!/usr/bin/env bash # Mac OS X (using BSD sed) # Script to adjust DDL made by ERMaster for MariaDB sed -i .bak1 -E '/ON UPDATE/!s/(update_ts timestamp DEFAULT current_timestamp NOT NULL)/\1 ON UPDATE current_timestamp/g' create_table.sql sed -i .bak2 -E '/BINARY/!s/(varchar\([0-9]+\))/\1 BINARY/g' create_table.sql rm create_table.sql.bak1 rm create_table.sql.bak2
ポイント2. コマンドの引用符はダブルクォートでなくシングルクォートで
じゃないと、!s
の ! が、BASHコマンドとして機能してしまってうまく動かない。
ポイント3. -i の後ろにバックアップファイルのサフィックスをつける
単純に上書きしたいだけなのに、バックアップが作られるので、後で消す。