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_column_label
  9. SQ_get_column_max_length
  10. SQ_row_next
  11. SQ_get_column_string
  12. SQ_get_column_string_nocopy
  13. SQ_get_column_strings
  14. SQ_get_column_int
  15. SQ_result_to_string
  16. SQ_free_result
  17. SQ_close_connection
  18. SQ_num_rows
  19. SQ_info_to_string
  20. SQ_error
  21. SQ_errno
  22. SQ_get_info
  23. SQ_duplicate_connection
  24. SQ_abort_query

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

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