【データカタログ作成/Streamlit】テーブルのカラム情報を瞬時に確認できるアプリを作成した。

# はじめに
現在、Streamlitを使用してデータカタログの作成に挑戦中です。

今回は、作成した機能の中から、テーブルのカラム名やデータタイプ、データの概要を参照できる機能をご紹介します。



## 機能の使い方
サイドバーの`テーブル選択`にて、データベース・スキーマ・テーブルをドロップダウンで選択すると、
以下のように、指定したテーブルのカラム毎のデータタイプやデータの概要などを瞬時に確認することができます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/67f54c6e-e155-1e9d-9112-5daf6fcd0f32.png)




### テーブル選択
サイドバーのテーブル選択では、以下のようにテーブルを選択できるように実装しました。
1. データベースをドロップダウン形式で選択
1. **選択したデータベース内のスキーマ**をドロップダウン形式で選択
1. **選択したスキーマ内のテーブル**をドロップダウン形式で選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/3f10c4b9-549b-0da8-3fa7-fef50ce554a5.png)


データベースやスキーマを選択したら、その傘下のスキーマやテーブルしかドロップダウン選択時に表示されるようにフィルタリングされるように工夫をしました。

### カラム情報

`テーブルの選択`にてテーブルを選択すると、
カラム名・データタイプ・データ概要などの情報を表示できるように実装しました。

`概要`カラムはSnowflakeのcomment機能を使用しています。
カラム毎にcommentを入力して、そちらを`概要`として表示されるように実装してあります。
commentに、カラムにどんなデータが入っているのか入力しておけば、瞬時に確認できるようになります。

また、スクショ上部にてテーブル名を表示するようにしていて、
どのテーブルのカラム情報を参照しているのか分かるように実装してあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/b8578139-e48f-bb2f-bde6-f08260691ef1.png)



# 作成方法
上記の機能を作成した方法をご紹介させていただきます。
## 事前準備
コードを作成する前に、まずは以下のように準備をしておきます。
### ディレクトリ構成
以下のようにディレクトリを組みます。
今回は`secrets.toml`を使用するので、ローカルで動かす前提です。
```
data-catalog(ルートディレクトリ)
├── data-catalog.py (上記のデータカタログのコード)
└── .streamlit
    └── secrets.toml (Snowflakeの接続情報を記載)
```
`data-catalog.py`にはデータカタログのコード、
`secrets.toml`には、Snowflakeへの接続情報を記載していきます。


### commentを入れておく
Snowflakeのcomment機能を使って、こんな感じでカラム毎にデータの概要を入れておきます。
このように、カラム毎にcommentを入れておくことで、`概要`カラムにデータの概要を表示させます。
```sql
COMMENT ON COLUMN テーブル名.カラム名 IS 'データカタログのテストコメント';
```
https://docs.snowflake.com/ja/sql-reference/sql/comment


## 実装したコード
作成したコードは以下の通りです。
### secrets.toml
Snowflakeの接続情報を記載します。
```secrets.toml
[snowflake]
user      = "[ユーザー名]"
account   = "[アカウント名].ap-northeast-1.aws"
password  = "[パスワード]"
warehouse = "[ウェアハウス名]"
role      = "[ロール名]"
```

### data-catalog.py
今回ご紹介している機能を実装するコードです。
```data-catalog.py
import streamlit as st
import streamlit_authenticator as stauth
import snowflake.connector
import pandas as pd
from snowflake.snowpark import Session

st.set_page_config( 
    page_title="データカタログ",
    layout="wide",
    )


@st.cache_resource
def init_connection():
    return snowflake.connector.connect(
        **st.secrets["snowflake"],
        client_session_keep_alive=True
    )


conn = init_connection()


def run_query(query):
    with conn.cursor() as cur:
        cur.execute(query)
        return cur.fetchall()


# Snowflakeに接続
connection_parameters = {
    "account": st.secrets["snowflake"]["account"],
    "user": st.secrets["snowflake"]["user"],
    "password": st.secrets["snowflake"]["password"],
    "warehouse": st.secrets["snowflake"]["warehouse"],
    "role": st.secrets["snowflake"]["role"]
}
session = Session.builder.configs(connection_parameters).create()


with st.sidebar:
    st.markdown('# テーブル選択')

    # データベースの一覧をリスト型で取得してselectboxで一つ選択
    show_databases = run_query("SHOW DATABASES;")
    database_rows = [row[1] for row in show_databases]
    select_database = st.selectbox('データベースを選択してください', database_rows)

    # スキーマの一覧をリスト型で取得してselectboxで一つ選択
    show_schemas = run_query(f"SHOW SCHEMAS IN DATABASE {select_database};")
    schema_rows = [row[1] for row in show_schemas]
    select_schema = st.selectbox('スキーマを選択してください', schema_rows)

    # テーブルとビューの一覧をリスト型で取得してselectboxで一つ選択
    # SHOW TABLESだけだとviewの情報を抽出することができないので、SHOW TABLESとSHOW VIEWSを別々に実行
    show_tables = run_query(f"SHOW TABLES IN {select_database}.{select_schema}")
    show_views = run_query(f"SHOW VIEWS IN {select_database}.{select_schema}")
    table_rows = [row[1] for row in show_tables]
    view_rows = [row[1] for row in show_views]
    table_view_rows = table_rows + view_rows
    select_table = st.selectbox('テーブルを選択してください', table_view_rows)


# ページのタイトル
st.markdown(f"# データカタログ")


# テーブルのカラムの詳細を表示
st.markdown(f"## カラム情報：{select_table}")
columns_details = run_query(f"DESC TABLE {select_database}.{select_schema}.{select_table}")
column_detail_df = pd.DataFrame(columns_details)
column_detail_df = column_detail_df.rename(columns={0: 'column_name', 1: 'data_type', 9: 'comment'})
column_detail_df = column_detail_df.loc[:, ['column_name', 'data_type', 'comment']]
st.dataframe(
    column_detail_df,
    column_config={
        "column_name": st.column_config.TextColumn("カラム名"),
        "data_type": st.column_config.TextColumn("データタイプ", width="medium"),
        "comment": st.column_config.TextColumn("概要", width="large")
    },
    hide_index=True,
)
```
以上です！

# まとめ
以上のように、テーブル毎にカラム情報を表示できるように実装しました。
その他にも便利な機能を作成中なので、またご紹介できればと思います！