Client 2 - Adding Error Checking

   

Client 2 ”Adding Error Checking

The client1.c application discussed has a fundamental flaw ”there is no way to tell whether the connection attempt was successful. This next program attempts a connection and displays an error message if the attempt fails:

 1 /*  2 ** File: client2.c  3 */  4  5 #include <stdlib.h>  6 #include <libpq-fe.h>  7  8 int main( int argc, char * argv[] )  9 { 10   PGconn * connection; 11 12   if( argc != 2 ) 13   { 14     printf( "usage  : %s \"connection-string\"\n", argv[0] ); 15     printf( "example: %s \"user=myname password=cows\"\n", argv[0]); 16     exit( 1 ); 17   } 18 19   if(( connection = PQconnectdb( argv[1] )) == NULL ) 20   { 21     printf( "Fatal error - unable to allocate connection\n" ); 22     exit( 1 ); 23   } 24 25   if( PQstatus( connection ) != CONNECTION_OK ) 26     printf( "%s\n", PQerrorMessage( connection )); 27   else 28     printf( "Connection ok, disconnecting\n" ); 29 30   PQfinish( connection ); 31 32   exit( 0 ); 33 34 } 

You can specify a connection string on the command line when you run this program. If you want to include more than one connection attribute, enclose the entire connection string in double quotes. For example:

 $ ./client2 user=korry Connection ok, disconnecting $ ./client2 "user=korry password=cows" Connection ok, disconnecting 

I recommend that you run this program a few times, feeding it a variety of invalid connect strings so you become familiar with the error messages that you might receive when things go wrong. For example:

 $ ./client2 host=badhost connectDBStart() --  unknown hostname: badhost $ ./client2 port=1000 connectDBStart() -- connect() failed: No such file or directory         Is the postmaster running locally         and accepting connections on Unix socket '/tmp/.s.PGSQL.1000'? $ ./client2 badparameter ERROR: Missing '=' after 'badparameter' in conninfo $ ./client2 badparameter=1000 ERROR: Unknown conninfo option 'badparameter' 

Viewing Connection Attributes

In the get_dflts application I showed you how to use the PQconndefaults( ) function to view the default connection attributes that will be used to establish a connection.

libpq also provides a number of functions that you can use to retrieve the actual connection attributes after you have a PGconn object. These functions are useful because in most situations, you won't explicitly specify every connection attribute. Instead, many (perhaps all) of the connection attributes will be defaulted for you.

PQconnectdb() will return a PGconn pointer in almost every case (only if libpq runs out of memory, PQconnectdb() will return a NULL pointer).

The following program attempts to make a connection and then print the set of connection parameters. I've modified client2.c to show the complete set of final connection parameters after a connection attempt. The new application is called client2b :

 1 /*  2 ** File: client2b.c  3 */  4  5 #include <stdlib.h>  6 #include <libpq-fe.h>  7  8 static void show_connection_attributes( const PGconn * conn );  9 static const char * check( const char * value ); 10 11 int main( int argc, char * argv[] ) 12 { 13   PGconn * connection; 14 15   if( argc != 2 ) 16   { 17     printf( "usage  : %s \"connection-string\"\n", argv[0] ); 18     printf( "example: %s \"user=myname password=cows\"\n", argv[0]); 19     exit( 1 ); 20   } 21 22   if(( connection = PQconnectdb( argv[1] )) == NULL ) 23   { 24     printf( "Fatal error - unable to allocate connection\n" ); 25     exit( 1 ); 26   } 27 28   if( PQstatus( connection ) != CONNECTION_OK ) 29     printf( "%s\n", PQerrorMessage( connection )); 30   else 31     printf( "Connection ok\n" ); 32 33   show_connection_attributes( connection ); 34 35   PQfinish( connection ); 36 37   exit( 0 ); 38 39 } 40 41 static const char * check( const char * value ) 42 { 43     if( value ) 44     return( value ); 45     else 46     return( "(null)" ); 47 } 48 49 static void show_connection_attributes( const PGconn * c ) 50 { 51   printf( "dbname   = %s\n", check( PQdb( c ))); 52   printf( "user     = %s\n", check( PQuser( c ))); 53   printf( "password = %s\n", check( PQpass( c ))); 54   printf( "host     = %s\n", check( PQhost( c ))); 55   printf( "port     = %s\n", check( PQport( c ))); 56   printf( "tty      = %s\n", check( PQtty( c ))); 57   printf( "options  = %s\n", check( PQoptions( c ))); 58 } 

Take a look at the show_connection_attributes() function (lines 49 “58). Given a PGconn pointer, you can find the connection attributes that result after all the defaults are applied by calling PQdb() , PQuser() , and so on. In some cases, one of these functions returns a NULL pointer, so I wrapped each function invocation in a call to check() (lines 41 “47) so you don't try to give any bad pointers to printf() .

Remember that PQconnectdb() returns a PGconn pointer even when a connection attempt fails; it is often instructive to see the final connection attributes for a failed connection attempt. Here are the results when I try to connect to a nonexistent database on my system:

 $ ./client2b user=korry FATAL 1:  Database "korry" does not exist in the system catalog. dbname   = korry user     = korry password = host     = (null) port     = 5432 tty      = options  = 

In this case, I can see that libpq chose an invalid database name (defaulted from my username).

   


PostgreSQL
PostgreSQL (2nd Edition)
ISBN: 0672327562
EAN: 2147483647
Year: 2005
Pages: 220
Authors: Korry Douglas

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net