「分析SQLそのまま可視化したい」を叶えるツールを作った
概要
久しぶりの記事投稿となります。
DuckDBを去年から個人的に使用しており、何度か記事も投稿していました。
記事投稿をする内に、記事よりこれを使った何かを作ってみたいなと常々思っており、
現在DuckDBの拡張機能として「miniplot」と「Sql2Viz」というツールをOSSとして作っています。
どちらもSQLを書くその流れを止めずになんとかビジュアライゼーションをできないか?という考えのもと作成しました。
DuckDB Advent Calendar 2025 の9日目の記事として書かせていただいています。
Github
LT会
datatech-jp Casual Talks #8
スライド
上記LT会で共有させていただく予定のスライドです。
スライド内で触れなかった部分
なぜ作ったかとか何ができるかはスライドで共有しているので技術的なことをわかる範囲で解説しておこうと思います。
DuckDBコミュニティエクステンション(拡張機能)
DuckDBコミュニティエクステンションというのはDuckDBの半公式の拡張機能のことで、ユーザーが自作した拡張機能を登録することでDuckDBのインストールコマンドから作成した拡張機能を呼び出せるようにできるものです。
こんな感じで呼べます。
INSTALL miniplot FROM community;
LOAD miniplot;
作成方法は以下テンプレートをクローンしてからC++で記述していきます。一応他言語も使用できるらしいです。
あとはこのテンプレートで自作ツールを記述して、別途以下に自分の作成したツールをextensionに追加して公式にPRを出します。
そして公式のCIをクリアしたら、コミュニティエクステンションとして登録されます。
このCIを通るのがかなり苦労した覚えがあります。
miniplotの中身
正直なところC++を手で書く自信がなく、ほとんどがClaude頼みで作っていました。
なのでざっくりとした説明になると思います。
list()の中身をstd::vectorに変換
miniplotでは以下のような構文を使用します。
SELECT bar_chart(
list(month),
list(revenue),
'Monthly Revenue'
) FROM sales
一番目のlistがx軸、二番目のlistがy軸の列名を入れてます。
正直list()を外せれば良かったんですが、リストにして渡す方法となりました。
// 文字列のリストを抽出
static std::vector<string> ExtractStringList(const Vector &list_vector, idx_t row_idx)
// 数値のリストを抽出
static std::vector<double> ExtractDoubleList(const Vector &list_vector, idx_t row_idx)
HTMLを生成
まずhtml という変数(バッファ)を作ります。
そこに<!DOCTYPE html>から始まるPlotly.jsのCDN URLを含んだHTMLをまず文字列として流し込みます。
EscapeString()などの関数がHTMLに埋め込まれており、ここでlistの中身が動的に埋め込まれます。
Plotly.jsはCDNで呼ぶしかなくオンラインでしかこのツールは使用できないという制約が出てしまいました。
htmlをtmpフォルダに保存→ブラウザを開いてそのファイルを開く。
生成したhtmlを一回tmpフォルダに保存します。そしてそのファイルをブラウザで開きます...
本当はそのまま開くとかwebviewとかで開くとかできたら良かったんですが、拡張機能としてはそこが越えられずこういった方法を取るしかありませんでした。
なのでtmpにどんどんhtmlファイルが溜まります。(回避策としてhtmlをパス指定して保存もできます。)
Sql2Vizの中身
こちらもRustを手で書く自信がなく、ほとんどがClaude頼みで作っていました。
このツールはduckdbをエンジンにsqlを解釈させ、結果を返させてます。
その結果をicedというrustのguiクレートに渡しています。
後日追記するかもしれません。
Discussion