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