public inbox for [email protected]  
help / color / mirror / Atom feed
old testlo example code
7+ messages / 5 participants
[nested] [flat]

* old testlo example code
@ 2013-01-05 02:27  Josh Kupershmidt <[email protected]>
  0 siblings, 1 reply; 7+ messages in thread

From: Josh Kupershmidt @ 2013-01-05 02:27 UTC (permalink / raw)
  To: pgsql-docs

This documentation page:
  http://www.postgresql.org/docs/current/static/lo-examplesect.html

contains a hardcoded copy of ./src/test/examples/testlo.c, and it
seems like this version hasn't been updated along with its source. The
version from the docs no longer compiles for me, at least not when I
drop it into the place of the current ./src/test/examples/testlo.c.
That's easy enough to fix, though I have a historical question about
this code.

Building the unmodified code in ./src/test/examples, I see:

  testlo.c:35: warning: ‘importFile’ defined but not used
  testlo.c:151: warning: ‘exportFile’ defined but not used
  ...
  testlo64.c:35: warning: ‘importFile’ defined but not used
  testlo64.c:173: warning: ‘exportFile’ defined but not used

since the calls to those functions are commented out in favor of
lo_import() and lo_export(). I'm wondering if there is some reason to
leave those importFile() and exportFile() definitions in this example
code if they're not used? The code has apparently been like this (at
least for testlo.c, and I guess testlo64.c just copy-pasted from its
older sibling) since the first commit, d31084e9.

Josh


-- 
Sent via pgsql-docs mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-docs



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: old testlo example code
@ 2013-01-05 14:14  Magnus Hagander <[email protected]>
  parent: Josh Kupershmidt <[email protected]>
  0 siblings, 2 replies; 7+ messages in thread

From: Magnus Hagander @ 2013-01-05 14:14 UTC (permalink / raw)
  To: Josh Kupershmidt <[email protected]>; +Cc: pgsql-docs

On Sat, Jan 5, 2013 at 3:27 AM, Josh Kupershmidt <[email protected]> wrote:
> This documentation page:
>   http://www.postgresql.org/docs/current/static/lo-examplesect.html
>
> contains a hardcoded copy of ./src/test/examples/testlo.c, and it
> seems like this version hasn't been updated along with its source. The
> version from the docs no longer compiles for me, at least not when I
> drop it into the place of the current ./src/test/examples/testlo.c.
> That's easy enough to fix, though I have a historical question about
> this code.

ISTM we should either remove the example programs and replace them
with just a reference, or find a way to include the source code into
the documentation with some kind of include statement instead of
haivng a copy of it. That should be done the same way for all the
example programs, not just the testlo ones of course.

Not sure if it's possible to create such an include though - someone
who knows our toolchain better can hopefully comment on that?

-- 
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/


-- 
Sent via pgsql-docs mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-docs



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: old testlo example code
@ 2013-01-06 09:12  Dmitriy Igrishin <[email protected]>
  parent: Magnus Hagander <[email protected]>
  1 sibling, 1 reply; 7+ messages in thread

From: Dmitriy Igrishin @ 2013-01-06 09:12 UTC (permalink / raw)
  To: Magnus Hagander <[email protected]>; +Cc: Josh Kupershmidt <[email protected]>; pgsql-docs

2013/1/5 Magnus Hagander <[email protected]>

> On Sat, Jan 5, 2013 at 3:27 AM, Josh Kupershmidt <[email protected]>
> wrote:
> > This documentation page:
> >   http://www.postgresql.org/docs/current/static/lo-examplesect.html
> >
> > contains a hardcoded copy of ./src/test/examples/testlo.c, and it
> > seems like this version hasn't been updated along with its source. The
> > version from the docs no longer compiles for me, at least not when I
> > drop it into the place of the current ./src/test/examples/testlo.c.
> > That's easy enough to fix, though I have a historical question about
> > this code.
>
> ISTM we should either remove the example programs and replace them
> with just a reference, or find a way to include the source code into
> the documentation with some kind of include statement instead of
> haivng a copy of it. That should be done the same way for all the
> example programs, not just the testlo ones of course.
>
> Not sure if it's possible to create such an include though - someone
> who knows our toolchain better can hopefully comment on that?
>
I think it's possible with Doxygen.

>
> --
>  Magnus Hagander
>  Me: http://www.hagander.net/
>  Work: http://www.redpill-linpro.com/
>
>
> --
> Sent via pgsql-docs mailing list ([email protected])
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-docs
>



-- 
// Dmitriy.


^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: old testlo example code
@ 2013-01-06 10:33  Magnus Hagander <[email protected]>
  parent: Dmitriy Igrishin <[email protected]>
  0 siblings, 0 replies; 7+ messages in thread

From: Magnus Hagander @ 2013-01-06 10:33 UTC (permalink / raw)
  To: Dmitriy Igrishin <[email protected]>; +Cc: Josh Kupershmidt <[email protected]>; pgsql-docs

On Sun, Jan 6, 2013 at 10:12 AM, Dmitriy Igrishin <[email protected]> wrote:
>
>
>
> 2013/1/5 Magnus Hagander <[email protected]>
>>
>> On Sat, Jan 5, 2013 at 3:27 AM, Josh Kupershmidt <[email protected]>
>> wrote:
>> > This documentation page:
>> >   http://www.postgresql.org/docs/current/static/lo-examplesect.html
>> >
>> > contains a hardcoded copy of ./src/test/examples/testlo.c, and it
>> > seems like this version hasn't been updated along with its source. The
>> > version from the docs no longer compiles for me, at least not when I
>> > drop it into the place of the current ./src/test/examples/testlo.c.
>> > That's easy enough to fix, though I have a historical question about
>> > this code.
>>
>> ISTM we should either remove the example programs and replace them
>> with just a reference, or find a way to include the source code into
>> the documentation with some kind of include statement instead of
>> haivng a copy of it. That should be done the same way for all the
>> example programs, not just the testlo ones of course.
>>
>> Not sure if it's possible to create such an include though - someone
>> who knows our toolchain better can hopefully comment on that?
>
> I think it's possible with Doxygen.

I was referring to the SGML documentation here, so that won't actually help.


--
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/


-- 
Sent via pgsql-docs mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-docs



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: old testlo example code
@ 2013-02-15 02:30  Peter Eisentraut <[email protected]>
  parent: Magnus Hagander <[email protected]>
  1 sibling, 1 reply; 7+ messages in thread

From: Peter Eisentraut @ 2013-02-15 02:30 UTC (permalink / raw)
  To: Magnus Hagander <[email protected]>; +Cc: Josh Kupershmidt <[email protected]>; pgsql-docs

On Sat, 2013-01-05 at 15:14 +0100, Magnus Hagander wrote:
> ISTM we should either remove the example programs and replace them
> with just a reference, or find a way to include the source code into
> the documentation with some kind of include statement instead of
> haivng a copy of it. That should be done the same way for all the
> example programs, not just the testlo ones of course.
> 
> Not sure if it's possible to create such an include though - someone
> who knows our toolchain better can hopefully comment on that? 

I've been looking into this.  It's not easily possible with the current
SGML setup.  (XInclude with XML would probably work.)  So for now it
would be best if someone could just sync up the docs with the code until
we figure out a better way.



-- 
Sent via pgsql-docs mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-docs



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: old testlo example code
@ 2013-02-27 03:18  Josh Kupershmidt <[email protected]>
  parent: Peter Eisentraut <[email protected]>
  0 siblings, 1 reply; 7+ messages in thread

From: Josh Kupershmidt @ 2013-02-27 03:18 UTC (permalink / raw)
  To: Peter Eisentraut <[email protected]>; +Cc: Magnus Hagander <[email protected]>; pgsql-docs

On Thu, Feb 14, 2013 at 7:30 PM, Peter Eisentraut <[email protected]> wrote:
> On Sat, 2013-01-05 at 15:14 +0100, Magnus Hagander wrote:
>> ISTM we should either remove the example programs and replace them
>> with just a reference, or find a way to include the source code into
>> the documentation with some kind of include statement instead of
>> haivng a copy of it. That should be done the same way for all the
>> example programs, not just the testlo ones of course.
>>
>> Not sure if it's possible to create such an include though - someone
>> who knows our toolchain better can hopefully comment on that?
>
> I've been looking into this.  It's not easily possible with the current
> SGML setup.  (XInclude with XML would probably work.)  So for now it
> would be best if someone could just sync up the docs with the code until
> we figure out a better way.

OK, here's a patch to update the example code in the docs to match the
example programs in ./src/test/examples . In addition to the testlo
example discussed, I updated the libpq examples as well. There's a
fair amount of whitespace churn in the diff, though I assume that's
from a pgindent change of the test code at some point.

Josh


-- 
Sent via pgsql-docs mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-docs


Attachments:

  [application/octet-stream] example_code_in_documentation.diff (31.0K, 2-example_code_in_documentation.diff)
  download | inline diff:
*** 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>


^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: old testlo example code
@ 2013-09-11 01:03  Bruce Momjian <[email protected]>
  parent: Josh Kupershmidt <[email protected]>
  0 siblings, 0 replies; 7+ messages in thread

From: Bruce Momjian @ 2013-09-11 01:03 UTC (permalink / raw)
  To: Josh Kupershmidt <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Magnus Hagander <[email protected]>; pgsql-docs

On Tue, Feb 26, 2013 at 08:18:40PM -0700, Josh Kupershmidt wrote:
> On Thu, Feb 14, 2013 at 7:30 PM, Peter Eisentraut <[email protected]> wrote:
> > On Sat, 2013-01-05 at 15:14 +0100, Magnus Hagander wrote:
> >> ISTM we should either remove the example programs and replace them
> >> with just a reference, or find a way to include the source code into
> >> the documentation with some kind of include statement instead of
> >> haivng a copy of it. That should be done the same way for all the
> >> example programs, not just the testlo ones of course.
> >>
> >> Not sure if it's possible to create such an include though - someone
> >> who knows our toolchain better can hopefully comment on that?
> >
> > I've been looking into this.  It's not easily possible with the current
> > SGML setup.  (XInclude with XML would probably work.)  So for now it
> > would be best if someone could just sync up the docs with the code until
> > we figure out a better way.
> 
> OK, here's a patch to update the example code in the docs to match the
> example programs in ./src/test/examples . In addition to the testlo
> example discussed, I updated the libpq examples as well. There's a
> fair amount of whitespace churn in the diff, though I assume that's
> from a pgindent change of the test code at some point.

Patch applied, and tabs converted to 4 spaces.  Thanks.

-- 
  Bruce Momjian  <[email protected]>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + It's impossible for everything to be true. +


-- 
Sent via pgsql-docs mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-docs




^ permalink  raw  reply  [nested|flat] 7+ messages in thread


end of thread, other threads:[~2013-09-11 01:03 UTC | newest]

Thread overview: 7+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2013-01-05 02:27 old testlo example code Josh Kupershmidt <[email protected]>
2013-01-05 14:14 ` Magnus Hagander <[email protected]>
2013-01-06 09:12   ` Dmitriy Igrishin <[email protected]>
2013-01-06 10:33     ` Magnus Hagander <[email protected]>
2013-02-15 02:30   ` Peter Eisentraut <[email protected]>
2013-02-27 03:18     ` Josh Kupershmidt <[email protected]>
2013-09-11 01:03       ` Bruce Momjian <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox