It is also possible to establish the initial connection to the database in a nonblocking way by using PQconnectStart and PQconnectPoll:
PGconn *PQconnectStart(const char *conninfo);
PostgresPollingStatusType *PQconnectPoll(PGconn *conn);
PQconnectStart is similar to PQconnectdb, except that it returns immediately, before the connection requested in the conninfo string has been established. As long as the host name parameter does not result in a DNS lookup, PQconnectStart will not block.
Before using the new connection, we must be sure that it is ready. First, we must call PQstatus to make sure that the call to PQconnectStart did not fail and leave a connection with a status of CONNECTION_BAD. We can then check the connection’s condition with PQconnectPoll, which will not block. The return results from PQconnectPoll include the following:
PGRES_POLLING_FAILED /*the connection has failed*/
PGRES_POLLING_OK /*the connection has been made*/
By polling while the result is not PGRES_POLLING_FAILED, and until it becomes PGRES_POLLING_OK, we can detect the end of the connection establishment process in a nonblocking fashion.
Here is a sample program (async2.c) that makes an asynchronous database connection:
#include <stdlib.h>
#include <libpq-fe.h>
int main() {
PGresult *result;
PGconn *conn;
/* Start an asynchronous connection */
conn = PQconnectStart("");
if(PQstatus(conn) == CONNECTION_BAD) {
printf(" cannot start connect: %s\n", PQerrorMessage(conn));
} else {
/* do some work, calling PQconnectPoll from time to time */
PostgresPollingStatusType status;
do {
printf("polling\n");
status = PQconnectPoll(conn);
}
while(status != PGRES_POLLING_FAILED &&
status != PGRES_POLLING_OK);
if(status == PGRES_POLLING_OK) printf("connection made!\n");
else
printf("connection failed: %s\n", PQerrorMessage(conn));
}
PQfinish(conn);
return EXIT_SUCCESS;
}
When we run this program, we see many polling messages before the connection is reported as made or failed:
$ PGDATABASE=bpfinal ./async2 polling
polling ...
connection made!
$
■Note If you run this program several times, you may see a different number of polling messages appear before the connection is made. The exact number will depend on how long it takes the server to respond to the connection request.
Summary
In this chapter, we looked at creating PostgreSQL applications in C. We saw how the libpq library provides access to the low-level functions of PostgreSQL, allowing us to connect to a database on a local machine or on a server across the network. We have used sample programs to make and close connections, and execute SQL statements to query, insert, or update rows in our database tables.
We have considered problems of handling large volumes of data and looked at how to use cursors to marshal query results into manageable units. We have looked at the problem of blocking and considered ways of creating applications that continue to service the user while accessing a database server.
We can also access PostgreSQL from C using embedded SQL, which is the subject of the next chapter.
419
■ ■ ■
Accessing PostgreSQL from C Using Embedded SQL
In the previous chapter, we introduced the libpq library, a collection of C functions specific to PostgreSQL that allow programs to connect to a database and select data from tables. We also saw how to effectively execute standard SQL queries and perform updates, insertions, and deletions on rows in the database tables using this library.
Although libpq does unleash the power of the PostgreSQL database system for our appli- cations, it is in some ways unfortunate that the interface itself is unique to PostgreSQL, different from any other C API we might use for accessing other relational databases. Another drawback to using libpq is that it is not easy to see the SQL, as the supporting code tends to hide the all-important SQL statements, and that makes it more difficult to maintain the code.
Help is at hand however. Many database systems, particularly commercial ones, support the concept of embedded SQL. The SQL92 standard specified interfaces for embedding SQL in various languages, not only in C, but also in FORTRAN, ADA, and others. In December 1998, ANSI also ratified a standard for embedding SQL in Java, SQLJ, although that is not widely used.
Using embedded SQL in C code, following the SQL standards, enables us to create appli- cations that are more portable to other databases. Furthermore, it makes writing code to access PostgreSQL easier, since it provides a higher-level, more intuitive way of writing an application.
PostgreSQL supports this feature using a preprocessor known as ecpg, and an additional library to support the code that is generated from ecpg.
In this chapter, we will explore how to use SQL in C programs by embedding SQL state- ments directly in the source code. If you have used embedded SQL in another database system, you will be right at home in this chapter.