Backend API を作っていると、結局いつも同じ問題にぶつかります。管理画面や internal tool から柔軟な filter 条件を渡したい。でも、毎回 if/else で SQL を組み立てるのはつらいし、生の SQL を受け付けるのはもっと危ない。欲しいのは、表現力はそこそこ高いのに、型と境界が崩れにくい条件表現です。

今日紹介したい SPANDigital/cel2sql は、その問題にかなり素直に答える project です。CEL(Common Expression Language) の式を SQL 条件へ変換し、PostgreSQL、MySQL、SQLite、DuckDB、BigQuery、Apache Spark SQL をサポートします。つまり、上位の system は CEL で filter を記述し、実際の database 向け SQL はこの library に任せる、という分離ができます。

公開時点の GitHub page では、project は約 37 stars3 forks。主言語は Go、license は Apache-2.0 です。Repository の作成日は 2025-07-10、最新 release は v3.8.6、公開日は 2026-06-15 でした。

Project overview

項目内容
RepositorySPANDigital/cel2sql
位置づけCEL 式を複数 SQL dialect の条件へ変換する library
Stars約 37
Forks3
主要言語Go
LicenseApache-2.0
対応 dialectPostgreSQL、MySQL、SQLite、DuckDB、BigQuery、Spark SQL
Latest releasev3.8.6

解いているのは SQL 生成そのものより、制御された filter 公開

多くの service は SQL を書けないわけではありません。本当に困るのは、「柔軟な filter 条件をどう安全に外へ開くか」です。

ありがちな方法は、だいたい次のどれかです。

  • filter 項目ごとに backend 側で分岐を増やし続ける。
  • 独自 DSL を作るが、型も tooling も弱い。
  • ひどい場合は SQL 断片を受け取ってしまう。

cel2sql はもっと筋の良い中間層を置きます。条件表現には CEL を使い、まず AST まで compile してから SQL に変換します。つまり、適当な文字列変換ではなく、構文と型の確認を先に通したうえで database dialect へ落とす設計です。

README の基本例も分かりやすいです。表 schema を定義し、CEL environment を作り、user.age >= 18 && user.active のような式を compile し、その結果を user.age >= 18 AND user.active IS TRUE のような SQL 条件に変えます。管理画面の filter、report API、rule engine、検索条件 API にはかなり相性がよさそうです。

一つの式から複数 dialect を出せるのが実務的

この project の実用性は、単に CEL を SQL にすることだけではなく、それを 複数 dialect に対してそろえているところにあります。

現時点での対応先は:

  • PostgreSQL
  • MySQL
  • SQLite
  • DuckDB
  • BigQuery
  • Apache Spark SQL

現実の system は、見た目以上に複数の database をまたぎます。主系は PostgreSQL でも、分析用に BigQuery、local test に SQLite や DuckDB、data processing に Spark を使うことは珍しくありません。そのたびに query layer を分岐させるのは面倒です。

cel2sql は filter expression を先に固定し、差分を dialect 実装側へ押し込めます。しかも最新の v3.8.6 では Spark SQL dialect が追加され、regex、JSON、array literal、一部の comprehension 相当まで含めて広げています。小さな utility に見えて、意外と本気で方言差分に向き合っています。

schema と type provider があるので文字列テンプレートで終わらない

こういう tool で一番不安なのは、結局 string template の延長なのではないか、という点です。

cel2sql はそこを schema と type provider で支えています。典型的な流れは:

  • table schema を定義する。
  • それを type provider に渡す。
  • CEL environment に variable と object type を登録する。
  • compile 段階で field や type を検査する。

これにより、少なくとも次のような問題を早い段階で見つけやすくなります。

  • 存在しない field を参照している。
  • 型の合わない比較をしている。
  • 式の構文がおかしい。

さらに良いのは、schema を全部手で持たなくてもよい点です。docs/getting-started.md では NewTypeProviderWithConnectionLoadTableSchema が紹介されていて、database 接続から schema を読み込めます。実運用では schema の手書き同期はすぐ崩れるので、この方向はかなり助かります。

security boundary が最初から明文化されている

動的 filter を扱う tool で大事なのは、何が安全で何が利用者の責任かを曖昧にしないことです。

cel2sql の docs はこの点が比較的はっきりしています。標準で入っている防御として、たとえば:

  • field name validation
  • JSON field 名の escape
  • regex ReDoS 防止
  • expression depth の制限
  • context timeout の利用

が挙げられています。

つまり、ただ AST を SQL 文字列に展開するだけではなく、「user input 由来の式を production で扱う」前提で防御を積んでいます。

その一方で、docs は過剰に万能感を出していません。引き続き:

  • 入力 validation を行うこと
  • 実行時は prepared statement を使うこと
  • 公開 field を絞ること
  • 自分の edge case をテストすること

を勧めています。このバランスは好印象です。security tool というより、filter layer の安全性を底上げする部品として正直です。

JSON、配列、timestamp、logging まで含めて現実寄り

もしこの種の library が a > b 程度しか扱えないなら、実案件ではすぐ詰まります。

cel2sql の docs では、かなり現実寄りの例が並んでいます。

  • startsWithcontains
  • timestamp 比較
  • 配列の membership と長さ判定
  • JSON/JSONB の扱い
  • structured logging
  • context による timeout と cancel

このあたりを見ると、作者は単なる parser ではなく、実際の query-facing component として育てています。

特に logging と timeout があるのは良いです。複雑な filter 条件は「なぜこういう SQL になったのか」を追いたくなるので、schema lookup や JSON path の判断が見える設計は運用上助かります。

向いている場面

cel2sql は次のような場面で特に合いそうです。

第一に、管理画面や internal platform で custom filter を提供したい backend API。項目追加のたびに endpoint を増やしたくない時に向いています。

第二に、rule engine や alert 条件、data 配信条件のような「表現式が必要な SaaS 機能」です。CEL を中間層にすると、完全に自由な SQL を渡すよりずっと扱いやすくなります。

第三に、同じ service が複数の database dialect をまたぐ場合です。OLTP は PostgreSQL、分析は BigQuery、local test は DuckDB や SQLite、という構成なら、一つの expression から出し分けられる価値は大きいです。

境界は理解して使うべき

もちろん、cel2sql は万能な query builder ではありません。

主に解くのは 条件式から SQL 条件への変換 です。最終的な SELECT 全体、JOIN 戦略、アクセス制御、どの table/field を許可するか、といった設計は依然として application 側の責任です。

また、CEL は生 SQL よりは安全に扱いやすいですが、一般ユーザーがそのまま素で書く UI が最適とは限りません。現実には form builder、preset、rule editor と組み合わせる方が自然だと思います。

まとめ

SPANDigital/cel2sql が良いのは、CEL を SQL に変えるという一点だけでなく、それを多方言、型認識、schema introspection、安全防御、logging、timeout を含む形でまとめているところです。

「柔軟な filter は欲しいが、SQL をそのまま表へ出したくない」という backend には、かなり実用的な小さめの project だと思います。