Postgres.js - ไคลเอนต์ PostgreSQL สำหรับ Node.js และ Deno
(github.com/porsager)- เป็นไคลเอนต์ PostgreSQL ที่ใช้กับ Node.js และ Deno โดยใช้ ES6 tagged template strings เป็น API หลัก และติดตั้งผ่านแพ็กเกจ npm
postgres - พารามิเตอร์ของคิวรีจะถูกประมวลผลก่อนการแทรกค่า และแทนที่ด้วย placeholder ของโปรโตคอล PostgreSQL คือ
$1, $2, ...จากนั้นค่าจะถูกส่งไปยังฐานข้อมูลแยกต่างหาก เพื่อให้ฐานข้อมูลจัดการการ escape และ casting - การเรียก `sql``...``` รองรับการสร้างคิวรีที่ปลอดภัยและการประกอบคิวรีแบบไดนามิก โดยจัดการได้ทั้ง partial query, ฟิลเตอร์แบบไดนามิก, การจัดเรียงแบบไดนามิก และการประกอบ identifier ของชื่อตารางและชื่อคอลัมน์ โดยไม่มีความเสี่ยงจาก SQL injection ที่มาจากการต่อสตริงแบบทั่วไป
- สามารถตั้งค่าการเชื่อมต่อได้ผ่าน URL แบบ
postgres://, อ็อบเจ็กต์ตัวเลือก หรือ environment variable แบบเดียวกับที่ใช้ในpsqlและค่าในอ็อบเจ็กต์ตัวเลือกจะเขียนทับค่าจาก URL - คิวรีจะถูกรันเมื่อมีการ
awaitและผลลัพธ์จะถูกส่งกลับเป็นอาร์เรย์Resultที่แมปชื่อคอลัมน์เข้ากับอ็อบเจ็กต์ของแต่ละแถว และสามารถใช้.execute()เพื่อรันทันทีได้ - โฟลว์การใช้งานหลักประกอบด้วย insert/update แบบไดนามิก, การ insert หลายแถว, รายการค่า
where in, ทรานแซกชันsql.begin, savepoint, prepared transaction, คิวรีจากไฟล์, cursor และเมธอดคิวรีขั้นสูงอย่าง.forEach,.describe,.values,.raw - รองรับการเชื่อมกับความสามารถของ PostgreSQL เช่น
LISTEN/NOTIFY, การสมัครรับข้อมูลแบบเรียลไทม์ บนโปรโตคอล logical replication, การเปิดเผยสตรีม Node.js ของCOPY ...และการยกเลิกคิวรีที่กำลังทำงานอยู่- การสมัครรับข้อมูลแบบเรียลไทม์ต้องมีการสร้าง publication ในฐานข้อมูล, ตั้งค่า
wal_level = logicalในpostgresql.confและเชื่อมต่อด้วยผู้ใช้ replication หรือ superuser - API สตรีมของ
COPY ...ไม่ได้ให้ type safety และต้องจัดให้พารามิเตอร์ของ copy query สอดคล้องกับโค้ดอ่าน/เขียนสตรีมของ Node.js รวมถึงการจัดการ backpressure
- การสมัครรับข้อมูลแบบเรียลไทม์ต้องมีการสร้าง publication ในฐานข้อมูล, ตั้งค่า
- ตัวเลือกการแปลงข้อมูลรองรับการแปลงระหว่าง camelCase, PascalCase, Kebab-Case และ snake_case, การแปลงค่า
undefinedและฟังก์ชันแปลง column/value/row แบบกำหนดเอง - connection pool จะถูกสร้างแบบหน่วงเวลาเมื่อมีการสร้างคิวรี โดยจำนวนการเชื่อมต่อสูงสุดเริ่มต้นคือ
max: 10และระหว่างทำทรานแซกชันจะมีการจองการเชื่อมต่อไว้จากพูลก่อนส่งคืนหลังเสร็จสิ้น - รองรับ TCP socket API ของ Cloudflare Workers และหากต้องการให้ทำงานในสภาพแวดล้อม Workers ต้องตั้งค่า
compatibility_flags = ["nodejs_compat"]ในwrangler.toml - การรองรับ TypeScript มีเป้าหมายเพื่อให้ type ของ public API แต่มีข้อจำกัดว่าประเภทข้อมูลอาจไม่ได้อัปเดตพร้อมกันทุกครั้งเมื่อมีการเพิ่มหรือเปลี่ยนฟีเจอร์
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ถ้าอยากใช้ SQL โดยตรง เพื่อดึงจุดเด่นของ Postgres ออกมา ไลบรารีนี้ทำงานด้วยแล้วสนุกมาก
ไม่มี abstraction ที่ดูหรูและทำเป็นทันสมัยแบบ Prisma ไม่มี type annotation ซับซ้อนเหมือนไลบรารี TypeScript อื่น ๆ แค่เขียนคำสั่ง SQL ธรรมดา ๆ ตามสไตล์ JavaScript ก็พอ
หลายปีก่อนผมเบื่อกับการฝืนปรับตัวให้เข้ากับ Prisma เลยเริ่มเรียน Postgres อย่างจริงจังและลองทางเลือกหลายตัว แต่พอได้ใช้ตัวนี้ไม่กี่นาทีก็รู้สึกว่าจะไม่กลับไปอีกแล้ว
ไลบรารีนี้เร็วจริง ๆ อย่ามัวเทียบกับไลบรารีอื่นเพราะเห็นแค่ไวยากรณ์ string template คล้ายกันแล้วพลาดสาระสำคัญไป
มันไม่ได้พึ่ง
pgแต่ implement low-level client เองผมสร้างระบบที่โหลดเรคคอร์ดทีละ 10,000 รายการหลายครั้งด้วยตัวนี้ แล้วประสิทธิภาพเหนือชั้นมาก
ขึ้นกับ use case แค่นี้ก็อาจเปลี่ยนเกมได้แล้ว และถ้าคุ้นกับมาตรฐานที่คิดว่าเป็นไปได้ในสภาพแวดล้อมอย่าง Ruby ก็จะยิ่งน่าประทับใจ
นอกจากนี้ยังรองรับ logical decoding ด้วย จึงเปิดความเป็นไปได้หลายอย่างสำหรับการประมวลผลอีเวนต์การเปลี่ยนผ่าน เป็นโปรเจกต์ที่น่าประทับใจจริง ๆ และน่าเสียดายถ้ามองข้าม
บทความที่เกี่ยวข้อง:
Show HN: Postgres.js – Fastest Full-Featured PostgreSQL Client for Node and Deno - https://news.ycombinator.com/item?id=30794332 - มีนาคม 2022, 83 ความคิดเห็น
Show HN: Postgres.js – Fast PostgreSQL Client for Node.js - https://news.ycombinator.com/item?id=21864245 - ธันวาคม 2019, 12 ความคิดเห็น
อาจไม่ได้มีฟีเจอร์มากเท่าไลบรารีในโพสต์ต้นฉบับ แต่ https://pgtyped.dev/ ก็มีประโยชน์เหมือนกัน
ถ้าเขียน query เป็น ไฟล์ SQL pgtyped จะสร้างฟังก์ชันที่มี type กำกับให้เรียกด้วยพารามิเตอร์ของ query ได้
ผมเป็นผู้เขียนเอง อยากเสริมว่าตอนนี้รองรับ Cloudflare แล้วด้วย
ชอบตรงที่มี dependency 0 รายการ
สงสัยว่าประโยค “prepared statement จะถูกสร้างโดยอัตโนมัติสำหรับทุก query ที่สามารถอนุมานได้ว่าเป็น static query” หมายความว่าอย่างไรกันแน่
หมายถึงจะสร้าง prepared statement จริง ๆ ใน DB session แม้ไม่มี binding variable และ query นั้นถูกเรียกแค่ครั้งเดียวหรือเปล่า?
ถ้าใช่ก็น่าสนใจ แต่ดูเป็นแนวทางที่มีจุดยืนค่อนข้างชัดเจนทีเดียว
แต่โดยทั่วไปจะใช้ prepared statement หรือ portal แบบไม่มีชื่อ และ PostgreSQL จะจัดการเก็บกวาดให้ จึงเท่ากับคงไว้จริง ๆ แค่หนึ่งรายการต่อ session หรือก็คือต่อ connection
ผมไม่เข้าใจประโยคนั้นเลยไปดูโค้ด พบว่าที่พูดถึงคือการใช้ prepared statement แบบมีชื่อโดยอัตโนมัติ เพื่อ cache prepared statement ทั้งใน PostgreSQL และภายใน driver เอง มีการสร้าง signature ของ statement อยู่ ดังนั้นนี่เป็นการออกแบบที่มีจุดยืนชัดเจนจริง ๆ
ส่วนตัวคิดว่าโค้ดบริเวณที่สร้างข้อมูล parse/describe/bind/execute/sync เป็นหลักนั้นค่อนข้างไม่ค่อยดี: https://github.com/porsager/postgres/blob/bf082a5c0ffe214924...
มีอธิบายไว้ที่ https://www.postgresql.org/docs/current/sql-prepare.html และดูประเภทของแผนได้ในส่วน “Notes”
คิดว่าควรพูดถึง Zapatos ด้วย เป็น Postgres JavaScript client อีกตัวที่มีการออกแบบคล้ายกันมาก คือเขียน SQL ใน template string แต่ให้ type safety เต็มรูปแบบ
ถ้าชอบ TypeScript น่าจะถูกใจ: https://jawj.github.io/zapatos/
ส่วนตัวรู้สึกว่าเป็นหนึ่งในไลบรารี TypeScript ที่ออกแบบและทำเอกสารได้ดีที่สุดตัวหนึ่ง และเสียดายที่ไม่ค่อยเป็นที่รู้จัก
ผมเลือก PgTyped เป็นทางเลือกแทน และผ่านไป 2 ปีตอนนี้คิดว่าตัดสินใจย้ายถูกมาก
pgไม่ใช่ PostgresJsผมไปดูมาเพราะสงสัยว่าโปรเจกต์นี้เก่าแค่ไหน:
v1.0.1 - มกราคม 2020
v2.0.0 - มิถุนายน 2020 แต่เหมือนจะไม่เคยพ้น beta
v3.0.0 - มีนาคม 2022 ตั้งแต่นั้นดูเหมือนโปรเจกต์จะเริ่มจริงจัง
ดูน่าสนใจทีเดียว เลยสงสัยด้วยว่าแข็งแกร่งแค่ไหน
Postgres.js เป็นหนึ่งในไลบรารีระดับดีที่สุดเท่าที่เคยใช้มา
วิธีใช้ template ของ JavaScript นั้น intuitive มากจริง ๆ