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