1    | /***************************************
2    |   $Revision: 1.26 $
3    | 
4    |   SQL module (sq) - this is a MySQL implementation of the SQL module.
5    | 
6    |   Status: NOT REVUED, TESTED
7    | 
8    |   ******************/ /******************
9    |   Filename            : mysql_driver.c
10   |   Authors             : ottrey@ripe.net
11   |                         marek@ripe.net
12   |   OSs Tested          : Solaris 7 / sun4u / sparc
13   |   ******************/ /******************
14   |   Copyright (c) 1999                              RIPE NCC
15   |  
16   |   All Rights Reserved
17   |   
18   |   Permission to use, copy, modify, and distribute this software and its
19   |   documentation for any purpose and without fee is hereby granted,
20   |   provided that the above copyright notice appear in all copies and that
21   |   both that copyright notice and this permission notice appear in
22   |   supporting documentation, and that the name of the author not be
23   |   used in advertising or publicity pertaining to distribution of the
24   |   software without specific, written prior permission.
25   |   
26   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32   |   ***************************************/
33   | #include <stdlib.h>
34   | #include <stdio.h>
35   | #include <sys/timeb.h>
36   | #include <strings.h>
37   | 
38   | #include "mysql_driver.h"
39   | #include "constants.h"
40   | #include "memwrap.h"
41   | 
42   | /*+ String sizes +*/
43   | #define STR_S   63
44   | #define STR_M   255
45   | #define STR_L   1023
46   | #define STR_XL  4095
47   | #define STR_XXL 16383
48   | 
49   | 
50   | /* log_query() */
51   | /*++++++++++++++++++++++++++++++++++++++
52   |   Log the query.  This should/will get merged with a tracing module.
53   | 
54   |   More:
55   |   +html+ <PRE>
56   |   Authors:
57   |         ottrey
58   |   +html+ </PRE><DL COMPACT>
59   |   +html+ <DT>Online References:
60   |   +html+ <DD><UL>
61   |   +html+ </UL></DL>
62   | 
63   |   ++++++++++++++++++++++++++++++++++++++*/
64   | void log_query(const char *logfile, const char *query, struct timeb *start, struct timeb *stop) {
65   |   FILE *logf;
66   |   int seconds;
67   |   int milliseconds;
68   | 
69   |   seconds = (int)(stop->time - start->time);
70   |   milliseconds = (int)(stop->millitm - start->millitm);
71   |   if (milliseconds < 0) {
72   |     milliseconds += 1000;
73   |     seconds--;
74   |   }
75   | 
76   |   if (strcmp(logfile, "stdout") == 0) {
77   |     printf("query=[%s] took %d sec %d msec\n", query, seconds, milliseconds);
78   |   }
79   |   else {
80   |     logf = fopen(logfile, "a");
81   |     fprintf(logf, "query=[%s] took %d sec %d msec\n", query, seconds, milliseconds);
82   |     fclose(logf);
83   |   }
84   | 
85   | } /* log_query() */
86   | 
87   | /* SQ_get_connection() */
88   | /*++++++++++++++++++++++++++++++++++++++
89   |   Get a connection to the database.
90   | 
91   |   const char *host
92   |   
93   |   unsigned int port
94   | 
95   |   const char *db
96   |   
97   |   const char *user
98   |   
99   |   const char *password
100  |    
101  |   More:
102  |   +html+ <PRE>
103  |   Authors:
104  |         ottrey
105  |   +html+ </PRE><DL COMPACT>
106  |   +html+ <DT>Online References:
107  |   +html+ <DD><UL>
108  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_init">mysql_init()</A>
109  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_real_connect">mysql_real_connect()</A>
110  |   +html+ </UL></DL>
111  | 
112  |   ++++++++++++++++++++++++++++++++++++++*/
113  | SQ_connection_t *SQ_get_connection(const char *host, unsigned int port, const char *db, const char *user, const char *password) {
114  | 
115  |   SQ_connection_t *sql_connection;
116  | 
117  |   sql_connection = mysql_init(NULL);
118  |   if (!sql_connection) {
119  | /* Check for errors */
120  | 	  fprintf(stderr, "Connection init error\n");
121  |   }
122  | 
123  |   if (!mysql_real_connect(sql_connection, host, user, password, db, port, NULL, 0)) {
124  | /* Check for errors */
125  |      fprintf(stderr, "Connection error: Failed to connect to database %s", db);
126  |      fprintf(stderr, "ERROR: %s\n", mysql_error(sql_connection));
127  |      sql_connection=NULL;	  
128  |     /* XXX Don't be so harsh!
129  |     exit(-1);
130  |     */
131  |   }
132  | 
133  |   return sql_connection;
134  | 
135  | } /* SQ_get_connection() */
136  | 
137  | SQ_connection_t *SQ_get_connection2(void) {
138  |   return SQ_get_connection(CO_get_host(),
139  |                            CO_get_database_port(),
140  |                            CO_get_database(),
141  |                            CO_get_user(),
142  |                            CO_get_password()
143  |                           );
144  | } /* SQ_get_connection() */
145  | 
146  | /* SQ_execute_query() */
147  | /*++++++++++++++++++++++++++++++++++++++
148  |   Execute the sql query.
149  | 
150  |   SQ_connection_t *sql_connection Connection to database.
151  |   
152  |   const char *query SQL query.
153  | 
154  |   SQ_result_set_t *result ptr to the structure to hold result. 
155  |   May be NULL if no result is needed.
156  | 
157  |   Returns: 
158  |     0 if the query was successful.
159  |     Non-zero if an error occured.
160  |   
161  |   More:
162  |   +html+ <PRE>
163  |   Authors:
164  |         ottrey
165  |   +html+ </PRE><DL COMPACT>
166  |   +html+ <DT>Online References:
167  |   +html+ <DD><UL>
168  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_query">mysql_query()</A>
169  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_use_result">mysql_use_result()</A>
170  |   +html+ </UL></DL>
171  | 
172  |   ++++++++++++++++++++++++++++++++++++++*/
173  | int SQ_execute_query(SQ_connection_t *sql_connection, 
174  | 				  const char *query, SQ_result_set_t **result_ptr) 
175  | {
176  |   
177  |   int err;
178  |   SQ_result_set_t *result;
179  | /*  
180  |     struct timeb *start_time;
181  |     struct timeb *stop_time;
182  | 
183  |   if (CO_get_query_logging() == 1) {
184  |     //start_time=(struct timeb *)calloc(1, sizeof(struct timeb)+1);
185  |     //stop_time=(struct timeb *)calloc(1, sizeof(struct timeb)+1);
186  | 
187  |     ftime(start_time);
188  |     err = mysql_query(sql_connection, query);
189  |     ftime(stop_time);
190  | 
191  |     log_query(CO_get_query_logfile(), query, start_time, stop_time);
192  |     
193  |     //free(start_time);
194  |     //free(stop_time);
195  |   }
196  |   else 
197  | */  
198  |   {
199  |     err = mysql_query(sql_connection, query);
200  |   }
201  | 
202  |   if (err == 0) {
203  |     result = mysql_store_result(sql_connection);
204  |     if(result_ptr) *result_ptr=result;
205  |     else if(result) mysql_free_result(result);
206  |     return(0);
207  |   }
208  |   else return(-1);  
209  |  
210  | } /* SQ_execute_query() */
211  | 
212  | /* SQ_get_column_count() */
213  | /*++++++++++++++++++++++++++++++++++++++
214  |   Get the column count.
215  | 
216  |   SQ_result_set_t *result The results from the query.
217  |   
218  |   More:
219  |   +html+ <PRE>
220  |   Authors:
221  |         ottrey
222  |   +html+ </PRE><DL COMPACT>
223  |   +html+ <DT>Online References:
224  |   +html+ <DD><UL>
225  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_num_fields">mysql_num_fields()</A>
226  |   +html+ </UL></DL>
227  | 
228  |   ++++++++++++++++++++++++++++++++++++++*/
229  | int SQ_get_column_count(SQ_result_set_t *result) {
230  |   int cols;
231  | 
232  |   cols = mysql_num_fields(result);
233  | 
234  |   return cols;
235  | 
236  | } /* SQ_get_column_count() */
237  | 
238  | /* SQ_get_table_size() */
239  | /*++++++++++++++++++++++++++++++++++++++
240  |   Get the row count of a table
241  | 
242  |   char *table   The table to be examined
243  |   
244  |   More:
245  |   +html+ <PRE>
246  |   Authors:
247  |         marek
248  |   +html+ </PRE>
249  | 
250  |   ++++++++++++++++++++++++++++++++++++++*/
251  | int SQ_get_table_size(SQ_connection_t *sql_connection,
252  | 		     char *table) {  
253  |   int count;
254  |   char sql_command[128];
255  |   SQ_result_set_t *result;
256  |   SQ_row_t *row;
257  |   char *countstr;
258  |   
259  |   sprintf(sql_command, "SELECT COUNT(*) FROM %s", table);
260  |   dieif(SQ_execute_query(sql_connection, sql_command, &result) == -1 );
261  |   row = SQ_row_next(result);
262  |   
263  |   countstr = SQ_get_column_string(result, row, 0);
264  |   sscanf(countstr, "%d", &count);	
265  |   wr_free(countstr);
266  |   
267  |   SQ_free_result(result);
268  | 	
269  |   return count;  
270  | } /* SQ_get_table_size() */
271  | 
272  | /* SQ_get_affected_rows() */
273  | /*++++++++++++++++++++++++++++++++++++++
274  |   Get the row count of a table
275  | 
276  |   char *table   The table to be examined
277  |   
278  |   More:
279  |   +html+ <PRE>
280  |   Authors:
281  |         marek
282  |   +html+ </PRE>
283  | 
284  |   ++++++++++++++++++++++++++++++++++++++*/
285  | int SQ_get_affected_rows(SQ_connection_t *sql_connection)
286  | {
287  |   return mysql_affected_rows(sql_connection);
288  | }/* SQ_get_affected_rows() */
289  | 		      
290  | 
291  | /* SQ_get_column_label() */
292  | /*++++++++++++++++++++++++++++++++++++++
293  |   Get the column label.
294  | 
295  |   SQ_result_set_t *result The results from the query.
296  |   
297  |   unsigned int column The column index.
298  | 
299  |   More:
300  |   +html+ <PRE>
301  |   Authors:
302  |         ottrey
303  |   +html+ </PRE><DL COMPACT>
304  |   +html+ <DT>Online References:
305  |   +html+ <DD><UL>
306  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_fetch_field_direct">mysql_fetch_field_direct()</A>
307  |   +html+ </UL></DL>
308  | 
309  |   ++++++++++++++++++++++++++++++++++++++*/
310  | char *SQ_get_column_label(SQ_result_set_t *result, unsigned int column) {
311  |   char *str;
312  | /* MySQL decided to change their interface.  Doh! */
313  | #ifdef OLDMYSQL
314  |   MYSQL_FIELD field;
315  | 
316  |   field = mysql_fetch_field_direct(result, column);
317  | 
318  |   /*str = (char *)calloc(1, strlen(field.name)+1);*/
319  |   dieif( wr_malloc((void **)&str, strlen(field.name)+1) != UT_OK);  
320  |   strcpy(str, field.name);
321  | #else
322  |   MYSQL_FIELD *field;
323  | 
324  |   field = mysql_fetch_field_direct(result, column);
325  | 
326  |   /*str = (char *)calloc(1, strlen(field->name)+1);*/
327  |   dieif( wr_malloc((void **)&str, strlen(field->name)+1) != UT_OK); 
328  |   strcpy(str, field->name);
329  | #endif
330  | 
331  | /*
332  |   printf("column=%d\n", column);
333  |   printf("field.name=%s\n", field.name);
334  |   printf("field.table=%s\n", field.table);
335  | 
336  |   printf("field.def=%s\n", field.def);
337  | 
338  |   printf("field.type=%d\n", field.type);
339  |   printf("field.length=%d\n", field.length);
340  |   printf("field.max_length=%d\n", field.max_length);
341  |   printf("field.flags=%d\n", field.flags);
342  |   printf("field.decimals=%d\n", field.decimals);
343  | */
344  | 
345  |   return str;
346  | 
347  | } /* SQ_get_column_label() */
348  | 
349  | /* SQ_get_column_max_length() */
350  | /*++++++++++++++++++++++++++++++++++++++
351  |   Get the max length of the column.
352  | 
353  |   SQ_result_set_t *result The results from the query.
354  |   
355  |   unsigned int column The column index.
356  | 
357  |   More:
358  |   +html+ <PRE>
359  |   Authors:
360  |         ottrey
361  |   +html+ </PRE><DL COMPACT>
362  |   +html+ <DT>Online References:
363  |   +html+ <DD><UL>
364  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_fetch_field_direct">mysql_fetch_field_direct()</A>
365  |   +html+ </UL></DL>
366  | 
367  |   ++++++++++++++++++++++++++++++++++++++*/
368  | unsigned int SQ_get_column_max_length(SQ_result_set_t *result, unsigned int column) {
369  | /* MySQL decided to change their interface.  Doh! */
370  | #ifdef OLDMYSQL
371  |   MYSQL_FIELD field;
372  | 
373  |   field = mysql_fetch_field_direct(result, column);
374  | 
375  |   return field.length;
376  | #else
377  |   MYSQL_FIELD *field;
378  | 
379  |   field = mysql_fetch_field_direct(result, column);
380  | 
381  |   return field->length;
382  | #endif
383  | 
384  | } /* SQ_get_column_max_length() */
385  | 
386  | /* SQ_row_next() */
387  | /*++++++++++++++++++++++++++++++++++++++
388  |   Get the next row.
389  | 
390  |   SQ_result_set_t *result The results from the query.
391  |   
392  |   unsigned int column The column index.
393  | 
394  |   More:
395  |   +html+ <PRE>
396  |   Authors:
397  |         ottrey
398  |   +html+ </PRE><DL COMPACT>
399  |   +html+ <DT>Online References:
400  |   +html+ <DD><UL>
401  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_fetch_row">mysql_fetch_row()</A>
402  |   +html+ </UL></DL>
403  | 
404  |   ++++++++++++++++++++++++++++++++++++++*/
405  | SQ_row_t *SQ_row_next(SQ_result_set_t *result) {
406  | 
407  |   return (SQ_row_t *)mysql_fetch_row(result);
408  | 
409  | } /* SQ_row_next() */
410  | 
411  | /* SQ_get_column_string() */
412  | /*++++++++++++++++++++++++++++++++++++++
413  |   Get the column string.
414  | 
415  |   SQ_row_t *current_row The current row (obtained from a SQ_row_next() ).
416  |   
417  |   unsigned int column The column index.
418  | 
419  |   More:
420  |   +html+ <PRE>
421  |   Authors:
422  |         ottrey
423  |   +html+ </PRE><DL COMPACT>
424  |   +html+ <DT>Online References:
425  |   +html+ <DD><UL>
426  |   +html+ </UL></DL>
427  | 
428  |   ++++++++++++++++++++++++++++++++++++++*/
429  | char *SQ_get_column_string(SQ_result_set_t *result, SQ_row_t *current_row, unsigned int column) {
430  |   char *str=NULL;
431  |   int length = mysql_fetch_lengths(result)[column];
432  | 
433  |   /* XXX workaround of a mysql bug : sometimes mysql_fetch_lengths
434  |      returns completely weird results */
435  |   if( length > 10000 ) {
436  |     length = strlen(current_row[column]);
437  |   }
438  |   
439  |   if (current_row != NULL && current_row[column] != NULL) {
440  |     /*str = (char *)malloc(length + 1);*/
441  |     dieif( wr_malloc((void **)&str, length + 1) != UT_OK);  
442  |     if (str != NULL) {
443  |       memcpy(str, current_row[column], length );
444  |       str[length] = '\0';
445  |     }
446  |   }
447  | 
448  |   return str;
449  |   
450  | } /* SQ_get_column_string() */
451  | 
452  | /* SQ_get_column_strings() */
453  | /*++++++++++++++++++++++++++++++++++++++
454  |   Get the all the strings in one column.
455  | 
456  |   SQ_result_set_t *result The results.
457  |   
458  |   unsigned int column The column index.
459  | 
460  |   More:
461  |   +html+ <PRE>
462  |   Authors:
463  |         ottrey
464  |   +html+ </PRE><DL COMPACT>
465  |   +html+ <DT>Online References:
466  |   +html+ <DD><UL>
467  |   +html+ </UL></DL>
468  | 
469  |   ++++++++++++++++++++++++++++++++++++++*/
470  | char *SQ_get_column_strings(SQ_result_set_t *result, unsigned int column) {
471  |   MYSQL_ROW row;
472  |   char str_buffer[STR_XXL];
473  |   char str_buffer_tmp[STR_L];
474  |   char *str;
475  | 
476  |   strcpy(str_buffer, "");
477  | 
478  |   while ((row = mysql_fetch_row(result)) != NULL) {
479  |     if (row[column] != NULL) {
480  |       sprintf(str_buffer_tmp, "%s\n", row[column]);
481  |     }
482  |     strcat(str_buffer, str_buffer_tmp);
483  | 
484  |     if (strlen(str_buffer) >= (STR_XXL - STR_XL) ) {
485  |       strcat(str_buffer, "And some more stuff...\n");
486  |       break;
487  |     }
488  |   }
489  | 
490  |   if (strcmp(str_buffer, "") != 0) {
491  |     /*str = (char *)calloc(1, strlen(str_buffer)+1);*/
492  |     dieif( wr_malloc((void **)&str, strlen(str_buffer)+1) != UT_OK);  
493  |     strcpy(str, str_buffer);
494  |   }
495  |   else {
496  |     str = NULL;
497  |   }
498  | 
499  |   return str;
500  | 
501  | } /* SQ_get_column_strings() */
502  | 
503  | /* SQ_get_column_int() */
504  | /*++++++++++++++++++++++++++++++++++++++
505  |   Get an integer from the column.
506  | 
507  |   SQ_result_set_t *result The results.
508  |   
509  |   SQ_row_t *current_row The current row.
510  | 
511  |   unsigned int column The column index.
512  | 
513  |   long *resultptr     pointer where the result should be stored
514  | 
515  |   returns -1 if error occurs, 0 otherwise.
516  |   Note - it never says what error occured....
517  | 
518  |   More:
519  |   +html+ <PRE>
520  |   Authors:
521  |         ottrey
522  |   +html+ </PRE><DL COMPACT>
523  |   +html+ <DT>Online References:
524  |   +html+ <DD><UL>
525  |   +html+ </UL></DL>
526  | 
527  |   ++++++++++++++++++++++++++++++++++++++*/
528  | int SQ_get_column_int(SQ_result_set_t *result, SQ_row_t *current_row, unsigned int column, long  *resultptr) {
529  |   int ret_val=-1;
530  | 
531  |   if (*current_row[column] != NULL) {
532  |       if( sscanf( *current_row[column], "%ld", resultptr) > 0 ) {
533  | 	ret_val = 0;
534  |       }
535  |   }
536  |   return ret_val;
537  |   
538  | } /* SQ_get_column_int() */
539  | 
540  | 
541  | /* SQ_result_to_string() */
542  | /*++++++++++++++++++++++++++++++++++++++
543  |   Convert the result set to a string.
544  | 
545  |   SQ_result_set_t *result The results.
546  |   
547  |   More:
548  |   +html+ <PRE>
549  |   Authors:
550  |         ottrey
551  |   +html+ </PRE><DL COMPACT>
552  |   +html+ <DT>Online References:
553  |   +html+ <DD><UL>
554  |   +html+ </UL></DL>
555  | 
556  |   ++++++++++++++++++++++++++++++++++++++*/
557  | char *SQ_result_to_string(SQ_result_set_t *result) {
558  |   MYSQL_ROW row;
559  |   unsigned int no_cols;
560  |   unsigned int i, j;
561  |   char str_buffer[STR_XXL];
562  |   char str_buffer_tmp[STR_L];
563  |   char border[STR_L];
564  |   char *str;
565  | 
566  |   char *label;
567  | 
568  |   unsigned int length[STR_S];
569  | 
570  |   strcpy(str_buffer, "");
571  | 
572  |   no_cols = mysql_num_fields(result);
573  | 
574  |   /* Determine the maximum column widths */
575  |   /* XXX Surely MySQL should keep note of this for me! */
576  |   strcpy(border, "");
577  |   for (i=0; i < no_cols; i++) {
578  |     length[i] = SQ_get_column_max_length(result, i);
579  |     /* Make sure the lenghts don't get too long */
580  |     if (length[i] > STR_M) {
581  |       length[i] = STR_M;
582  |     }
583  |     strcat(border, "*");
584  |     for (j=0; (j <= length[i]) && (j < STR_L); j++) {
585  |       strcat(border, "-");
586  |     }
587  |   }
588  |   strcat(border, "*\n");
589  |   /*
590  |   for (i=0; i < no_cols; i++) {
591  |     printf("length[%d]=%d\n", i, length[i]);
592  |   }
593  |   */
594  | 
595  |   strcat(str_buffer, border);
596  | 
597  |   for (i=0; i < no_cols; i++) {
598  |     label = SQ_get_column_label(result, i);
599  |     if (label != NULL) {
600  |       sprintf(str_buffer_tmp, "| %-*s", length[i], label);
601  |       strcat(str_buffer, str_buffer_tmp);
602  |     }
603  |   }
604  |   strcat(str_buffer, "|\n");
605  |   
606  |   strcat(str_buffer, border);
607  | 
608  | 
609  |   while ((row = mysql_fetch_row(result)) != NULL) {
610  |     for (i=0; i < no_cols; i++) {
611  |       if (row[i] != NULL) {
612  |         sprintf(str_buffer_tmp, "| %-*s", length[i], row[i]);
613  |       }
614  |       else {
615  |         sprintf(str_buffer_tmp, "| %-*s", length[i], "NuLL");
616  |       }
617  |       strcat(str_buffer, str_buffer_tmp);
618  |     }
619  |     strcat(str_buffer, "|\n");
620  | 
621  |     if (strlen(str_buffer) >= (STR_XXL - STR_XL) ) {
622  |       strcat(str_buffer, "And some more stuff...\n");
623  |       break;
624  |     }
625  |   }
626  | 
627  |   strcat(str_buffer, border);
628  |   
629  |   /* str = (char *)calloc(1, strlen(str_buffer)+1);*/
630  |   dieif( wr_malloc((void **)&str, strlen(str_buffer)+1) != UT_OK);  
631  |   strcpy(str, str_buffer);
632  | 
633  |   return str;
634  | 
635  | } /* SQ_result_to_string() */
636  | 
637  | /* SQ_free_result() */
638  | /*++++++++++++++++++++++++++++++++++++++
639  |   Free the result set.
640  | 
641  |   SQ_result_set_t *result The results.
642  |   
643  |   More:
644  |   +html+ <PRE>
645  |   Authors:
646  |         ottrey
647  |   +html+ </PRE><DL COMPACT>
648  |   +html+ <DT>Online References:
649  |   +html+ <DD><UL>
650  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_free_result">mysql_free_result()</A>
651  |   +html+ </UL></DL>
652  | 
653  |   ++++++++++++++++++++++++++++++++++++++*/
654  | void SQ_free_result(SQ_result_set_t *result) {
655  |   mysql_free_result(result);
656  | } /* SQ_free_result() */
657  | 
658  | 
659  | /* SQ_close_connection() */
660  | /*++++++++++++++++++++++++++++++++++++++
661  |   Call this function to close a connection to the server
662  | 
663  |   SQ_connection_t *sql_connection The connection to the database.
664  |   
665  |   More:
666  |   +html+ <PRE>
667  |   Authors:
668  |         ottrey
669  |   +html+ </PRE><DL COMPACT>
670  |   +html+ <DT>Online References:
671  |   +html+ <DD><UL>
672  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_close">mysql_close()</A>
673  |   +html+ </UL></DL>
674  | 
675  |   ++++++++++++++++++++++++++++++++++++++*/
676  | void SQ_close_connection(SQ_connection_t *sql_connection) {
677  | 
678  |   mysql_close(sql_connection);
679  | 
680  | }
681  | 
682  | /* SQ_num_rows() */
683  | /*++++++++++++++++++++++++++++++++++++++
684  |   Call this function to find out how many rows are in a query result
685  | 
686  |   SQ_result_set_t *result The results.
687  |   
688  |   More:
689  |   +html+ <PRE>
690  |   Authors:
691  |         ottrey
692  |   +html+ </PRE><DL COMPACT>
693  |   +html+ <DT>Online References:
694  |   +html+ <DD><UL>
695  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_num_rows">mysql_num_rows()</A>
696  |   +html+ </UL></DL>
697  | 
698  |   ++++++++++++++++++++++++++++++++++++++*/
699  | int SQ_num_rows(SQ_result_set_t *result) {
700  |   int rows=-1;
701  | 
702  |   if (result != NULL) {
703  |     rows = mysql_num_rows(result);
704  |   }
705  | 
706  |   return rows;
707  | }
708  | 
709  | /* SQ_info_to_string() */
710  | /*++++++++++++++++++++++++++++++++++++++
711  |   Convert all available information about the sql server into a string.
712  | 
713  |   SQ_connection_t *sql_connection The connection to the database.
714  | 
715  |   More:
716  |   +html+ <PRE>
717  |   Authors:
718  |         ottrey
719  |   +html+ </PRE><DL COMPACT>
720  |   +html+ <DT>Online References:
721  |   +html+ <DD><UL>
722  |   +html+ </UL></DL>
723  | 
724  |   ++++++++++++++++++++++++++++++++++++++*/
725  | char *SQ_info_to_string(SQ_connection_t *sql_connection) {
726  |   char str_buffer[STR_XXL];
727  |   char str_buffer_tmp[STR_L];
728  |   char *str;
729  |   char *str_tmp;
730  | 
731  |   strcpy(str_buffer, "");
732  | 
733  |   /* Makes the server dump debug information to the log. */
734  |   sprintf(str_buffer_tmp, "mysql_dump_debug_info()=%d\n", mysql_dump_debug_info(sql_connection));
735  |   strcat(str_buffer, str_buffer_tmp);
736  | 
737  |   /* Returns the error number from the last MySQL function. */
738  |   sprintf(str_buffer_tmp, "mysql_errno()=%d\n", mysql_errno(sql_connection));
739  |   strcat(str_buffer, str_buffer_tmp);
740  | 
741  |   /* Returns the error message from the last MySQL function. */
742  |   sprintf(str_buffer_tmp, "mysql_error()=%s\n", mysql_error(sql_connection));
743  |   strcat(str_buffer, str_buffer_tmp);
744  | 
745  |   /* Returns client version information. */
746  |   sprintf(str_buffer_tmp, "mysql_get_client_info()=%s\n", mysql_get_client_info() );
747  |   strcat(str_buffer, str_buffer_tmp);
748  | 
749  |   /* Returns a string describing the connection. */
750  |   sprintf(str_buffer_tmp, "mysql_get_host_info()=%s\n", mysql_get_host_info(sql_connection));
751  |   strcat(str_buffer, str_buffer_tmp);
752  | 
753  |   /* Returns the protocol version used by the connection. */
754  |   sprintf(str_buffer_tmp, "mysql_get_proto_info()=%d\n", mysql_get_proto_info(sql_connection));
755  |   strcat(str_buffer, str_buffer_tmp);
756  | 
757  |   /* Returns the server version number. */
758  |   sprintf(str_buffer_tmp, "mysql_get_server_info()=%s\n", mysql_get_server_info(sql_connection));
759  |   strcat(str_buffer, str_buffer_tmp);
760  | 
761  |   /* Information about the most recently executed query. */
762  |   /* XXX Check for NULL */
763  |   str_tmp = mysql_info(sql_connection);
764  |   if (str_tmp != NULL) {
765  |     sprintf(str_buffer_tmp, "mysql_info()=%s\n", str_tmp);
766  |   }
767  |   else {
768  |     sprintf(str_buffer_tmp, "mysql_info()=%s\n", "NulL");
769  |   }
770  |   strcat(str_buffer, str_buffer_tmp);
771  | 
772  | 
773  |   /* Returns a list of the current server threads. 
774  | 
775  |      NOT Used here, because it returns a RESULT struct that must be 
776  |      iterated through.
777  |      
778  |      sprintf(str_buffer_tmp, "mysql_list_processes()=%x\n", mysql_list_processes(sql_connection));
779  |      strcat(str_buffer, str_buffer_tmp);
780  |      
781  |   */
782  | 
783  |   /* Checks if the connection to the server is working. */
784  |   sprintf(str_buffer_tmp, "mysql_ping()=%d\n", mysql_ping(sql_connection));
785  |   strcat(str_buffer, str_buffer_tmp);
786  | 
787  |   /* Returns the server status as a string. */
788  |   sprintf(str_buffer_tmp, "mysql_stat()=%s\n", mysql_stat(sql_connection));
789  |   strcat(str_buffer, str_buffer_tmp);
790  | 
791  |   /* Returns the current thread id. */
792  |   sprintf(str_buffer_tmp, "mysql_thread_id()=%ld\n", mysql_thread_id(sql_connection));
793  |   strcat(str_buffer, str_buffer_tmp);
794  | 
795  | 
796  |   /*str = (char *)calloc(1, strlen(str_buffer)+1);*/
797  |   dieif( wr_malloc((void **)&str, strlen(str_buffer)+1) != UT_OK);  
798  |   strcpy(str, str_buffer);
799  | 
800  |   return str;
801  | 
802  | } /* SQ_info_to_string() */
803  | 
804  | /* SQ_error() */
805  | /*++++++++++++++++++++++++++++++++++++++
806  |   Get the error string for the last error.
807  | 
808  |   SQ_connection_t *sql_connection The connection to the database.
809  | 
810  |   More:
811  |   +html+ <PRE>
812  |   Authors:
813  |         ottrey
814  |   +html+ </PRE><DL COMPACT>
815  |   +html+ <DT>Online References:
816  |   +html+ <DD><UL>
817  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_error">mysql_error()</A>
818  |   +html+ </UL></DL>
819  | 
820  |   ++++++++++++++++++++++++++++++++++++++*/
821  | char *SQ_error(SQ_connection_t *sql_connection) {
822  | 
823  |   return mysql_error(sql_connection);
824  | 
825  | } /* SQ_error() */
826  | 
827  | /* SQ_errno() */
828  | /*++++++++++++++++++++++++++++++++++++++
829  |   Get the error number for the last error.
830  | 
831  |   SQ_connection_t *sql_connection The connection to the database.
832  | 
833  |   More:
834  |   +html+ <PRE>
835  |   Authors:
836  |         ottrey
837  |   +html+ </PRE><DL COMPACT>
838  |   +html+ <DT>Online References:
839  |   +html+ <DD><UL>
840  |   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_free_result">mysql_free_result()</A>
841  |   +html+ </UL></DL>
842  | 
843  |   ++++++++++++++++++++++++++++++++++++++*/
844  | int SQ_errno(SQ_connection_t *sql_connection) {
845  | 
846  |   return mysql_errno(sql_connection);
847  | 
848  | } /* SQ_errno() */
849  | 
850  | /* SQ_get_info() */
851  | /*++++++++++++++++++++++++++++++++++++++
852  |   Get additional information about the most 
853  |   recently executed query.
854  |   
855  |   SQ_connection_t *sql_connection The connection to the database.
856  |   int info[3] array of integers where information is stored
857  |   
858  |   The meaning of the numbers returned depends on the query type:
859  |   
860  |   info[SQL_RECORDS] - # of Records for INSERT
861  |   info[SQL_MATCHES] - # of Matches for UPDATE
862  |   info[SQL_DUPLICATES] - # of Duplicates
863  |   info[SQL_WARNINGS] - # of Warnings
864  |   
865  |   More:
866  |  +html+ <PRE>
867  |  Authors:
868  |   andrei
869  |  +html+ </PRE><DL COMPACT>
870  |  +html+ <DT>Online References:
871  |  +html+ <DD><UL>
872  |  +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_info">mysql_info()</A>
873  |  +html+ </UL></DL>
874  | 
875  | ++++++++++++++++++++++++++++++++++++++*/  
876  |   
877  | int SQ_get_info(SQ_connection_t *sql_connection, int info[3])
878  | {
879  | int ii;
880  | char *colon, *buf_ptr, buf[20]; 
881  | char *infoline;
882  | 
883  |   infoline=mysql_info(sql_connection); 
884  |   ii=0;
885  |   colon = infoline;
886  |   while (*colon != '\0') {
887  |    colon++;
888  |    buf_ptr=buf;
889  |    if(isdigit((int)*colon)){
890  |     while(isdigit((int)*colon)){
891  |      *buf_ptr=*colon; buf_ptr++; colon++;
892  |     }
893  |     *buf_ptr='\0';
894  |     info[ii]=atoi(buf); ii++;
895  |    } 
896  |   }
897  |  return(0);
898  | }