34.9. Asynchronous Notification

|34.9. Asynchronous Notification|                |                             |                  |                        |
|:-----------------------------:|----------------|-----------------------------|------------------|------------------------|
|  [Prev](libpq-fastpath.html)  |[Up](libpq.html)|Chapter 34. libpq — C Library|[Home](index.html)| [Next](libpq-copy.html)|

---

## 34.9. Asynchronous Notification

[]()

PostgreSQL offers asynchronous notification via the `LISTEN` and `NOTIFY` commands. A client session registers its interest in a particular notification channel with the `LISTEN` command (and can stop listening with the `UNLISTEN` command). All sessions listening on a particular channel will be notified asynchronously when a `NOTIFY` command with that channel name is executed by any session. A “payload” string can be passed to communicate additional data to the listeners.

libpq applications submit `LISTEN`, `UNLISTEN`, and `NOTIFY` commands as ordinary SQL commands. The arrival of `NOTIFY` messages can subsequently be detected by calling `PQnotifies`.[]()

 The function `PQnotifies` returns the next notification from a list of unhandled notification messages received from the server. It returns a null pointer if there are no pending notifications. Once a notification is returned from `PQnotifies`, it is considered handled and will be removed from the list of notifications.

```
PGnotify *PQnotifies(PGconn *conn);

typedef struct pgNotify
{
    char *relname;              /* notification channel name */
    int  be_pid;                /* process ID of notifying server process */
    char *extra;                /* notification payload string */
} PGnotify;

```

 After processing a `PGnotify` object returned by `PQnotifies`, be sure to free it with [`PQfreemem`](libpq-misc.html#LIBPQ-PQFREEMEM). It is sufficient to free the `PGnotify` pointer; the `relname` and `extra` fields do not represent separate allocations. (The names of these fields are historical; in particular, channel names need not have anything to do with relation names.)

[Example 34.2](libpq-example.html#LIBPQ-EXAMPLE-2) gives a sample program that illustrates the use of asynchronous notification.

`PQnotifies` does not actually read data from the server; it just returns messages previously absorbed by another libpq function. In ancient releases of libpq, the only way to ensure timely receipt of `NOTIFY` messages was to constantly submit commands, even empty ones, and then check `PQnotifies` after each [`PQexec`](libpq-exec.html#LIBPQ-PQEXEC). While this still works, it is deprecated as a waste of processing power.

 A better way to check for `NOTIFY` messages when you have no useful commands to execute is to call [`PQconsumeInput` ](libpq-async.html#LIBPQ-PQCONSUMEINPUT), then check `PQnotifies`. You can use `select()` to wait for data to arrive from the server, thereby using no CPU power unless there is something to do. (See [`PQsocket`](libpq-status.html#LIBPQ-PQSOCKET) to obtain the file descriptor number to use with `select()`.) Note that this will work OK whether you submit commands with [`PQsendQuery`](libpq-async.html#LIBPQ-PQSENDQUERY)/[`PQgetResult`](libpq-async.html#LIBPQ-PQGETRESULT) or simply use [`PQexec`](libpq-exec.html#LIBPQ-PQEXEC). You should, however, remember to check `PQnotifies` after each [`PQgetResult`](libpq-async.html#LIBPQ-PQGETRESULT) or [`PQexec`](libpq-exec.html#LIBPQ-PQEXEC), to see if any notifications came in during the processing of the command.

---

| [Prev](libpq-fastpath.html) | [Up](libpq.html) |               [Next](libpq-copy.html)              |
|:----------------------------|:----------------:|---------------------------------------------------:|
|34.8. The Fast-Path Interface|[Home](index.html)| 34.10. Functions Associated with the `COPY` Command|

 // \<![CDATA[ \<-- For SVG support if ('WebSocket' in window) { (function() { function refreshCSS() { var sheets = [].slice.call(document.getElementsByTagName("link")); var head = document.getElementsByTagName("head")[0]; for (var i = 0; i \< sheets.length; ++i) { var elem = sheets[i]; head.removeChild(elem); var rel = elem.rel; if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") { var url = elem.href.replace(/(&|\\?)\_cacheOverride=\\d+/, ''); elem.href = url + (url.indexOf('?') \>= 0 ? '&' : '?') + '\_cacheOverride=' + (new Date().valueOf()); } head.appendChild(elem); } } var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://'; var address = protocol + window.location.host + window.location.pathname + '/ws'; var socket = new WebSocket(address); socket.onmessage = function(msg) { if (msg.data == 'reload') window.location.reload(); else if (msg.data == 'refreshcss') refreshCSS(); }; console.log('Live reload enabled.'); })(); } // ]]\>