Postgres.js - Node.js と Deno 向けの PostgreSQL クライアント
(github.com/porsager)- Node.js と Deno で使用する PostgreSQL クライアントで、ES6 tagged template strings を中核 API とし、npm パッケージ
postgresとしてインストールする構成 - クエリパラメータは補間前に処理され、PostgreSQL プロトコルのプレースホルダー
$1, $2, ...に置き換えられ、値は別途データベースに渡されて、エスケープとキャストをデータベースが処理する方式 sql``...``呼び出しは、安全なクエリ生成と動的クエリ構築をサポートし、通常の文字列連結による SQL injection のリスクなしに、部分クエリ、動的フィルター、動的ソート、テーブル名・カラム名の識別子構築を扱える- 接続は
postgres://URL、オプションオブジェクト、またはpsqlで使われる環境変数ベースで設定でき、オプションオブジェクトの値が URL の値を上書きする方式 - クエリは
awaitされたときに実行され、結果はカラム名を各行オブジェクトにマッピングしたResult配列として返される。.execute()を使うと即時実行できる - 主な利用フローは、動的 insert/update、複数行 insert、
where inの値リスト、トランザクションsql.begin、savepoint、prepared transaction、ファイルベースのクエリ、カーソル、.forEach、.describe、.values、.rawなどの高度なクエリメソッドで構成される - PostgreSQL 機能との連携として、
LISTEN/NOTIFY、論理レプリケーションプロトコルベースのリアルタイム購読、COPY ...の Node.js ストリーム公開、実行中クエリのキャンセルをサポート- リアルタイム購読には、データベース publication の作成、
postgresql.confのwal_level = logical、replication ユーザーまたは superuser 接続が必要 COPY ...ストリーム API は型安全性を提供せず、copy クエリパラメータと Node.js ストリームの読み書きコード、および backpressure 処理を合わせる必要がある
- リアルタイム購読には、データベース publication の作成、
- データ変換オプションは、camelCase、PascalCase、Kebab-Case と snake_case 間の変換、
undefined値の変換、ユーザー定義の column/value/row 変換関数をサポート - コネクションプールはクエリが作られるときに遅延生成され、デフォルトの最大接続数は
max: 10。トランザクション中は接続をプールから予約し、終了後に返却する方式 - Cloudflare Workers の TCP socket API をサポートし、Workers 環境で動作させるには
wrangler.tomlにcompatibility_flags = ["nodejs_compat"]の設定が必要 - TypeScript サポートは公開 API の型提供を目標としているが、機能追加や変更時に型が常に同時に更新されるとは限らないという制約がある
1件のコメント
Hacker News の意見
Postgres の優れた機能を活かして直接 SQLを書きたいなら、このライブラリで作業するのは本当に楽しい
Prisma のような派手で今風を装った抽象化もなく、ほかの TypeScript ライブラリのような複雑な型注釈もなく、ただ JavaScript らしく普通の SQL 文を書けばよい
数年前、Prisma に無理やり合わせて使うのにうんざりして Postgres をきちんと学び始め、いくつか代替を試したが、これを数分使ってみてもう戻らないと感じた
このライブラリは本当に速い。似たような文字列テンプレート構文だけを見て他のライブラリと比べていると、肝心な点を見落としてしまう
pgに依存せず、独自の低レベルクライアントを実装しているこれで一度に1万件単位のレコードを何度も投入するシステムを作ったが、性能は圧倒的だった
ユースケースによっては、これだけで状況を一変させ得るし、Ruby のような環境で可能だと思っていた水準に慣れているなら、さらに印象的だ
また論理デコーディングもサポートしており、遷移イベント処理にさまざまな可能性を開いてくれる。本当に印象的なプロジェクトなので見逃すのは惜しい
関連記事:
Show HN: Postgres.js – Fastest Full-Featured PostgreSQL Client for Node and Deno - https://news.ycombinator.com/item?id=30794332 - 2022年3月、コメント83件
Show HN: Postgres.js – Fast PostgreSQL Client for Node.js - https://news.ycombinator.com/item?id=21864245 - 2019年12月、コメント12件
元記事のライブラリほど機能は多くないかもしれないが、https://pgtyped.dev/ も便利だった
クエリを SQL ファイルとして書くと、pgtyped がクエリパラメータで呼び出せる型付き関数を生成してくれる
作者です。今は Cloudflare もサポートしていることを付け加えておきたい
依存関係が0個なのが気に入っている
「静的クエリだと推論できるすべてのクエリについて、prepared statement が自動生成される」という文が実際に何を意味するのか気になる
バインド変数がなく、そのクエリが一度しか実行されない場合でも、DB セッションに実際のprepared statementが作られるということなのか?
だとすると興味深いが、かなり強い主張を含んだアプローチに見える
ただし通常は名前なしの prepared statement やポータルを使い、PostgreSQL がそれを整理してくれるため、セッション、つまり接続ごとに実質1つだけ維持されるような形になる
その文が理解できなかったのでコードを見たところ、ここで言っているのは名前付き prepared statement を自動的に使い、PostgreSQL とドライバ内部に prepared statement をキャッシュするという意味だった。文のシグネチャを作っているので、これは確かに意見の入った設計だ
parse/describe/bind/execute/sync データが主に作られている箇所のコードは、個人的にはかなり微妙だと思う: https://github.com/porsager/postgres/blob/bf082a5c0ffe214924...
https://www.postgresql.org/docs/current/sql-prepare.html に説明されており、プランの種類については “Notes” セクションを見ればよい
ここでは Zapatos にも触れておくべきだと思う。テンプレート文字列の中に SQL を書く、非常によく似た設計のもう一つの Postgres JavaScript クライアントで、完全な型安全性を提供している
TypeScript が好きなら気に入るかもしれない: https://jawj.github.io/zapatos/
個人的には、設計とドキュメント化が最もよくできた TypeScript ライブラリの一つだと感じており、あまり知られていないのが惜しい
代替として PgTyped を選び、2年経った今では移行して本当に良かったと思っている
pgに依存している理由を知っているか気になるこのプロジェクトがどれくらい古いのか気になって見てみた:
v1.0.1 - 2020年1月
v2.0.0 - 2020年6月、ただしベータを抜けられず
v3.0.0 - 2022年3月、この頃からプロジェクトが本格的に始まったように見える
かなり興味深そうなので、どれくらい堅牢なのかも気になる
Postgres.js はこれまで使ってきたライブラリの中でも最高水準だ
JavaScript のテンプレートの活用方法が本当に直感的だ