Example Programs

Example 1-1. libpq Example Program 1

/*
 * testlibpq.c
 *  Test the C version of LIBPQ, the POSTGRES frontend library.
 */
#include <stdio.h>
#include "libpq-fe.h"

static void
exit_nicely(PGconn *conn)
{
 PQfinish(conn);
 exit(1);
}

int
main()
{
 char    *pghost,
         *pgport,
         *pgoptions,
         *pgtty;
 char    *dbName;
 int   nFields;
 int   i,
       j;

#ifdef DEBUG
 FILE    *debug;

#endif  /* DEBUG */

 PGconn    *conn;
 PGresult   *res;

 /*
  * Begin by setting the parameters for a backend connection.
  * If the parameters are NULL, the system tries to use 
  * reasonable defaults by looking up environment variables 
  * or, failing that, using hardwired constants.
  */
 pghost = NULL;    /* host name of the backend server */
 pgport = NULL;    /* port of the backend server */
 pgoptions = NULL; /* options to start up the backend server */
 pgtty = NULL;     /* debugging tty for the backend server */
 dbName = "template1";

 /* make a connection to the database */
 conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);

 /* check to see that the backend connection was successfully made */
 if (PQstatus(conn) == CONNECTION_BAD)
 {
  fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
  fprintf(stderr, "%s", PQerrorMessage(conn));
  exit_nicely(conn);
 }

#ifdef DEBUG
 debug = fopen("/tmp/trace.out", "w");
 PQtrace(conn, debug);
#endif  /* DEBUG */

 /* start a transaction block */
 res = PQexec(conn, "BEGIN");
 if (PQresultStatus(res) != PGRES_COMMAND_OK)
 {
  fprintf(stderr, "BEGIN command failed\n");
  PQclear(res);
  exit_nicely(conn);
 }

 /*
  * should PQclear PGresult whenever it is no longer needed to avoid
  * memory leaks
  */
 PQclear(res);

 /*
  * fetch instances from the pg_database, the system catalog of
  * databases
  */
 res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from
pg_database");
 if (PQresultStatus(res) != PGRES_COMMAND_OK)
 {
  fprintf(stderr, "DECLARE CURSOR command failed\n");
  PQclear(res);
  exit_nicely(conn);
 }
 PQclear(res);

 res = PQexec(conn, "FETCH ALL in myportal");
 if (PQresultStatus(res) != PGRES_TUPLES_OK)
 {
  fprintf(stderr, "FETCH ALL command didn't return tuples properly\n");
  PQclear(res);
  exit_nicely(conn);
 }

 /* first, print out the attribute names */
 nFields = PQnfields(res);
 for (i = 0; i < nFields; i++)
  printf("%-15s", PQfname(res, i));
 printf("\n\n");

 /* next, print out the instances */
 for (i = 0; i < PQntuples(res); i++)
 {
  for (j = 0; j < nFields; j++)
   printf("%-15s", PQgetvalue(res, i, j));
  printf("\n");
 }

 PQclear(res);

 /* close the portal */
 res = PQexec(conn, "CLOSE myportal");
 PQclear(res);

 /* end the transaction */
 res = PQexec(conn, "END");
 PQclear(res);

 /* close the connection to the database and cleanup */
 PQfinish(conn);

#ifdef DEBUG
 fclose(debug);
#endif  /* DEBUG */

 return 0;
}

Example 1-2. libpq Example Program 2

/*
 * 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);

 *
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"

static void
exit_nicely(PGconn *conn)
{
 PQfinish(conn);
 exit(1);
}

int
main()
{
 char    *pghost,
      *pgport,
      *pgoptions,
      *pgtty;
 char    *dbName;

 /*
  * int   nFields; int    i, j;
  */

 PGconn    *conn;
 PGresult   *res;
 PGnotify   *notify;

 /*
  * Begin by setting the parameters for a backend connection. 
  * If the parameters are NULL, the system will try to use 
  * reasonable defaults by looking up environment variables 
  * or, failing that, using hardwired constants.
  */
 pghost = NULL;    /* host name of the backend server */
 pgport = NULL;    /* port of the backend server */
 pgoptions = NULL; /* options to start up the backend server */
 pgtty = NULL;     /* debugging tty for the backend server */
 dbName = getenv("USER"); /* change this to your test database name */

 /* make a connection to the database */
 conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);

 /* check to see that the backend connection was successfully made */
 if (PQstatus(conn) == CONNECTION_BAD)
 {
  fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
  fprintf(stderr, "%s", PQerrorMessage(conn));
  exit_nicely(conn);
 }

 res = PQexec(conn, "LISTEN TBL2");
 if (PQresultStatus(res) != PGRES_COMMAND_OK)
 {
  fprintf(stderr, "LISTEN command failed\n");
  PQclear(res);
  exit_nicely(conn);
 }

 /*
  * should PQclear PGresult whenever it is no longer needed to avoid
  * memory leaks
  */
 PQclear(res);

 while (1)
 {
  /* 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)
  {
   fprintf(stderr,
     "ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
     notify->relname, notify->be_pid);
   free(notify);
   break;
  }
  PQclear(res);
 }

 /* close the connection to the database and cleanup */
 PQfinish(conn);
 return 0;     /* Though PQfinish(conn1) has called
         * exit(1) */
}

Example 1-3. libpq Example Program 3

/*
 * testlibpq3.c
 *  Test the C version of LIBPQ, the POSTGRES frontend library.
 *  tests the binary cursor interface
 *
 *
 * populate a database by doing the following:
 */

CREATE TABLE test1 (i int4, d float4, p polygon);

INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);

INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);

 the expected output is:

tuple 0: got
 i = (4 bytes) 1,
 d = (4 bytes) 3.567000,
 p = (4 bytes) 2 points   boundbox = (hi=3.000000/4.000000, lo =
1.000000,2.000000)
tuple 1: got
 i = (4 bytes) 2,
 d = (4 bytes) 89.050003,
 p = (4 bytes) 2 points   boundbox = (hi=4.000000/3.000000, lo =
2.000000,1.000000)

 *
 */
#include "postgres.h"   /* -> "c.h" -> int16, in access/attnum.h */
#include "libpq-fe.h"
#include "utils/geo_decls.h" /* for the POLYGON type */

static void
exit_nicely(PGconn *conn)
{
 PQfinish(conn);
 exit(1);
}

int
main()
{
 char    *pghost,
      *pgport,
      *pgoptions,
      *pgtty;
 char    *dbName;

 /*
  * int   nFields; int    i, j;
  */
 int   i;
 int   i_fnum,
    d_fnum,
    p_fnum;

 PGconn    *conn;
 PGresult   *res;

 /*
  * 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.
  */
 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 */

 /* make a connection to the database */
 conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);

 /* check to see that the backend connection was successfully made */
 if (PQstatus(conn) == CONNECTION_BAD)
 {
  fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
  fprintf(stderr, "%s", PQerrorMessage(conn));
  exit_nicely(conn);
 }

 /* start a transaction block */
 res = PQexec(conn, "BEGIN");
 if (PQresultStatus(res) != PGRES_COMMAND_OK)
 {
  fprintf(stderr, "BEGIN command failed\n");
  PQclear(res);
  exit_nicely(conn);
 }

 /*
  * should PQclear PGresult whenever it is no longer needed to avoid
  * memory leaks
  */
 PQclear(res);

 /*
  * fetch instances from the pg_database, the system catalog of
  * databases
  */
 res = PQexec(conn, "DECLARE mycursor BINARY CURSOR FOR select * from
test1");
 if (res == NULL ||
  PQresultStatus(res) != PGRES_COMMAND_OK)
 {
  fprintf(stderr, "DECLARE CURSOR command failed\n");
  if (res)
   PQclear(res);
  exit_nicely(conn);
 }
 PQclear(res);

 res = PQexec(conn, "FETCH ALL in mycursor");
 if (res == NULL ||
  PQresultStatus(res) != PGRES_TUPLES_OK)
 {
  fprintf(stderr, "FETCH ALL command didn't return tuples properly\n");
  if (res)
   PQclear(res);
  exit_nicely(conn);
 }

 i_fnum = PQfnumber(res, "i");
 d_fnum = PQfnumber(res, "d");
 p_fnum = PQfnumber(res, "p");

 for (i = 0; i < 3; i++)
 {
  printf("type[%d] = %d, size[%d] = %d\n",
      i, PQftype(res, i),
      i, PQfsize(res, i));
 }
 for (i = 0; i < PQntuples(res); i++)
 {
  int     *ival;
  float    *dval;
  int   plen;
  POLYGON    *pval;

  /* we hard-wire this to the 3 fields we know about */
  ival = (int *) PQgetvalue(res, i, i_fnum);
  dval = (float *) PQgetvalue(res, i, d_fnum);
  plen = PQgetlength(res, i, p_fnum);

  /*
   * plen doesn't include the length field so need to increment by
   * VARHDSZ
   */
  pval = (POLYGON *) malloc(plen + VARHDRSZ);
  pval->size = plen;
  memmove((char *) &pval->npts, PQgetvalue(res, i, p_fnum), plen);
  printf("tuple %d: got\n", i);
  printf(" i = (%d bytes) %d,\n",
      PQgetlength(res, i, i_fnum), *ival);
  printf(" d = (%d bytes) %f,\n",
      PQgetlength(res, i, d_fnum), *dval);
  printf(" p = (%d bytes) %d points \tboundbox = (hi=%f/%f, lo = %f,%f)\n",
      PQgetlength(res, i, d_fnum),
      pval->npts,
      pval->boundbox.high.x,
      pval->boundbox.high.y,
      pval->boundbox.low.x,
      pval->boundbox.low.y);
 }

 PQclear(res);

 /* close the portal */
 res = PQexec(conn, "CLOSE mycursor");
 PQclear(res);

 /* end the transaction */
 res = PQexec(conn, "END");
 PQclear(res);

 /* close the connection to the database and cleanup */
 PQfinish(conn);
 return 0;     /* Though PQfinish(conn1) has called
         * exit(1) */
}