## 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] */