tblsを使ってテーブルのPlantumlを生成&vscodeで表示までしてみる


はじめに

テーブル定義を元にER図が作れたら便利ですよね。

この記事では、tblsを使ってテーブル定義を元にしたuml(PlantUML)を生成し、そのumlをvscodeで確認するまでの手順を紹介します。

開発マシーン

OS: macOS Catalina
バージョン: 10.15.4

Plantumlの環境構築

必要なものは以下3点。

  • Javaの実行環境
  • Graphvizっていうソフトウェア
  • PlantUMLっていうvscodeのプラグイン

Java

Javaは以下のサイトからダウンロードして、インストールしてください。
https://java.com/ja/
ちなみに私のJava環境は、すでに以下の状態だったのでスルー。

$ java --version
java 13.0.1 2019-10-15
Java(TM) SE Runtime Environment (build 13.0.1+9)
Java HotSpot(TM) 64-Bit Server VM (build 13.0.1+9, mixed mode, sharing)

Graphviz

Graphvizは、以下のようにインストール

brew install install graphviz

PlantUML

PlantUMLのプラグインは以下のものをインストール

これだけだったはずです!

tblsの環境構築

tblsを以下のようにインストール

brew install k1LoW/tap/tbls

こちらもこれだけだったはず。

tblsを使ってPlantUMLを確認してみる!

環境構築がうまくできたと信じて、実際に tblsコマンド実行 -> PlantUML生成 -> PlantUML確認 までを試していきます!

例1. MySQL

MySQLのセッティング

すぐに試したかったので、ローカルPC環境直下にDB・テーブルをセットしました。

$ mysql --version
mysql  Ver 8.0.25 for macos10.15 on x86_64 (Homebrew)

$ mysql.server start

$ mysql -uroot

mysql> CREATE TABLE departments (
    department_id int primary key,
    department_name varchar(20)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;

mysql> CREATE TABLE employees (
    employee_id int primary key,
    department_id int,
    name varchar(20),
    age int,
    CONSTRAINT fk_department_id
        FOREIGN KEY (department_id) 
        REFERENCES departments (department_id)
        ON DELETE RESTRICT ON UPDATE RESTRICT
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;

PlantUML生成&確認

以下のようにmysqlのプロセスが生きてること確認して、

 lsof -i | grep mysql
mysqld    68269 fukazawakeisuke   31u  IPv4 0x3e18e99c4a7abba3      0t0  TCP localhost:33060 (LISTEN)
mysqld    68269 fukazawakeisuke   35u  IPv4 0x3e18e99c4a186ba3      0t0  TCP localhost:mysql (LISTEN)

tbls out my://root:mypass@localhost:33306/testdb -t cacoo -o schema.csv

上記のtblsコマンド例を参考に、以下を実行しました。

tbls out my://root:@localhost:3306/hoge -t plantuml -o hoge.plantuml

すると先ほど作成したMySQLのテーブル定義が、以下のようにPlantUMLとして生成されていることが確認できます。

$ cat hoge.plantuml 
@startuml
!define table(name, desc) entity name as "desc" << (T,#5DBCD2) >>
!define view(name, desc) entity name as "desc" << (V,#C6EDDB) >>
!define column(name, type, desc) name <font color="#666666">[type]</font><font color="#333333">desc</font>
hide methods
hide stereotypes

skinparam class {
  BackgroundColor White
  BorderColor #6E6E6E
  ArrowColor #6E6E6E
}

' tables
table("departments", "departments") {
  column("+ department_id", "int", "")
  column("department_name", "varchar(20)", "")
}
table("employees", "employees") {
  column("+ employee_id", "int", "")
  column("# department_id", "int", "")
  column("name", "varchar(20)", "")
  column("age", "int", "")
}

' relations
"employees" }-- "departments" : "FOREIGN KEY (department_id) REFERENCES departments (department_id)"

@enduml

生成したPlantUMLは、vscode上で以下のように確認できます!

例2. BigQuery

BigQueryのセッティング

※テーブル(VIEW)の作成をGCPのコンソール上で行いました。
※コンソール上の操作の説明は省略します。

まず以下のコマンドでログインします。

gcloud auth application-default login

BigQuery内のスキーマとテーブルが、それぞれ以下の状態にセッティングされていることを確認します。

$ bq ls
      datasetId       
 -------------------- 
  training_dataset_1

$ bq ls training-project-314502:training_dataset_1
             tableId              Type    Labels   Time Partitioning   Clustered Fields  
 ------------------------------- ------- -------- ------------------- ------------------ 
  departments                     TABLE                                                  
  employee_and_departments_view   VIEW                                                   
  employees                       TABLE                                                  

$ bq query --nouse_legacy_sql \
> 'SELECT * FROM `training-project-314502.training_dataset_1`.INFORMATION_SCHEMA.COLUMNS'
Waiting on bqjob_r474bd2474752300_00000179f5b4a5da_1 ... (0s) Current status: DONE   
+-------------------------+--------------------+-------------------------------+-----------------+------------------+-------------+-----------+--------------+-----------------------+-----------+-----------+--------------+-------------------+------------------------+-----------------------------+
|      table_catalog      |    table_schema    |          table_name           |   column_name   | ordinal_position | is_nullable | data_type | is_generated | generation_expression | is_stored | is_hidden | is_updatable | is_system_defined | is_partitioning_column | clustering_ordinal_position |
+-------------------------+--------------------+-------------------------------+-----------------+------------------+-------------+-----------+--------------+-----------------------+-----------+-----------+--------------+-------------------+------------------------+-----------------------------+
| training-project-314502 | training_dataset_1 | employees                     | employee_id     |                1 | YES         | INT64     | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | employees                     | department_id   |                2 | YES         | INT64     | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | employees                     | name            |                3 | YES         | STRING    | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | employees                     | age             |                4 | YES         | INT64     | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | employee_and_departments_view | employee_id     |                1 | YES         | INT64     | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | employee_and_departments_view | department_id   |                2 | YES         | INT64     | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | employee_and_departments_view | name            |                3 | YES         | STRING    | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | employee_and_departments_view | age             |                4 | YES         | INT64     | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | employee_and_departments_view | department_id_1 |                5 | YES         | INT64     | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | employee_and_departments_view | department_name |                6 | YES         | STRING    | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | departments                   | department_id   |                1 | YES         | INT64     | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
| training-project-314502 | training_dataset_1 | departments                   | department_name |                2 | YES         | STRING    | NEVER        | NULL                  | NULL      | NO        | NULL         | NO                | NO                     |                        NULL |
+-------------------------+--------------------+-------------------------------+-----------------+------------------+-------------+-----------+--------------+-----------------------+-----------+-----------+--------------+-------------------+------------------------+-----------------------------+

PlantUML生成&確認

MySQLの時と同様に、以下のコマンドでPlantUMLを生成します。

$ tbls out bq://training-project-314502/training_dataset_1 -t plantuml -o training_dataset_1.plantuml

以下のように、生成されたPlantUMLを確認します。

$ cat training_dataset_1.plantuml 
@startuml
!define table(name, desc) entity name as "desc" << (T,#5DBCD2) >>
!define view(name, desc) entity name as "desc" << (V,#C6EDDB) >>
!define column(name, type, desc) name <font color="#666666">[type]</font><font color="#333333">desc</font>
hide methods
hide stereotypes

skinparam class {
  BackgroundColor White
  BorderColor #6E6E6E
  ArrowColor #6E6E6E
}

' tables
table("departments", "departments") {
  column("department_id", "INTEGER", "")
  column("department_name", "STRING", "")
}
view("employee_and_departments_view", "employee_and_departments_view") {
  column("employee_id", "INTEGER", "")
  column("department_id", "INTEGER", "")
  column("name", "STRING", "")
  column("age", "INTEGER", "")
  column("department_id_1", "INTEGER", "")
  column("department_name", "STRING", "")
}
table("employees", "employees") {
  column("employee_id", "INTEGER", "")
  column("department_id", "INTEGER", "")
  column("name", "STRING", "")
  column("age", "INTEGER", "")
}

' relations

@enduml

こちらも同様に、vscodeでPlantUMLを表示してみました。