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