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