Brian C 1aa08274a5
Migrate docs repo into monorepo (#2823)
* Move files over

* Finish initial port of content
2022-10-10 12:20:46 -05:00

115 lines
5.5 KiB
Markdown

---
title: Upgrading
slug: /guides/upgrading
---
# Upgrading to 8.0
node-postgres at 8.0 introduces a breaking change to ssl-verified connections. If you connect with ssl and use
```
const client = new Client({ ssl: true })
```
and the server's SSL certificate is self-signed, connections will fail as of node-postgres 8.0. To keep the existing behavior, modify the invocation to
```
const client = new Client({ ssl: { rejectUnauthorized: false } })
```
The rest of the changes are relatively minor and unlikely to cause issues; see [the announcement](/announcements#2020-02-25) for full details.
# Upgrading to 7.0
node-postgres at 7.0 introduces somewhat significant breaking changes to the public API.
## node version support
Starting with `pg@7.0` the earliest version of node supported will be `node@4.x LTS`. Support for `node@0.12.x` and `node@.10.x` is dropped, and the module wont work as it relies on new es6 features not available in older versions of node.
## pg singleton
In the past there was a singleton pool manager attached to the root `pg` object in the package. This singleton could be used to provision connection pools automatically by calling `pg.connect`. This API caused a lot of confusion for users. It also introduced a opaque module-managed singleton which was difficult to reason about, debug, error-prone, and inflexible. Starting in pg@6.0 the methods' documentation was removed, and starting in pg@6.3 the methods were deprecated with a warning message.
If your application still relies on these they will be _gone_ in `pg@7.0`. In order to migrate you can do the following:
```js
// old way, deprecated in 6.3.0:
// connection using global singleton
pg.connect(function(err, client, done) {
client.query(/* etc, etc */)
done()
})
// singleton pool shutdown
pg.end()
// ------------------
// new way, available since 6.0.0:
// create a pool
var pool = new pg.Pool()
// connection using created pool
pool.connect(function(err, client, done) {
client.query(/* etc, etc */)
done()
})
// pool shutdown
pool.end()
```
node-postgres ships with a built-in pool object provided by [pg-pool](https://github.com/brianc/node-pg-pool) which is already used internally by the `pg.connect` and `pg.end` methods. Migrating to a user-managed pool (or set of pools) allows you to more directly control their set up their life-cycle.
## client.query(...).on
Before `pg@7.0` the `client.query` method would _always_ return an instance of a query. The query instance was an event emitter, accepted a callback, and was also a promise. A few problems...
- too many flow control options on a single object was confusing
- event emitter `.on('error')` does not mix well with promise `.catch`
- the `row` event was a common source of errors: it looks like a stream but has no support for back-pressure, misleading users into trying to pipe results or handling them in the event emitter for a desired performance gain.
- error handling with a `.done` and `.error` emitter pair for every query is cumbersome and returning the emitter from `client.query` indicated this sort of pattern may be encouraged: it is not.
Starting with `pg@7.0` the return value `client.query` will be dependent on what you pass to the method: I think this aligns more with how most node libraries handle the callback/promise combo, and I hope it will make the "just works" :tm: feeling better while reducing surface area and surprises around event emitter / callback combos.
### client.query with a callback
```js
const query = client.query('SELECT NOW()', (err, res) => {
/* etc, etc */
})
assert(query === undefined) // true
```
If you pass a callback to the method `client.query` will return `undefined`. This limits flow control to the callback which is in-line with almost all of node's core APIs.
### client.query without a callback
```js
const query = client.query('SELECT NOW()')
assert(query instanceof Promise) // true
assert(query.on === undefined) // true
query.then((res) => /* etc, etc */)
```
If you do **not** pass a callback `client.query` will return an instance of a `Promise`. This will **not** be a query instance and will not be an event emitter. This is in line with how most promise-based APIs work in node.
### client.query(Submittable)
`client.query` has always accepted any object that has a `.submit` method on it. In this scenario the client calls `.submit` on the object, delegating execution responsibility to it. In this situation the client also **returns the instance it was passed**. This is how [pg-cursor](https://github.com/brianc/node-pg-cursor) and [pg-query-stream](https://github.com/brianc/node-pg-query-stream) work. So, if you need the event emitter functionality on your queries for some reason, it is still possible because `Query` is an instance of `Submittable`:
```js
const { Client, Query } = require('pg')
const query = client.query(new Query('SELECT NOW()'))
query.on('row', row => {})
query.on('end', res => {})
query.on('error', res => {})
```
`Query` is considered a public, documented part of the API of node-postgres and this form will be supported indefinitely.
_note: I have been building apps with node-postgres for almost 7 years. In that time I have never used the event emitter API as the primary way to execute queries. I used to use callbacks and now I use async/await. If you need to stream results I highly recommend you use [pg-cursor](https://github.com/brianc/node-pg-cursor) or [pg-query-stream](https://github.com/brianc/node-pg-query-stream) and **not** the query object as an event emitter._