Skip to content

Commit

Permalink
Move docs from old repo
Browse files Browse the repository at this point in the history
Initial port of old doc files
  • Loading branch information
brianc committed Jul 15, 2019
1 parent 1b9603c commit 0420b2b
Show file tree
Hide file tree
Showing 35 changed files with 15,782 additions and 387 deletions.
59 changes: 26 additions & 33 deletions config.js
@@ -1,35 +1,28 @@
const config = {
"gatsby": {
"pathPrefix": "/",
"siteUrl": "https://learn.hasura.io",
"gaTrackingId": null
},
"header": {
"logo": "https://graphql-engine-cdn.hasura.io/img/hasura_icon_white.svg",
"title": "Gatsby Gitbook Boilerplate",
"githubUrl": "https://github.com/hasura/gatsby-gitbook-boilerplate",
"helpUrl": "",
"tweetText": "",
"links": [
{ "text": "", "link": ""}
],
},
"sidebar": {
"forcedNavOrder": [
"/introduction",
"/codeblock"
],
"links": [
{ "text": "", "link": ""},
]
},
"siteMetadata": {
"title": "Gatsby Gitbook Boilerplate | Hasura",
"description": "Documentation built with mdx. Powering learn.hasura.io ",
"ogImage": null,
"docsLocation": "https://github.com/hasura/gatsby-gitbook-boilerplate/tree/master/content",
"favicon": "https://graphql-engine-cdn.hasura.io/img/hasura_icon_black.svg"
},
};
gatsby: {
pathPrefix: '/',
siteUrl: 'https://learn.hasura.io',
gaTrackingId: null,
},
header: {
logo: '',
title: 'node-postgres',
githubUrl: 'https://github.com/brianc/node-postgres',
helpUrl: '',
tweetText: '',
links: [{ text: '', link: '' }],
},
sidebar: {
forcedNavOrder: ['/', '/announcements', '/features', '/guides', '/api'],
links: [{ text: '', link: '' }],
},
siteMetadata: {
title: 'node-postgres',
description: 'Documentation for node-postgres, the postgres database client for node.js',
ogImage: null,
docsLocation: 'https://github.com/hasura/gatsby-gitbook-boilerplate/tree/master/content',
favicon: 'https://graphql-engine-cdn.hasura.io/img/hasura_icon_black.svg',
},
}

module.exports = config;
module.exports = config
56 changes: 56 additions & 0 deletions content/announcements.mdx
@@ -0,0 +1,56 @@
## 2017-08-12 - code execution vulnerability

Today [@sehrope](https://github.com/sehrope) found and reported a code execution vulnerability in node-postgres. This affects all versions from `pg@2.x` through `pg@7.1.0`.

I have published a fix on the tip of each major version branch of all affected versions as well as a fix on each minor version branch of `pg@6.x` and `pg@7.x`:

### Fixes

The following versions have been published to npm & contain a patch to fix the vulnerability:

```
pg@2.11.2
pg@3.6.4
pg@4.5.7
pg@5.2.1
pg@6.0.5
pg@6.1.6
pg@6.2.5
pg@6.3.3
pg@6.4.2
pg@7.0.3
pg@7.1.2
```

### Example

To demonstrate the issue & see if you are vunerable execute the following in node:

```js
const { Client } = require('pg')
const client = new Client()
client.connect()

const sql = `SELECT 1 AS "\\'/*", 2 AS "\\'*/\n + console.log(process.env)] = null;\n//"`

client.query(sql, (err, res) => {
client.end()
})
```

You will see your environment variables printed to your console. An attacker can use this exploit to execute any arbitrary node code within your process.

### Impact

This vulnerability _likely_ does not impact you if you are connecting to a database you control and not executing user-supplied sql. Still, you should **absolutely** upgrade to the most recent patch version as soon as possible to be safe.

Two attack vectors we quickly thought of:

- 1 - executing unsafe, user-supplied sql which contains a malicious column name like the one above.
- 2 - connecting to an untrusted database and executing a query which returns results where any of the column names are malicious.

### Support

I have created [an issue](https://github.com/brianc/node-postgres/issues/1408) you can use to discuss the vulnerability with me or ask questions, and I have reported this issue [on twitter](https://twitter.com/briancarlson) and directly to Heroku and [nodesecurity.io](https://nodesecurity.io/).

I take security very seriously. If you or your company benefit from node-postgres **[please sponsor my work](https://www.patreon.com/node_postgres)**: this type of issue is one of the many things I am responsible for, and I want to be able to continue to tirelessly provide a world-class PostgreSQL experience in node for years to come.
3 changes: 3 additions & 0 deletions content/api.mdx
@@ -0,0 +1,3 @@
---
title: API
---
228 changes: 228 additions & 0 deletions content/api/1-pool.mdx
@@ -0,0 +1,228 @@
---
title: pg.Pool
slug: /api/pool
---

## new Pool([config: object])

Every field of the `config` object is entirely optional. The config passed to the pool is also passed to every client instance within the pool when the pool creates that client.

```flow
config = {
// all valid client config options are also valid here
// in addition here are the pool specific configuration parameters:
// number of milliseconds to wait before timing out when connecting a new client
// by default this is 0 which means no timeout
connectionTimeoutMillis?: int,
// number of milliseconds a client must sit idle in the pool and not be checked out
// before it is disconnected from the backend and discarded
// default is 10000 (10 seconds) - set to 0 to disable auto-disconnection of idle clients
idleTimeoutMillis?: int,
// maximum number of clients the pool should contain
// by default this is set to 10.
max?: int,
}
```

example to create a new pool with configuration:

```js
const { Pool } = require('pg')

const pool = new Pool({
host: 'localhost',
user: 'database-user',
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
})
```

## pool.connect

### `pool.connect(callback: (err?: Error, client: pg.Client, release: releaseCallback) => void) => void`

Acquires a client from the pool. If the pool is 'full' and all clients are currently checked out, this will wait in a FIFO queue until a client becomes available by it being released back to the pool. If there are idle clients in the pool it will be returned to the callback on `process.nextTick`. If the pool is not full a new client will be created & returned to this callback.

```js
const { Pool } = require('pg')

const pool = new Pool()

pool.connect((err, client, release) => {
if (err) {
return console.error('Error acquiring client', err.stack)
}
client.query('SELECT NOW()', (err, result) => {
release()
if (err) {
return console.error('Error executing query', err.stack)
}
console.log(result.rows)
})
})
```

### `pool.connect() => Promise<pg.Client>`

```js
const { Pool } = require('pg')

const pool = new Pool()

;(async function() {
const client = await pool.connect()
await client.query('SELECT NOW()')
client.release()
})()
```

<div class="alert alert-warning">
You <strong>must</strong> call the <span className="code">releaseCallback</span> or{' '}
<span className="code">client.release</span> (which points to the <span className="code">releaseCallback</span>) when
you are finished with a client. If you forget to release the client then your application will quickly exhaust
available, idle clients in the pool and all further calls to <span className="code">pool.connect</span> will timeout
with an error or hang indefinitely if you have <span className="code">connectionTimeoutMills</span> configured to 0.
</div>

## releaseCallback

### release: (err?: Error)

The `releaseCallback` releases an acquired client back to the pool. If you pass a truthy value in the `err` position to the callback, instead of releasing the client to the pool, the pool will be instructed to disconnect and destroy this client, leaving a space within itself for a new client.

```js
const { Pool } = require('pg')

const pool = new Pool()
assert(pool.totalCount === 0)
assert(pool.idleCount === 0)
;(async function() {
const client = await pool.connect()
await client.query('SELECT NOW()')
assert(pool.totalCount === 1)
assert(pool.idleCount === 0)

// tell the pool to destroy this client
client.release(true)
assert(pool.idleCount === 0)
assert(pool.totalCount === 0)
})()
```

Client instances returned from `pool.connect` will have a `release` method which will release them from the pool. This is the same method that is passed to the connect callback as the 3rd argument if you're using the pool with callbacks.

```js
const { Pool } = require('pg')

const pool = new Pool()
pool.connect((err, client, release) => {
assert(client.release === release)
})
```

## pool.query

Often we only need to run a single query on the database, so as convenience the pool has a method to run a query on the first available idle client and return its result.

### pool.query(callback: (err?: Error, result: pg.Result)) => void

```js
const { Pool } = require('pg')

const pool = new Pool()

pool.query('SELECT $1::text as name', ['brianc'], (err, result) => {
if (err) {
return console.error('Error executing query', err.stack)
}
console.log(result.rows[0].name) // brianc
})
```

Promises are also supported:

### `pool.query() => Promise<pg.Result>`

```js
const { Pool } = require('pg')

const pool = new Pool()

pool
.query('SELECT $1::text as name', ['brianc'])
.then(res => console.log(res.rows[0].name)) // brianc
.catch(err => console.error('Error executing query', err.stack))
```

Notice in the example above no `releaseCallback` was necessary. The pool is doing the acquiring and releasing internally. I find `pool.query` to be a handy shortcut in a lot of situations.

<div className="alert alert-danger">
Do <strong>not</strong> use pool.query if you need transactional integrity: the pool will dispatch every query passed
to pool.query on the first available idle client. Transactions within PostgreSQL are scoped to a single client and so
dispatching individual queries within a single transaction across multiple, random clients will cause big problems in
your app and not work. For more info please read <a href="/features/transactions">transactions</a>.
</div>

## pool.end

Calling `pool.end` will drain the pool of all active clients, disconnect them, and shut down any internal timers in the pool. It is common to call this at the end of a script using the pool or when your process is attempting to shut down cleanly.

```js
// again both promises and callbacks are supported:
const { Pool } = require('pg')

const pool = new Pool()

// either this:
pool.end(() => {
console.log('pool has ended')
})

// or this:
pool.end().then(() => console.log('pool has ended'))
```

## `pool.totalCount: int`

The total number of clients existing within the pool.

## `pool.idleCount: int`

The number of clients which are not checked out but are currently idle in the pool.

## `pool.waitingCount: int`

The number of queued requests waiting on a client when all clients are checked out. It can be helpful to monitor this number to see if you need to adjust the size of the pool.

## `pool.on('connect', (client: Client) => void) => void`

Whenever the pool establishes a new client connection to the PostgreSQL backend it will emit the `connect` event with the newly connected client. This presents an opportunity for you to run setup commands on a client.

```js
const pool = new Pool()
pool.on('connect', client => {
client.query('SET DATESTYLE = iso, mdy')
})
```

## `pool.on('acquire', (client: Client) => void) => void`

Whenever the a client is checked out from the pool the pool will emit the `acquire` event with the client that was acquired.

## `pool.on('error', (err: Error, client: Client) => void) => void`

When a client is sitting idly in the pool it can still emit errors because it is connected to a live backend. If the backend goes down or a network partition is encountered all the idle, connected clients in your application will emit an error _through_ the pool's error event emitter. The error listener is passed the error as the first argument and the client upon which the error occurred as the 2nd argument. The client will be automatically terminated and removed from the pool, it is only passed to the error handler in case you want to inspect it.

<div class="alert alert-warning">
It is important you add an event listener to the pool to catch errors. Just like other event emitters, if a pool emits
an <span className="code">error</span> event and no listeners are added node will emit an uncaught error and
potentially exit.
</div>

## `pool.on('remove', (client: Client) => void) => void`

Whenever a client is closed & removed from the pool the pool will emit the `remove` event.

0 comments on commit 0420b2b

Please sign in to comment.