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