*** a/doc/src/sgml/libpq.sgml
--- b/doc/src/sgml/libpq.sgml
***************
*** 7840,7971 **** main(int argc, char **argv)
  <![CDATA[
  /*
   * testlibpq2.c
!  *      Test of the asynchronous notification interface
   *
   * 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
  exit_nicely(PGconn *conn)
  {
!     PQfinish(conn);
!     exit(1);
  }
  
  int
  main(int argc, char **argv)
  {
!     const char *conninfo;
!     PGconn     *conn;
!     PGresult   *res;
!     PGnotify   *notify;
!     int         nnotifies;
! 
!     /*
!      * If the user supplies a parameter on the command line, use it as the
!      * conninfo string; otherwise default to setting dbname=postgres and using
!      * environment variables or defaults for all other connection parameters.
!      */
!     if (argc > 1)
!         conninfo = argv[1];
!     else
!         conninfo = "dbname = postgres";
! 
!     /* Make a connection to the database */
!     conn = PQconnectdb(conninfo);
! 
!     /* Check to see that the backend connection was successfully made */
!     if (PQstatus(conn) != CONNECTION_OK)
!     {
!         fprintf(stderr, "Connection to database failed: %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: %s", PQerrorMessage(conn));
!         PQclear(res);
!         exit_nicely(conn);
!     }
! 
!     /*
!      * should PQclear PGresult whenever it is no longer needed to avoid memory
!      * leaks
!      */
!     PQclear(res);
! 
!     /* Quit after four notifies are received. */
!     nnotifies = 0;
!     while (nnotifies < 4)
!     {
!         /*
!          * 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' received from backend PID %d\n",
!                     notify->relname, notify->be_pid);
!             PQfreemem(notify);
!             nnotifies++;
!         }
!     }
! 
!     fprintf(stderr, "Done.\n");
! 
!     /* close the connection to the database and cleanup */
!     PQfinish(conn);
! 
!     return 0;
  }
  ]]>
  </programlisting>
--- 7840,7976 ----
  <![CDATA[
  /*
   * testlibpq2.c
!  *		Test of the asynchronous notification interface
   *
   * 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);
   */
+ 
+ #ifdef WIN32
+ #include <windows.h>
+ #endif
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <errno.h>
  #include <sys/time.h>
! #include <sys/types.h>
! #include "libpq-fe.h"
  
  static void
  exit_nicely(PGconn *conn)
  {
! 	PQfinish(conn);
! 	exit(1);
  }
  
  int
  main(int argc, char **argv)
  {
! 	const char *conninfo;
! 	PGconn	   *conn;
! 	PGresult   *res;
! 	PGnotify   *notify;
! 	int			nnotifies;
! 
! 	/*
! 	 * If the user supplies a parameter on the command line, use it as the
! 	 * conninfo string; otherwise default to setting dbname=postgres and using
! 	 * environment variables or defaults for all other connection parameters.
! 	 */
! 	if (argc > 1)
! 		conninfo = argv[1];
! 	else
! 		conninfo = "dbname = postgres";
! 
! 	/* Make a connection to the database */
! 	conn = PQconnectdb(conninfo);
! 
! 	/* Check to see that the backend connection was successfully made */
! 	if (PQstatus(conn) != CONNECTION_OK)
! 	{
! 		fprintf(stderr, "Connection to database failed: %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: %s", PQerrorMessage(conn));
! 		PQclear(res);
! 		exit_nicely(conn);
! 	}
! 
! 	/*
! 	 * should PQclear PGresult whenever it is no longer needed to avoid memory
! 	 * leaks
! 	 */
! 	PQclear(res);
! 
! 	/* Quit after four notifies are received. */
! 	nnotifies = 0;
! 	while (nnotifies < 4)
! 	{
! 		/*
! 		 * 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' received from backend PID %d\n",
! 					notify->relname, notify->be_pid);
! 			PQfreemem(notify);
! 			nnotifies++;
! 		}
! 	}
! 
! 	fprintf(stderr, "Done.\n");
! 
! 	/* close the connection to the database and cleanup */
! 	PQfinish(conn);
! 
! 	return 0;
  }
  ]]>
  </programlisting>
***************
*** 7978,7984 **** main(int argc, char **argv)
  <![CDATA[
  /*
   * testlibpq3.c
!  *      Test out-of-line parameters and binary I/O.
   *
   * Before running this, populate a database with the following commands
   * (provided in src/test/examples/testlibpq3.sql):
--- 7983,7989 ----
  <![CDATA[
  /*
   * testlibpq3.c
!  *		Test out-of-line parameters and binary I/O.
   *
   * Before running this, populate a database with the following commands
   * (provided in src/test/examples/testlibpq3.sql):
***************
*** 7991,8010 **** main(int argc, char **argv)
   * The expected output is:
   *
   * tuple 0: got
!  *  i = (4 bytes) 1
!  *  t = (11 bytes) 'joe's place'
!  *  b = (5 bytes) \000\001\002\003\004
   *
   * tuple 0: got
!  *  i = (4 bytes) 2
!  *  t = (8 bytes) 'ho there'
!  *  b = (5 bytes) \004\003\002\001\000
   */
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <sys/types.h>
! #include <libpq-fe.h>
  
  /* for ntohl/htonl */
  #include <netinet/in.h>
--- 7996,8021 ----
   * The expected output is:
   *
   * tuple 0: got
!  *	i = (4 bytes) 1
!  *	t = (11 bytes) 'joe's place'
!  *	b = (5 bytes) \000\001\002\003\004
   *
   * tuple 0: got
!  *	i = (4 bytes) 2
!  *	t = (8 bytes) 'ho there'
!  *	b = (5 bytes) \004\003\002\001\000
   */
+ 
+ #ifdef WIN32
+ #include <windows.h>
+ #endif
+ 
  #include <stdio.h>
  #include <stdlib.h>
+ #include <stdint.h>
  #include <string.h>
  #include <sys/types.h>
! #include "libpq-fe.h"
  
  /* for ntohl/htonl */
  #include <netinet/in.h>
***************
*** 8014,8021 **** main(int argc, char **argv)
  static void
  exit_nicely(PGconn *conn)
  {
!     PQfinish(conn);
!     exit(1);
  }
  
  /*
--- 8025,8032 ----
  static void
  exit_nicely(PGconn *conn)
  {
! 	PQfinish(conn);
! 	exit(1);
  }
  
  /*
***************
*** 8026,8191 **** exit_nicely(PGconn *conn)
  static void
  show_binary_results(PGresult *res)
  {
!     int         i,
!                 j;
!     int         i_fnum,
!                 t_fnum,
!                 b_fnum;
! 
!     /* Use PQfnumber to avoid assumptions about field order in result */
!     i_fnum = PQfnumber(res, "i");
!     t_fnum = PQfnumber(res, "t");
!     b_fnum = PQfnumber(res, "b");
! 
!     for (i = 0; i < PQntuples(res); i++)
!     {
!         char       *iptr;
!         char       *tptr;
!         char       *bptr;
!         int         blen;
!         int         ival;
! 
!         /* Get the field values (we ignore possibility they are null!) */
!         iptr = PQgetvalue(res, i, i_fnum);
!         tptr = PQgetvalue(res, i, t_fnum);
!         bptr = PQgetvalue(res, i, b_fnum);
! 
!         /*
!          * The binary representation of INT4 is in network byte order, which
!          * we'd better coerce to the local byte order.
!          */
!         ival = ntohl(*((uint32_t *) iptr));
! 
!         /*
!          * The binary representation of TEXT is, well, text, and since libpq
!          * was nice enough to append a zero byte to it, it'll work just fine
!          * as a C string.
!          *
!          * The binary representation of BYTEA is a bunch of bytes, which could
!          * include embedded nulls so we have to pay attention to field length.
!          */
!         blen = PQgetlength(res, i, b_fnum);
! 
!         printf("tuple %d: got\n", i);
!         printf(" i = (%d bytes) %d\n",
!                PQgetlength(res, i, i_fnum), ival);
!         printf(" t = (%d bytes) '%s'\n",
!                PQgetlength(res, i, t_fnum), tptr);
!         printf(" b = (%d bytes) ", blen);
!         for (j = 0; j < blen; j++)
!             printf("\\%03o", bptr[j]);
!         printf("\n\n");
!     }
  }
  
  int
  main(int argc, char **argv)
  {
!     const char *conninfo;
!     PGconn     *conn;
!     PGresult   *res;
!     const char *paramValues[1];
!     int         paramLengths[1];
!     int         paramFormats[1];
!     uint32_t    binaryIntVal;
! 
!     /*
!      * If the user supplies a parameter on the command line, use it as the
!      * conninfo string; otherwise default to setting dbname=postgres and using
!      * environment variables or defaults for all other connection parameters.
!      */
!     if (argc > 1)
!         conninfo = argv[1];
!     else
!         conninfo = "dbname = postgres";
! 
!     /* Make a connection to the database */
!     conn = PQconnectdb(conninfo);
! 
!     /* Check to see that the backend connection was successfully made */
!     if (PQstatus(conn) != CONNECTION_OK)
!     {
!         fprintf(stderr, "Connection to database failed: %s",
!                 PQerrorMessage(conn));
!         exit_nicely(conn);
!     }
! 
!     /*
!      * The point of this program is to illustrate use of PQexecParams() with
!      * out-of-line parameters, as well as binary transmission of data.
!      *
!      * This first example transmits the parameters as text, but receives the
!      * results in binary format.  By using out-of-line parameters we can
!      * avoid a lot of tedious mucking about with quoting and escaping, even
!      * though the data is text.  Notice how we don't have to do anything
!      * special with the quote mark in the parameter value.
!      */
! 
!     /* Here is our out-of-line parameter value */
!     paramValues[0] = "joe's place";
! 
!     res = PQexecParams(conn,
!                        "SELECT * FROM test1 WHERE t = $1",
!                        1,       /* one param */
!                        NULL,    /* let the backend deduce param type */
!                        paramValues,
!                        NULL,    /* don't need param lengths since text */
!                        NULL,    /* default to all text params */
!                        1);      /* ask for binary results */
! 
!     if (PQresultStatus(res) != PGRES_TUPLES_OK)
!     {
!         fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
!         PQclear(res);
!         exit_nicely(conn);
!     }
! 
!     show_binary_results(res);
! 
!     PQclear(res);
! 
!     /*
!      * In this second example we transmit an integer parameter in binary
!      * form, and again retrieve the results in binary form.
!      *
!      * Although we tell PQexecParams we are letting the backend deduce
!      * parameter type, we really force the decision by casting the parameter
!      * symbol in the query text.  This is a good safety measure when sending
!      * binary parameters.
!      */
! 
!     /* Convert integer value "2" to network byte order */
!     binaryIntVal = htonl((uint32_t) 2);
! 
!     /* Set up parameter arrays for PQexecParams */
!     paramValues[0] = (char *) &binaryIntVal;
!     paramLengths[0] = sizeof(binaryIntVal);
!     paramFormats[0] = 1;        /* binary */
! 
!     res = PQexecParams(conn,
!                        "SELECT * FROM test1 WHERE i = $1::int4",
!                        1,       /* one param */
!                        NULL,    /* let the backend deduce param type */
!                        paramValues,
!                        paramLengths,
!                        paramFormats,
!                        1);      /* ask for binary results */
! 
!     if (PQresultStatus(res) != PGRES_TUPLES_OK)
!     {
!         fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
!         PQclear(res);
!         exit_nicely(conn);
!     }
! 
!     show_binary_results(res);
! 
!     PQclear(res);
! 
!     /* close the connection to the database and cleanup */
!     PQfinish(conn);
! 
!     return 0;
  }
  ]]>
  </programlisting>
--- 8037,8202 ----
  static void
  show_binary_results(PGresult *res)
  {
! 	int			i,
! 				j;
! 	int			i_fnum,
! 				t_fnum,
! 				b_fnum;
! 
! 	/* Use PQfnumber to avoid assumptions about field order in result */
! 	i_fnum = PQfnumber(res, "i");
! 	t_fnum = PQfnumber(res, "t");
! 	b_fnum = PQfnumber(res, "b");
! 
! 	for (i = 0; i < PQntuples(res); i++)
! 	{
! 		char	   *iptr;
! 		char	   *tptr;
! 		char	   *bptr;
! 		int			blen;
! 		int			ival;
! 
! 		/* Get the field values (we ignore possibility they are null!) */
! 		iptr = PQgetvalue(res, i, i_fnum);
! 		tptr = PQgetvalue(res, i, t_fnum);
! 		bptr = PQgetvalue(res, i, b_fnum);
! 
! 		/*
! 		 * The binary representation of INT4 is in network byte order, which
! 		 * we'd better coerce to the local byte order.
! 		 */
! 		ival = ntohl(*((uint32_t *) iptr));
! 
! 		/*
! 		 * The binary representation of TEXT is, well, text, and since libpq
! 		 * was nice enough to append a zero byte to it, it'll work just fine
! 		 * as a C string.
! 		 *
! 		 * The binary representation of BYTEA is a bunch of bytes, which could
! 		 * include embedded nulls so we have to pay attention to field length.
! 		 */
! 		blen = PQgetlength(res, i, b_fnum);
! 
! 		printf("tuple %d: got\n", i);
! 		printf(" i = (%d bytes) %d\n",
! 			   PQgetlength(res, i, i_fnum), ival);
! 		printf(" t = (%d bytes) '%s'\n",
! 			   PQgetlength(res, i, t_fnum), tptr);
! 		printf(" b = (%d bytes) ", blen);
! 		for (j = 0; j < blen; j++)
! 			printf("\\%03o", bptr[j]);
! 		printf("\n\n");
! 	}
  }
  
  int
  main(int argc, char **argv)
  {
! 	const char *conninfo;
! 	PGconn	   *conn;
! 	PGresult   *res;
! 	const char *paramValues[1];
! 	int			paramLengths[1];
! 	int			paramFormats[1];
! 	uint32_t	binaryIntVal;
! 
! 	/*
! 	 * If the user supplies a parameter on the command line, use it as the
! 	 * conninfo string; otherwise default to setting dbname=postgres and using
! 	 * environment variables or defaults for all other connection parameters.
! 	 */
! 	if (argc > 1)
! 		conninfo = argv[1];
! 	else
! 		conninfo = "dbname = postgres";
! 
! 	/* Make a connection to the database */
! 	conn = PQconnectdb(conninfo);
! 
! 	/* Check to see that the backend connection was successfully made */
! 	if (PQstatus(conn) != CONNECTION_OK)
! 	{
! 		fprintf(stderr, "Connection to database failed: %s",
! 				PQerrorMessage(conn));
! 		exit_nicely(conn);
! 	}
! 
! 	/*
! 	 * The point of this program is to illustrate use of PQexecParams() with
! 	 * out-of-line parameters, as well as binary transmission of data.
! 	 *
! 	 * This first example transmits the parameters as text, but receives the
! 	 * results in binary format.  By using out-of-line parameters we can avoid
! 	 * a lot of tedious mucking about with quoting and escaping, even though
! 	 * the data is text.  Notice how we don't have to do anything special with
! 	 * the quote mark in the parameter value.
! 	 */
! 
! 	/* Here is our out-of-line parameter value */
! 	paramValues[0] = "joe's place";
! 
! 	res = PQexecParams(conn,
! 					   "SELECT * FROM test1 WHERE t = $1",
! 					   1,		/* one param */
! 					   NULL,	/* let the backend deduce param type */
! 					   paramValues,
! 					   NULL,	/* don't need param lengths since text */
! 					   NULL,	/* default to all text params */
! 					   1);		/* ask for binary results */
! 
! 	if (PQresultStatus(res) != PGRES_TUPLES_OK)
! 	{
! 		fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
! 		PQclear(res);
! 		exit_nicely(conn);
! 	}
! 
! 	show_binary_results(res);
! 
! 	PQclear(res);
! 
! 	/*
! 	 * In this second example we transmit an integer parameter in binary form,
! 	 * and again retrieve the results in binary form.
! 	 *
! 	 * Although we tell PQexecParams we are letting the backend deduce
! 	 * parameter type, we really force the decision by casting the parameter
! 	 * symbol in the query text.  This is a good safety measure when sending
! 	 * binary parameters.
! 	 */
! 
! 	/* Convert integer value "2" to network byte order */
! 	binaryIntVal = htonl((uint32_t) 2);
! 
! 	/* Set up parameter arrays for PQexecParams */
! 	paramValues[0] = (char *) &binaryIntVal;
! 	paramLengths[0] = sizeof(binaryIntVal);
! 	paramFormats[0] = 1;		/* binary */
! 
! 	res = PQexecParams(conn,
! 					   "SELECT * FROM test1 WHERE i = $1::int4",
! 					   1,		/* one param */
! 					   NULL,	/* let the backend deduce param type */
! 					   paramValues,
! 					   paramLengths,
! 					   paramFormats,
! 					   1);		/* ask for binary results */
! 
! 	if (PQresultStatus(res) != PGRES_TUPLES_OK)
! 	{
! 		fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
! 		PQclear(res);
! 		exit_nicely(conn);
! 	}
! 
! 	show_binary_results(res);
! 
! 	PQclear(res);
! 
! 	/* close the connection to the database and cleanup */
! 	PQfinish(conn);
! 
! 	return 0;
  }
  ]]>
  </programlisting>
*** a/doc/src/sgml/lobj.sgml
--- b/doc/src/sgml/lobj.sgml
***************
*** 589,841 **** SELECT lo_export(image.raster, '/tmp/motd') FROM image
    <example id="lo-example">
     <title>Large Objects with <application>libpq</application> Example Program</title>
  <programlisting><![CDATA[
! /*--------------------------------------------------------------
   *
!  * testlo.c--
!  *    test using large objects with libpq
   *
!  * Copyright (c) 1994, Regents of the University of California
   *
!  *--------------------------------------------------------------
   */
  #include <stdio.h>
  #include "libpq-fe.h"
  #include "libpq/libpq-fs.h"
  
! #define BUFSIZE          1024
  
  /*
!  * importFile
!  *    import file "in_filename" into database as large object "lobjOid"
   *
   */
! Oid
  importFile(PGconn *conn, char *filename)
  {
!     Oid         lobjId;
!     int         lobj_fd;
!     char        buf[BUFSIZE];
!     int         nbytes,
!                 tmp;
!     int         fd;
! 
!     /*
!      * open the file to be read in
!      */
!     fd = open(filename, O_RDONLY, 0666);
!     if (fd < 0)
!     {                           /* error */
!         fprintf(stderr, "cannot open unix file %s\n", filename);
!     }
! 
!     /*
!      * create the large object
!      */
!     lobjId = lo_creat(conn, INV_READ | INV_WRITE);
!     if (lobjId == 0)
!         fprintf(stderr, "cannot create large object\n");
! 
!     lobj_fd = lo_open(conn, lobjId, INV_WRITE);
! 
!     /*
!      * read in from the Unix file and write to the inversion file
!      */
!     while ((nbytes = read(fd, buf, BUFSIZE)) > 0)
!     {
!         tmp = lo_write(conn, lobj_fd, buf, nbytes);
!         if (tmp < nbytes)
!             fprintf(stderr, "error while reading large object\n");
!     }
! 
!     (void) close(fd);
!     (void) lo_close(conn, lobj_fd);
! 
!     return lobjId;
  }
  
! void
  pickout(PGconn *conn, Oid lobjId, int start, int len)
  {
!     int         lobj_fd;
!     char       *buf;
!     int         nbytes;
!     int         nread;
! 
!     lobj_fd = lo_open(conn, lobjId, INV_READ);
!     if (lobj_fd < 0)
!     {
!         fprintf(stderr, "cannot open large object %d\n",
!                 lobjId);
!     }
! 
!     lo_lseek(conn, lobj_fd, start, SEEK_SET);
!     buf = malloc(len + 1);
! 
!     nread = 0;
!     while (len - nread > 0)
!     {
!         nbytes = lo_read(conn, lobj_fd, buf, len - nread);
!         buf[nbytes] = ' ';
!         fprintf(stderr, ">>> %s", buf);
!         nread += nbytes;
!     }
!     free(buf);
!     fprintf(stderr, "\n");
!     lo_close(conn, lobj_fd);
  }
  
! void
  overwrite(PGconn *conn, Oid lobjId, int start, int len)
  {
!     int         lobj_fd;
!     char       *buf;
!     int         nbytes;
!     int         nwritten;
!     int         i;
! 
!     lobj_fd = lo_open(conn, lobjId, INV_WRITE);
!     if (lobj_fd < 0)
!     {
!         fprintf(stderr, "cannot open large object %d\n",
!                 lobjId);
!     }
! 
!     lo_lseek(conn, lobj_fd, start, SEEK_SET);
!     buf = malloc(len + 1);
! 
!     for (i = 0; i < len; i++)
!         buf[i] = 'X';
!     buf[i] = ' ';
! 
!     nwritten = 0;
!     while (len - nwritten > 0)
!     {
!         nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
!         nwritten += nbytes;
!     }
!     free(buf);
!     fprintf(stderr, "\n");
!     lo_close(conn, lobj_fd);
  }
  
  /*
!  * exportFile
!  *    export large object "lobjOid" to file "out_filename"
   *
   */
! void
  exportFile(PGconn *conn, Oid lobjId, char *filename)
  {
!     int         lobj_fd;
!     char        buf[BUFSIZE];
!     int         nbytes,
!                 tmp;
!     int         fd;
! 
!     /*
!      * open the large object
!      */
!     lobj_fd = lo_open(conn, lobjId, INV_READ);
!     if (lobj_fd < 0)
!     {
!         fprintf(stderr, "cannot open large object %d\n",
!                 lobjId);
!     }
! 
!     /*
!      * open the file to be written to
!      */
!     fd = open(filename, O_CREAT | O_WRONLY, 0666);
!     if (fd < 0)
!     {                           /* error */
!         fprintf(stderr, "cannot open unix file %s\n",
!                 filename);
!     }
! 
!     /*
!      * read in from the inversion file and write to the Unix file
!      */
!     while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0)
!     {
!         tmp = write(fd, buf, nbytes);
!         if (tmp < nbytes)
!         {
!             fprintf(stderr, "error while writing %s\n",
!                     filename);
!         }
!     }
! 
!     (void) lo_close(conn, lobj_fd);
!     (void) close(fd);
! 
!     return;
  }
  
! void
  exit_nicely(PGconn *conn)
  {
!     PQfinish(conn);
!     exit(1);
  }
  
  int
  main(int argc, char **argv)
  {
!     char       *in_filename,
!                *out_filename;
!     char       *database;
!     Oid         lobjOid;
!     PGconn     *conn;
!     PGresult   *res;
! 
!     if (argc != 4)
!     {
!         fprintf(stderr, "Usage: %s database_name in_filename out_filename\n",
!                 argv[0]);
!         exit(1);
!     }
! 
!     database = argv[1];
!     in_filename = argv[2];
!     out_filename = argv[3];
! 
!     /*
!      * set up the connection
!      */
!     conn = PQsetdb(NULL, NULL, NULL, NULL, database);
! 
!     /* check to see that the backend connection was successfully made */
!     if (PQstatus(conn) == CONNECTION_BAD)
!     {
!         fprintf(stderr, "Connection to database '%s' failed.\n", database);
!         fprintf(stderr, "%s", PQerrorMessage(conn));
!         exit_nicely(conn);
!     }
! 
!     res = PQexec(conn, "begin");
!     PQclear(res);
! 
!     printf("importing file %s\n", in_filename);
! /*  lobjOid = importFile(conn, in_filename); */
!     lobjOid = lo_import(conn, in_filename);
! /*
!     printf("as large object %d.\n", lobjOid);
! 
!     printf("picking out bytes 1000-2000 of the large object\n");
!     pickout(conn, lobjOid, 1000, 1000);
! 
!     printf("overwriting bytes 1000-2000 of the large object with X's\n");
!     overwrite(conn, lobjOid, 1000, 1000);
! */
! 
!     printf("exporting large object to file %s\n", out_filename);
! /*    exportFile(conn, lobjOid, out_filename); */
!     lo_export(conn, lobjOid, out_filename);
! 
!     res = PQexec(conn, "end");
!     PQclear(res);
!     PQfinish(conn);
!     exit(0);
  }
  ]]>
  </programlisting>
--- 589,855 ----
    <example id="lo-example">
     <title>Large Objects with <application>libpq</application> Example Program</title>
  <programlisting><![CDATA[
! /*-------------------------------------------------------------------------
   *
!  * testlo.c
!  *	  test using large objects with libpq
   *
!  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
!  * Portions Copyright (c) 1994, Regents of the University of California
   *
!  *
!  * IDENTIFICATION
!  *	  src/test/examples/testlo.c
!  *
!  *-------------------------------------------------------------------------
   */
  #include <stdio.h>
+ #include <stdlib.h>
+ 
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ 
  #include "libpq-fe.h"
  #include "libpq/libpq-fs.h"
  
! #define BUFSIZE			1024
  
  /*
!  * importFile -
!  *	  import file "in_filename" into database as large object "lobjOid"
   *
   */
! static Oid
  importFile(PGconn *conn, char *filename)
  {
! 	Oid			lobjId;
! 	int			lobj_fd;
! 	char		buf[BUFSIZE];
! 	int			nbytes,
! 				tmp;
! 	int			fd;
! 
! 	/*
! 	 * open the file to be read in
! 	 */
! 	fd = open(filename, O_RDONLY, 0666);
! 	if (fd < 0)
! 	{							/* error */
! 		fprintf(stderr, "cannot open unix file\"%s\"\n", filename);
! 	}
! 
! 	/*
! 	 * create the large object
! 	 */
! 	lobjId = lo_creat(conn, INV_READ | INV_WRITE);
! 	if (lobjId == 0)
! 		fprintf(stderr, "cannot create large object");
! 
! 	lobj_fd = lo_open(conn, lobjId, INV_WRITE);
! 
! 	/*
! 	 * read in from the Unix file and write to the inversion file
! 	 */
! 	while ((nbytes = read(fd, buf, BUFSIZE)) > 0)
! 	{
! 		tmp = lo_write(conn, lobj_fd, buf, nbytes);
! 		if (tmp < nbytes)
! 			fprintf(stderr, "error while reading \"%s\"", filename);
! 	}
! 
! 	close(fd);
! 	lo_close(conn, lobj_fd);
! 
! 	return lobjId;
  }
  
! static void
  pickout(PGconn *conn, Oid lobjId, int start, int len)
  {
! 	int			lobj_fd;
! 	char	   *buf;
! 	int			nbytes;
! 	int			nread;
! 
! 	lobj_fd = lo_open(conn, lobjId, INV_READ);
! 	if (lobj_fd < 0)
! 		fprintf(stderr, "cannot open large object %u", lobjId);
! 
! 	lo_lseek(conn, lobj_fd, start, SEEK_SET);
! 	buf = malloc(len + 1);
! 
! 	nread = 0;
! 	while (len - nread > 0)
! 	{
! 		nbytes = lo_read(conn, lobj_fd, buf, len - nread);
! 		buf[nbytes] = '\0';
! 		fprintf(stderr, ">>> %s", buf);
! 		nread += nbytes;
! 		if (nbytes <= 0)
! 			break;				/* no more data? */
! 	}
! 	free(buf);
! 	fprintf(stderr, "\n");
! 	lo_close(conn, lobj_fd);
  }
  
! static void
  overwrite(PGconn *conn, Oid lobjId, int start, int len)
  {
! 	int			lobj_fd;
! 	char	   *buf;
! 	int			nbytes;
! 	int			nwritten;
! 	int			i;
! 
! 	lobj_fd = lo_open(conn, lobjId, INV_WRITE);
! 	if (lobj_fd < 0)
! 		fprintf(stderr, "cannot open large object %u", lobjId);
! 
! 	lo_lseek(conn, lobj_fd, start, SEEK_SET);
! 	buf = malloc(len + 1);
! 
! 	for (i = 0; i < len; i++)
! 		buf[i] = 'X';
! 	buf[i] = '\0';
! 
! 	nwritten = 0;
! 	while (len - nwritten > 0)
! 	{
! 		nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
! 		nwritten += nbytes;
! 		if (nbytes <= 0)
! 		{
! 			fprintf(stderr, "\nWRITE FAILED!\n");
! 			break;
! 		}
! 	}
! 	free(buf);
! 	fprintf(stderr, "\n");
! 	lo_close(conn, lobj_fd);
  }
  
+ 
  /*
!  * exportFile -
!  *	  export large object "lobjOid" to file "out_filename"
   *
   */
! static void
  exportFile(PGconn *conn, Oid lobjId, char *filename)
  {
! 	int			lobj_fd;
! 	char		buf[BUFSIZE];
! 	int			nbytes,
! 				tmp;
! 	int			fd;
! 
! 	/*
! 	 * open the large object
! 	 */
! 	lobj_fd = lo_open(conn, lobjId, INV_READ);
! 	if (lobj_fd < 0)
! 		fprintf(stderr, "cannot open large object %u", lobjId);
! 
! 	/*
! 	 * open the file to be written to
! 	 */
! 	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
! 	if (fd < 0)
! 	{							/* error */
! 		fprintf(stderr, "cannot open unix file\"%s\"",
! 				filename);
! 	}
! 
! 	/*
! 	 * read in from the inversion file and write to the Unix file
! 	 */
! 	while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0)
! 	{
! 		tmp = write(fd, buf, nbytes);
! 		if (tmp < nbytes)
! 		{
! 			fprintf(stderr, "error while writing \"%s\"",
! 					filename);
! 		}
! 	}
! 
! 	lo_close(conn, lobj_fd);
! 	close(fd);
! 
! 	return;
  }
  
! static void
  exit_nicely(PGconn *conn)
  {
! 	PQfinish(conn);
! 	exit(1);
  }
  
  int
  main(int argc, char **argv)
  {
! 	char	   *in_filename,
! 			   *out_filename;
! 	char	   *database;
! 	Oid			lobjOid;
! 	PGconn	   *conn;
! 	PGresult   *res;
! 
! 	if (argc != 4)
! 	{
! 		fprintf(stderr, "Usage: %s database_name in_filename out_filename\n",
! 				argv[0]);
! 		exit(1);
! 	}
! 
! 	database = argv[1];
! 	in_filename = argv[2];
! 	out_filename = argv[3];
! 
! 	/*
! 	 * set up the connection
! 	 */
! 	conn = PQsetdb(NULL, NULL, NULL, NULL, database);
! 
! 	/* check to see that the backend connection was successfully made */
! 	if (PQstatus(conn) != CONNECTION_OK)
! 	{
! 		fprintf(stderr, "Connection to database failed: %s",
! 				PQerrorMessage(conn));
! 		exit_nicely(conn);
! 	}
! 
! 	res = PQexec(conn, "begin");
! 	PQclear(res);
! 	printf("importing file \"%s\" ...\n", in_filename);
! /*	lobjOid = importFile(conn, in_filename); */
! 	lobjOid = lo_import(conn, in_filename);
! 	if (lobjOid == 0)
! 		fprintf(stderr, "%s\n", PQerrorMessage(conn));
! 	else
! 	{
! 		printf("\tas large object %u.\n", lobjOid);
! 
! 		printf("picking out bytes 1000-2000 of the large object\n");
! 		pickout(conn, lobjOid, 1000, 1000);
! 
! 		printf("overwriting bytes 1000-2000 of the large object with X's\n");
! 		overwrite(conn, lobjOid, 1000, 1000);
! 
! 		printf("exporting large object to file \"%s\" ...\n", out_filename);
! /*		exportFile(conn, lobjOid, out_filename); */
! 		if (lo_export(conn, lobjOid, out_filename) < 0)
! 			fprintf(stderr, "%s\n", PQerrorMessage(conn));
! 	}
! 
! 	res = PQexec(conn, "end");
! 	PQclear(res);
! 	PQfinish(conn);
! 	return 0;
  }
  ]]>
  </programlisting>
