Client 4 - An Interactive Query Processor

   

Client 4 ”An Interactive Query Processor

To wrap up this chapter, you'll convert the interactive query processor from the previous chapter into a libpgeasy client.

Most of the code remains the same, so I'll point out only the differences. The most important change is that you no longer have to pass the PGconn * (connection handle) to every function ”libpgeasy is managing the connection handle for you.

 1 /*  2 ** File: client4.c  3 */  4  5 #include <stdlib.h>  6 #include <string.h>  7 #include <libpq-fe.h>  8 #include <libpgeasy.h>  9 #include <readline/readline.h> 10 #include <readline/history.h> 11 12 typedef enum { FALSE, TRUE } bool; 13 14 #define MAX_PRINT_LEN40 15 16 static char separator[MAX_PRINT_LEN+1]; 17 18 void print_result_set(PGresult * result) 19 { 20   int          col; 21   int          row; 22   int        * sizes; 23 24 /* 25 ** Compute the size for each column 26 */ 27   sizes = (int *)calloc(PQnfields(result), sizeof(int)); 28 29   for(col = 0; col < PQnfields(result); col++) 30   { 31     int   len = 0; 32 33     for(row = 0; row < PQntuples(result); row++) 34     { 35       if(PQgetisnull(result, row, col)) 36         len = 0; 37       else 38          len = PQgetlength(result, row, col); 39 40       if(len > sizes[col]) 41          sizes[col] = len; 42     } 43 44     if((len = strlen(PQfname(result, col))) > sizes[col]) 45       sizes[col] = len; 46 47     if(sizes[col] > MAX_PRINT_LEN) 48       sizes[col] = MAX_PRINT_LEN; 49   } 50 51 /* 52 ** Print the field names. 53 */ 54   for(col = 0; col < PQnfields(result); col++) 55   { 56     printf("%-*s ", sizes[col], PQfname(result, col)); 57   } 58 59   printf("\n"); 60 61 /* 62 ** Print the separator line 63 */ 64   memset(separator, '-', MAX_PRINT_LEN); 65 66   for(col = 0; col < PQnfields(result); col++) 67   { 68     printf("%*.*s ", sizes[col], sizes[col], separator); 69   } 70 71   printf("\n"); 72 73 /* 74 ** Now loop through each of the tuples returned by 75 ** our query and print the results. 76 */ 77   for(row = 0; row < PQntuples(result); row++) 78   { 79     for(col = 0; col < PQnfields(result); col++) 80     { 81       if(PQgetisnull(result, row, col)) 82          printf("%*s", sizes[col], ""); 83       else 84          printf("%*s ", sizes[col], PQgetvalue(result, row, col)); 85     } 86 87     printf("\n"); 88 89   } 90   printf("(%d rows)\n", PQntuples(result)); 91 92   free(sizes); 93 } 

You can't use the fetch() or fetchwithnulls() in the print_result_set() function. There is no way to construct a call to these functions because you can't know (at the time the program is compiled) how many columns will be returned by a query.

The process_query() function is very simple. The call to doquery() sends the command to the server and returns a pointer to the result set.

 95 void process_query(char * buf)  96 {  97   PGresult *  result;  98  99   result = doquery(buf); 100 101   if(PQresultStatus(result) == PGRES_TUPLES_OK) 102   { 103     print_result_set(result); 104   } 105   else if(PQresultStatus(result) == PGRES_COMMAND_OK) 106   { 107     printf("%s", PQcmdStatus(result)); 108 109     if(strlen(PQcmdTuples(result))) 110       printf(" - %s rows\n", PQcmdTuples(result)); 111     else 112       printf("\n"); 113   } 114   else 115   { 116       printf("%s\n", PQresultErrorMessage(result)); 117   } 118 } 

The main() function is largely unchanged. I don't bother to save the connection handle returned by connectdb() because libpgeasy remembers it for me. The only other change in main() is that you set the error-handling mode calling on_error_continue() . If you don't set the error-handling mode, libpgeasy assumes that it should terminate your application if an error is encountered .

 120 int main(int argc, char * argv[]) 121 { 122   char    * buf; 123 124   connectdb(argc > 1 ? argv[1] : ""); 125 126   on_error_continue(); 127 128   using_history(); 129   read_history(".pg_history"); 130 131   while((buf = readline(">")) != NULL) 132   { 133     if(strncmp(buf, "quit", sizeof("quit") - 1) == 0) 134     { 135       break; 136     } 137     else 138     { 139       if(strlen(buf) != 0) 140       { 141          add_history(buf); 142          process_query(buf); 143       } 144       free(buf); 145     } 146   } 147 148   write_history(".pg_history"); 149 150   disconnectdb(); 151 152   exit(EXIT_SUCCESS); 153 } 
   


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