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 | }