Skip to content

sql-storage-adapter v0.6.15

Choose a tag to compare

@github-actions github-actions released this 15 Oct 18:59
· 366 commits to master since this release
fc86133

Added

  • Pool control on the PostgreSQL adapter. withConnection(fn) holds one pooled connection for fn, for session settings, session advisory locks, temporary tables and statements outside a transaction. It returns the connection to the pool when fn resolves. It closes the connection when fn throws (rethrowing fn's error) or returns inside a transaction it began (rejecting; pg 8.21 and later report the status). The connection refuses statements after fn ends. getPoolStats() returns { total, idle, waiting }, or null when the adapter is not open. transaction(fn, { isolationLevel, readOnly, deferrable }) sets how the transaction begins, on the adapter and on a held connection, and refuses an unknown isolation level before any SQL is sent. The allowExitOnIdle option passes pg's option to the pool, so Node can exit while the pool is idle. The types are PostgresConnection, PostgresPoolStats, PostgresTransactionOptions and PostgresIsolationLevel.
  • strict on createDatabase() and resolveStorageAdapter(), for servers: only the database the options name opens. A postgres candidate that fails ends resolution with a StorageResolutionError whose causes hold its error, whatever priority lists after it; without strict it falls through to better-sqlite3, IndexedDB and sql.js. With DATABASE_URL or Postgres options that name a server and no priority, ['postgres'] is the whole list. An explicit file path outranks DATABASE_URL, which is then not read. A url or postgres option that names no server ({ url: process.env.DATABASE_URL } with the variable unset), or Postgres options given to the resolver with no DATABASE_URL to fill them in, fails instead of opening the local default, unless a file is given. strict is off by default, and resolution without it is unchanged.

Changed

  • CI runs the PostgreSQL integration suite (17 tests) and the dialect and full-text search suite (9 tests) against its PostgreSQL 16 service; both skipped in CI before. They read POSTGRES_TEST_URL, as the createDatabase specs do: the integration suite read TEST_POSTGRES_URL, which it still reads when POSTGRES_TEST_URL is unset, and the dialect suite read DATABASE_URL, which also moves the resolver's default to Postgres. The integration suite fails when its server cannot be reached, where its tests returned early and passed, and its granular-configuration test takes the host, port, database, user and password from the URL.

Fixed

  • PostgreSQL transaction(): when the connection broke and ROLLBACK failed too, the ROLLBACK error replaced the transaction's own error. A caller looking for a unique violation, or its own exception, saw "Client has encountered a connection error and is not queryable" instead. The transaction's own error (the callback's, or COMMIT's) is thrown now, with the ROLLBACK error on it as a non-enumerable rollbackError property, and the adapter logs one warning. The broken connection is closed instead of returned to the pool. It was released as healthy.
  • PostgreSQL transaction() and withConnection(): a connection the server closed while a callback held it, between statements, ended the process. pg emits that error on the client when no query is running, and pg-pool listens only on idle clients. Examples are idle_in_transaction_session_timeout, a failover and an administrator's pg_terminate_backend. A checked-out connection now has a listener; the error closes the connection when it is released, and the pool opens a new one. A BEGIN that fails closes the connection too.
  • PostgreSQL: a transaction's handle used after its transaction ended ran its statements on the pooled connection it had held. When another caller held that connection inside a transaction, the statements ran in that caller's transaction and were undone by its rollback, after the handle's caller had been told they succeeded. Once its transaction has ended, the handle now runs on the pool, as the adapter's own statements do. Its transaction() begins a new transaction; before, it ran the callback with no transaction at all. This matches better-sqlite3, where a handle used after its transaction waits like any other caller.
  • The createDatabase() documentation and the remote-connection guide said that createDatabase() with no options opens PostgreSQL when DATABASE_URL is set. It opens the local default; pass url: process.env.DATABASE_URL. The README's cloud example passed postgres: { connectionString: process.env.DATABASE_URL }, which opens a local SQLite file when the variable is unset; it passes url with strict now.
  • The README showed createDatabase() taking performance and hooks options. DatabaseOptions has neither, and no adapter applies a tier or runs hooks: the README now shows the exported resolvePerformanceConfig() and combineHooks() instead, and the optimization guide says so at its top.