PostgreSQL 互換の DBMS を自作してみた

WEB+DB PRESS Vol.122

WEB+DB PRESS Vol.122

  • 発売日: 2021/04/24
  • メディア: Kindle

※ この記事では「PostgreSQL 互換」を「PostgreSQL client から接続できる」という意味で使っています。

最近はやりの自作 DBMS というものを私もやってみたので忘れぬうちに感想を書いておきます。

github.com

https://raw.githubusercontent.com/goropikari/psqlittle/main/doc/demo.gif

今回作った DBMS は Go の練習がてら書いたもので製作期間はおよそ10日でした。

SQL で操作できることを主とし、簡単な SELECT, UPDATE, DELETE, INSERT, CREATE TABLE, DROP TABLE に対応することができました。 また PostgreSQL client からも接続できるようにしたので、自分の中ではより DBMS を作った感がありました。 自作 DBMSPostgreSQL client から接続できるようにした人を今の所見たことないので、そこに関しては結構マニアックなことをしたのかなと思います。

PostgreSQL client 対応については別途記事にまとめてあります。

goropikari.hatenablog.com

SQL parser は自作ではなく pg_query_go1 を使用しました。PostgreSQL の文法なら過不足なく parse できるという安心感があることが主な選定理由です。

github.com

テーブルのレコードは slice に slice を突っ込んでいくだけの実装だったため、今回の自作 DBMS の主な作業は pg_query_go が生成する parse tree の評価方法を考えることでした。

以前コンパイラを作ったことがあったのでこの手のことは慣れていると思っていたのですが、SELECT id ... と書かれたときの id の値はレコードごとに違うので、どうやって値を持ってくるかということに悩みました。 最終的に「引数にレコードをとって該当する値を返す関数」を動的に生成することでそれっぽい動きをするものはできましたが、実際の DBMS ではこんなことをしていないと思うのでどうやっているのか気になるところです。

goropikari.hatenablog.com

SQL が3値論理を採用しているせいでプログラミング言語標準の &&|| を使うと NULL の値が入ってきたときにバグるので3値論理用の二項演算を定義したりと地味なところが地味に大変でした。

最終的にテスト等も含めると5000行ほど書いたので Go の使い方を覚えるのにはちょうどよい分量でした。このくらいの機能だったらこのくらいの分量でかけるという肌感もついたので良かったです。 最初は REPL も自作していましたが、もっとリッチな REPL がほしいと思い何故か PostgreSQL client 対応もしましたが、おかげで PostgreSQLプロトコルMySQL に比べるととても読みやすいということがわかったのは収穫でした。再び自作 DBMS に挑戦することになったら、そのときも PostgreSQL 互換に作ろうと思います。


  1. postgres parser である pg_query の Go ラッパー