自動生成された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

ポイント1. BSD sed では ignore case できない

なので、s/target/replace/gi と書きたくても書けない。

ポイント2. コマンドの引用符はダブルクォートでなくシングルクォートで

じゃないと、!s の ! が、BASHコマンドとして機能してしまってうまく動かない。

ポイント3. -i の後ろにバックアップファイルのサフィックスをつける

単純に上書きしたいだけなのに、バックアップが作られるので、後で消す。

ポイント4. -E をつければ正規表現のエスケープは基本いらない

\( とか \+ とかは文字そのものを表す。
-e の時と逆。



ちょっとしたことだけれども、なんだかハマり所がたくさんあったなぁ(コナミ)