## modules/sq/mysql_driver.c

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

## FUNCTIONS

This source file includes following functions.

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

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

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