node-red-contrib-postgresql
Version:
Node-RED node for PostgreSQL, supporting parameters, split, back-pressure
180 lines (125 loc) • 7.13 kB
Markdown
//github.com/alexandrainst/node-red-contrib-postgresql)
is a [**Node-RED**](https://nodered.org/) node to query a [**PostgreSQL**](https://www.postgresql.org/) 🐘 database.
It supports *splitting* the resultset and *backpressure* (flow control), to allow working with large datasets.
It supports *parameterized queries* and *multiple queries*.
The response (rows) is provided in `msg.payload` as an array.
An exception is if the *Split results* option is enabled and the *Number of rows per message* is set to **1**,
then `msg.payload` is not an array but the single-row response.
Additional information is provided as `msg.pgsql.rowCount` and `msg.pgsql.command`.
See the [underlying documentation](https://node-postgres.com/apis/result) for details.
In the case of multiple queries, then `msg.pgsql` is an array.
## Inputs
### SQL query template
This node uses the [Mustache template system](https://github.com/janl/mustache.js) to generate queries based on the message:
```sql
-- INTEGER id column
SELECT * FROM table WHERE id = {{{ msg.id }}};
-- TEXT id column
SELECT * FROM table WHERE id = '{{{ msg.id }}}';
```
As an alternative to using the query template above, this node also accepts an SQL query via the `msg.query` parameter.
Parameters for parameterized queries can be passed as a parameter array `msg.params`:
```js
// In a function, provide parameters for the parameterized query
msg.params = [ msg.id ];
```
```sql
-- In this node, use a parameterized query
SELECT * FROM table WHERE id = $1;
```
As an alternative to numeric parameters,
named parameters for parameterized queries can be passed as a parameter object `msg.queryParameters`:
```js
// In a function, provide parameters for the named parameterized query
msg.queryParameters.id = msg.id;
```
```sql
-- In this node, use a named parameterized query
SELECT * FROM table WHERE id = $id;
```
*Note*: named parameters are not natively supported by PostgreSQL, and this library just emulates them,
so this is less robust than numeric parameters.
If the information about which database server to connect and how needs to be dynamic,
it is possible to pass a [custom client configuration](https://node-postgres.com/apis/client) in the message:
```js
msg.pgConfig = {
user?: string, // default process.env.PGUSER || process.env.USER
password?: string, //or function, default process.env.PGPASSWORD
host?: string, // default process.env.PGHOST
database?: string, // default process.env.PGDATABASE || process.env.USER
port?: number, // default process.env.PGPORT
connectionString?: string, // e.g. postgres://user:password@host:5432/database
ssl?: any, // passed directly to node.TLSSocket, supports all tls.connect options
types?: any, // custom type parsers
statement_timeout?: number, // number of milliseconds before a statement in query will time out, default is no timeout
query_timeout?: number, // number of milliseconds before a query call will timeout, default is no timeout
application_name?: string, // The name of the application that created this Client instance
connectionTimeoutMillis?: number, // number of milliseconds to wait for connection, default is no timeout
idle_in_transaction_session_timeout?: number, // number of milliseconds before terminating any session with an open idle transaction, default is no timeout
};
```
However, this does not use a [connection pool](https://node-postgres.com/features/pooling), and is therefore less efficient.
It is therefore recommended in most cases not to use `msg.pgConfig` at all and instead stick to the built-in configuration node.
You can install [**node-red-contrib-postgresql**](https://flows.nodered.org/node/node-red-contrib-postgresql) directly using the editor:
Select *Manage Palette* from the menu (top right), and then select the *Install* tab in the palette.
### Using npm
You can alternatively install the [npm-packaged node](https://www.npmjs.com/package/node-red-contrib-postgresql):
* Locally within your user data directory (by default, `$HOME/.node-red`):
```sh
cd $HOME/.node-red
npm i node-red-contrib-postgresql
```
* or globally alongside Node-RED:
```sh
npm i -g node-red-contrib-postgresql
```
You will then need to restart Node-RED.
## Backpressure
This node supports *backpressure* / *flow control*:
when the *Split results* option is enabled, it waits for a *tick* before releasing the next batch of lines,
to make sure the rest of your Node-RED flow is ready to process more data
(instead of risking an out-of-memory condition), and also conveys this information upstream.
So when the *Split results* option is enabled, this node will only output one message at first,
and then awaits a message containing a truthy `msg.tick` before releasing the next message.
To make this behaviour potentially automatic (avoiding manual wires), this node declares its ability by exposing a truthy `node.tickConsumer`
for downstream nodes to detect this feature, and a truthy `node.tickProvider` for upstream nodes.
Likewise, this node detects upstream nodes using the same back-pressure convention, and automatically sends ticks.
### Example of flow
Example adding a new column in a table, then streaming (split) many lines from that table, batch-updating several lines at a time,
then getting a sample consisting of a few lines:
Example: [flow.json](examples/flow.json)

The *debug* nodes illustrate some relevant information to look at.
## Sequences for split results
When the *Split results* option is enabled (streaming), the messages contain some information following the
conventions for [*messages sequences*](https://nodered.org/docs/user-guide/messages#message-sequences).
```js
{
payload: '...',
parts: {
id: 0.1234, // sequence ID, randomly generated (changes for every sequence)
index: 5, // incremented for each message of the same sequence
count: 6, // total number of messages; only available in the last message of a sequence
parts: {}, // optional upstream parts information
},
complete: true, // True only for the last message of a sequence
}
```
Major rewrite in July 2021 by [Alexandre Alapetite](https://alexandra.dk/alexandre.alapetite) ([Alexandra Institute](https://alexandra.dk)),
of parents forks:
[ ](https://github.com/andreabat/node-red-contrib-postgrestor) /
[ ](https://github.com/doing-things-with-node-red/node-red-contrib-postgrestor) /
[ ](https://github.com/HySoaKa/node-red-contrib-postgrestor),
with inspiration from [node-red-contrib-re-postgres](https://flows.nodered.org/node/node-red-contrib-re-postgres)
([code](https://github.com/elmagopy/node-red-contrib-re2-postgres)).
This node builds uppon the [node-postgres](https://github.com/brianc/node-postgres) (`pg`) library.
Contributions and collaboration welcome.
[ ](https: