この記事は、勉強会で発表したスライドを Qiita Engineer Festa 向けに書き直したものです。
PL/pgSQL Language Server を開発しました。
PostgreSQL の開発がつらい
弊社では RDS として PostgreSQL を採用しており、
ロジック部分を PL/pgSQL の Stored Function / Procedure を用いて書くことがあります。
しかし、これがつらい
まるでメモ帳で開発をしているかのようだ...(著者の感想)
TypeScript や Rust のような補完や構文チェックが欲しい~~~~ということで
VSCode 用に PL/pgSQL の Language Server を作りました
PL/pgSQL Language Server
できたのがこれです。
できること一覧
- テーブル名などの補完
- 定義への移動
- シンボルへの移動
- 定義のホバー表示
- 構文チェック
- 静的解析チェック(plpgsql_check を使っている時だけ)
- 「現在のファイルを実行」コマンド
- マルチワークスペース の対応
各機能の現在の対応表は下記です。
補完 | 定義へ移動 | ホバー表示 | |
---|---|---|---|
DOMAIN | ✔️ | ✔️ | ✔️ |
FUNCTION | ✔️ | ✔️ | ✔️ |
INDEX | - | ✔️ | ✔️ |
MATERIALIZED VIEW | ✔️ | ✔️ | ✔️ |
PROCEDURE | ✔️ | ✔️ | ✔️ |
TABLE | ✔️ | ✔️ | ✔️ |
TRIGGER | - | ✔️ | ✔️ |
TYPE | ✔️ | ✔️ | ✔️ |
VIEW | ✔️ | ✔️ | ✔️ |
使い方
ワークスペースで設定するだけ
VSCode のワークスペース毎に接続したいデータベースを設定します。
{
"plpgsqlLanguageServer.database": "データベース名",
"plpgsqlLanguageServer.user": "ユーザ名",
"plpgsqlLanguageServer.password": "パスワード",
"plpgsqlLanguageServer.definitionFiles": [
// glob をサポート。
"**/*.sql",
"**/*.psql",
"**/*.pgsql"
],
// Language Server が対応するファイルの拡張子はデフォルトで ['*.pgsql', '*.psql'] です。
// ( SQLite など他の RDS と競合させないためです。)
// '*.sql' のファイルも対応させたい場合は、下記の設定を追加してください。
"files.associations": {
"*.sql": "postgres"
}
}
エディタを開くだけで補完などが効くようにデザインされています
ここは、既存の Postgres 拡張の操作が煩雑であったところを意識しています。
複数のデータベースに接続するアプリケーションの場合は、
データベースごとにワークスペースを分けて運用してください。
使用感
拡張がなかったころに比べて、はるかに快適になりました
気になったらすぐに定義に飛べるのはやはりいいです。
また、今までは更新したときに何が起こるのかを把握しにくくなるトリガーなどの使用を避ける傾向にありましたが、
テーブル名をホバーすることでインデックスやトリガーの一覧を確認できるので、開発スタイルそのものが変わりそうです。
課題
あまり開発の工数を増やしたくないので、自前のパーサなどは作っていないのですが、それゆえの問題を抱えています
- コメントの場所を解析できない
- 関数名が始まる部分の位置情報などを教えてくれない
- コーティング中の未完成な状態での構文解析
それが原因で、下記の機能は実現できていません。
- 自動フォーマット
- 文脈を理解した補完(カラム名補完)
- より正確なシンタックスハイライト
- コメント文を利用した行単位の細やかな Language Server の制御
特に、自動フォーマット は欲しくてたまらない機能なのですが、パーサを開発するコストを懸念して実装していないままです。
(できれば PL/pgSQL のフォーマッタは PostgreSQL 本体に対応してほしいところ...)
libpg-query よりも優れたパーサをご存じの方がいればコメントをしていただけると幸いです。