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