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