]> begriffs open source - ai-pg/blob - full-docs/txt/libpq-example.txt
Convert HTML docs to more streamlined TXT
[ai-pg] / full-docs / txt / libpq-example.txt
1
2 32.23. Example Programs #
3
4    These examples and others can be found in the directory
5    src/test/examples in the source code distribution.
6
7    Example 32.1. libpq Example Program 1
8
9 /*
10  * src/test/examples/testlibpq.c
11  *
12  *
13  * testlibpq.c
14  *
15  *      Test the C version of libpq, the PostgreSQL frontend library.
16  */
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include "libpq-fe.h"
20
21 static void
22 exit_nicely(PGconn *conn)
23 {
24     PQfinish(conn);
25     exit(1);
26 }
27
28 int
29 main(int argc, char **argv)
30 {
31     const char *conninfo;
32     PGconn     *conn;
33     PGresult   *res;
34     int         nFields;
35     int         i,
36                 j;
37
38     /*
39      * If the user supplies a parameter on the command line, use it as the
40      * conninfo string; otherwise default to setting dbname=postgres and using
41      * environment variables or defaults for all other connection parameters.
42      */
43     if (argc > 1)
44         conninfo = argv[1];
45     else
46         conninfo = "dbname = postgres";
47
48     /* Make a connection to the database */
49     conn = PQconnectdb(conninfo);
50
51     /* Check to see that the backend connection was successfully made */
52     if (PQstatus(conn) != CONNECTION_OK)
53     {
54         fprintf(stderr, "%s", PQerrorMessage(conn));
55         exit_nicely(conn);
56     }
57
58     /* Set always-secure search path, so malicious users can't take control. */
59     res = PQexec(conn,
60                  "SELECT pg_catalog.set_config('search_path', '', false)");
61     if (PQresultStatus(res) != PGRES_TUPLES_OK)
62     {
63         fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
64         PQclear(res);
65         exit_nicely(conn);
66     }
67
68     /*
69      * Should PQclear PGresult whenever it is no longer needed to avoid memory
70      * leaks
71      */
72     PQclear(res);
73
74     /*
75      * Our test case here involves using a cursor, for which we must be inside
76      * a transaction block.  We could do the whole thing with a single
77      * PQexec() of "select * from pg_database", but that's too trivial to make
78      * a good example.
79      */
80
81     /* Start a transaction block */
82     res = PQexec(conn, "BEGIN");
83     if (PQresultStatus(res) != PGRES_COMMAND_OK)
84     {
85         fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
86         PQclear(res);
87         exit_nicely(conn);
88     }
89     PQclear(res);
90
91     /*
92      * Fetch rows from pg_database, the system catalog of databases
93      */
94     res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database");
95     if (PQresultStatus(res) != PGRES_COMMAND_OK)
96     {
97         fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn));
98         PQclear(res);
99         exit_nicely(conn);
100     }
101     PQclear(res);
102
103     res = PQexec(conn, "FETCH ALL in myportal");
104     if (PQresultStatus(res) != PGRES_TUPLES_OK)
105     {
106         fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn));
107         PQclear(res);
108         exit_nicely(conn);
109     }
110
111     /* first, print out the attribute names */
112     nFields = PQnfields(res);
113     for (i = 0; i < nFields; i++)
114         printf("%-15s", PQfname(res, i));
115     printf("\n\n");
116
117     /* next, print out the rows */
118     for (i = 0; i < PQntuples(res); i++)
119     {
120         for (j = 0; j < nFields; j++)
121             printf("%-15s", PQgetvalue(res, i, j));
122         printf("\n");
123     }
124
125     PQclear(res);
126
127     /* close the portal ... we don't bother to check for errors ... */
128     res = PQexec(conn, "CLOSE myportal");
129     PQclear(res);
130
131     /* end the transaction */
132     res = PQexec(conn, "END");
133     PQclear(res);
134
135     /* close the connection to the database and cleanup */
136     PQfinish(conn);
137
138     return 0;
139 }
140
141
142    Example 32.2. libpq Example Program 2
143
144 /*
145  * src/test/examples/testlibpq2.c
146  *
147  *
148  * testlibpq2.c
149  *      Test of the asynchronous notification interface
150  *
151  * Start this program, then from psql in another window do
152  *   NOTIFY TBL2;
153  * Repeat four times to get this program to exit.
154  *
155  * Or, if you want to get fancy, try this:
156  * populate a database with the following commands
157  * (provided in src/test/examples/testlibpq2.sql):
158  *
159  *   CREATE SCHEMA TESTLIBPQ2;
160  *   SET search_path = TESTLIBPQ2;
161  *   CREATE TABLE TBL1 (i int4);
162  *   CREATE TABLE TBL2 (i int4);
163  *   CREATE RULE r1 AS ON INSERT TO TBL1 DO
164  *     (INSERT INTO TBL2 VALUES (new.i); NOTIFY TBL2);
165  *
166  * Start this program, then from psql do this four times:
167  *
168  *   INSERT INTO TESTLIBPQ2.TBL1 VALUES (10);
169  */
170
171 #ifdef WIN32
172 #include <windows.h>
173 #endif
174 #include <stdio.h>
175 #include <stdlib.h>
176 #include <string.h>
177 #include <errno.h>
178 #include <sys/select.h>
179 #include <sys/time.h>
180 #include <sys/types.h>
181
182 #include "libpq-fe.h"
183
184 static void
185 exit_nicely(PGconn *conn)
186 {
187     PQfinish(conn);
188     exit(1);
189 }
190
191 int
192 main(int argc, char **argv)
193 {
194     const char *conninfo;
195     PGconn     *conn;
196     PGresult   *res;
197     PGnotify   *notify;
198     int         nnotifies;
199
200     /*
201      * If the user supplies a parameter on the command line, use it as the
202      * conninfo string; otherwise default to setting dbname=postgres and using
203      * environment variables or defaults for all other connection parameters.
204      */
205     if (argc > 1)
206         conninfo = argv[1];
207     else
208         conninfo = "dbname = postgres";
209
210     /* Make a connection to the database */
211     conn = PQconnectdb(conninfo);
212
213     /* Check to see that the backend connection was successfully made */
214     if (PQstatus(conn) != CONNECTION_OK)
215     {
216         fprintf(stderr, "%s", PQerrorMessage(conn));
217         exit_nicely(conn);
218     }
219
220     /* Set always-secure search path, so malicious users can't take control. */
221     res = PQexec(conn,
222                  "SELECT pg_catalog.set_config('search_path', '', false)");
223     if (PQresultStatus(res) != PGRES_TUPLES_OK)
224     {
225         fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
226         PQclear(res);
227         exit_nicely(conn);
228     }
229
230     /*
231      * Should PQclear PGresult whenever it is no longer needed to avoid memory
232      * leaks
233      */
234     PQclear(res);
235
236     /*
237      * Issue LISTEN command to enable notifications from the rule's NOTIFY.
238      */
239     res = PQexec(conn, "LISTEN TBL2");
240     if (PQresultStatus(res) != PGRES_COMMAND_OK)
241     {
242         fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn));
243         PQclear(res);
244         exit_nicely(conn);
245     }
246     PQclear(res);
247
248     /* Quit after four notifies are received. */
249     nnotifies = 0;
250     while (nnotifies < 4)
251     {
252         /*
253          * Sleep until something happens on the connection.  We use select(2)
254          * to wait for input, but you could also use poll() or similar
255          * facilities.
256          */
257         int         sock;
258         fd_set      input_mask;
259
260         sock = PQsocket(conn);
261
262         if (sock < 0)
263             break;              /* shouldn't happen */
264
265         FD_ZERO(&input_mask);
266         FD_SET(sock, &input_mask);
267
268         if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
269         {
270             fprintf(stderr, "select() failed: %s\n", strerror(errno));
271             exit_nicely(conn);
272         }
273
274         /* Now check for input */
275         PQconsumeInput(conn);
276         while ((notify = PQnotifies(conn)) != NULL)
277         {
278             fprintf(stderr,
279                     "ASYNC NOTIFY of '%s' received from backend PID %d\n",
280                     notify->relname, notify->be_pid);
281             PQfreemem(notify);
282             nnotifies++;
283             PQconsumeInput(conn);
284         }
285     }
286
287     fprintf(stderr, "Done.\n");
288
289     /* close the connection to the database and cleanup */
290     PQfinish(conn);
291
292     return 0;
293 }
294
295
296    Example 32.3. libpq Example Program 3
297
298 /*
299  * src/test/examples/testlibpq3.c
300  *
301  *
302  * testlibpq3.c
303  *      Test out-of-line parameters and binary I/O.
304  *
305  * Before running this, populate a database with the following commands
306  * (provided in src/test/examples/testlibpq3.sql):
307  *
308  * CREATE SCHEMA testlibpq3;
309  * SET search_path = testlibpq3;
310  * SET standard_conforming_strings = ON;
311  * CREATE TABLE test1 (i int4, t text, b bytea);
312  * INSERT INTO test1 values (1, 'joe''s place', '\000\001\002\003\004');
313  * INSERT INTO test1 values (2, 'ho there', '\004\003\002\001\000');
314  *
315  * The expected output is:
316  *
317  * tuple 0: got
318  *  i = (4 bytes) 1
319  *  t = (11 bytes) 'joe's place'
320  *  b = (5 bytes) \000\001\002\003\004
321  *
322  * tuple 0: got
323  *  i = (4 bytes) 2
324  *  t = (8 bytes) 'ho there'
325  *  b = (5 bytes) \004\003\002\001\000
326  */
327
328 #ifdef WIN32
329 #include <windows.h>
330 #endif
331
332 #include <stdio.h>
333 #include <stdlib.h>
334 #include <stdint.h>
335 #include <string.h>
336 #include <sys/types.h>
337 #include "libpq-fe.h"
338
339 /* for ntohl/htonl */
340 #include <netinet/in.h>
341 #include <arpa/inet.h>
342
343
344 static void
345 exit_nicely(PGconn *conn)
346 {
347     PQfinish(conn);
348     exit(1);
349 }
350
351 /*
352  * This function prints a query result that is a binary-format fetch from
353  * a table defined as in the comment above.  We split it out because the
354  * main() function uses it twice.
355  */
356 static void
357 show_binary_results(PGresult *res)
358 {
359     int         i,
360                 j;
361     int         i_fnum,
362                 t_fnum,
363                 b_fnum;
364
365     /* Use PQfnumber to avoid assumptions about field order in result */
366     i_fnum = PQfnumber(res, "i");
367     t_fnum = PQfnumber(res, "t");
368     b_fnum = PQfnumber(res, "b");
369
370     for (i = 0; i < PQntuples(res); i++)
371     {
372         char       *iptr;
373         char       *tptr;
374         char       *bptr;
375         int         blen;
376         int         ival;
377
378         /* Get the field values (we ignore possibility they are null!) */
379         iptr = PQgetvalue(res, i, i_fnum);
380         tptr = PQgetvalue(res, i, t_fnum);
381         bptr = PQgetvalue(res, i, b_fnum);
382
383         /*
384          * The binary representation of INT4 is in network byte order, which
385          * we'd better coerce to the local byte order.
386          */
387         ival = ntohl(*((uint32_t *) iptr));
388
389         /*
390          * The binary representation of TEXT is, well, text, and since libpq
391          * was nice enough to append a zero byte to it, it'll work just fine
392          * as a C string.
393          *
394          * The binary representation of BYTEA is a bunch of bytes, which could
395          * include embedded nulls so we have to pay attention to field length.
396          */
397         blen = PQgetlength(res, i, b_fnum);
398
399         printf("tuple %d: got\n", i);
400         printf(" i = (%d bytes) %d\n",
401                PQgetlength(res, i, i_fnum), ival);
402         printf(" t = (%d bytes) '%s'\n",
403                PQgetlength(res, i, t_fnum), tptr);
404         printf(" b = (%d bytes) ", blen);
405         for (j = 0; j < blen; j++)
406             printf("\\%03o", bptr[j]);
407         printf("\n\n");
408     }
409 }
410
411 int
412 main(int argc, char **argv)
413 {
414     const char *conninfo;
415     PGconn     *conn;
416     PGresult   *res;
417     const char *paramValues[1];
418     int         paramLengths[1];
419     int         paramFormats[1];
420     uint32_t    binaryIntVal;
421
422     /*
423      * If the user supplies a parameter on the command line, use it as the
424      * conninfo string; otherwise default to setting dbname=postgres and using
425      * environment variables or defaults for all other connection parameters.
426      */
427     if (argc > 1)
428         conninfo = argv[1];
429     else
430         conninfo = "dbname = postgres";
431
432     /* Make a connection to the database */
433     conn = PQconnectdb(conninfo);
434
435     /* Check to see that the backend connection was successfully made */
436     if (PQstatus(conn) != CONNECTION_OK)
437     {
438         fprintf(stderr, "%s", PQerrorMessage(conn));
439         exit_nicely(conn);
440     }
441
442     /* Set always-secure search path, so malicious users can't take control. */
443     res = PQexec(conn, "SET search_path = testlibpq3");
444     if (PQresultStatus(res) != PGRES_COMMAND_OK)
445     {
446         fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
447         PQclear(res);
448         exit_nicely(conn);
449     }
450     PQclear(res);
451
452     /*
453      * The point of this program is to illustrate use of PQexecParams() with
454      * out-of-line parameters, as well as binary transmission of data.
455      *
456      * This first example transmits the parameters as text, but receives the
457      * results in binary format.  By using out-of-line parameters we can avoid
458      * a lot of tedious mucking about with quoting and escaping, even though
459      * the data is text.  Notice how we don't have to do anything special with
460      * the quote mark in the parameter value.
461      */
462
463     /* Here is our out-of-line parameter value */
464     paramValues[0] = "joe's place";
465
466     res = PQexecParams(conn,
467                        "SELECT * FROM test1 WHERE t = $1",
468                        1,       /* one param */
469                        NULL,    /* let the backend deduce param type */
470                        paramValues,
471                        NULL,    /* don't need param lengths since text */
472                        NULL,    /* default to all text params */
473                        1);      /* ask for binary results */
474
475     if (PQresultStatus(res) != PGRES_TUPLES_OK)
476     {
477         fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
478         PQclear(res);
479         exit_nicely(conn);
480     }
481
482     show_binary_results(res);
483
484     PQclear(res);
485
486     /*
487      * In this second example we transmit an integer parameter in binary form,
488      * and again retrieve the results in binary form.
489      *
490      * Although we tell PQexecParams we are letting the backend deduce
491      * parameter type, we really force the decision by casting the parameter
492      * symbol in the query text.  This is a good safety measure when sending
493      * binary parameters.
494      */
495
496     /* Convert integer value "2" to network byte order */
497     binaryIntVal = htonl((uint32_t) 2);
498
499     /* Set up parameter arrays for PQexecParams */
500     paramValues[0] = (char *) &binaryIntVal;
501     paramLengths[0] = sizeof(binaryIntVal);
502     paramFormats[0] = 1;        /* binary */
503
504     res = PQexecParams(conn,
505                        "SELECT * FROM test1 WHERE i = $1::int4",
506                        1,       /* one param */
507                        NULL,    /* let the backend deduce param type */
508                        paramValues,
509                        paramLengths,
510                        paramFormats,
511                        1);      /* ask for binary results */
512
513     if (PQresultStatus(res) != PGRES_TUPLES_OK)
514     {
515         fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
516         PQclear(res);
517         exit_nicely(conn);
518     }
519
520     show_binary_results(res);
521
522     PQclear(res);
523
524     /* close the connection to the database and cleanup */
525     PQfinish(conn);
526
527     return 0;
528 }
529