Source File modules/sq/mysql_driver.c

    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,
    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) {
    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,
    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,
    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) {
    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,
    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)
    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) {
    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) {
    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) {
    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) {
    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,
    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) {
    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) {
    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) {
    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) {
    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) {
    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) {
    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) {
    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) {
    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) {
    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])
    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)
    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)
    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 | }