4 points par GN⁺ 2023-10-16 | 1 commentaires | Partager sur WhatsApp
  • Client PostgreSQL destiné à Node.js et Deno, dont l’API principale repose sur les template strings taggées ES6 et qui s’installe via le package npm postgres
  • Les paramètres de requête sont traités avant l’interpolation, remplacés par les placeholders du protocole PostgreSQL $1, $2, ..., et les valeurs sont transmises séparément à la base de données, qui se charge de l’échappement et du cast
  • Les appels sql``...`` permettent de générer des requêtes sûres et de composer des requêtes dynamiques, en gérant requêtes partielles, filtres dynamiques, tris dynamiques et identifiants de noms de tables ou de colonnes sans risque d’injection SQL lié à la concaténation de chaînes classique
  • La connexion peut être configurée via une URL postgres://, un objet d’options ou les variables d’environnement utilisées par psql, les valeurs de l’objet d’options remplaçant celles de l’URL
  • Les requêtes sont exécutées lorsqu’elles sont utilisées avec await, et le résultat est renvoyé sous forme de tableau Result qui mappe les noms de colonnes sur chaque objet de ligne ; .execute() permet de les exécuter immédiatement
  • Les principaux flux d’utilisation couvrent les insert/update dynamiques, l’insertion de plusieurs lignes, les listes de valeurs where in, les transactions sql.begin, les savepoints, les transactions préparées, les requêtes basées sur des fichiers, les curseurs, ainsi que des méthodes de requête avancées comme .forEach, .describe, .values et .raw
  • L’intégration avec les fonctionnalités PostgreSQL prend en charge LISTEN/NOTIFY, les abonnements en temps réel basés sur le protocole de réplication logique, l’exposition des flux Node.js pour COPY ..., ainsi que l’annulation des requêtes en cours
    • Les abonnements en temps réel nécessitent la création d’une publication dans la base de données, wal_level = logical dans postgresql.conf, et une connexion avec un utilisateur de réplication ou un superuser
    • L’API de flux COPY ... n’offre pas de sûreté de type ; il faut aligner les paramètres des requêtes copy avec le code de lecture/écriture des streams Node.js et la gestion de la backpressure
  • Les options de transformation des données prennent en charge les conversions entre camelCase, PascalCase, Kebab-Case et snake_case, la transformation des valeurs undefined, ainsi que des fonctions personnalisées de transformation de colonnes, valeurs et lignes
  • Le pool de connexions est créé paresseusement lors de la création d’une requête ; le nombre maximal de connexions par défaut est max: 10, et pendant une transaction, une connexion est réservée dans le pool puis rendue à la fin
  • Prend en charge l’API TCP socket de Cloudflare Workers ; pour fonctionner dans l’environnement Workers, compatibility_flags = ["nodejs_compat"] doit être configuré dans wrangler.toml
  • La prise en charge de TypeScript vise à fournir les types de l’API publique, avec la limite que les types ne sont pas toujours mis à jour en même temps que les ajouts ou changements de fonctionnalités

1 commentaires

 
GN⁺ 2023-10-16
Avis Hacker News
  • Si vous voulez tirer parti des bonnes fonctionnalités de Postgres en écrivant du SQL directement, cette bibliothèque est vraiment agréable à utiliser
    Pas d’abstractions tape-à-l’œil qui se donnent des airs modernes comme Prisma, pas d’annotations de types complexes comme dans d’autres bibliothèques TypeScript : on écrit simplement des requêtes SQL ordinaires, comme on le ferait en JavaScript
    Il y a quelques années, lassé de devoir faire rentrer Prisma au chausse-pied, j’ai commencé à vraiment apprendre Postgres et essayé plusieurs alternatives ; après avoir utilisé celle-ci quelques minutes, j’ai compris que je ne reviendrais pas en arrière

    • J’aimerais qu’il existe en JavaScript une bibliothèque comme Ecto en Elixir. Parmi les outils que j’ai vus pour travailler avec SQL, c’est le meilleur jusqu’ici : simple, puissant et facile à comprendre
    • Les couches ajoutées par-dessus SQL ne m’ont jamais vraiment convaincu. SQL, il faudra me l’arracher de mes mains froides
    • Ça doit être vraiment amusant de reprendre ce genre de code après le départ de l’entreprise du développeur responsable. Pas de types, pas de commentaires, pas d’abstraction, pas de migrations : juste du SQL pur
    • Je suis curieux de savoir ce qui ne vous a pas plu dans la fonctionnalité de raw query de Prisma
  • Cette bibliothèque est vraiment rapide. Il ne faut pas passer à côté de l’essentiel en la comparant à d’autres bibliothèques seulement parce qu’elles ont une syntaxe similaire de templates de chaînes
    Elle ne dépend pas de pg et implémente son propre client bas niveau
    J’ai construit avec elle un système qui chargeait plusieurs fois des lots de 10 000 enregistrements, et les performances étaient écrasantes

    • Pour donner plus de détails, il était possible de charger environ 10 000 à 20 000 enregistrements en moins de 20 ms, alors que l’opération aurait normalement pris autour de 150 ms
      Selon le cas d’usage, cela peut à lui seul changer la donne, et c’est encore plus impressionnant si vous êtes habitué aux niveaux de performance que l’on pensait possibles dans des environnements comme Ruby
      Elle prend aussi en charge le décodage logique, ce qui ouvre de nombreuses possibilités pour le traitement d’événements de transition. C’est un projet vraiment impressionnant qu’il serait dommage d’ignorer
  • Articles liés :
    Show HN: Postgres.js – Fastest Full-Featured PostgreSQL Client for Node and Deno - https://news.ycombinator.com/item?id=30794332 - mars 2022, 83 commentaires
    Show HN: Postgres.js – Fast PostgreSQL Client for Node.js - https://news.ycombinator.com/item?id=21864245 - décembre 2019, 12 commentaires

  • Elle n’a peut-être pas autant de fonctionnalités que la bibliothèque de l’article d’origine, mais https://pgtyped.dev/ m’a aussi été utile
    Si vous écrivez les requêtes sous forme de fichiers SQL, pgtyped génère des fonctions typées que vous pouvez appeler avec les paramètres de la requête

  • Je suis l’auteur. Je voudrais ajouter qu’elle prend désormais aussi en charge Cloudflare

  • J’aime le fait qu’elle ait 0 dépendance

    • C’est suffisamment rare de nos jours pour mériter d’être souligné
  • Je me demande ce que signifie concrètement la phrase « des instructions préparées sont générées automatiquement pour toutes les requêtes qui peuvent être déduites comme statiques »
    Est-ce que cela veut dire qu’une véritable instruction préparée est créée dans la session DB même si la requête n’a pas de variable liée et n’est exécutée qu’une seule fois ?
    Si c’est le cas, c’est intéressant, mais cela me semble être une approche assez tranchée

    • Si vous utilisez des requêtes paramétrées, vous devez forcément utiliser le flux de requêtes étendu de PostgreSQL, et beaucoup de gens considèreront cela comme une instruction préparée. En soi, ce n’est pas un choix particulièrement dogmatique
      En général toutefois, on utilise une instruction préparée ou un portail sans nom, et PostgreSQL s’en charge, si bien qu’il n’en reste effectivement qu’un par session, c’est-à-dire par connexion
      Comme cette phrase n’était pas claire pour moi, j’ai regardé le code : ce dont il est question ici, c’est l’utilisation automatique d’instructions préparées nommées afin de mettre en cache les instructions préparées côté PostgreSQL et à l’intérieur du pilote. Comme une signature d’instruction est créée, c’est clairement un choix de conception affirmé
      Le code où sont principalement créées les données parse/describe/bind/execute/sync me paraît personnellement assez mauvais : https://github.com/porsager/postgres/blob/bf082a5c0ffe214924...
    • Postgres prend en charge deux types d’instructions préparées. Il y a les instructions préparées génériques, qui peuvent recevoir des paramètres, et les instructions préparées personnalisées, préparées pour une exécution donnée et qui intègrent les paramètres dans le plan
      C’est expliqué ici : https://www.postgresql.org/docs/current/sql-prepare.html ; pour le type de plan, voir la section « Notes »
  • Il me semble qu’il faut aussi mentionner Zapatos ici. C’est un autre client JavaScript pour Postgres au design très similaire, avec du SQL dans des chaînes de template, mais qui offre une sécurité de typage complète
    Si vous aimez TypeScript, cela pourrait vous plaire : https://jawj.github.io/zapatos/
    Personnellement, je trouve que c’est l’une des bibliothèques TypeScript les mieux conçues et les mieux documentées, et je regrette qu’elle ne soit pas plus connue

    • J’ai finalement dû abandonner Zapatos. Il ne prenait pas en charge plusieurs schémas, et les types générés n’étaient pas toujours faciles à lire
      J’ai choisi PgTyped comme alternative, et deux ans plus tard je suis vraiment content d’avoir migré
    • D’accord. Grâce à la fonctionnalité de lateral join et à la combinaison de fonctions raccourcies, il est très facile de construire un backend en écrivant du vrai SQL sans sacrifier l’ergonomie
    • À première vue, Zapatos ne semble pas compatible avec Cloudflare Workers ; je serais ravi qu’on me corrige si ce n’est pas le cas
    • Je me demande si quelqu’un sait pourquoi zapatos dépend de pg plutôt que de PostgresJs
  • Je me suis demandé depuis combien de temps ce projet existait, alors j’ai regardé :
    v1.0.1 - janvier 2020
    v2.0.0 - juin 2020, mais elle n’est jamais sortie de bêta
    v3.0.0 - mars 2022, moment à partir duquel le projet semble avoir vraiment démarré
    Cela a l’air assez intéressant, et je me demande aussi à quel point c’est robuste

    • Je l’utilise depuis un moment en production avec Deno. C’est assez solide, mais la documentation manque beaucoup ; pour les tâches complexes, il faut souvent tâtonner soi-même pour trouver comment faire
  • Postgres.js fait partie des meilleures bibliothèques que j’aie utilisées jusqu’ici
    Sa façon d’exploiter les templates JavaScript est vraiment intuitive