mirror of
https://github.com/postgres/postgres.git
synced 2025-12-21 05:21:08 +03:00
Bring the libpq example programs into the 21st century.
This commit is contained in:
@@ -2,24 +2,30 @@
|
||||
* testlibpq2.c
|
||||
* Test of the asynchronous notification interface
|
||||
*
|
||||
populate a database with the following:
|
||||
|
||||
CREATE TABLE TBL1 (i int4);
|
||||
|
||||
CREATE TABLE TBL2 (i int4);
|
||||
|
||||
CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
|
||||
|
||||
* Then start up this program
|
||||
* After the program has begun, do
|
||||
|
||||
INSERT INTO TBL1 values (10);
|
||||
|
||||
* Start this program, then from psql in another window do
|
||||
* NOTIFY TBL2;
|
||||
* Repeat four times to get this program to exit.
|
||||
*
|
||||
* Or, if you want to get fancy, try this:
|
||||
* populate a database with the following commands
|
||||
* (provided in src/test/examples/testlibpq2.sql):
|
||||
*
|
||||
* CREATE TABLE TBL1 (i int4);
|
||||
*
|
||||
* CREATE TABLE TBL2 (i int4);
|
||||
*
|
||||
* CREATE RULE r1 AS ON INSERT TO TBL1 DO
|
||||
* (INSERT INTO TBL2 VALUES (new.i); NOTIFY TBL2);
|
||||
*
|
||||
* and do this four times:
|
||||
*
|
||||
* INSERT INTO TBL1 VALUES (10);
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include "libpq-fe.h"
|
||||
|
||||
static void
|
||||
@@ -30,51 +36,43 @@ exit_nicely(PGconn *conn)
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *pghost,
|
||||
*pgport,
|
||||
*pgoptions,
|
||||
*pgtty;
|
||||
char *dbName;
|
||||
|
||||
/*
|
||||
* int nFields; int i, j;
|
||||
*/
|
||||
|
||||
const char *conninfo;
|
||||
PGconn *conn;
|
||||
PGresult *res;
|
||||
PGnotify *notify;
|
||||
int nnotifies;
|
||||
|
||||
/*
|
||||
* begin, by setting the parameters for a backend connection if the
|
||||
* parameters are null, then the system will try to use reasonable
|
||||
* defaults by looking up environment variables or, failing that,
|
||||
* using hardwired constants
|
||||
* If the user supplies a parameter on the command line, use it as
|
||||
* the conninfo string; otherwise default to setting dbname=template1
|
||||
* and using environment variables or defaults for all other connection
|
||||
* parameters.
|
||||
*/
|
||||
pghost = NULL; /* host name of the backend server */
|
||||
pgport = NULL; /* port of the backend server */
|
||||
pgoptions = NULL; /* special options to start up the backend
|
||||
* server */
|
||||
pgtty = NULL; /* debugging tty for the backend server */
|
||||
dbName = getenv("USER"); /* change this to the name of your test
|
||||
* database */
|
||||
if (argc > 1)
|
||||
conninfo = argv[1];
|
||||
else
|
||||
conninfo = "dbname = template1";
|
||||
|
||||
/* make a connection to the database */
|
||||
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
|
||||
/* Make a connection to the database */
|
||||
conn = PQconnectdb(conninfo);
|
||||
|
||||
/* check to see that the backend connection was successfully made */
|
||||
if (PQstatus(conn) == CONNECTION_BAD)
|
||||
/* Check to see that the backend connection was successfully made */
|
||||
if (PQstatus(conn) != CONNECTION_OK)
|
||||
{
|
||||
fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
|
||||
fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn));
|
||||
fprintf(stderr, "%s", PQerrorMessage(conn));
|
||||
exit_nicely(conn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue LISTEN command to enable notifications from the rule's NOTIFY.
|
||||
*/
|
||||
res = PQexec(conn, "LISTEN TBL2");
|
||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
{
|
||||
fprintf(stderr, "LISTEN command failed\n");
|
||||
fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn));
|
||||
PQclear(res);
|
||||
exit_nicely(conn);
|
||||
}
|
||||
@@ -85,27 +83,48 @@ main()
|
||||
*/
|
||||
PQclear(res);
|
||||
|
||||
while (1)
|
||||
/* Quit after four notifies are received. */
|
||||
nnotifies = 0;
|
||||
while (nnotifies < 4)
|
||||
{
|
||||
/* async notification only come back as a result of a query */
|
||||
/* we can send empty queries */
|
||||
res = PQexec(conn, " ");
|
||||
/* printf("res->status = %s\n", PQresStatus(PQresultStatus(res))); */
|
||||
/* check for asynchronous returns */
|
||||
notify = PQnotifies(conn);
|
||||
if (notify)
|
||||
/*
|
||||
* Sleep until something happens on the connection. We use select(2)
|
||||
* to wait for input, but you could also use poll() or similar
|
||||
* facilities.
|
||||
*/
|
||||
int sock;
|
||||
fd_set input_mask;
|
||||
|
||||
sock = PQsocket(conn);
|
||||
|
||||
if (sock < 0)
|
||||
break; /* shouldn't happen */
|
||||
|
||||
FD_ZERO(&input_mask);
|
||||
FD_SET(sock, &input_mask);
|
||||
|
||||
if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
|
||||
{
|
||||
fprintf(stderr, "select() failed: %s\n", strerror(errno));
|
||||
exit_nicely(conn);
|
||||
}
|
||||
|
||||
/* Now check for input */
|
||||
PQconsumeInput(conn);
|
||||
while ((notify = PQnotifies(conn)) != NULL)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
|
||||
"ASYNC NOTIFY of '%s' received from backend pid %d\n",
|
||||
notify->relname, notify->be_pid);
|
||||
PQfreemem(notify);
|
||||
break;
|
||||
nnotifies++;
|
||||
}
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Done.\n");
|
||||
|
||||
/* close the connection to the database and cleanup */
|
||||
PQfinish(conn);
|
||||
return 0; /* Though PQfinish(conn1) has called
|
||||
* exit(1) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user