1 | /*************************************** 2 | $Revision: 1.36 $ 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, 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) { 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, 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, 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) { 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, 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) 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) 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) { 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) { 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) { 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) { 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, 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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]) 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) 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) 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) 1067 | { 1068 | return(mysql_ping(sql_connection)); 1069 | } 1070 |