Skip to content

Make async/await the primary examples in the docs #2932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
May 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/pages/announcements.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ _If you find `pg` valuable to you or your business please consider [supporting](

After a _very_ long time on my todo list I've ported the docs from my old hand-rolled webapp running on route53 + elb + ec2 + dokku (I know, I went overboard!) to [gatsby](https://www.gatsbyjs.org/) hosted on [netlify](https://www.netlify.com/) which is _so_ much easier to manage. I've released the code at [https://github.com/brianc/node-postgres-docs](https://github.com/brianc/node-postgres-docs) and invite your contributions! Let's make this documentation better together. Any time changes are merged to master on the documentation repo it will automatically deploy.

If you see an error in the docs, big or small, use the "edit on github" button to edit the page & submit a pull request right there. I'll get a new version out ASAP with your changes! If you want to add new pages of documentation open an issue if you need guidance, and I'll help you get started.
If you see an error in the docs, big or small, use the "edit on GitHub" button to edit the page & submit a pull request right there. I'll get a new version out ASAP with your changes! If you want to add new pages of documentation open an issue if you need guidance, and I'll help you get started.

I want to extend a special **thank you** to all the [supporters](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and [contributors](https://github.com/brianc/node-postgres/graphs/contributors) to the project that have helped keep me going through times of burnout or life "getting in the way." ❤️

Expand Down Expand Up @@ -116,7 +116,7 @@ [email protected]
To demonstrate the issue & see if you are vunerable execute the following in node:

```js
const { Client } = require('pg')
import { Client } from 'pg'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also updated the examples to use [ESM] instead of [CJS].

This doesn’t work, see #2534.

const client = new Client()
client.connect()

Expand Down
147 changes: 28 additions & 119 deletions docs/pages/apis/client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type Config = {
example to create a client with specific connection information:

```js
const { Client } = require('pg')
import { Client } from 'pg'

const client = new Client({
host: 'my.database-server.com',
Expand All @@ -42,33 +42,13 @@ const client = new Client({

## client.connect

Calling `client.connect` with a callback:

```js
const { Client } = require('pg')
import { Client } from 'pg'
const client = new Client()
client.connect((err) => {
if (err) {
console.error('connection error', err.stack)
} else {
console.log('connected')
}
})
```

Calling `client.connect` without a callback yields a promise:

```js
const { Client } = require('pg')
const client = new Client()
client
.connect()
.then(() => console.log('connected'))
.catch((err) => console.error('connection error', err.stack))
await client.connect()
```

_note: connect returning a promise only available in [email protected] or above_

## client.query

### QueryConfig
Expand All @@ -95,77 +75,43 @@ type QueryConfig {
}
```

### callback API

```ts
client.query(text: string, values?: any[], callback?: (err: Error, result: QueryResult) => void) => void
```

**Plain text query with a callback:**

```js
const { Client } = require('pg')
const client = new Client()
client.connect()
client.query('SELECT NOW()', (err, res) => {
if (err) throw err
console.log(res)
client.end()
})
client.query(text: string, values?: any[]) => Promise<Result>
```

**Parameterized query with a callback:**
**Plain text query**

```js
const { Client } = require('pg')
import { Client } from 'pg'
const client = new Client()
client.connect()
client.query('SELECT $1::text as name', ['brianc'], (err, res) => {
if (err) throw err
console.log(res)
client.end()
})
```

### Promise API
await client.connect()

If you call `client.query` with query text and optional parameters but **don't** pass a callback, then you will receive a `Promise` for a query result.
const result = await client.query('SELECT NOW()')
console.log(result)

```ts
client.query(text: string, values?: any[]) => Promise<Result>
await client.end()
```

**Plain text query with a promise**
**Parameterized query**

```js
const { Client } = require('pg')
import { Client } from 'pg'
const client = new Client()
client.connect()
client
.query('SELECT NOW()')
.then((result) => console.log(result))
.catch((e) => console.error(e.stack))
.then(() => client.end())
```

**Parameterized query with a promise**
await client.connect()

```js
const { Client } = require('pg')
const client = new Client()
client.connect()
client
.query('SELECT $1::text as name', ['brianc'])
.then((result) => console.log(result))
.catch((e) => console.error(e.stack))
.then(() => client.end())
const result = await client.query('SELECT $1::text as name', ['brianc'])
console.log(result)

await client.end()
```

```ts
client.query(config: QueryConfig) => Promise<Result>
```

**client.query with a QueryConfig and a callback**
**client.query with a QueryConfig**

If you pass a `name` parameter to the `client.query` method, the client will create a [prepared statement](/features/queries#prepared-statements).

Expand All @@ -177,42 +123,18 @@ const query = {
rowMode: 'array',
}

client.query(query, (err, res) => {
if (err) {
console.error(err.stack)
} else {
console.log(res.rows) // ['brianc']
}
})
```

**client.query with a QueryConfig and a Promise**
const result = await client.query(query)
console.log(result.rows) // ['brianc']

```js
const query = {
name: 'get-name',
text: 'SELECT $1::text',
values: ['brianc'],
rowMode: 'array',
}

// promise
client
.query(query)
.then((res) => {
console.log(res.rows) // ['brianc']
})
.catch((e) => {
console.error(e.stack)
})
await client.end()
```

**client.query with a `Submittable`**

If you pass an object to `client.query` and the object has a `.submit` function on it, the client will pass it's PostgreSQL server connection to the object and delegate query dispatching to the supplied object. This is an advanced feature mostly intended for library authors. It is incidentally also currently how the callback and promise based queries above are handled internally, but this is subject to change. It is also how [pg-cursor](https://github.com/brianc/node-pg-cursor) and [pg-query-stream](https://github.com/brianc/node-pg-query-stream) work.

```js
const Query = require('pg').Query
import { Query } from 'pg'
const query = new Query('select $1::text as name', ['brianc'])

const result = client.query(query)
Expand All @@ -222,9 +144,11 @@ assert(query === result) // true
query.on('row', (row) => {
console.log('row!', row) // { name: 'brianc' }
})

query.on('end', () => {
console.log('query done')
})

query.on('error', (err) => {
console.error(err.stack)
})
Expand All @@ -237,25 +161,10 @@ query.on('error', (err) => {
Disconnects the client from the PostgreSQL server.

```js
client.end((err) => {
console.log('client has disconnected')
if (err) {
console.log('error during disconnection', err.stack)
}
})
await client.end()
console.log('client has disconnected')
```

Calling end without a callback yields a promise:

```js
client
.end()
.then(() => console.log('client has disconnected'))
.catch((err) => console.error('error during disconnection', err.stack))
```

_note: end returning a promise is only available in pg7.0 and above_

## events

### error
Expand All @@ -264,7 +173,7 @@ _note: end returning a promise is only available in pg7.0 and above_
client.on('error', (err: Error) => void) => void
```

When the client is in the process of connecting, dispatching a query, or disconnecting it will catch and foward errors from the PostgreSQL server to the respective `client.connect` `client.query` or `client.end` callback/promise; however, the client maintains a long-lived connection to the PostgreSQL back-end and due to network partitions, back-end crashes, fail-overs, etc the client can (and over a long enough time period _will_) eventually be disconnected while it is idle. To handle this you may want to attach an error listener to a client to catch errors. Here's a contrived example:
When the client is in the process of connecting, dispatching a query, or disconnecting it will catch and foward errors from the PostgreSQL server to the respective `client.connect` `client.query` or `client.end` promise; however, the client maintains a long-lived connection to the PostgreSQL back-end and due to network partitions, back-end crashes, fail-overs, etc the client can (and over a long enough time period _will_) eventually be disconnected while it is idle. To handle this you may want to attach an error listener to a client to catch errors. Here's a contrived example:

```js
const client = new pg.Client()
Expand Down Expand Up @@ -301,7 +210,7 @@ type Notification {

```js
const client = new pg.Client()
client.connect()
await client.connect()

client.query('LISTEN foo')

Expand Down
27 changes: 12 additions & 15 deletions docs/pages/apis/cursor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ $ npm install pg pg-cursor
Instantiates a new Cursor. A cursor is an instance of `Submittable` and should be passed directly to the `client.query` method.

```js
const { Pool } = require('pg')
const Cursor = require('pg-cursor')
import { Pool } from 'pg'
import Cursor from 'pg-cursor'

const pool = new Pool()
const client = await pool.connect()
Expand Down Expand Up @@ -48,7 +48,7 @@ type CursorQueryConfig {

## read

### `cursor.read(rowCount: Number, callback: (err: Error, rows: Row[], result: pg.Result) => void) => void`
### `cursor.read(rowCount: Number) => Promise<pg.Result>`

Read `rowCount` rows from the cursor instance. The callback will be called when the rows are available, loaded into memory, parsed, and converted to JavaScript types.

Expand All @@ -57,25 +57,22 @@ If the cursor has read to the end of the result sets all subsequent calls to cur
Here is an example of reading to the end of a cursor:

```js
const { Pool } = require('pg')
const Cursor = require('pg-cursor')
import { Pool } from 'pg'
import Cursor from 'pg-cursor'

const pool = new Pool()
const client = await pool.connect()
const cursor = client.query(new Cursor('select * from generate_series(0, 5)'))
cursor.read(100, (err, rows) => {
if (err) {
throw err
}
assert(rows.length == 6)
cursor.read(100, (err, rows) => {
assert(rows.length == 0)
})
})

let rows = await cursor.read(100)
assert(rows.length == 6)

rows = await cursor.read(100)
assert(rows.length == 0)
```

## close

### `cursor.close(callback: () => void) => void`
### `cursor.close() => Promise<void>`

Used to close the cursor early. If you want to stop reading from the cursor before you get all of the rows returned, call this.
Loading