PostgreSQL(準)互換SQLのパース事例集
前提・背景
SQLは標準仕様があるが、標準実装はない
各実装がそれぞれに独自の方言を持つ
「標準に準拠」していることはあっても、ミニマルに標準のみの機能を持つツールは無い
PostgreSQLはOSSなRDBMS(の一つ)で、SQLパーサの grammar (yacc) も公開されている
SQL関連ツールでは、PostgreSQLの方言を含むSQLが扱えることがしばしばある
PostgreSQLは人気でユーザが多いから?
ここでの「SQLを扱うツール」とは、(R)DBMS自体・SQLのLanguage Serverやフォーマッタ などを指す
疑問
世のツールは文法がPostgreSQL(準)互換であるためにどのような方法を取っているか?
パーサジェネレータと文法が公開されているから、本物のパーサを用意することは可能だよね
ただこれを使ってゴニョゴニョするためには、ツールをCで書くか、多言語からFFIして使うかのどちらかになる
独自でパーサを書いて、「おんなじ文法だよ!」と言い張っているだけの可能性もありうる
文法を独自管理しているのか、PostgreSQL本家のgram.yとyacc generatedなパーサを使っているのか、もっと工夫があるのか知りたい
調査と分類
1. 完全独自パーサ派
DuckDB
C++製
ポスグレの方言と近いよと言っているだけで、準拠と言っているわけではない
DuckDB's SQL dialect closely follows the conventions of the PostgreSQL dialect. The few exceptions to this are listed on this page.
YugabyteDB
C/C++製
PostgreSQL互換を謳っている
独自の lexer/parser で頑張ってそう
tree-sitter-sql
tree-sitter でSQLの文法を定義
特にPostgreSQL互換とかではない
2. 本家grammarの流用派
PostgreSQLからパーサだけを切り出したCのライブラリ
ポスグレ本体のgrammarを使ってる
pg_query (Ruby)
pg_query.go (Go)
pg_query.rs (Rust)
pgsql-parser (Node)
psqlparse (Python)
pglast (Python 3)
postgres_lsp
Supabaseが提供する SQL向け Language Server
Rust製
パーサには libpg_query を使っているとある
pg_query.rs ではないのかな、FFIを自分でやっている?lemonadern.icon
あとでよむlemonadern.icon
3. 本家grammar + 別言語でのパーサジェネレータ実装派
ポスグレの文法を流用してGoでパーサジェネレータ自体を書いている?lemonadern.icon
.yなファイルにGoが書いてある
postgresql-cst-parser
ポスグレの文法を流用してRustでYaccのaction部分とジェネレータを書いている
ASTじゃなくCSTを取るために、libpg_query.rs のパッチを当てたものを基にしている
考察
ここで挙げているものは、「DBMSの一部分としてのパーサ」と「SQL解析のためのパーサ」がある
DBMSの場合、独自の方言を追加したいケースがあったり、実装したところで旨味の薄いポスグレの機能とかもあるはず
PostgreSQL完全互換じゃなくてもいい
本家のパーサを使うとそれに縛られる
→「ポスグレ互換」である事自体はコアの機能じゃないので、パースは独自で頑張っているところのほうが多そう
SQL解析パーサは、ValidなPostgreSQLは全部パースしたい、だけど独自の文法を追加したくなることはない
→ちょっとトリッキーなことをしてでも本家のパーサを使おうとする場合がある
参考