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