diff options
Diffstat (limited to 'src/test/examples/testlibpq3.c')
-rw-r--r-- | src/test/examples/testlibpq3.c | 154 |
1 files changed, 107 insertions, 47 deletions
diff --git a/src/test/examples/testlibpq3.c b/src/test/examples/testlibpq3.c index 918d142c7b..c7e4e09732 100644 --- a/src/test/examples/testlibpq3.c +++ b/src/test/examples/testlibpq3.c @@ -17,6 +17,10 @@ * 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> @@ -36,6 +40,66 @@ exit_nicely(PGconn *conn) exit(1); } +/* + * This function prints a query result that is a binary-format fetch from + * a table defined as in the comment above. We split it out because the + * main() function uses it twice. + */ +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) { @@ -43,11 +107,9 @@ main(int argc, char **argv) PGconn *conn; PGresult *res; const char *paramValues[1]; - int i, - j; - int i_fnum, - t_fnum, - b_fnum; + int paramLengths[1]; + int paramFormats[1]; + uint32_t binaryIntVal; /* * If the user supplies a parameter on the command line, use it as the @@ -72,10 +134,13 @@ main(int argc, char **argv) /* * The point of this program is to illustrate use of PQexecParams() with - * out-of-line parameters, as well as binary transmission of results. By - * using out-of-line parameters we can avoid a lot of tedious mucking - * about with quoting and escaping. Notice how we don't have to do - * anything special with the quote mark in the parameter value. + * 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 */ @@ -97,51 +162,46 @@ main(int argc, char **argv) exit_nicely(conn); } - /* 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"); + show_binary_results(res); - for (i = 0; i < PQntuples(res); i++) - { - char *iptr; - char *tptr; - char *bptr; - int blen; - int ival; + PQclear(res); - /* 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); + /* + * 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. + */ - /* - * 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)); + /* Convert integer value "2" to network byte order */ + binaryIntVal = htonl((uint32_t) 2); - /* - * 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); + /* Set up parameter arrays for PQexecParams */ + paramValues[0] = (char *) &binaryIntVal; + paramLengths[0] = sizeof(binaryIntVal); + paramFormats[0] = 1; /* binary */ - 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"); + 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 */ |