Header And Logo

PostgreSQL
| The world's most advanced open source database.

testlibpq3.c

Go to the documentation of this file.
00001 /*
00002  * src/test/examples/testlibpq3.c
00003  *
00004  *
00005  * testlibpq3.c
00006  *      Test out-of-line parameters and binary I/O.
00007  *
00008  * Before running this, populate a database with the following commands
00009  * (provided in src/test/examples/testlibpq3.sql):
00010  *
00011  * CREATE TABLE test1 (i int4, t text, b bytea);
00012  *
00013  * INSERT INTO test1 values (1, 'joe''s place', '\\000\\001\\002\\003\\004');
00014  * INSERT INTO test1 values (2, 'ho there', '\\004\\003\\002\\001\\000');
00015  *
00016  * The expected output is:
00017  *
00018  * tuple 0: got
00019  *  i = (4 bytes) 1
00020  *  t = (11 bytes) 'joe's place'
00021  *  b = (5 bytes) \000\001\002\003\004
00022  *
00023  * tuple 0: got
00024  *  i = (4 bytes) 2
00025  *  t = (8 bytes) 'ho there'
00026  *  b = (5 bytes) \004\003\002\001\000
00027  */
00028 
00029 #ifdef WIN32
00030 #include <windows.h>
00031 #endif
00032 
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <stdint.h>
00036 #include <string.h>
00037 #include <sys/types.h>
00038 #include "libpq-fe.h"
00039 
00040 /* for ntohl/htonl */
00041 #include <netinet/in.h>
00042 #include <arpa/inet.h>
00043 
00044 
00045 static void
00046 exit_nicely(PGconn *conn)
00047 {
00048     PQfinish(conn);
00049     exit(1);
00050 }
00051 
00052 /*
00053  * This function prints a query result that is a binary-format fetch from
00054  * a table defined as in the comment above.  We split it out because the
00055  * main() function uses it twice.
00056  */
00057 static void
00058 show_binary_results(PGresult *res)
00059 {
00060     int         i,
00061                 j;
00062     int         i_fnum,
00063                 t_fnum,
00064                 b_fnum;
00065 
00066     /* Use PQfnumber to avoid assumptions about field order in result */
00067     i_fnum = PQfnumber(res, "i");
00068     t_fnum = PQfnumber(res, "t");
00069     b_fnum = PQfnumber(res, "b");
00070 
00071     for (i = 0; i < PQntuples(res); i++)
00072     {
00073         char       *iptr;
00074         char       *tptr;
00075         char       *bptr;
00076         int         blen;
00077         int         ival;
00078 
00079         /* Get the field values (we ignore possibility they are null!) */
00080         iptr = PQgetvalue(res, i, i_fnum);
00081         tptr = PQgetvalue(res, i, t_fnum);
00082         bptr = PQgetvalue(res, i, b_fnum);
00083 
00084         /*
00085          * The binary representation of INT4 is in network byte order, which
00086          * we'd better coerce to the local byte order.
00087          */
00088         ival = ntohl(*((uint32_t *) iptr));
00089 
00090         /*
00091          * The binary representation of TEXT is, well, text, and since libpq
00092          * was nice enough to append a zero byte to it, it'll work just fine
00093          * as a C string.
00094          *
00095          * The binary representation of BYTEA is a bunch of bytes, which could
00096          * include embedded nulls so we have to pay attention to field length.
00097          */
00098         blen = PQgetlength(res, i, b_fnum);
00099 
00100         printf("tuple %d: got\n", i);
00101         printf(" i = (%d bytes) %d\n",
00102                PQgetlength(res, i, i_fnum), ival);
00103         printf(" t = (%d bytes) '%s'\n",
00104                PQgetlength(res, i, t_fnum), tptr);
00105         printf(" b = (%d bytes) ", blen);
00106         for (j = 0; j < blen; j++)
00107             printf("\\%03o", bptr[j]);
00108         printf("\n\n");
00109     }
00110 }
00111 
00112 int
00113 main(int argc, char **argv)
00114 {
00115     const char *conninfo;
00116     PGconn     *conn;
00117     PGresult   *res;
00118     const char *paramValues[1];
00119     int         paramLengths[1];
00120     int         paramFormats[1];
00121     uint32_t    binaryIntVal;
00122 
00123     /*
00124      * If the user supplies a parameter on the command line, use it as the
00125      * conninfo string; otherwise default to setting dbname=postgres and using
00126      * environment variables or defaults for all other connection parameters.
00127      */
00128     if (argc > 1)
00129         conninfo = argv[1];
00130     else
00131         conninfo = "dbname = postgres";
00132 
00133     /* Make a connection to the database */
00134     conn = PQconnectdb(conninfo);
00135 
00136     /* Check to see that the backend connection was successfully made */
00137     if (PQstatus(conn) != CONNECTION_OK)
00138     {
00139         fprintf(stderr, "Connection to database failed: %s",
00140                 PQerrorMessage(conn));
00141         exit_nicely(conn);
00142     }
00143 
00144     /*
00145      * The point of this program is to illustrate use of PQexecParams() with
00146      * out-of-line parameters, as well as binary transmission of data.
00147      *
00148      * This first example transmits the parameters as text, but receives the
00149      * results in binary format.  By using out-of-line parameters we can avoid
00150      * a lot of tedious mucking about with quoting and escaping, even though
00151      * the data is text.  Notice how we don't have to do anything special with
00152      * the quote mark in the parameter value.
00153      */
00154 
00155     /* Here is our out-of-line parameter value */
00156     paramValues[0] = "joe's place";
00157 
00158     res = PQexecParams(conn,
00159                        "SELECT * FROM test1 WHERE t = $1",
00160                        1,       /* one param */
00161                        NULL,    /* let the backend deduce param type */
00162                        paramValues,
00163                        NULL,    /* don't need param lengths since text */
00164                        NULL,    /* default to all text params */
00165                        1);      /* ask for binary results */
00166 
00167     if (PQresultStatus(res) != PGRES_TUPLES_OK)
00168     {
00169         fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
00170         PQclear(res);
00171         exit_nicely(conn);
00172     }
00173 
00174     show_binary_results(res);
00175 
00176     PQclear(res);
00177 
00178     /*
00179      * In this second example we transmit an integer parameter in binary form,
00180      * and again retrieve the results in binary form.
00181      *
00182      * Although we tell PQexecParams we are letting the backend deduce
00183      * parameter type, we really force the decision by casting the parameter
00184      * symbol in the query text.  This is a good safety measure when sending
00185      * binary parameters.
00186      */
00187 
00188     /* Convert integer value "2" to network byte order */
00189     binaryIntVal = htonl((uint32_t) 2);
00190 
00191     /* Set up parameter arrays for PQexecParams */
00192     paramValues[0] = (char *) &binaryIntVal;
00193     paramLengths[0] = sizeof(binaryIntVal);
00194     paramFormats[0] = 1;        /* binary */
00195 
00196     res = PQexecParams(conn,
00197                        "SELECT * FROM test1 WHERE i = $1::int4",
00198                        1,       /* one param */
00199                        NULL,    /* let the backend deduce param type */
00200                        paramValues,
00201                        paramLengths,
00202                        paramFormats,
00203                        1);      /* ask for binary results */
00204 
00205     if (PQresultStatus(res) != PGRES_TUPLES_OK)
00206     {
00207         fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
00208         PQclear(res);
00209         exit_nicely(conn);
00210     }
00211 
00212     show_binary_results(res);
00213 
00214     PQclear(res);
00215 
00216     /* close the connection to the database and cleanup */
00217     PQfinish(conn);
00218 
00219     return 0;
00220 }