Metabase のパラメータを埋め込んだクエリを外部で検証したいとき

2021-03-31

そんなときはないかもしれませんが私にはありました。 タイトルにある "Metabase のパラメータを埋め込んだクエリ" というのは次のようなもので、 GitHub Flavored Markdown に倣って、ここでは Metabase flavored query と呼ぶことにします。

SELECT
  *
FROM
  items
WHERE
  foo = {{ bar }}     -- `{{ }}` で囲まれた部分を Param といい、剥き出しの時は必須
  [[ AND {{ baz }} ]] -- `[[ ]]` で囲まれた部分は Optional Clause という

この例は Param や Optional Clause が埋まっている以外は RDBMS 用の SQL なので、そこさえ解決できれば libpg_query などといった各種 SQL の方言に対応した静的解析器にかけることができます。 これが必要なシーンとしては、前回に引き続き Metabase に投入するクエリをコードで管理していて、デプロイ前に CI などである程度のチェックをしたいときなどです。

というモチベーションで作ったのがこれです。

先程のようなクエリをパースして、適当なパラメータで Param を置き換えたり、Optional Clause を外した上で素のエンジンが解釈できる文字列に戻すことができます。

sql = 'SELECT * FROM items WHERE foo={{bar}} [[ AND {{baz}} ]]'
query = Metasql::Parser.parse(sql)
# => #<Metasql::Query ...>

query.with({ bar: 1 }).deparse
# => 'SELECT * FROM items WHERE foo=1 '

当初の目的は達成できたので今のところこれでいいかなという感じですが、 Syntax Error となった位置が手に入らないなど parse という名に対する実装として足りない点は多いので、いつかアップデートできたらなと思います。

参考