sue445/plant_erd の MySQL コマンドの出力を修正する PR を出した
RDB の ER 図を PlantUML の DSL で出力する plant_erd
の出力を修正する PR を出した & マージされた。
plant_erd
は MySQL, PostgreSQL, SQLite3, OracleDB を対象に実際のデータベースにクエリを投げてテーブル定義を収集し、ER 図(に変換可能な PlantUML 向けテキスト)を出力する。
MySQL モードの時だけ出力に View が含まれていた。他のデータベースでは明確に View を取り除くためのクエリを使っていたのでバグだと判断。念の為 Issue を上げて作者に確認した後、PR を出した。
View の除外
job
, person
というテーブル2つと、それらから作った personal_job
という View が1つあるデータベースを考える。
CREATE TABLE job ( id int NOT NULL, name varchar(256), PRIMARY KEY (id) ); CREATE TABLE person ( id int NOT NULL, name varchar(256), job_id int NOT NULL, INDEX job_idx (job_id), FOREIGN KEY (job_id) REFERENCES job(id) ON DELETE CASCADE ); CREATE VIEW personal_job AS SELECT person.name AS person_name, job.name AS job_name FROM person INNER JOIN job ON person.job_id = job.id;
修正前の時点では以下のクエリで、対象データベースのテーブル名一覧を取得していた。
SELECT table_name FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name;
information_schema.tables
には View も含まれているので、出力には personal_job
も含んでしまう。
mysql> SELECT table_name FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name; +--------------+ | table_name | +--------------+ | job | | person | | personal_job | +--------------+
テーブルと View を区別するために、where 句に table_type
カラムの値を確認するようにした(table_type
カラムの値は 'BASE TABLE'
と 'VIEW'
のどちらか)。
SELECT table_name FROM information_schema.tables WHERE table_schema=database() AND table_type = 'BASE TABLE' ORDER BY table_name;
これによりテーブルのみを抽出することができた。
mysql> SELECT table_name FROM information_schema.tables WHERE table_schema=database() AND table_type = 'BASE TABLE' ORDER BY table_name; +------------+ | table_name | +------------+ | job | | person | +------------+
そもそもの経緯
当初は出力に View を含むのが仕様だと思いこんでいたので、View を除外する/View だけを出力するオプションを追加する PR を出そうかと思っていた。ユースケースをどうやって説明しようか悩んでいたが、よくよく調べたら仕様ではなくバグだったので、気兼ねなく PR を出せた。
機能追加にしろバグ修正にしろ、対象の箇所ピンポイントだけでなく周辺の実装(今回の場合は MySQL 以外の DB 向けの実装)も一緒に調べるの大事。