4 Punkte von GN⁺ 2023-10-16 | 1 Kommentare | Auf WhatsApp teilen
  • Ein PostgreSQL-Client für Node.js und Deno, dessen Kern-API auf ES6 tagged template strings basiert und der über das npm-Paket postgres installiert wird
  • Query-Parameter werden vor der Interpolation verarbeitet und durch PostgreSQL-Protokoll-Platzhalter $1, $2, ... ersetzt; die Werte werden separat an die Datenbank übergeben, sodass Escaping und Casting von der Datenbank übernommen werden
  • Der Aufruf sql``...`` unterstützt die sichere Erstellung von Queries und den Aufbau dynamischer Queries und verarbeitet partielle Queries, dynamische Filter, dynamische Sortierung sowie Bezeichner für Tabellen- und Spaltennamen ohne das SQL-Injection-Risiko gewöhnlicher String-Verkettung
  • Verbindungen lassen sich über eine postgres://-URL, ein Optionsobjekt oder über umgebungsvariablenbasierte Konfiguration wie in psql einrichten; Werte aus dem Optionsobjekt überschreiben dabei die Werte aus der URL
  • Queries werden ausgeführt, wenn sie awaitet werden, und das Ergebnis wird als Result-Array zurückgegeben, das Spaltennamen auf die Objekte der einzelnen Zeilen abbildet; mit .execute() ist eine sofortige Ausführung möglich
  • Der zentrale Nutzungsablauf umfasst dynamische Insert-/Update-Operationen, Insert mehrerer Zeilen, where in-Wertelisten, Transaktionen mit sql.begin, Savepoints, vorbereitete Transaktionen, dateibasierte Queries, Cursor sowie fortgeschrittene Query-Methoden wie .forEach, .describe, .values und .raw
  • Zu den integrierten PostgreSQL-Funktionen gehören LISTEN/NOTIFY, Echtzeit-Abonnements auf Basis des logischen Replikationsprotokolls, die Bereitstellung von COPY ... als Node.js-Streams sowie das Abbrechen laufender Queries
    • Für Echtzeit-Abonnements sind das Anlegen einer Database-Publication, wal_level = logical in postgresql.conf sowie eine Verbindung mit einem Replikationsbenutzer oder Superuser erforderlich
    • Die Stream-API für COPY ... bietet keine Typsicherheit; Query-Parameter für Copy sowie Lese-/Schreibcode für Node.js-Streams und Backpressure-Behandlung müssen aufeinander abgestimmt werden
  • Die Optionen zur Datentransformation unterstützen Konvertierungen zwischen camelCase, PascalCase, Kebab-Case und snake_case, die Umwandlung von undefined-Werten sowie benutzerdefinierte Transformationsfunktionen für Spalten, Werte und Zeilen
  • Der Connection-Pool wird verzögert erstellt, wenn eine Query erzeugt wird; die Standardobergrenze liegt bei max: 10, und während Transaktionen wird eine Verbindung aus dem Pool reserviert und nach Abschluss zurückgegeben
  • Unterstützt die TCP-Socket-API von Cloudflare Workers; für den Betrieb in einer Workers-Umgebung ist in wrangler.toml die Einstellung compatibility_flags = ["nodejs_compat"] erforderlich
  • Die TypeScript-Unterstützung zielt darauf ab, Typen für die öffentliche API bereitzustellen, hat jedoch die Einschränkung, dass Typen bei Funktionsergänzungen oder Änderungen nicht immer gleichzeitig aktualisiert werden

1 Kommentare

 
GN⁺ 2023-10-16
Meinungen auf Hacker News
  • Wenn man die guten Funktionen von Postgres nutzen und direkt SQL schreiben möchte, macht die Arbeit mit dieser Bibliothek wirklich Spaß.
    Es gibt keine schicken, so tun, als seien sie hochmodernen Abstraktionen wie Prisma, keine komplizierten Typannotationen wie in anderen TypeScript-Bibliotheken, sondern man schreibt einfach ganz normale SQL-Statements, wie es zu JavaScript passt.
    Vor ein paar Jahren hatte ich genug davon, Prisma mit Gewalt passend zu machen, begann Postgres richtig zu lernen und probierte mehrere Alternativen aus. Nachdem ich dieses hier ein paar Minuten benutzt hatte, wusste ich, dass ich nicht mehr zurückgehen würde.

    • Ich wünschte, es gäbe für JavaScript eine Bibliothek wie Ecto aus Elixir. Unter den Tools für SQL war es das Beste, was ich bisher gesehen habe: einfach, leistungsfähig und leicht verständlich.
    • Schichten über SQL zu legen, mochte ich schon immer nicht besonders. SQL sollen sie mir erst aus meinen kalten, toten Händen nehmen.
    • Das macht bestimmt richtig Spaß, wenn man solchen Code übernimmt, nachdem der verantwortungsbewusste Entwickler das Unternehmen verlassen hat. Keine Typen, keine Kommentare, keine Abstraktionen, keine Migrationen, nur reines SQL.
    • Ich bin neugierig, was dir an Prismas raw query-Funktion nicht gefallen hat.
  • Diese Bibliothek ist wirklich schnell. Man sollte nicht nur wegen der ähnlichen String-Template-Syntax mit anderen Bibliotheken vergleichen und dabei den Kern übersehen.
    Sie hängt nicht von pg ab, sondern implementiert einen eigenen Low-Level-Client.
    Ich habe damit ein System gebaut, das mehrfach jeweils 10.000 Datensätze auf einmal lädt, und die Performance war überwältigend.

    • Etwas ausführlicher: Ich konnte etwa 10.000 bis 20.000 Datensätze in unter 20 ms laden; normalerweise hätte diese Arbeit ungefähr 150 ms gedauert.
      Je nach Anwendungsfall kann das allein schon ein Gamechanger sein, und wenn man an Maßstäbe gewöhnt ist, die man etwa in Umgebungen wie Ruby für möglich hält, ist es noch beeindruckender.
      Außerdem wird auch logisches Decoding unterstützt, was viele Möglichkeiten für die Verarbeitung von Übergangs-Events eröffnet. Ein wirklich beeindruckendes Projekt, das man nicht übergehen sollte.
  • Verwandte Beiträge:
    Show HN: Postgres.js – Fastest Full-Featured PostgreSQL Client for Node and Deno - https://news.ycombinator.com/item?id=30794332 - März 2022, 83 Kommentare
    Show HN: Postgres.js – Fast PostgreSQL Client for Node.js - https://news.ycombinator.com/item?id=21864245 - Dezember 2019, 12 Kommentare

  • Es hat vielleicht nicht so viele Funktionen wie die Bibliothek im Originalbeitrag, aber https://pgtyped.dev/ war ebenfalls nützlich.
    Wenn man Queries als SQL-Dateien schreibt, erzeugt pgtyped daraus typisierte Funktionen, die man mit Query-Parametern aufrufen kann.

  • Ich bin der Autor. Ich möchte ergänzen, dass jetzt auch Cloudflare unterstützt wird.

  • Mir gefällt, dass es 0 Abhängigkeiten hat.

    • Das ist heutzutage selten genug, um es ausdrücklich hervorzuheben.
  • Ich frage mich, was der Satz „Prepared Statements werden automatisch für alle Queries erzeugt, die als statische Queries abgeleitet werden können“ in der Praxis bedeutet.
    Heißt das, dass in der DB-Session tatsächlich ein Prepared Statement angelegt wird, auch wenn es keine Bind-Variablen gibt und diese Query nur einmal ausgeführt wird?
    Falls ja, ist das interessant, wirkt aber wie ein Ansatz mit einer ziemlich starken Meinung dahinter.

    • Wenn man parametrisierte Queries verwendet, muss man den Extended Query Flow von PostgreSQL nutzen, und viele Leute werden das als Prepared Statement betrachten. Das ist an sich keine besonders meinungsstarke Entscheidung.
      Normalerweise verwendet man jedoch unbenannte Prepared Statements oder Portale, und PostgreSQL räumt diese auf, sodass pro Session, also pro Verbindung, faktisch nur eines erhalten bleibt.
      Ich habe den Satz nicht verstanden und mir den Code angesehen; gemeint ist hier, dass automatisch benannte Prepared Statements verwendet werden, um Prepared Statements in PostgreSQL und intern im Treiber zu cachen. Da eine Statement-Signatur erzeugt wird, ist das definitiv ein meinungsstarkes Design.
      Den Code an der Stelle, an der parse/describe/bind/execute/sync-Daten hauptsächlich erzeugt werden, finde ich persönlich ziemlich unschön: https://github.com/porsager/postgres/blob/bf082a5c0ffe214924...
    • Postgres unterstützt zwei Arten von Prepared Statements: generic Prepared Statements, die Parameter entgegennehmen können, und custom Prepared Statements, die für eine bestimmte Ausführung vorbereitet werden und Parameter in den Plan einbeziehen.
      Das ist unter https://www.postgresql.org/docs/current/sql-prepare.html beschrieben; den Plantyp findet man im Abschnitt „Notes“.
  • Ich denke, hier sollte auch Zapatos erwähnt werden. Das ist ein weiterer Postgres-JavaScript-Client mit sehr ähnlichem Design, bei dem SQL in Template-Strings geschrieben wird, der aber vollständige Typsicherheit bietet.
    Wenn man TypeScript mag, könnte es einem gefallen: https://jawj.github.io/zapatos/
    Persönlich empfinde ich es als eine der am besten designten und dokumentierten TypeScript-Bibliotheken, und es ist schade, dass sie nicht bekannter ist.

    • Zapatos musste ich am Ende aufgeben. Es unterstützte keine mehreren Schemas, und die Typen waren nicht immer gut lesbar.
      Als Alternative habe ich PgTyped gewählt, und nach zwei Jahren bin ich sehr froh über den Wechsel.
    • Stimme zu. Dank der Kombination aus lateral join-Funktion und Shortcut-Funktionen ist es sehr einfach, ein Backend zu bauen, ohne auf die Nutzbarkeit zu verzichten und trotzdem echtes SQL zu schreiben.
    • Auf den ersten Blick scheint Zapatos nicht mit Cloudflare Workers kompatibel zu sein; falls das nicht stimmt, lasse ich mich gern korrigieren.
    • Ich frage mich, ob jemand weiß, warum zapatos von pg abhängt und nicht von PostgresJs.
  • Ich habe nachgesehen, weil ich wissen wollte, wie alt dieses Projekt ist:
    v1.0.1 - Januar 2020
    v2.0.0 - Juni 2020, blieb aber offenbar in der Beta
    v3.0.0 - März 2022, ab da sieht es so aus, als sei das Projekt richtig gestartet
    Es sieht ziemlich interessant aus, und ich frage mich auch, wie robust es ist.

    • Ich verwende es seit einiger Zeit in einer Produktionsumgebung mit Deno. Es ist ziemlich robust, aber die Dokumentation ist stark lückenhaft, sodass man sich bei komplexeren Aufgaben oft selbst durchprobieren muss.
  • Postgres.js gehört zu den besten Bibliotheken, die ich bisher verwendet habe.
    Die Art, wie JavaScript-Templates genutzt werden, ist wirklich intuitiv.