modules/sq/mysql_driver.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SQ_try_connection
  2. SQ_get_connection
  3. SQ_execute_query
  4. SQ_execute_query_nostore
  5. SQ_get_column_count
  6. SQ_get_table_size
  7. SQ_get_affected_rows
  8. SQ_get_insert_id
  9. SQ_get_column_label
  10. SQ_get_column_max_length
  11. SQ_row_next
  12. SQ_get_column_string
  13. SQ_get_column_string_nocopy
  14. SQ_get_column_strings
  15. SQ_get_column_int
  16. SQ_result_to_string
  17. SQ_free_result
  18. SQ_close_connection
  19. SQ_num_rows
  20. SQ_info_to_string
  21. SQ_error
  22. SQ_errno
  23. SQ_get_info
  24. SQ_duplicate_connection
  25. SQ_abort_query
  26. SQ_ping

   1 /***************************************
   2   $Revision: 1.36 $
   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 <time.h>
  36 #include <sys/timeb.h>
  37 #include <strings.h>
  38 #include <sys/types.h>
  39 #include <limits.h>
  40 #include <errno.h>
  41 
  42 #include "mysql_driver.h"
  43 #include "constants.h"
  44 #include "memwrap.h"
  45 #include "timediff.h"
  46 
  47 /*+ String sizes +*/
  48 #define STR_S   63
  49 #define STR_M   255
  50 #define STR_L   1023
  51 #define STR_XL  4095
  52 #define STR_XXL 16383
  53 
  54 /* 
  55 Description:
  56 
  57   Connect to the the MySQL database, returning an error if unsuccessful.
  58 
  59 Arguments:
  60 
  61   SQ_connection_t **conn; used to return pointer to connection structure
  62 
  63   const char *host; database server host to connect to, may be NULL or 
  64     "localhost", in which case Unix sockets may be used
  65 
  66   unsigned int port; port to connect to database server on, may be 0 to use  
  67     default
  68 
  69   const char *db; name of database to use, may be NULL
  70 
  71   const char *user; name of user to connect as, if NULL then the current Unix 
  72     user login is used
  73 
  74   const char *password; password to send, may be NULL to not use a password
  75 
  76 Returns:
  77   
  78   SQ_OK on success
  79 
  80   SQ_CTCONN on error; the exact reason may be determined by using SQ_error() 
  81     on the value returned in *conn - this structure should be properly via
  82     SQ_close_connection(), even on error
  83 
  84 Notes:
  85 
  86   Most parameters are passed straight through to the MySQL connect function,
  87   so the MySQL documentation should be checked for current meaning.
  88 */
  89 
  90 er_ret_t 
  91 SQ_try_connection (SQ_connection_t **conn, const char *host,
     /* [<][>][^][v][top][bottom][index][help] */
  92                    unsigned int port, const char *db,
  93                    const char *user, const char *password)
  94 {
  95     SQ_connection_t *res;
  96     
  97     *conn = mysql_init(NULL);
  98     dieif(*conn == NULL);  /* XXX SK - need to call "out of memory handler" */
  99 
 100     res = mysql_real_connect(*conn, host, user, password, db, port, NULL, 0);
 101     if (res == NULL) {
 102         return SQ_CTCONN;
 103     } else {
 104         return SQ_OK;
 105     }
 106 }
 107 
 108 /* SQ_get_connection() */
 109 /*++++++++++++++++++++++++++++++++++++++
 110   Get a connection to the database.
 111 
 112   const char *host
 113   
 114   unsigned int port
 115 
 116   const char *db
 117   
 118   const char *user
 119   
 120   const char *password
 121    
 122   More:
 123   +html+ <PRE>
 124   Authors:
 125         ottrey
 126   +html+ </PRE><DL COMPACT>
 127   +html+ <DT>Online References:
 128   +html+ <DD><UL>
 129   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_init">mysql_init()</A>
 130   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_real_connect">mysql_real_connect()</A>
 131   +html+ </UL></DL>
 132 
 133   ++++++++++++++++++++++++++++++++++++++*/
 134 SQ_connection_t *SQ_get_connection(const char *host, unsigned int port, const char *db, const char *user, const char *password) {
     /* [<][>][^][v][top][bottom][index][help] */
 135 
 136   SQ_connection_t *sql_connection;
 137   er_ret_t res;
 138   unsigned try = 0;
 139 
 140   /* XXX MB.
 141      This is really kludgy! 
 142      For some (unknown yet) reason, sometimes the connection does not
 143      work the first time. So we try up to 3 times here, and give up only
 144      then.
 145 
 146      Check the logfiles for warnings, especially with newer mysql version,
 147      like 3.23. The problem may or may not go away.
 148 
 149      SK - I added a sleep() to avoid crushing the poor server.
 150   */
 151 
 152   for (;;) {
 153     /* try to connect */
 154     res = SQ_try_connection(&sql_connection, host, port, db, user, password);
 155 
 156     /* on success, return our result */
 157     if (NOERR(res)) {
 158         return sql_connection;
 159     }
 160     else {
 161       
 162       /* if we've tried enough, exit with error */
 163       if (try >= 3) {
 164         ER_perror(FAC_SQ, SQ_CTCONN, " %s; %s", db, 
 165                   sql_connection ? SQ_error(sql_connection) : "-?");
 166         die;
 167       }
 168 
 169       /* otherwise, prepare to try again */
 170       ER_perror(FAC_SQ, SQ_CNCT, " %s; %s", db, 
 171                 sql_connection ? SQ_error(sql_connection) : "-?");
 172 
 173       if (try > 0) {
 174         sleep(try);
 175       }
 176       try++;
 177       
 178       if( sql_connection ) {
 179         SQ_close_connection(sql_connection);
 180       }
 181     }
 182   }/* for(;;) */
 183 } /* SQ_get_connection() */
 184 
 185 /* SQ_execute_query() */
 186 /*++++++++++++++++++++++++++++++++++++++
 187   Execute the sql query.
 188 
 189   SQ_connection_t *sql_connection Connection to database.
 190   
 191   const char *query SQL query.
 192 
 193   SQ_result_set_t *result ptr to the structure to hold result. 
 194   May be NULL if no result is needed.
 195 
 196   Returns: 
 197     0 if the query was successful.
 198     Non-zero if an error occured.
 199   
 200   More:
 201   +html+ <PRE>
 202   Authors:
 203         ottrey, andrei, marek
 204   +html+ </PRE><DL COMPACT>
 205   +html+ <DT>Online References:
 206   +html+ <DD><UL>
 207   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_query">mysql_query()</A>
 208   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_use_result">mysql_use_result()</A>
 209   +html+ </UL></DL>
 210 
 211   ++++++++++++++++++++++++++++++++++++++*/
 212 int SQ_execute_query(SQ_connection_t *sql_connection, 
     /* [<][>][^][v][top][bottom][index][help] */
 213                      const char *query, SQ_result_set_t **result_ptr) 
 214 {
 215   int err;
 216   SQ_result_set_t *result;
 217 
 218   ut_timer_t start_time, stop_time; 
 219   
 220   UT_timeget(&start_time);
 221   
 222   err = mysql_query(sql_connection, query);
 223 
 224   /* log the time and result of the query */
 225   if (err == 0) {
 226     result = mysql_store_result(sql_connection);
 227     
 228     if (ER_is_traced(FAC_SQ, ASP_SQ_QRYTIME)) {
 229       float seconds;
 230 
 231       UT_timeget(&stop_time);      
 232       seconds = UT_timediff( &start_time, &stop_time );
 233   
 234       ER_dbg_va(FAC_SQ, ASP_SQ_QRYTIME,
 235                 "spent %.2f sec; got %d rows from [%s: %s]", 
 236                 seconds, 
 237                 SQ_get_affected_rows(sql_connection),
 238                 sql_connection->db, 
 239                 query);
 240     }
 241     
 242     if(result_ptr) *result_ptr=result;
 243     else if(result) mysql_free_result(result);
 244     return(0);
 245   }
 246   else return(-1);  
 247   
 248 } /* SQ_execute_query() */
 249 
 250 /* 
 251 Description:
 252  
 253     Performs identially to SQ_execute_query(), except that it does not read the
 254     entire query into memory.
 255 
 256 Notes:
 257 
 258     No data may be written to the table until the entire result set is read,
 259     so this should only be used in cases where:
 260 
 261     1. an unacceptably large amount of memory will be returned by the query
 262     2. there is no chance that a user can accidentally or maliciously 
 263        prevent the result set from being read in a expedicious manner
 264 */
 265 
 266 int 
 267 SQ_execute_query_nostore(SQ_connection_t *sql_connection, 
     /* [<][>][^][v][top][bottom][index][help] */
 268                          const char *query, SQ_result_set_t **result_ptr) 
 269 {
 270   int err;
 271   SQ_result_set_t *result;
 272 
 273   err = mysql_query(sql_connection, query);
 274   if (err != 0) {
 275       return -1;
 276   }
 277   result = mysql_use_result(sql_connection);
 278   if (result == NULL) {
 279       return -1;
 280   } 
 281   *result_ptr = result;
 282   return 0;
 283 } /* SQ_execute_query_nostore() */
 284 
 285 /* SQ_get_column_count() */
 286 /*++++++++++++++++++++++++++++++++++++++
 287   Get the column count.
 288 
 289   SQ_result_set_t *result The results from the query.
 290   
 291   More:
 292   +html+ <PRE>
 293   Authors:
 294         ottrey
 295   +html+ </PRE><DL COMPACT>
 296   +html+ <DT>Online References:
 297   +html+ <DD><UL>
 298   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_num_fields">mysql_num_fields()</A>
 299   +html+ </UL></DL>
 300 
 301   ++++++++++++++++++++++++++++++++++++++*/
 302 int SQ_get_column_count(SQ_result_set_t *result) {
     /* [<][>][^][v][top][bottom][index][help] */
 303   int cols;
 304 
 305   cols = mysql_num_fields(result);
 306 
 307   return cols;
 308 
 309 } /* SQ_get_column_count() */
 310 
 311 /* SQ_get_table_size() */
 312 /*++++++++++++++++++++++++++++++++++++++
 313   Get the row count of a table
 314 
 315   char *table   The table to be examined
 316   
 317   More:
 318   +html+ <PRE>
 319   Authors:
 320         marek
 321   +html+ </PRE>
 322 
 323   ++++++++++++++++++++++++++++++++++++++*/
 324 int SQ_get_table_size(SQ_connection_t *sql_connection,
     /* [<][>][^][v][top][bottom][index][help] */
 325                      char *table) {  
 326   int count;
 327   char sql_command[128];
 328   SQ_result_set_t *result;
 329   SQ_row_t *row;
 330   char *countstr;
 331   
 332   sprintf(sql_command, "SELECT COUNT(*) FROM %s", table);
 333   dieif(SQ_execute_query(sql_connection, sql_command, &result) == -1 );
 334   row = SQ_row_next(result);
 335   
 336   countstr = SQ_get_column_string(result, row, 0);
 337   sscanf(countstr, "%d", &count);       
 338   wr_free(countstr);
 339   
 340   SQ_free_result(result);
 341         
 342   return count;  
 343 } /* SQ_get_table_size() */
 344 
 345 /* SQ_get_affected_rows() */
 346 /*++++++++++++++++++++++++++++++++++++++
 347   Get the row count of a table
 348 
 349   char *table   The table to be examined
 350   
 351   More:
 352   +html+ <PRE>
 353   Authors:
 354         marek
 355   +html+ </PRE>
 356 
 357   ++++++++++++++++++++++++++++++++++++++*/
 358 int SQ_get_affected_rows(SQ_connection_t *sql_connection)
     /* [<][>][^][v][top][bottom][index][help] */
 359 {
 360   return (int)mysql_affected_rows(sql_connection);
 361 }/* SQ_get_affected_rows() */
 362                       
 363 /* SQ_get_insert_id() */
 364 /*++++++++++++++++++++++++++++++++++++++
 365   Get the ID that was most recently generated for an AUTO_INCREMENT field
 366 
 367  
 368   More:
 369   +html+ <PRE>
 370   Authors:
 371         andrei
 372   +html+ </PRE>
 373 
 374   ++++++++++++++++++++++++++++++++++++++*/
 375 long SQ_get_insert_id(SQ_connection_t *sql_connection)
     /* [<][>][^][v][top][bottom][index][help] */
 376 {
 377   return (long)mysql_insert_id(sql_connection);
 378 }/* SQ_get_insert_id() */
 379         
 380 /* SQ_get_column_label() */
 381 /*++++++++++++++++++++++++++++++++++++++
 382   Get the column label.
 383 
 384   SQ_result_set_t *result The results from the query.
 385   
 386   unsigned int column The column index.
 387 
 388   More:
 389   +html+ <PRE>
 390   Authors:
 391         ottrey
 392   +html+ </PRE><DL COMPACT>
 393   +html+ <DT>Online References:
 394   +html+ <DD><UL>
 395   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_fetch_field_direct">mysql_fetch_field_direct()</A>
 396   +html+ </UL></DL>
 397 
 398   ++++++++++++++++++++++++++++++++++++++*/
 399 char *SQ_get_column_label(SQ_result_set_t *result, unsigned int column) {
     /* [<][>][^][v][top][bottom][index][help] */
 400   char *str;
 401 /* MySQL decided to change their interface.  Doh! */
 402 #ifdef OLDMYSQL
 403   MYSQL_FIELD field;
 404 
 405   field = mysql_fetch_field_direct(result, column);
 406 
 407   /*str = (char *)calloc(1, strlen(field.name)+1);*/
 408   dieif( wr_malloc((void **)&str, strlen(field.name)+1) != UT_OK);  
 409   strcpy(str, field.name);
 410 #else
 411   MYSQL_FIELD *field;
 412 
 413   field = mysql_fetch_field_direct(result, column);
 414 
 415   /*str = (char *)calloc(1, strlen(field->name)+1);*/
 416   dieif( wr_malloc((void **)&str, strlen(field->name)+1) != UT_OK); 
 417   strcpy(str, field->name);
 418 #endif
 419 
 420 /*
 421   printf("column=%d\n", column);
 422   printf("field.name=%s\n", field.name);
 423   printf("field.table=%s\n", field.table);
 424 
 425   printf("field.def=%s\n", field.def);
 426 
 427   printf("field.type=%d\n", field.type);
 428   printf("field.length=%d\n", field.length);
 429   printf("field.max_length=%d\n", field.max_length);
 430   printf("field.flags=%d\n", field.flags);
 431   printf("field.decimals=%d\n", field.decimals);
 432 */
 433 
 434   return str;
 435 
 436 } /* SQ_get_column_label() */
 437 
 438 /* SQ_get_column_max_length() */
 439 /*++++++++++++++++++++++++++++++++++++++
 440   Get the max length of the column.
 441 
 442   SQ_result_set_t *result The results from the query.
 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+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_fetch_field_direct">mysql_fetch_field_direct()</A>
 454   +html+ </UL></DL>
 455 
 456   ++++++++++++++++++++++++++++++++++++++*/
 457 unsigned int SQ_get_column_max_length(SQ_result_set_t *result, unsigned int column) {
     /* [<][>][^][v][top][bottom][index][help] */
 458 /* MySQL decided to change their interface.  Doh! */
 459 #ifdef OLDMYSQL
 460   MYSQL_FIELD field;
 461 
 462   field = mysql_fetch_field_direct(result, column);
 463 
 464   return field.length;
 465 #else
 466   MYSQL_FIELD *field;
 467 
 468   field = mysql_fetch_field_direct(result, column);
 469 
 470   return field->length;
 471 #endif
 472 
 473 } /* SQ_get_column_max_length() */
 474 
 475 /* SQ_row_next() */
 476 /*++++++++++++++++++++++++++++++++++++++
 477   Get the next row.
 478 
 479   SQ_result_set_t *result The results from the query.
 480   
 481   unsigned int column The column index.
 482 
 483   More:
 484   +html+ <PRE>
 485   Authors:
 486         ottrey
 487   +html+ </PRE><DL COMPACT>
 488   +html+ <DT>Online References:
 489   +html+ <DD><UL>
 490   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_fetch_row">mysql_fetch_row()</A>
 491   +html+ </UL></DL>
 492 
 493   ++++++++++++++++++++++++++++++++++++++*/
 494 SQ_row_t *SQ_row_next(SQ_result_set_t *result) {
     /* [<][>][^][v][top][bottom][index][help] */
 495 
 496   return (SQ_row_t *)mysql_fetch_row(result);
 497 
 498 } /* SQ_row_next() */
 499 
 500 /* SQ_get_column_string() */
 501 /*++++++++++++++++++++++++++++++++++++++
 502   Get the column string.
 503 
 504   SQ_row_t *current_row The current row (obtained from a SQ_row_next() ).
 505   
 506   unsigned int column The column index.
 507 
 508   More:
 509   +html+ <PRE>
 510   Authors:
 511         ottrey
 512   +html+ </PRE><DL COMPACT>
 513   +html+ <DT>Online References:
 514   +html+ <DD><UL>
 515   +html+ </UL></DL>
 516 
 517   ++++++++++++++++++++++++++++++++++++++*/
 518 char *SQ_get_column_string(SQ_result_set_t *result, SQ_row_t *current_row, unsigned int column) {
     /* [<][>][^][v][top][bottom][index][help] */
 519   char *str=NULL;
 520   unsigned length = mysql_fetch_lengths(result)[column];
 521   
 522   if (current_row != NULL && current_row[column] != NULL) {
 523     /*str = (char *)malloc(length + 1);*/
 524     dieif( wr_malloc((void **)&str, length + 1) != UT_OK);  
 525     if (str != NULL) {
 526       memcpy(str, current_row[column], length );
 527       str[length] = '\0';
 528     }
 529   }
 530 
 531   return str;
 532   
 533 } /* SQ_get_column_string() */
 534 
 535 /* SQ_get_column_string_nocopy - return pointer to the column string
 536    without making a copy of it */
 537 char *SQ_get_column_string_nocopy(SQ_result_set_t *result, 
     /* [<][>][^][v][top][bottom][index][help] */
 538                                   SQ_row_t *current_row, 
 539                                   unsigned int column) 
 540 {
 541   if (current_row != NULL && current_row[column] != NULL) {
 542     return (char *)current_row[column];
 543   }
 544   return NULL;
 545 }/* SQ_get_column_string_nocopy */
 546 
 547 
 548 
 549 /* SQ_get_column_strings() */
 550 /*++++++++++++++++++++++++++++++++++++++
 551   Get the all the strings in one column.
 552 
 553   SQ_result_set_t *result The results.
 554   
 555   unsigned int column The column index.
 556 
 557   More:
 558   +html+ <PRE>
 559   Authors:
 560         ottrey
 561   +html+ </PRE><DL COMPACT>
 562   +html+ <DT>Online References:
 563   +html+ <DD><UL>
 564   +html+ </UL></DL>
 565 
 566   ++++++++++++++++++++++++++++++++++++++*/
 567 char *SQ_get_column_strings(SQ_result_set_t *result, unsigned int column) {
     /* [<][>][^][v][top][bottom][index][help] */
 568   MYSQL_ROW row;
 569   char str_buffer[STR_XXL];
 570   char str_buffer_tmp[STR_L];
 571   char *str;
 572 
 573   strcpy(str_buffer, "");
 574 
 575   while ((row = mysql_fetch_row(result)) != NULL) {
 576     if (row[column] != NULL) {
 577       sprintf(str_buffer_tmp, "%s\n", row[column]);
 578     }
 579     strcat(str_buffer, str_buffer_tmp);
 580 
 581     if (strlen(str_buffer) >= (STR_XXL - STR_XL) ) {
 582       strcat(str_buffer, "And some more stuff...\n");
 583       break;
 584     }
 585   }
 586 
 587   if (strcmp(str_buffer, "") != 0) {
 588     /*str = (char *)calloc(1, strlen(str_buffer)+1);*/
 589     dieif( wr_malloc((void **)&str, strlen(str_buffer)+1) != UT_OK);  
 590     strcpy(str, str_buffer);
 591   }
 592   else {
 593     str = NULL;
 594   }
 595 
 596   return str;
 597 
 598 } /* SQ_get_column_strings() */
 599 
 600 /* SQ_get_column_int() */
 601 /*++++++++++++++++++++++++++++++++++++++
 602   Get an integer from the column.
 603 
 604   SQ_result_set_t *result The results.
 605   
 606   SQ_row_t *current_row The current row.
 607 
 608   unsigned int column The column index.
 609 
 610   long *resultptr     pointer where the result should be stored
 611 
 612   returns -1 if error occurs, 0 otherwise.
 613   Note - it never says what error occured....
 614 
 615   More:
 616   +html+ <PRE>
 617   Authors:
 618         ottrey
 619   +html+ </PRE><DL COMPACT>
 620   +html+ <DT>Online References:
 621   +html+ <DD><UL>
 622   +html+ </UL></DL>
 623 
 624   ++++++++++++++++++++++++++++++++++++++*/
 625 int SQ_get_column_int(SQ_result_set_t *result, SQ_row_t *current_row, unsigned int column, long  *resultptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 626   int ret_val;
 627   long col_val;
 628   char *endptr;
 629 
 630   if (current_row[column] != NULL) {
 631       col_val = strtol((char *)current_row[column], &endptr, 10);
 632 
 633       /* under- or over-flow */
 634       if (((col_val==LONG_MIN) || (col_val==LONG_MAX)) && (errno==ERANGE)) {
 635         ret_val = -1;
 636 
 637       /* unrecognized characters in string */
 638       } else if (*endptr != '\0') {
 639         ret_val = -1;
 640 
 641       /* good parse */
 642       } else {
 643         *resultptr = col_val;
 644         ret_val = 0;
 645       }
 646   } else {
 647       ret_val = -1;
 648   }
 649   return ret_val;
 650   
 651 } /* SQ_get_column_int() */
 652 
 653 
 654 /* SQ_result_to_string() */
 655 /*++++++++++++++++++++++++++++++++++++++
 656   Convert the result set to a string.
 657 
 658   SQ_result_set_t *result The results.
 659   
 660   More:
 661   +html+ <PRE>
 662   Authors:
 663         ottrey
 664   +html+ </PRE><DL COMPACT>
 665   +html+ <DT>Online References:
 666   +html+ <DD><UL>
 667   +html+ </UL></DL>
 668 
 669   ++++++++++++++++++++++++++++++++++++++*/
 670 char *SQ_result_to_string(SQ_result_set_t *result) {
     /* [<][>][^][v][top][bottom][index][help] */
 671   MYSQL_ROW row;
 672   unsigned int no_cols;
 673   unsigned int i, j;
 674   char str_buffer[STR_XXL];
 675   char str_buffer_tmp[STR_L];
 676   char border[STR_L];
 677   char *str;
 678 
 679   char *label;
 680 
 681   unsigned int length[STR_S];
 682 
 683   strcpy(str_buffer, "");
 684 
 685   no_cols = mysql_num_fields(result);
 686 
 687   /* Determine the maximum column widths */
 688   /* XXX Surely MySQL should keep note of this for me! */
 689   strcpy(border, "");
 690   for (i=0; i < no_cols; i++) {
 691     length[i] = SQ_get_column_max_length(result, i);
 692     /* Make sure the lenghts don't get too long */
 693     if (length[i] > STR_M) {
 694       length[i] = STR_M;
 695     }
 696     strcat(border, "*");
 697     for (j=0; (j <= length[i]) && (j < STR_L); j++) {
 698       strcat(border, "-");
 699     }
 700   }
 701   strcat(border, "*\n");
 702   /*
 703   for (i=0; i < no_cols; i++) {
 704     printf("length[%d]=%d\n", i, length[i]);
 705   }
 706   */
 707 
 708   strcat(str_buffer, border);
 709 
 710   for (i=0; i < no_cols; i++) {
 711     label = SQ_get_column_label(result, i);
 712     if (label != NULL) {
 713       sprintf(str_buffer_tmp, "| %-*s", length[i], label);
 714       strcat(str_buffer, str_buffer_tmp);
 715     }
 716   }
 717   strcat(str_buffer, "|\n");
 718   
 719   strcat(str_buffer, border);
 720 
 721 
 722   while ((row = mysql_fetch_row(result)) != NULL) {
 723     for (i=0; i < no_cols; i++) {
 724       if (row[i] != NULL) {
 725         sprintf(str_buffer_tmp, "| %-*s", length[i], row[i]);
 726       }
 727       else {
 728         sprintf(str_buffer_tmp, "| %-*s", length[i], "NuLL");
 729       }
 730       strcat(str_buffer, str_buffer_tmp);
 731     }
 732     strcat(str_buffer, "|\n");
 733 
 734     if (strlen(str_buffer) >= (STR_XXL - STR_XL) ) {
 735       strcat(str_buffer, "And some more stuff...\n");
 736       break;
 737     }
 738   }
 739 
 740   strcat(str_buffer, border);
 741   
 742   /* str = (char *)calloc(1, strlen(str_buffer)+1);*/
 743   dieif( wr_malloc((void **)&str, strlen(str_buffer)+1) != UT_OK);  
 744   strcpy(str, str_buffer);
 745 
 746   return str;
 747 
 748 } /* SQ_result_to_string() */
 749 
 750 /* SQ_free_result() */
 751 /*++++++++++++++++++++++++++++++++++++++
 752   Free the result set.
 753 
 754   SQ_result_set_t *result The results.
 755   
 756   More:
 757   +html+ <PRE>
 758   Authors:
 759         ottrey
 760   +html+ </PRE><DL COMPACT>
 761   +html+ <DT>Online References:
 762   +html+ <DD><UL>
 763   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_free_result">mysql_free_result()</A>
 764   +html+ </UL></DL>
 765 
 766   ++++++++++++++++++++++++++++++++++++++*/
 767 void SQ_free_result(SQ_result_set_t *result) {
     /* [<][>][^][v][top][bottom][index][help] */
 768   mysql_free_result(result);
 769 } /* SQ_free_result() */
 770 
 771 
 772 /* SQ_close_connection() */
 773 /*++++++++++++++++++++++++++++++++++++++
 774   Call this function to close a connection to the server
 775 
 776   SQ_connection_t *sql_connection The connection to the database.
 777   
 778   More:
 779   +html+ <PRE>
 780   Authors:
 781         ottrey
 782   +html+ </PRE><DL COMPACT>
 783   +html+ <DT>Online References:
 784   +html+ <DD><UL>
 785   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_close">mysql_close()</A>
 786   +html+ </UL></DL>
 787 
 788   ++++++++++++++++++++++++++++++++++++++*/
 789 void SQ_close_connection(SQ_connection_t *sql_connection) {
     /* [<][>][^][v][top][bottom][index][help] */
 790 
 791   mysql_close(sql_connection);
 792 
 793 }
 794 
 795 /* SQ_num_rows() */
 796 /*++++++++++++++++++++++++++++++++++++++
 797   Call this function to find out how many rows are in a query result
 798 
 799   SQ_result_set_t *result The results.
 800   
 801   More:
 802   +html+ <PRE>
 803   Authors:
 804         ottrey
 805   +html+ </PRE><DL COMPACT>
 806   +html+ <DT>Online References:
 807   +html+ <DD><UL>
 808   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_num_rows">mysql_num_rows()</A>
 809   +html+ </UL></DL>
 810 
 811   ++++++++++++++++++++++++++++++++++++++*/
 812 int SQ_num_rows(SQ_result_set_t *result) {
     /* [<][>][^][v][top][bottom][index][help] */
 813   int rows=-1;
 814 
 815   if (result != NULL) {
 816     rows = mysql_num_rows(result);
 817   }
 818 
 819   return rows;
 820 }
 821 
 822 /* SQ_info_to_string() */
 823 /*++++++++++++++++++++++++++++++++++++++
 824   Convert all available information about the sql server into a string.
 825 
 826   SQ_connection_t *sql_connection The connection to the database.
 827 
 828   More:
 829   +html+ <PRE>
 830   Authors:
 831         ottrey
 832   +html+ </PRE><DL COMPACT>
 833   +html+ <DT>Online References:
 834   +html+ <DD><UL>
 835   +html+ </UL></DL>
 836 
 837   ++++++++++++++++++++++++++++++++++++++*/
 838 char *SQ_info_to_string(SQ_connection_t *sql_connection) {
     /* [<][>][^][v][top][bottom][index][help] */
 839   char str_buffer[STR_XXL];
 840   char str_buffer_tmp[STR_L];
 841   char *str;
 842   char *str_tmp;
 843 
 844   strcpy(str_buffer, "");
 845 
 846   /* Makes the server dump debug information to the log. */
 847   sprintf(str_buffer_tmp, "mysql_dump_debug_info()=%d\n", mysql_dump_debug_info(sql_connection));
 848   strcat(str_buffer, str_buffer_tmp);
 849 
 850   /* Returns the error number from the last MySQL function. */
 851   sprintf(str_buffer_tmp, "mysql_errno()=%d\n", mysql_errno(sql_connection));
 852   strcat(str_buffer, str_buffer_tmp);
 853 
 854   /* Returns the error message from the last MySQL function. */
 855   sprintf(str_buffer_tmp, "mysql_error()=%s\n", mysql_error(sql_connection));
 856   strcat(str_buffer, str_buffer_tmp);
 857 
 858   /* Returns client version information. */
 859   sprintf(str_buffer_tmp, "mysql_get_client_info()=%s\n", mysql_get_client_info() );
 860   strcat(str_buffer, str_buffer_tmp);
 861 
 862   /* Returns a string describing the connection. */
 863   sprintf(str_buffer_tmp, "mysql_get_host_info()=%s\n", mysql_get_host_info(sql_connection));
 864   strcat(str_buffer, str_buffer_tmp);
 865 
 866   /* Returns the protocol version used by the connection. */
 867   sprintf(str_buffer_tmp, "mysql_get_proto_info()=%d\n", mysql_get_proto_info(sql_connection));
 868   strcat(str_buffer, str_buffer_tmp);
 869 
 870   /* Returns the server version number. */
 871   sprintf(str_buffer_tmp, "mysql_get_server_info()=%s\n", mysql_get_server_info(sql_connection));
 872   strcat(str_buffer, str_buffer_tmp);
 873 
 874   /* Information about the most recently executed query. */
 875   /* XXX Check for NULL */
 876   str_tmp = mysql_info(sql_connection);
 877   if (str_tmp != NULL) {
 878     sprintf(str_buffer_tmp, "mysql_info()=%s\n", str_tmp);
 879   }
 880   else {
 881     sprintf(str_buffer_tmp, "mysql_info()=%s\n", "NulL");
 882   }
 883   strcat(str_buffer, str_buffer_tmp);
 884 
 885 
 886   /* Returns a list of the current server threads. 
 887 
 888      NOT Used here, because it returns a RESULT struct that must be 
 889      iterated through.
 890      
 891      sprintf(str_buffer_tmp, "mysql_list_processes()=%x\n", mysql_list_processes(sql_connection));
 892      strcat(str_buffer, str_buffer_tmp);
 893      
 894   */
 895 
 896   /* Checks if the connection to the server is working. */
 897   sprintf(str_buffer_tmp, "mysql_ping()=%d\n", mysql_ping(sql_connection));
 898   strcat(str_buffer, str_buffer_tmp);
 899 
 900   /* Returns the server status as a string. */
 901   sprintf(str_buffer_tmp, "mysql_stat()=%s\n", mysql_stat(sql_connection));
 902   strcat(str_buffer, str_buffer_tmp);
 903 
 904   /* Returns the current thread id. */
 905   sprintf(str_buffer_tmp, "mysql_thread_id()=%ld\n", mysql_thread_id(sql_connection));
 906   strcat(str_buffer, str_buffer_tmp);
 907 
 908 
 909   /*str = (char *)calloc(1, strlen(str_buffer)+1);*/
 910   dieif( wr_malloc((void **)&str, strlen(str_buffer)+1) != UT_OK);  
 911   strcpy(str, str_buffer);
 912 
 913   return str;
 914 
 915 } /* SQ_info_to_string() */
 916 
 917 /* SQ_error() */
 918 /*++++++++++++++++++++++++++++++++++++++
 919   Get the error string for the last error.
 920 
 921   SQ_connection_t *sql_connection The connection to the database.
 922 
 923   More:
 924   +html+ <PRE>
 925   Authors:
 926         ottrey
 927   +html+ </PRE><DL COMPACT>
 928   +html+ <DT>Online References:
 929   +html+ <DD><UL>
 930   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_error">mysql_error()</A>
 931   +html+ </UL></DL>
 932 
 933   ++++++++++++++++++++++++++++++++++++++*/
 934 char *SQ_error(SQ_connection_t *sql_connection) {
     /* [<][>][^][v][top][bottom][index][help] */
 935 
 936   return mysql_error(sql_connection);
 937 
 938 } /* SQ_error() */
 939 
 940 /* SQ_errno() */
 941 /*++++++++++++++++++++++++++++++++++++++
 942   Get the error number for the last error.
 943 
 944   SQ_connection_t *sql_connection The connection to the database.
 945 
 946   More:
 947   +html+ <PRE>
 948   Authors:
 949         ottrey
 950   +html+ </PRE><DL COMPACT>
 951   +html+ <DT>Online References:
 952   +html+ <DD><UL>
 953   +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_free_result">mysql_free_result()</A>
 954   +html+ </UL></DL>
 955 
 956   ++++++++++++++++++++++++++++++++++++++*/
 957 int SQ_errno(SQ_connection_t *sql_connection) {
     /* [<][>][^][v][top][bottom][index][help] */
 958 
 959   return mysql_errno(sql_connection);
 960 
 961 } /* SQ_errno() */
 962 
 963 /* SQ_get_info() */
 964 /*++++++++++++++++++++++++++++++++++++++
 965   Get additional information about the most 
 966   recently executed query.
 967   
 968   SQ_connection_t *sql_connection The connection to the database.
 969   int info[3] array of integers where information is stored
 970   
 971   The meaning of the numbers returned depends on the query type:
 972   
 973   info[SQL_RECORDS] - # of Records for INSERT
 974   info[SQL_MATCHES] - # of Matches for UPDATE
 975   info[SQL_DUPLICATES] - # of Duplicates
 976   info[SQL_WARNINGS] - # of Warnings
 977   
 978   More:
 979  +html+ <PRE>
 980  Authors:
 981   andrei
 982  +html+ </PRE><DL COMPACT>
 983  +html+ <DT>Online References:
 984  +html+ <DD><UL>
 985  +html+     <LI><A HREF="http://www.tcx.se/Manual/manual.html#mysql_info">mysql_info()</A>
 986  +html+ </UL></DL>
 987 
 988 ++++++++++++++++++++++++++++++++++++++*/  
 989   
 990 int SQ_get_info(SQ_connection_t *sql_connection, int info[3])
     /* [<][>][^][v][top][bottom][index][help] */
 991 {
 992 int ii;
 993 char *colon, *buf_ptr, buf[20]; 
 994 char *infoline;
 995 
 996   infoline=mysql_info(sql_connection); 
 997   ii=0;
 998   colon = infoline;
 999   while (*colon != '\0') {
1000    colon++;
1001    buf_ptr=buf;
1002    if(isdigit((int)*colon)){
1003     while(isdigit((int)*colon)){
1004      *buf_ptr=*colon; buf_ptr++; colon++;
1005     }
1006     *buf_ptr='\0';
1007     info[ii]=atoi(buf); ii++;
1008    } 
1009   }
1010  return(0);
1011 }
1012 
1013 
1014 /* 
1015    open a connection with the same parameters
1016 
1017    by marek
1018 */
1019 SQ_connection_t *
1020 SQ_duplicate_connection(SQ_connection_t *orig)
     /* [<][>][^][v][top][bottom][index][help] */
1021 {
1022   return SQ_get_connection(orig->host, orig->port, orig->db, 
1023                            orig->user, orig->passwd);
1024 }
1025 
1026 /* 
1027    abort the current query on the given connection
1028 
1029    by marek
1030 */
1031 int
1032 SQ_abort_query(SQ_connection_t *sql_connection)
     /* [<][>][^][v][top][bottom][index][help] */
1033 {
1034   SQ_connection_t *contemp = SQ_duplicate_connection(sql_connection);
1035   int res = mysql_kill(contemp, sql_connection->thread_id);
1036 
1037   ER_dbg_va(FAC_SQ, ASP_SQ_ABORT,
1038             "connection %d aborted by tmp thread %d",
1039             sql_connection->thread_id,
1040             contemp->thread_id);
1041 
1042   SQ_close_connection(contemp);
1043 
1044   return res;
1045 }
1046 
1047 /* SQ_ping() */
1048 /*++++++++++++++++++++++++++++++++++++++
1049   Checks whether or not the connection to the server is working. 
1050   If it has gone down, an automatic reconnection is attempted.
1051 
1052   Return values
1053 
1054   Zero if the server is alive. Non-zero if an error occurred.
1055 
1056   More:
1057   +html+ <PRE>
1058   Authors:
1059         andrei
1060   +html+ </PRE><DL COMPACT>
1061   +html+ <DT>Online References:
1062   +html+ <DD><UL>
1063   +html+ </UL></DL>
1064 
1065   ++++++++++++++++++++++++++++++++++++++*/
1066 int SQ_ping(SQ_connection_t *sql_connection)
     /* [<][>][^][v][top][bottom][index][help] */
1067 {
1068         return(mysql_ping(sql_connection));
1069 }
1070 

/* [<][>][^][v][top][bottom][index][help] */