Livebook から KinoDB を使い、ノーコードでデータベース操作する

## はじめに

Livebook はブラウザ上で Elixir や Erlang などのコードを実行し、結果を視覚化できるツールです

Python における Jupyter に相当します

https://livebook.dev/

Livebook のはじめ方はこちら

https://qiita.com/RyoWakabayashi/items/dc82ad3ed866d58a8acf

Livebook には Smart Cell という機能があり、これを使うことで AI・機械学習や画像処理、グラフ表示など、様々なことが **ノーコードで簡単に実装できる**ようになっています

今回は KinoDB を使って、 Elixir を（ほぼ）書かずにデータベース操作する手順を紹介します

https://github.com/livebook-dev/kino_db

実装したノートブックはこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/kino/kino_db.livemd

## 環境の準備

Livebook と PostgreSQL をローカル起動している場合はそのまま進めて問題ありません

コンテナで起動したい場合、こちらの記事を参考にしてください

https://qiita.com/RyoWakabayashi/private/7f3e2c288259f6a0a955

## ノートブックの作成

Livebook のホーム画面、右上の `+ New notebook` をクリックします

![スクリーンショット 2023-10-31 9.29.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/d283d4b4-26be-d6d8-3db7-5b50b80d6904.png)

新しいノートブックが開きます

![スクリーンショット 2023-10-31 9.31.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/fe0dbd62-5407-dbe3-6c8e-6eac4737d023.png)

## セットアップ

`Notebook dependencies and setup` と書いてある枠（セットアップセル）をクリックし、その中に以下のコードを入力します

```Elixir
Mix.install([
  {:kino_db, "~> 0.2"},
  {:postgrex, "~> 0.17"}
])
```

これにより、 KinoDB と Postgrex が依存モジュールとしてインストールされます

KinoDB はデータベース用の Smart Cell （DB接続とクエリ実行用の UI）を提供しています

Postgrex が KinoDB の裏で PostgreSQL との接続、データベース操作を実行しています

https://github.com/elixir-ecto/postgrex

## データベース接続

### データベース接続用 Smart Cell の追加

`Section`　と書いてある行と黒い枠（セル）の間、横方向中央あたりにマウスカーソルを持っていくと、 `+ Elixir` `+ Block` `+ Smart` という3つのボタンが表示されます

`+ Smart` をクリックするとドロップダウンが出てくるので、 `Database connection` をクリックします

![スクリーンショット 2023-10-31 9.37.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/f3cb3750-ca6f-83bf-5f30-37a1139f011b.png)

すると、以下のようなデータベース接続用の入力フォームが表示されます

![スクリーンショット 2023-10-31 9.40.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/343c1fe7-725c-f07b-e83e-16f135d3c0b7.png)

### データベース接続情報の入力

各項目に接続先データベースの情報を入力します

コンテナ起動している場合、 Hostname はコンテナ名を指定してください
（上記 docker compose 定義の場合、 `postgres_for_livebook`）

Password は秘密情報のため、テキスト入力をクリックするとモーダルが表示されます

Name に適当な名前（`DB_PASSWORD` など）、 Value にパスワードを入力し、 `+ Add` ボタンをクリックしてください

![スクリーンショット 2023-10-31 9.43.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/ffc9f5c2-a183-98a2-f2f5-01b92ebfc5f1.png)

接続情報を全て入力したら Smart Cell 左上の `Evaluate` をクリックしましょう

![スクリーンショット 2023-10-31 9.46.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/59113353-21a6-f066-afd8-7d7a01a0940d.png)

Smart Cell の下に `{:ok, #PID<0.276.0>}` という出力が表示されれば接続できています

## クエリ実行

### クエリ実行用 Smart Cell の追加

データベース接続の結果の下、横方向中央あたりにマウスカーソルを移動すると、再び `+ Smart` のボタンが表示されるので、ドロップダウンから `SQL query` をクリックします

![スクリーンショット 2023-10-31 9.57.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/0a444904-1de7-cc8c-165b-f2023e4f43d6.png)

すると、以下のような Smart Cell が追加されます

![スクリーンショット 2023-10-31 9.59.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/8c1ccaa5-de82-d8e7-b216-c5d775f5275a.png)

### Smart Cell からのクエリ実行

黒い枠の中を以下のように変更して、左上の `Evaluate` をクリックしましょう

```sql
CREATE TABLE
  sample
(
  id integer,
  name varchar(20)
)
```

![スクリーンショット 2023-10-31 10.02.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/0f9d9fda-aa1e-8b20-84a2-881783d5fed0.png)

実行結果が以下のように表示されます

![スクリーンショット 2023-10-31 10.03.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/554ad5b6-66b0-fb52-e760-b557f7dab5b9.png)

もう一つ Smart Cell を追加して、今度は以下のような INSERT 文を実行してみましょう

```sql
INSERT INTO
  sample
(
  id,
  name
)
VALUES
(
  1,
  'John'
)
RETURNING
  id
```

RETURNING に書いた id が結果として返ってきました

![スクリーンショット 2023-10-31 10.05.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/3e218ecf-d447-58d0-ea31-d647f56379b0.png)

最後に以下の SELECT 文を実行します

```sql
SELECT
  *
FROM
  sample
```

実行結果がテーブルとして表示されました

![スクリーンショット 2023-10-31 10.07.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/e92eb443-e638-a51c-e86b-bd02408cc5d5.png)

## Smart Cell のコード化

Livebook では Smart Cell をコード化することができます

Smart Cell　が裏でやっていることを確認してみましょう

データベース接続用 Smart Cell の右上にある鉛筆アイコンをクリックします

![スクリーンショット 2023-10-31 10.11.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/c6940d69-50d6-b376-7820-8414318898f6.png)

以下のような警告モーダルが表示されるので、 `Convert` をクリックします

![スクリーンショット 2023-10-31 10.11.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/52f00d87-619f-695f-d64a-5c261b20ce9b.png)

すると、 Smart Cell が以下のコードセルに変換されます

```elixir
opts = [
  hostname: "postgres_for_livebook",
  port: 5432,
  username: "postgres",
  password: System.fetch_env!("LB_DB_PASSWORD"),
  database: "postgres"
]

{:ok, conn} = Kino.start_child({Postgrex, opts})
```

実態としては `Kino.start_child` で Postgrex を別プロセスで起動していることが分かります

また、 password は秘密情報なので、 `LB_DB_PASSWORD` という環境変数で渡しています

次にクエリ実行の Smart Cell をコード化すると、以下のようになります

```elixir
result =
  Postgrex.query!(
    conn,
    """
    CREATE TABLE
      sample
    (
      id integer,
      name varchar(20)
    )
    """,
    []
  )
```

データベース接続のセルで作成した接続 `conn` を指定し、 Postgrex のプロセス経由でクエリを実行しています

```mermaid
graph TD
  livebook(Livebook)
  postgrex(Postgrex)
  postgres[(PostgreSQL)]

  livebook -- query --> postgrex -- query --> postgres
  postgres -- result --> postgrex -- result --> livebook
```

## まとめ

KinoDB を使うことで、データベース接続、クエリ実行をノーコードで実装できました

また、クエリの結果は自動的にテーブル表示されるため、結果の UI について考える必要もありません

Livebook からデータベース操作をしたい場合、 KinoDB を活用しましょう