33.21. Example Programs

These examples and others can be found in the directory src/test/examples in the source code distribution.

Example 33.1. libpq Example Program 1

  1. /*
  2. * src/test/examples/testlibpq.c
  3. *
  4. *
  5. * testlibpq.c
  6. *
  7. * Test the C version of libpq, the PostgreSQL frontend library.
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include "libpq-fe.h"
  12. static void
  13. exit_nicely(PGconn *conn)
  14. {
  15. PQfinish(conn);
  16. exit(1);
  17. }
  18. int
  19. main(int argc, char **argv)
  20. {
  21. const char *conninfo;
  22. PGconn *conn;
  23. PGresult *res;
  24. int nFields;
  25. int i,
  26. j;
  27. /*
  28. * If the user supplies a parameter on the command line, use it as the
  29. * conninfo string; otherwise default to setting dbname=postgres and using
  30. * environment variables or defaults for all other connection parameters.
  31. */
  32. if (argc > 1)
  33. conninfo = argv[1];
  34. else
  35. conninfo = "dbname = postgres";
  36. /* Make a connection to the database */
  37. conn = PQconnectdb(conninfo);
  38. /* Check to see that the backend connection was successfully made */
  39. if (PQstatus(conn) != CONNECTION_OK)
  40. {
  41. fprintf(stderr, "Connection to database failed: %s",
  42. PQerrorMessage(conn));
  43. exit_nicely(conn);
  44. }
  45. /* Set always-secure search path, so malicous users can't take control. */
  46. res = PQexec(conn,
  47. "SELECT pg_catalog.set_config('search_path', '', false)");
  48. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  49. {
  50. fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
  51. PQclear(res);
  52. exit_nicely(conn);
  53. }
  54. /*
  55. * Should PQclear PGresult whenever it is no longer needed to avoid memory
  56. * leaks
  57. */
  58. PQclear(res);
  59. /*
  60. * Our test case here involves using a cursor, for which we must be inside
  61. * a transaction block. We could do the whole thing with a single
  62. * PQexec() of "select * from pg_database", but that's too trivial to make
  63. * a good example.
  64. */
  65. /* Start a transaction block */
  66. res = PQexec(conn, "BEGIN");
  67. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  68. {
  69. fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
  70. PQclear(res);
  71. exit_nicely(conn);
  72. }
  73. PQclear(res);
  74. /*
  75. * Fetch rows from pg_database, the system catalog of databases
  76. */
  77. res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database");
  78. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  79. {
  80. fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn));
  81. PQclear(res);
  82. exit_nicely(conn);
  83. }
  84. PQclear(res);
  85. res = PQexec(conn, "FETCH ALL in myportal");
  86. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  87. {
  88. fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn));
  89. PQclear(res);
  90. exit_nicely(conn);
  91. }
  92. /* first, print out the attribute names */
  93. nFields = PQnfields(res);
  94. for (i = 0; i < nFields; i++)
  95. printf("%-15s", PQfname(res, i));
  96. printf("\n\n");
  97. /* next, print out the rows */
  98. for (i = 0; i < PQntuples(res); i++)
  99. {
  100. for (j = 0; j < nFields; j++)
  101. printf("%-15s", PQgetvalue(res, i, j));
  102. printf("\n");
  103. }
  104. PQclear(res);
  105. /* close the portal ... we don't bother to check for errors ... */
  106. res = PQexec(conn, "CLOSE myportal");
  107. PQclear(res);
  108. /* end the transaction */
  109. res = PQexec(conn, "END");
  110. PQclear(res);
  111. /* close the connection to the database and cleanup */
  112. PQfinish(conn);
  113. return 0;
  114. }

Example 33.2. libpq Example Program 2

  1. /*
  2. * src/test/examples/testlibpq2.c
  3. *
  4. *
  5. * testlibpq2.c
  6. * Test of the asynchronous notification interface
  7. *
  8. * Start this program, then from psql in another window do
  9. * NOTIFY TBL2;
  10. * Repeat four times to get this program to exit.
  11. *
  12. * Or, if you want to get fancy, try this:
  13. * populate a database with the following commands
  14. * (provided in src/test/examples/testlibpq2.sql):
  15. *
  16. * CREATE SCHEMA TESTLIBPQ2;
  17. * SET search_path = TESTLIBPQ2;
  18. * CREATE TABLE TBL1 (i int4);
  19. * CREATE TABLE TBL2 (i int4);
  20. * CREATE RULE r1 AS ON INSERT TO TBL1 DO
  21. * (INSERT INTO TBL2 VALUES (new.i); NOTIFY TBL2);
  22. *
  23. * Start this program, then from psql do this four times:
  24. *
  25. * INSERT INTO TESTLIBPQ2.TBL1 VALUES (10);
  26. */
  27. #ifdef WIN32
  28. #include <windows.h>
  29. #endif
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <errno.h>
  34. #include <sys/time.h>
  35. #include <sys/types.h>
  36. #ifdef HAVE_SYS_SELECT_H
  37. #include <sys/select.h>
  38. #endif
  39. #include "libpq-fe.h"
  40. static void
  41. exit_nicely(PGconn *conn)
  42. {
  43. PQfinish(conn);
  44. exit(1);
  45. }
  46. int
  47. main(int argc, char **argv)
  48. {
  49. const char *conninfo;
  50. PGconn *conn;
  51. PGresult *res;
  52. PGnotify *notify;
  53. int nnotifies;
  54. /*
  55. * If the user supplies a parameter on the command line, use it as the
  56. * conninfo string; otherwise default to setting dbname=postgres and using
  57. * environment variables or defaults for all other connection parameters.
  58. */
  59. if (argc > 1)
  60. conninfo = argv[1];
  61. else
  62. conninfo = "dbname = postgres";
  63. /* Make a connection to the database */
  64. conn = PQconnectdb(conninfo);
  65. /* Check to see that the backend connection was successfully made */
  66. if (PQstatus(conn) != CONNECTION_OK)
  67. {
  68. fprintf(stderr, "Connection to database failed: %s",
  69. PQerrorMessage(conn));
  70. exit_nicely(conn);
  71. }
  72. /* Set always-secure search path, so malicous users can't take control. */
  73. res = PQexec(conn,
  74. "SELECT pg_catalog.set_config('search_path', '', false)");
  75. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  76. {
  77. fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
  78. PQclear(res);
  79. exit_nicely(conn);
  80. }
  81. /*
  82. * Should PQclear PGresult whenever it is no longer needed to avoid memory
  83. * leaks
  84. */
  85. PQclear(res);
  86. /*
  87. * Issue LISTEN command to enable notifications from the rule's NOTIFY.
  88. */
  89. res = PQexec(conn, "LISTEN TBL2");
  90. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  91. {
  92. fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn));
  93. PQclear(res);
  94. exit_nicely(conn);
  95. }
  96. PQclear(res);
  97. /* Quit after four notifies are received. */
  98. nnotifies = 0;
  99. while (nnotifies < 4)
  100. {
  101. /*
  102. * Sleep until something happens on the connection. We use select(2)
  103. * to wait for input, but you could also use poll() or similar
  104. * facilities.
  105. */
  106. int sock;
  107. fd_set input_mask;
  108. sock = PQsocket(conn);
  109. if (sock < 0)
  110. break; /* shouldn't happen */
  111. FD_ZERO(&input_mask);
  112. FD_SET(sock, &input_mask);
  113. if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
  114. {
  115. fprintf(stderr, "select() failed: %s\n", strerror(errno));
  116. exit_nicely(conn);
  117. }
  118. /* Now check for input */
  119. PQconsumeInput(conn);
  120. while ((notify = PQnotifies(conn)) != NULL)
  121. {
  122. fprintf(stderr,
  123. "ASYNC NOTIFY of '%s' received from backend PID %d\n",
  124. notify->relname, notify->be_pid);
  125. PQfreemem(notify);
  126. nnotifies++;
  127. }
  128. }
  129. fprintf(stderr, "Done.\n");
  130. /* close the connection to the database and cleanup */
  131. PQfinish(conn);
  132. return 0;
  133. }

Example 33.3. libpq Example Program 3

  1. /*
  2. * src/test/examples/testlibpq3.c
  3. *
  4. *
  5. * testlibpq3.c
  6. * Test out-of-line parameters and binary I/O.
  7. *
  8. * Before running this, populate a database with the following commands
  9. * (provided in src/test/examples/testlibpq3.sql):
  10. *
  11. * CREATE SCHEMA testlibpq3;
  12. * SET search_path = testlibpq3;
  13. * CREATE TABLE test1 (i int4, t text, b bytea);
  14. * INSERT INTO test1 values (1, 'joe''s place', '\\000\\001\\002\\003\\004');
  15. * INSERT INTO test1 values (2, 'ho there', '\\004\\003\\002\\001\\000');
  16. *
  17. * The expected output is:
  18. *
  19. * tuple 0: got
  20. * i = (4 bytes) 1
  21. * t = (11 bytes) 'joe's place'
  22. * b = (5 bytes) \000\001\002\003\004
  23. *
  24. * tuple 0: got
  25. * i = (4 bytes) 2
  26. * t = (8 bytes) 'ho there'
  27. * b = (5 bytes) \004\003\002\001\000
  28. */
  29. #ifdef WIN32
  30. #include <windows.h>
  31. #endif
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <stdint.h>
  35. #include <string.h>
  36. #include <sys/types.h>
  37. #include "libpq-fe.h"
  38. /* for ntohl/htonl */
  39. #include <netinet/in.h>
  40. #include <arpa/inet.h>
  41. static void
  42. exit_nicely(PGconn *conn)
  43. {
  44. PQfinish(conn);
  45. exit(1);
  46. }
  47. /*
  48. * This function prints a query result that is a binary-format fetch from
  49. * a table defined as in the comment above. We split it out because the
  50. * main() function uses it twice.
  51. */
  52. static void
  53. show_binary_results(PGresult *res)
  54. {
  55. int i,
  56. j;
  57. int i_fnum,
  58. t_fnum,
  59. b_fnum;
  60. /* Use PQfnumber to avoid assumptions about field order in result */
  61. i_fnum = PQfnumber(res, "i");
  62. t_fnum = PQfnumber(res, "t");
  63. b_fnum = PQfnumber(res, "b");
  64. for (i = 0; i < PQntuples(res); i++)
  65. {
  66. char *iptr;
  67. char *tptr;
  68. char *bptr;
  69. int blen;
  70. int ival;
  71. /* Get the field values (we ignore possibility they are null!) */
  72. iptr = PQgetvalue(res, i, i_fnum);
  73. tptr = PQgetvalue(res, i, t_fnum);
  74. bptr = PQgetvalue(res, i, b_fnum);
  75. /*
  76. * The binary representation of INT4 is in network byte order, which
  77. * we'd better coerce to the local byte order.
  78. */
  79. ival = ntohl(*((uint32_t *) iptr));
  80. /*
  81. * The binary representation of TEXT is, well, text, and since libpq
  82. * was nice enough to append a zero byte to it, it'll work just fine
  83. * as a C string.
  84. *
  85. * The binary representation of BYTEA is a bunch of bytes, which could
  86. * include embedded nulls so we have to pay attention to field length.
  87. */
  88. blen = PQgetlength(res, i, b_fnum);
  89. printf("tuple %d: got\n", i);
  90. printf(" i = (%d bytes) %d\n",
  91. PQgetlength(res, i, i_fnum), ival);
  92. printf(" t = (%d bytes) '%s'\n",
  93. PQgetlength(res, i, t_fnum), tptr);
  94. printf(" b = (%d bytes) ", blen);
  95. for (j = 0; j < blen; j++)
  96. printf("\\%03o", bptr[j]);
  97. printf("\n\n");
  98. }
  99. }
  100. int
  101. main(int argc, char **argv)
  102. {
  103. const char *conninfo;
  104. PGconn *conn;
  105. PGresult *res;
  106. const char *paramValues[1];
  107. int paramLengths[1];
  108. int paramFormats[1];
  109. uint32_t binaryIntVal;
  110. /*
  111. * If the user supplies a parameter on the command line, use it as the
  112. * conninfo string; otherwise default to setting dbname=postgres and using
  113. * environment variables or defaults for all other connection parameters.
  114. */
  115. if (argc > 1)
  116. conninfo = argv[1];
  117. else
  118. conninfo = "dbname = postgres";
  119. /* Make a connection to the database */
  120. conn = PQconnectdb(conninfo);
  121. /* Check to see that the backend connection was successfully made */
  122. if (PQstatus(conn) != CONNECTION_OK)
  123. {
  124. fprintf(stderr, "Connection to database failed: %s",
  125. PQerrorMessage(conn));
  126. exit_nicely(conn);
  127. }
  128. /* Set always-secure search path, so malicous users can't take control. */
  129. res = PQexec(conn, "SET search_path = testlibpq3");
  130. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  131. {
  132. fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
  133. PQclear(res);
  134. exit_nicely(conn);
  135. }
  136. PQclear(res);
  137. /*
  138. * The point of this program is to illustrate use of PQexecParams() with
  139. * out-of-line parameters, as well as binary transmission of data.
  140. *
  141. * This first example transmits the parameters as text, but receives the
  142. * results in binary format. By using out-of-line parameters we can avoid
  143. * a lot of tedious mucking about with quoting and escaping, even though
  144. * the data is text. Notice how we don't have to do anything special with
  145. * the quote mark in the parameter value.
  146. */
  147. /* Here is our out-of-line parameter value */
  148. paramValues[0] = "joe's place";
  149. res = PQexecParams(conn,
  150. "SELECT * FROM test1 WHERE t = $1",
  151. 1, /* one param */
  152. NULL, /* let the backend deduce param type */
  153. paramValues,
  154. NULL, /* don't need param lengths since text */
  155. NULL, /* default to all text params */
  156. 1); /* ask for binary results */
  157. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  158. {
  159. fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
  160. PQclear(res);
  161. exit_nicely(conn);
  162. }
  163. show_binary_results(res);
  164. PQclear(res);
  165. /*
  166. * In this second example we transmit an integer parameter in binary form,
  167. * and again retrieve the results in binary form.
  168. *
  169. * Although we tell PQexecParams we are letting the backend deduce
  170. * parameter type, we really force the decision by casting the parameter
  171. * symbol in the query text. This is a good safety measure when sending
  172. * binary parameters.
  173. */
  174. /* Convert integer value "2" to network byte order */
  175. binaryIntVal = htonl((uint32_t) 2);
  176. /* Set up parameter arrays for PQexecParams */
  177. paramValues[0] = (char *) &binaryIntVal;
  178. paramLengths[0] = sizeof(binaryIntVal);
  179. paramFormats[0] = 1; /* binary */
  180. res = PQexecParams(conn,
  181. "SELECT * FROM test1 WHERE i = $1::int4",
  182. 1, /* one param */
  183. NULL, /* let the backend deduce param type */
  184. paramValues,
  185. paramLengths,
  186. paramFormats,
  187. 1); /* ask for binary results */
  188. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  189. {
  190. fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
  191. PQclear(res);
  192. exit_nicely(conn);
  193. }
  194. show_binary_results(res);
  195. PQclear(res);
  196. /* close the connection to the database and cleanup */
  197. PQfinish(conn);
  198. return 0;
  199. }