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

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