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