1 /*
2 * libdbi - database independent abstraction layer for C.
3 * Copyright (C) 2001-2003, David Parker and Mark Tobenkin.
4 * http://libdbi.sourceforge.net
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * $Id: dbi_result.c,v 1.57 2013/01/08 23:54:30 mhoenicka Exp $
21 *
22 * (anything that has to do with row seeking or fetching fields goes in this file)
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <math.h>
37 #include <limits.h>
38 #include <time.h>
39
40 #include <dbi/dbi.h>
41 #include <dbi/dbi-dev.h>
42
43 #ifdef __MINGW32__
44 #warning "Using the thread-unsafe strtok function!"
45 #define strtok_r(s1,s2,s3) strtok(s1,s2)
46 #endif
47
48 // cast the opaque parameter to our struct pointer
49 #define RESULT ((dbi_result_t*)Result)
50
51 /* declarations for internal functions -- anything declared as static won't be accessible by name from client programs */
52 static _field_binding_t *_find_or_create_binding_node(dbi_result_t *result, const char *fieldname);
53 static void _remove_binding_node(dbi_result_t *result, _field_binding_t *deadbinding);
54 static unsigned int _find_field(dbi_result_t *result, const char *fieldname, dbi_error_flag* errflag);
55 static int _is_row_fetched(dbi_result_t *result, unsigned long long row);
56 static int _setup_binding(dbi_result_t *result, const char *fieldname, void *bindto, void *helperfunc);
57 static void _activate_bindings(dbi_result_t *result);
58 static unsigned int _parse_field_formatstr(const char *format, char ***tokens_dest, char ***fieldnames_dest);
59 static void _free_string_list(char **ptrs, int total);
60 static void _free_result_rows(dbi_result_t *result);
61 int _disjoin_from_conn(dbi_result_t *result);
62
63 static void _bind_helper_char(_field_binding_t *binding);
64 static void _bind_helper_uchar(_field_binding_t *binding);
65 static void _bind_helper_short(_field_binding_t *binding);
66 static void _bind_helper_ushort(_field_binding_t *binding);
67 static void _bind_helper_int(_field_binding_t *binding);
68 static void _bind_helper_uint(_field_binding_t *binding);
69 static void _bind_helper_longlong(_field_binding_t *binding);
70 static void _bind_helper_ulonglong(_field_binding_t *binding);
71 static void _bind_helper_float(_field_binding_t *binding);
72 static void _bind_helper_double(_field_binding_t *binding);
73 static void _bind_helper_string(_field_binding_t *binding);
74 static void _bind_helper_binary(_field_binding_t *binding);
75 static void _bind_helper_string_copy(_field_binding_t *binding);
76 static void _bind_helper_binary_copy(_field_binding_t *binding);
77 static void _bind_helper_datetime(_field_binding_t *binding);
78
79 /* XXX ROW SEEKING AND FETCHING XXX */
80
81 /* returns 1 if ok, 0 on error */
dbi_result_seek_row(dbi_result Result,unsigned long long rowidx)82 int dbi_result_seek_row(dbi_result Result, unsigned long long rowidx) {
83 int retval;
84
85 if (!RESULT) {
86 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
87 return 0;
88 }
89
90 _reset_conn_error(RESULT->conn);
91
92 if (RESULT->result_state == NOTHING_RETURNED
93 || rowidx <= 0 || rowidx > RESULT->numrows_matched) {
94 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
95 return 0;
96 }
97
98 if (_is_row_fetched(RESULT, rowidx) == 1) {
99 /* jump right to it */
100 RESULT->currowidx = rowidx;
101 _activate_bindings(RESULT);
102 return 1;
103 }
104
105 /* row is one-based for the user, but zero-based to the dbd conn */
106 retval = RESULT->conn->driver->functions->goto_row(RESULT, rowidx-1, RESULT->currowidx-1);
107 if (retval == -1) {
108 _error_handler(RESULT->conn, DBI_ERROR_DBD);
109 return 0;
110 }
111 retval = RESULT->conn->driver->functions->fetch_row(RESULT, rowidx-1);
112 if (retval == 0) {
113 _error_handler(RESULT->conn, DBI_ERROR_DBD);
114 return 0;
115 }
116
117 RESULT->currowidx = rowidx;
118 _activate_bindings(RESULT);
119 return retval;
120 }
121
dbi_result_first_row(dbi_result Result)122 int dbi_result_first_row(dbi_result Result) {
123 return dbi_result_seek_row(Result, 1);
124 }
125
dbi_result_last_row(dbi_result Result)126 int dbi_result_last_row(dbi_result Result) {
127 return dbi_result_seek_row(Result, dbi_result_get_numrows(Result));
128 }
129
dbi_result_has_prev_row(dbi_result Result)130 int dbi_result_has_prev_row(dbi_result Result) {
131 if (!RESULT) {
132 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
133 return 0;
134 }
135
136 _reset_conn_error(RESULT->conn);
137
138 return RESULT->result_state != NOTHING_RETURNED && RESULT->currowidx > 1;
139 }
140
dbi_result_prev_row(dbi_result Result)141 int dbi_result_prev_row(dbi_result Result) {
142 if (!RESULT) {
143 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
144 return 0;
145 }
146
147 _reset_conn_error(RESULT->conn);
148
149 if (!dbi_result_has_prev_row(Result)) {
150 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
151 return 0;
152 }
153 return dbi_result_seek_row(Result, RESULT->currowidx-1);
154 }
155
dbi_result_has_next_row(dbi_result Result)156 int dbi_result_has_next_row(dbi_result Result) {
157 if (!RESULT) {
158 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
159 return 0;
160 }
161
162 _reset_conn_error(RESULT->conn);
163
164 return RESULT->result_state != NOTHING_RETURNED
165 && RESULT->currowidx < dbi_result_get_numrows(Result);
166 }
167
dbi_result_next_row(dbi_result Result)168 int dbi_result_next_row(dbi_result Result) {
169 if (!RESULT) {
170 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
171 return 0;
172 }
173
174 _reset_conn_error(RESULT->conn);
175
176 if (!dbi_result_has_next_row(Result)) {
177 /* _error_handler(RESULT->conn, DBI_ERROR_BADIDX); */
178 return 0;
179 }
180 return dbi_result_seek_row(Result, RESULT->currowidx+1);
181 }
182
dbi_result_get_currow(dbi_result Result)183 unsigned long long dbi_result_get_currow(dbi_result Result) {
184 if (!RESULT) {
185 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
186 return 0;
187 }
188
189 _reset_conn_error(RESULT->conn);
190
191 return RESULT->currowidx;
192 }
193
dbi_result_get_numrows(dbi_result Result)194 unsigned long long dbi_result_get_numrows(dbi_result Result) {
195 if (!RESULT) {
196 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
197 return DBI_ROW_ERROR;
198 }
199
200 _reset_conn_error(RESULT->conn);
201
202 return RESULT->numrows_matched;
203 }
204
dbi_result_get_numrows_affected(dbi_result Result)205 unsigned long long dbi_result_get_numrows_affected(dbi_result Result) {
206 if (!RESULT) {
207 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
208 return DBI_ROW_ERROR;
209 }
210
211 _reset_conn_error(RESULT->conn);
212
213 return RESULT->numrows_affected;
214 }
215
216 /* returns the length of the string or binary, excluding a trailing \0 */
dbi_result_get_field_length(dbi_result Result,const char * fieldname)217 size_t dbi_result_get_field_length(dbi_result Result, const char *fieldname) {
218 unsigned int fieldidx = 0;
219 dbi_error_flag errflag = DBI_ERROR_NONE;
220
221 if (!RESULT) {
222 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
223 return DBI_LENGTH_ERROR;
224 }
225
226 _reset_conn_error(RESULT->conn);
227
228 fieldidx = _find_field(RESULT, fieldname, &errflag);
229 if (errflag != DBI_ERROR_NONE) {
230 _error_handler(RESULT->conn, errflag);
231 return DBI_LENGTH_ERROR;
232 }
233
234 return dbi_result_get_field_length_idx(Result, fieldidx+1);
235 }
236
dbi_result_get_field_length_idx(dbi_result Result,unsigned int fieldidx)237 size_t dbi_result_get_field_length_idx(dbi_result Result, unsigned int fieldidx) {
238 unsigned long long currowidx;
239
240 /* user-visible indexes start at 1 */
241 fieldidx--;
242
243 if (!RESULT || !RESULT->rows) {
244 _error_handler(RESULT ? RESULT->conn : NULL, DBI_ERROR_BADPTR);
245 return DBI_LENGTH_ERROR;
246 }
247
248 _reset_conn_error(RESULT->conn);
249
250 currowidx = RESULT->currowidx;
251 if (!RESULT->rows[currowidx] || !RESULT->rows[currowidx]->field_sizes) {
252 _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT);
253 return DBI_LENGTH_ERROR;
254 }
255 if (fieldidx >= RESULT->numfields) {
256 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
257 return DBI_LENGTH_ERROR;
258 }
259
260 return RESULT->rows[currowidx]->field_sizes[fieldidx];
261 }
262
263 /* the "field_size" functions are merely kept to support legacy
264 code. Their purpose was, er, unclear, their implementations were,
265 er, broke, and the name "field_length" is more appropriate to what
266 these functions do anyway. Support for the "field_size" functions
267 is likely to be dropped in the next release */
dbi_result_get_field_size(dbi_result Result,const char * fieldname)268 size_t dbi_result_get_field_size(dbi_result Result, const char *fieldname) {
269 return dbi_result_get_field_length(Result, fieldname);
270 }
271
dbi_result_get_field_size_idx(dbi_result Result,unsigned int fieldidx)272 size_t dbi_result_get_field_size_idx(dbi_result Result, unsigned int fieldidx) {
273 return dbi_result_get_field_length_idx(Result, fieldidx);
274 }
275
dbi_result_get_field_idx(dbi_result Result,const char * fieldname)276 unsigned int dbi_result_get_field_idx(dbi_result Result, const char *fieldname) {
277 unsigned int fieldidx = 0;
278 dbi_error_flag errflag = DBI_ERROR_NONE;
279
280 if (!RESULT) {
281 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
282 return 0;
283 }
284
285 _reset_conn_error(RESULT->conn);
286
287 /* user-visible indexes start at 1 */
288 fieldidx = _find_field(RESULT, fieldname, &errflag)+1;
289 if (errflag != DBI_ERROR_NONE) {
290 _error_handler(RESULT->conn, errflag);
291 return 0;
292 }
293
294 return fieldidx;
295 }
296
dbi_result_get_field_name(dbi_result Result,unsigned int fieldidx)297 const char *dbi_result_get_field_name(dbi_result Result, unsigned int fieldidx) {
298
299 if (!RESULT) {
300 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
301 return NULL;
302 }
303
304 _reset_conn_error(RESULT->conn);
305
306 if (fieldidx > RESULT->numfields) {
307 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
308 return NULL;
309 }
310 else if (RESULT->field_names == NULL) {
311 _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT);
312 return NULL;
313 }
314
315 return (const char *) RESULT->field_names[fieldidx-1];
316 }
317
dbi_result_get_numfields(dbi_result Result)318 unsigned int dbi_result_get_numfields(dbi_result Result) {
319 if (!RESULT) return DBI_FIELD_ERROR;
320
321 _reset_conn_error(RESULT->conn);
322
323 return RESULT->numfields;
324 }
325
dbi_result_get_field_type(dbi_result Result,const char * fieldname)326 unsigned short dbi_result_get_field_type(dbi_result Result, const char *fieldname) {
327 unsigned int fieldidx = 0;
328 dbi_error_flag errflag = DBI_ERROR_NONE;
329
330 if (!RESULT) {
331 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
332 return DBI_TYPE_ERROR;
333 }
334
335 _reset_conn_error(RESULT->conn);
336
337 fieldidx = _find_field(RESULT, fieldname, &errflag);
338 if (errflag != DBI_ERROR_NONE) {
339 _error_handler(RESULT->conn, errflag);
340 return DBI_TYPE_ERROR;
341 }
342
343 return dbi_result_get_field_type_idx(Result, fieldidx+1);
344 }
345
dbi_result_get_field_type_idx(dbi_result Result,unsigned int fieldidx)346 unsigned short dbi_result_get_field_type_idx(dbi_result Result, unsigned int fieldidx) {
347 fieldidx--;
348
349 if (!RESULT) {
350 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
351 return DBI_TYPE_ERROR;
352 }
353
354 _reset_conn_error(RESULT->conn);
355
356 if (!RESULT->field_types) {
357 _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT);
358 return DBI_TYPE_ERROR;
359 }
360 else if (fieldidx >= RESULT->numfields) {
361 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
362 return DBI_TYPE_ERROR;
363 }
364
365 return RESULT->field_types[fieldidx];
366 }
367
dbi_result_get_field_attrib(dbi_result Result,const char * fieldname,unsigned int attribmin,unsigned int attribmax)368 unsigned int dbi_result_get_field_attrib(dbi_result Result, const char *fieldname, unsigned int attribmin, unsigned int attribmax) {
369 unsigned int fieldidx = 0;
370 dbi_error_flag errflag = DBI_ERROR_NONE;
371
372 if (!RESULT) {
373 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
374 return DBI_ATTRIBUTE_ERROR;
375 }
376
377 _reset_conn_error(RESULT->conn);
378
379 fieldidx = _find_field(RESULT, fieldname, &errflag);
380 if (errflag != DBI_ERROR_NONE) {
381 _error_handler(RESULT->conn, errflag);
382 return DBI_ATTRIBUTE_ERROR;
383 }
384
385 return dbi_result_get_field_attrib_idx(Result, fieldidx+1, attribmin, attribmax);
386 }
387
dbi_result_get_field_attrib_idx(dbi_result Result,unsigned int fieldidx,unsigned int attribmin,unsigned int attribmax)388 unsigned int dbi_result_get_field_attrib_idx(dbi_result Result,
389 unsigned int fieldidx, unsigned int attribmin, unsigned int attribmax) {
390 fieldidx--;
391
392 if (!RESULT) {
393 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
394 return DBI_ATTRIBUTE_ERROR;
395 }
396
397 _reset_conn_error(RESULT->conn);
398
399 if (!RESULT->field_attribs) {
400 _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT);
401 return DBI_ATTRIBUTE_ERROR;
402 }
403 else if (fieldidx >= RESULT->numfields) {
404 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
405 return DBI_ATTRIBUTE_ERROR;
406 }
407
408 return _isolate_attrib(RESULT->field_attribs[fieldidx], attribmin, attribmax);
409 }
410
dbi_result_get_field_attribs(dbi_result Result,const char * fieldname)411 unsigned int dbi_result_get_field_attribs(dbi_result Result, const char *fieldname) {
412 unsigned int fieldidx = 0;
413 dbi_error_flag errflag = DBI_ERROR_NONE;
414
415 if (!RESULT) {
416 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
417 return DBI_ATTRIBUTE_ERROR;
418 }
419
420 _reset_conn_error(RESULT->conn);
421
422 fieldidx = _find_field(RESULT, fieldname, &errflag);
423 if (errflag != DBI_ERROR_NONE) {
424 _error_handler(RESULT->conn, errflag);
425 return DBI_ATTRIBUTE_ERROR;
426 }
427
428 return dbi_result_get_field_attribs_idx(Result, fieldidx+1);
429 }
430
dbi_result_get_field_attribs_idx(dbi_result Result,unsigned int fieldidx)431 unsigned int dbi_result_get_field_attribs_idx(dbi_result Result, unsigned int fieldidx) {
432 fieldidx--;
433
434 if (!RESULT) {
435 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
436 return DBI_ATTRIBUTE_ERROR;
437 }
438
439 _reset_conn_error(RESULT->conn);
440
441 if (!RESULT->field_attribs) {
442 _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT);
443 return DBI_ATTRIBUTE_ERROR;
444 }
445 else if (fieldidx >= RESULT->numfields) {
446 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
447 return DBI_ATTRIBUTE_ERROR;
448 }
449
450 return RESULT->field_attribs[fieldidx];
451 }
452
_set_field_flag(dbi_row_t * row,unsigned int fieldidx,unsigned char flag,unsigned char value)453 void _set_field_flag(dbi_row_t *row, unsigned int fieldidx, unsigned char flag, unsigned char value) {
454 unsigned char *flags = &row->field_flags[fieldidx];
455 if (value)
456 *flags |= flag; // if value = 1, set the flag
457 else
458 *flags &= ~flag; // set that bit to 0
459 }
460
_get_field_flag(dbi_row_t * row,unsigned int fieldidx,unsigned char flag)461 int _get_field_flag(dbi_row_t *row, unsigned int fieldidx, unsigned char flag) {
462 return (row->field_flags[fieldidx] & flag) != 0;
463 }
464
dbi_result_field_is_null(dbi_result Result,const char * fieldname)465 int dbi_result_field_is_null(dbi_result Result, const char *fieldname) {
466 unsigned int fieldidx = 0;
467 dbi_error_flag errflag = DBI_ERROR_NONE;
468
469 if (!RESULT) {
470 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
471 return DBI_FIELD_FLAG_ERROR;
472 }
473
474 _reset_conn_error(RESULT->conn);
475
476 fieldidx = _find_field(RESULT, fieldname, &errflag);
477 if (errflag != DBI_ERROR_NONE) {
478 _error_handler(RESULT->conn, errflag);
479 return DBI_FIELD_FLAG_ERROR;
480 }
481
482 return dbi_result_field_is_null_idx(Result, fieldidx+1);
483 }
484
dbi_result_field_is_null_idx(dbi_result Result,unsigned int fieldidx)485 int dbi_result_field_is_null_idx(dbi_result Result, unsigned int fieldidx) {
486 unsigned long long currowidx;
487
488 fieldidx--;
489
490 if (!RESULT || !RESULT->rows) {
491 _error_handler(RESULT ? RESULT->conn : NULL, DBI_ERROR_BADPTR);
492 return DBI_FIELD_FLAG_ERROR;
493 }
494
495 _reset_conn_error(RESULT->conn);
496
497 currowidx = RESULT->currowidx;
498 if (!RESULT->rows[currowidx] || !RESULT->rows[currowidx]->field_flags) {
499 _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT);
500 return DBI_FIELD_FLAG_ERROR;
501 }
502 if (fieldidx >= RESULT->numfields) {
503 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
504 return DBI_FIELD_FLAG_ERROR;
505 }
506
507 return _get_field_flag(RESULT->rows[currowidx], fieldidx, DBI_VALUE_NULL);
508 }
509
_disjoin_from_conn(dbi_result_t * result)510 int _disjoin_from_conn(dbi_result_t *result) {
511 /* todo: is int enough? */
512 int idx;
513 int found = -1;
514 int retval;
515
516 retval = result->conn->driver->functions->free_query(result);
517
518 for (idx = 0; idx < result->conn->results_used; idx++) {
519 if (found < 0) {
520 /* keep looking */
521 if (result->conn->results[idx] == result) {
522 found = idx;
523 result->conn->results[idx] = NULL;
524 }
525 }
526 else {
527 /* already found, shift remaining elements back one */
528 result->conn->results[idx-1] = result->conn->results[idx];
529 }
530 }
531 if (found >= 0) {
532 result->conn->results[result->conn->results_used-1] = NULL;
533 result->conn->results_used--;
534 }
535
536 result->conn = NULL;
537
538 return retval;
539 }
540
dbi_result_disjoin(dbi_result Result)541 int dbi_result_disjoin(dbi_result Result) {
542 return RESULT ? _disjoin_from_conn(RESULT) : -1;
543 }
544
dbi_result_free(dbi_result Result)545 int dbi_result_free(dbi_result Result) {
546 int retval = 0;
547
548 if (!RESULT) return -1;
549
550 if (RESULT->conn) {
551 retval = _disjoin_from_conn(RESULT);
552 }
553
554 _reset_conn_error(RESULT->conn);
555
556 while (RESULT->field_bindings) {
557 _remove_binding_node(RESULT, RESULT->field_bindings);
558 }
559
560 if (RESULT->rows) {
561 _free_result_rows(RESULT);
562 }
563
564 if (RESULT->numfields) {
565 _free_string_list(RESULT->field_names, RESULT->numfields);
566 free(RESULT->field_types);
567 free(RESULT->field_attribs);
568 }
569
570 if (retval == -1) {
571 _error_handler(RESULT->conn, DBI_ERROR_DBD);
572 }
573
574 free(RESULT);
575 return retval;
576 }
577
dbi_result_get_conn(dbi_result Result)578 dbi_conn dbi_result_get_conn(dbi_result Result) {
579
580 if (!RESULT) {
581 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
582 return NULL;
583 }
584
585 return RESULT->conn;
586 }
587
588 /* RESULT: mass retrieval functions */
589
_parse_field_formatstr(const char * format,char *** tokens_dest,char *** fieldnames_dest)590 static unsigned int _parse_field_formatstr(const char *format, char ***tokens_dest, char ***fieldnames_dest) {
591 unsigned int found = 0;
592 unsigned int cur = 0;
593 char **tokens = NULL;
594 char **fieldnames = NULL;
595 char *chunk;
596 char *fieldtype;
597 char *fieldname;
598 char *temp1;
599 char *temp2;
600 char *line = strdup(format);
601
602 temp1 = line;
603 while (temp1 && (temp1 = strchr(temp1, '.')) != NULL) {
604 temp1++;
605 found++;
606 }
607
608 tokens = calloc(found, sizeof(char *));
609 fieldnames = calloc(found, sizeof(char *));
610 if (!tokens || !fieldnames) return DBI_FIELD_ERROR;
611
612 chunk = strtok_r(line, " ", &temp1);
613 do {
614 temp2 = strchr(chunk, '.');
615 if (!temp2) continue;
616 fieldname = chunk;
617 *temp2 = '\0';
618 fieldtype = (temp2+2); /* ignore the % */
619 tokens[cur] = strdup(fieldtype);
620 fieldnames[cur] = strdup(fieldname);
621 cur++;
622 } while ((chunk = strtok_r(NULL, " ", &temp1)));
623
624 *tokens_dest = tokens;
625 *fieldnames_dest = fieldnames;
626
627 free(line);
628 return found;
629 }
630
_free_string_list(char ** ptrs,int total)631 static void _free_string_list(char **ptrs, int total) {
632 int i;
633
634 if (ptrs == NULL) return;
635 for (i = 0; i < total; ++i)
636 if (ptrs[i]) free(ptrs[i]);
637 free(ptrs);
638 return;
639 }
640
_free_result_rows(dbi_result_t * result)641 static void _free_result_rows(dbi_result_t *result) {
642 unsigned long long rowidx = 0;
643 unsigned int fieldidx = 0;
644
645 for (rowidx = 0; rowidx <= result->numrows_matched; rowidx++) {
646 if (!result->rows[rowidx]) continue;
647
648 for (fieldidx = 0; fieldidx < result->numfields; fieldidx++) {
649 if ((result->field_types[fieldidx] == DBI_TYPE_STRING
650 || result->field_types[fieldidx] == DBI_TYPE_BINARY)
651 && result->rows[rowidx]->field_values[fieldidx].d_string)
652 {
653 free(result->rows[rowidx]->field_values[fieldidx].d_string);
654 }
655 }
656
657 free(result->rows[rowidx]->field_values);
658 free(result->rows[rowidx]->field_sizes);
659 free(result->rows[rowidx]->field_flags);
660 free(result->rows[rowidx]);
661 }
662
663 free(result->rows);
664 }
665
dbi_result_get_fields(dbi_result Result,const char * format,...)666 unsigned int dbi_result_get_fields(dbi_result Result, const char *format, ...) {
667 char **tokens, **fieldnames;
668 unsigned int curidx = 0, numtokens = 0, uflag;
669 va_list ap;
670
671 if (!RESULT) return DBI_FIELD_ERROR;
672
673 numtokens = _parse_field_formatstr(format, &tokens, &fieldnames);
674
675 if (numtokens == DBI_FIELD_ERROR) {
676 return numtokens;
677 }
678
679 va_start(ap, format);
680 while (curidx < numtokens) {
681 uflag = strlen(tokens[curidx]) > 1 && tokens[curidx][0] == 'u';
682 switch (tokens[curidx][strlen(tokens[curidx])-1]) {
683 case 'c': /* char */
684 if (uflag) /* unsigned */
685 *va_arg(ap, unsigned char *) = dbi_result_get_uchar(Result, fieldnames[curidx]);
686 else
687 *va_arg(ap, char *) = dbi_result_get_char(Result, fieldnames[curidx]);
688 break;
689 case 'h': /* sHort ("S"tring was taken) */
690 if (uflag) /* unsigned */
691 *va_arg(ap, unsigned short *) = dbi_result_get_ushort(Result, fieldnames[curidx]);
692 else
693 *va_arg(ap, short *) = dbi_result_get_short(Result, fieldnames[curidx]);
694 break;
695 case 'l': /* 4-byte integer (both l and i work) */
696 case 'i':
697 if (uflag) /* unsigned */
698 *va_arg(ap, unsigned int *) = dbi_result_get_uint(Result, fieldnames[curidx]);
699 else
700 *va_arg(ap, int *) = dbi_result_get_int(Result, fieldnames[curidx]);
701 break;
702 case 'L': /* long long */
703 if (uflag) /* unsigned */
704 *va_arg(ap, unsigned long long *) = dbi_result_get_ulonglong(Result, fieldnames[curidx]);
705 else
706 *va_arg(ap, long long *) = dbi_result_get_longlong(Result, fieldnames[curidx]);
707 break;
708 case 'f': /* float */
709 *va_arg(ap, float *) = dbi_result_get_float(Result, fieldnames[curidx]);
710 break;
711 case 'd': /* double */
712 *va_arg(ap, double *) = dbi_result_get_double(Result, fieldnames[curidx]);
713 break;
714 case 's': /* string */
715 *va_arg(ap, const char **) = dbi_result_get_string(Result, fieldnames[curidx]);
716 break;
717 case 'b': /* binary */
718 *va_arg(ap, const unsigned char **) = dbi_result_get_binary(Result, fieldnames[curidx]);
719 break;
720 case 'S': /* string copy */
721 *va_arg(ap, char **) = dbi_result_get_string_copy(Result, fieldnames[curidx]);
722 break;
723 case 'B': /* binary copy */
724 *va_arg(ap, unsigned char **) = dbi_result_get_binary_copy(Result, fieldnames[curidx]);
725 break;
726 case 'm': /* datetiMe (what... you have any better ideas?? */
727 *va_arg(ap, time_t *) = dbi_result_get_datetime(Result, fieldnames[curidx]);
728 break;
729 }
730 curidx++;
731 }
732 va_end(ap);
733
734 _free_string_list(tokens, numtokens);
735 _free_string_list(fieldnames, numtokens);
736 return numtokens;
737 }
738
dbi_result_bind_fields(dbi_result Result,const char * format,...)739 unsigned int dbi_result_bind_fields(dbi_result Result, const char *format, ...) {
740 char **tokens, **fieldnames;
741 unsigned int curidx = 0, numtokens = 0, uflag;
742 va_list ap;
743
744 if (!RESULT) return DBI_FIELD_ERROR;
745
746 numtokens = _parse_field_formatstr(format, &tokens, &fieldnames);
747
748 if (numtokens == DBI_FIELD_ERROR) {
749 return numtokens;
750 }
751
752 va_start(ap, format);
753 while (curidx < numtokens) {
754 uflag = strlen(tokens[curidx]) > 1 && tokens[curidx][0] == 'u';
755 switch (tokens[curidx][strlen(tokens[curidx])-1]) {
756 case 'c': /* char */
757 if (uflag) /* unsigned */
758 dbi_result_bind_uchar(Result, fieldnames[curidx], va_arg(ap, unsigned char *));
759 else
760 dbi_result_bind_char(Result, fieldnames[curidx], va_arg(ap, char *));
761 break;
762 case 'h': /* sHort ("S"tring was taken) */
763 if (uflag) /* unsigned */
764 dbi_result_bind_ushort(Result, fieldnames[curidx], va_arg(ap, unsigned short *));
765 else
766 dbi_result_bind_short(Result, fieldnames[curidx], va_arg(ap, short *));
767 break;
768 case 'l': /* 4-byte integer (both l and i work) */
769 case 'i':
770 if (uflag) /* unsigned */
771 dbi_result_bind_uint(Result, fieldnames[curidx], va_arg(ap, unsigned int *));
772 else
773 dbi_result_bind_int(Result, fieldnames[curidx], va_arg(ap, int *));
774 break;
775 case 'L': /* long long */
776 if (uflag) /* unsigned */
777 dbi_result_bind_ulonglong(Result, fieldnames[curidx], va_arg(ap, unsigned long long *));
778 else
779 dbi_result_bind_longlong(Result, fieldnames[curidx], va_arg(ap, long long *));
780 break;
781 case 'f': /* float */
782 dbi_result_bind_float(Result, fieldnames[curidx], va_arg(ap, float *));
783 break;
784 case 'd': /* double */
785 dbi_result_bind_double(Result, fieldnames[curidx], va_arg(ap, double *));
786 break;
787 case 's': /* string */
788 dbi_result_bind_string(Result, fieldnames[curidx], va_arg(ap, const char **));
789 break;
790 case 'b': /* binary */
791 dbi_result_bind_binary(Result, fieldnames[curidx], va_arg(ap, const unsigned char **));
792 break;
793 case 'S': /* string copy */
794 dbi_result_bind_string_copy(Result, fieldnames[curidx], va_arg(ap, char **));
795 break;
796 case 'B': /* binary copy */
797 dbi_result_bind_binary_copy(Result, fieldnames[curidx], va_arg(ap, unsigned char **));
798 break;
799 case 'm': /* datetiMe (what... you have any better ideas?? */
800 dbi_result_bind_datetime(Result, fieldnames[curidx], va_arg(ap, time_t *));
801 break;
802 }
803 curidx++;
804 }
805 va_end(ap);
806
807 _free_string_list(tokens, numtokens);
808 _free_string_list(fieldnames, numtokens);
809 return numtokens;
810 }
811
812 /* RESULT: get_* functions */
813
dbi_result_get_char(dbi_result Result,const char * fieldname)814 signed char dbi_result_get_char(dbi_result Result, const char *fieldname) {
815 signed char my_ERROR = 0;
816 unsigned int fieldidx;
817 dbi_error_flag errflag = DBI_ERROR_NONE;
818
819 _reset_conn_error(RESULT->conn);
820
821 fieldidx = _find_field(RESULT, fieldname, &errflag);
822 if (errflag != DBI_ERROR_NONE) {
823 dbi_conn_t *conn = RESULT->conn;
824 _error_handler(conn, errflag);
825 return my_ERROR;
826 }
827 return dbi_result_get_char_idx(Result, fieldidx+1);
828 }
829
dbi_result_get_char_idx(dbi_result Result,unsigned int fieldidx)830 signed char dbi_result_get_char_idx(dbi_result Result, unsigned int fieldidx) {
831 signed char my_ERROR = 0;
832
833 fieldidx--;
834
835 _reset_conn_error(RESULT->conn);
836
837 if (fieldidx >= RESULT->numfields) {
838 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
839 return my_ERROR;
840 }
841 if (RESULT->field_types[fieldidx] != DBI_TYPE_INTEGER) {
842 _verbose_handler(RESULT->conn, "%s: field `%s` is not integer type\n",
843 __func__, dbi_result_get_field_name(Result, fieldidx+1));
844 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
845 return my_ERROR;
846 }
847
848 switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) {
849 case DBI_INTEGER_SIZE1:
850 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_char;
851 case DBI_INTEGER_SIZE2:
852 case DBI_INTEGER_SIZE3:
853 case DBI_INTEGER_SIZE4:
854 case DBI_INTEGER_SIZE8:
855 _verbose_handler(RESULT->conn, "%s: field `%s` is more than 1 byte wide\n",
856 __func__, dbi_result_get_field_name(Result, fieldidx+1));
857 default:
858 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
859 return my_ERROR;
860 }
861 }
862
dbi_result_get_short(dbi_result Result,const char * fieldname)863 short dbi_result_get_short(dbi_result Result, const char *fieldname) {
864 short my_ERROR = 0;
865 unsigned int fieldidx;
866 dbi_error_flag errflag = DBI_ERROR_NONE;
867
868 _reset_conn_error(RESULT->conn);
869
870 fieldidx = _find_field(RESULT, fieldname, &errflag);
871 if (errflag != DBI_ERROR_NONE) {
872 dbi_conn_t *conn = RESULT->conn;
873 _error_handler(conn, DBI_ERROR_BADNAME);
874 return my_ERROR;
875 }
876 return dbi_result_get_short_idx(Result, fieldidx+1);
877 }
878
dbi_result_get_short_idx(dbi_result Result,unsigned int fieldidx)879 short dbi_result_get_short_idx(dbi_result Result, unsigned int fieldidx) {
880 short my_ERROR = 0;
881 fieldidx--;
882
883 _reset_conn_error(RESULT->conn);
884
885 if (fieldidx >= RESULT->numfields) {
886 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
887 return my_ERROR;
888 }
889 if (RESULT->field_types[fieldidx] != DBI_TYPE_INTEGER) {
890 _verbose_handler(RESULT->conn, "%s: field `%s` is not integer type\n",
891 __func__, dbi_result_get_field_name(Result, fieldidx+1));
892 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
893 return my_ERROR;
894 }
895
896 switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) {
897 case DBI_INTEGER_SIZE1:
898 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_char;
899 case DBI_INTEGER_SIZE2:
900 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_short;
901 case DBI_INTEGER_SIZE3:
902 case DBI_INTEGER_SIZE4:
903 case DBI_INTEGER_SIZE8:
904 _verbose_handler(RESULT->conn, "%s: field `%s` is more than 2 bytes wide\n",
905 __func__, dbi_result_get_field_name(Result, fieldidx+1));
906 default:
907 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
908 return my_ERROR;
909 }
910 }
911
dbi_result_get_long(dbi_result Result,const char * fieldname)912 int dbi_result_get_long(dbi_result Result, const char *fieldname) {
913 return dbi_result_get_int(Result, fieldname);
914 }
915
dbi_result_get_int(dbi_result Result,const char * fieldname)916 int dbi_result_get_int(dbi_result Result, const char *fieldname) {
917 long my_ERROR = 0;
918 unsigned int fieldidx;
919 dbi_error_flag errflag = DBI_ERROR_NONE;
920
921 _reset_conn_error(RESULT->conn);
922
923 fieldidx = _find_field(RESULT, fieldname, &errflag);
924 if (errflag != DBI_ERROR_NONE) {
925 dbi_conn_t *conn = RESULT->conn;
926 _error_handler(conn, DBI_ERROR_BADNAME);
927 return my_ERROR;
928 }
929 return dbi_result_get_int_idx(Result, fieldidx+1);
930 }
931
dbi_result_get_long_idx(dbi_result Result,unsigned int fieldidx)932 int dbi_result_get_long_idx(dbi_result Result, unsigned int fieldidx) {
933 return dbi_result_get_int_idx(Result, fieldidx);
934 }
935
dbi_result_get_int_idx(dbi_result Result,unsigned int fieldidx)936 int dbi_result_get_int_idx(dbi_result Result, unsigned int fieldidx) {
937 long my_ERROR = 0;
938 fieldidx--;
939
940 _reset_conn_error(RESULT->conn);
941
942 if (fieldidx >= RESULT->numfields) {
943 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
944 return my_ERROR;
945 }
946 if (RESULT->field_types[fieldidx] != DBI_TYPE_INTEGER) {
947 _verbose_handler(RESULT->conn, "%s: field `%s` is not integer type\n",
948 __func__, dbi_result_get_field_name(Result, fieldidx+1));
949 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
950 return my_ERROR;
951 }
952
953 switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) {
954 case DBI_INTEGER_SIZE1:
955 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_char;
956 case DBI_INTEGER_SIZE2:
957 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_short;
958 case DBI_INTEGER_SIZE3:
959 case DBI_INTEGER_SIZE4:
960 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_long;
961 case DBI_INTEGER_SIZE8:
962 _verbose_handler(RESULT->conn, "%s: field `%s` is more than 4 bytes wide\n",
963 __func__, dbi_result_get_field_name(Result, fieldidx+1));
964 default:
965 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
966 return my_ERROR;
967 }
968 }
969
dbi_result_get_longlong(dbi_result Result,const char * fieldname)970 long long dbi_result_get_longlong(dbi_result Result, const char *fieldname) {
971 long long my_ERROR = 0;
972 unsigned int fieldidx;
973 dbi_error_flag errflag = DBI_ERROR_NONE;
974
975 _reset_conn_error(RESULT->conn);
976
977 fieldidx = _find_field(RESULT, fieldname, &errflag);
978 if (errflag != DBI_ERROR_NONE) {
979 dbi_conn_t *conn = RESULT->conn;
980 _error_handler(conn, DBI_ERROR_BADNAME);
981 return my_ERROR;
982 }
983 return dbi_result_get_longlong_idx(Result, fieldidx+1);
984 }
985
dbi_result_get_longlong_idx(dbi_result Result,unsigned int fieldidx)986 long long dbi_result_get_longlong_idx(dbi_result Result, unsigned int fieldidx) {
987 long long my_ERROR = 0;
988 fieldidx--;
989
990 _reset_conn_error(RESULT->conn);
991
992 if (fieldidx >= RESULT->numfields) {
993 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
994 return my_ERROR;
995 }
996 if (RESULT->field_types[fieldidx] != DBI_TYPE_INTEGER) {
997 _verbose_handler(RESULT->conn, "%s: field `%s` is not integer type\n",
998 __func__, dbi_result_get_field_name(Result, fieldidx+1));
999 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1000 return my_ERROR;
1001 }
1002
1003 switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) {
1004 case DBI_INTEGER_SIZE1:
1005 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_char;
1006 case DBI_INTEGER_SIZE2:
1007 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_short;
1008 case DBI_INTEGER_SIZE3:
1009 case DBI_INTEGER_SIZE4:
1010 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_long;
1011 case DBI_INTEGER_SIZE8:
1012 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_longlong;
1013 default:
1014 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1015 return my_ERROR;
1016 }
1017 }
1018
dbi_result_get_uchar(dbi_result Result,const char * fieldname)1019 unsigned char dbi_result_get_uchar(dbi_result Result, const char *fieldname) {
1020 return (unsigned char)dbi_result_get_char(Result, fieldname);
1021 }
1022
dbi_result_get_uchar_idx(dbi_result Result,unsigned int fieldidx)1023 unsigned char dbi_result_get_uchar_idx(dbi_result Result, unsigned int fieldidx) {
1024 return (unsigned char)dbi_result_get_char_idx(Result, fieldidx);
1025 }
1026
dbi_result_get_ushort(dbi_result Result,const char * fieldname)1027 unsigned short dbi_result_get_ushort(dbi_result Result, const char *fieldname) {
1028 return (unsigned short)dbi_result_get_short(Result, fieldname);
1029 }
1030
dbi_result_get_ushort_idx(dbi_result Result,unsigned int fieldidx)1031 unsigned short dbi_result_get_ushort_idx(dbi_result Result, unsigned int fieldidx) {
1032 return (unsigned short)dbi_result_get_short_idx(Result, fieldidx);
1033 }
1034
dbi_result_get_uint(dbi_result Result,const char * fieldname)1035 unsigned int dbi_result_get_uint(dbi_result Result, const char *fieldname) {
1036 return (unsigned int)dbi_result_get_int(Result, fieldname);
1037 }
1038
dbi_result_get_ulong(dbi_result Result,const char * fieldname)1039 unsigned int dbi_result_get_ulong(dbi_result Result, const char *fieldname) {
1040 return dbi_result_get_uint(Result, fieldname);
1041 }
1042
dbi_result_get_uint_idx(dbi_result Result,unsigned int fieldidx)1043 unsigned int dbi_result_get_uint_idx(dbi_result Result, unsigned int fieldidx) {
1044 return (unsigned int)dbi_result_get_int_idx(Result, fieldidx);
1045 }
1046
dbi_result_get_ulong_idx(dbi_result Result,unsigned int fieldidx)1047 unsigned int dbi_result_get_ulong_idx(dbi_result Result, unsigned int fieldidx) {
1048 return dbi_result_get_uint_idx(Result, fieldidx);
1049 }
1050
dbi_result_get_ulonglong(dbi_result Result,const char * fieldname)1051 unsigned long long dbi_result_get_ulonglong(dbi_result Result, const char *fieldname) {
1052 return (unsigned long long)dbi_result_get_longlong(Result, fieldname);
1053 }
1054
dbi_result_get_ulonglong_idx(dbi_result Result,unsigned int fieldidx)1055 unsigned long long dbi_result_get_ulonglong_idx(dbi_result Result, unsigned int fieldidx) {
1056 return (unsigned long long)dbi_result_get_longlong_idx(Result, fieldidx);
1057 }
1058
dbi_result_get_float(dbi_result Result,const char * fieldname)1059 float dbi_result_get_float(dbi_result Result, const char *fieldname) {
1060 float my_ERROR = 0.0;
1061 dbi_error_flag errflag = DBI_ERROR_NONE;
1062 unsigned int fieldidx;
1063
1064 _reset_conn_error(RESULT->conn);
1065
1066 fieldidx = _find_field(RESULT, fieldname, &errflag);
1067 if (errflag != DBI_ERROR_NONE) {
1068 dbi_conn_t *conn = RESULT->conn;
1069 _error_handler(conn, DBI_ERROR_BADNAME);
1070 return my_ERROR;
1071 }
1072 return dbi_result_get_float_idx(Result, fieldidx+1);
1073 }
1074
dbi_result_get_float_idx(dbi_result Result,unsigned int fieldidx)1075 float dbi_result_get_float_idx(dbi_result Result, unsigned int fieldidx) {
1076 float my_ERROR = 0.0;
1077 fieldidx--;
1078
1079 _reset_conn_error(RESULT->conn);
1080
1081
1082 if (fieldidx >= RESULT->numfields) {
1083 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
1084 return my_ERROR;
1085 }
1086 if (RESULT->field_types[fieldidx] != DBI_TYPE_DECIMAL) {
1087 _verbose_handler(RESULT->conn, "%s: field `%s` is not float type\n",
1088 __func__, dbi_result_get_field_name(Result, fieldidx+1));
1089 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1090 return my_ERROR;
1091 }
1092
1093 switch (RESULT->field_attribs[fieldidx] & DBI_DECIMAL_SIZEMASK) {
1094 case DBI_DECIMAL_SIZE4:
1095 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_float;
1096 case DBI_DECIMAL_SIZE8:
1097 _verbose_handler(RESULT->conn, "%s: field `%s` is double, not float\n",
1098 __func__, dbi_result_get_field_name(Result, fieldidx+1));
1099 default:
1100 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1101 return my_ERROR;
1102 }
1103 }
1104
dbi_result_get_double(dbi_result Result,const char * fieldname)1105 double dbi_result_get_double(dbi_result Result, const char *fieldname) {
1106 double my_ERROR = 0.0;
1107 unsigned int fieldidx;
1108 dbi_error_flag errflag = DBI_ERROR_NONE;
1109
1110 _reset_conn_error(RESULT->conn);
1111
1112 fieldidx = _find_field(RESULT, fieldname, &errflag);
1113 if (errflag != DBI_ERROR_NONE) {
1114 dbi_conn_t *conn = RESULT->conn;
1115 _error_handler(conn, DBI_ERROR_BADNAME);
1116 return my_ERROR;
1117 }
1118 return dbi_result_get_double_idx(Result, fieldidx+1);
1119 }
1120
dbi_result_get_double_idx(dbi_result Result,unsigned int fieldidx)1121 double dbi_result_get_double_idx(dbi_result Result, unsigned int fieldidx) {
1122 double my_ERROR = 0.0;
1123 fieldidx--;
1124
1125 _reset_conn_error(RESULT->conn);
1126
1127 if (fieldidx >= RESULT->numfields) {
1128 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
1129 return my_ERROR;
1130 }
1131 if (RESULT->field_types[fieldidx] != DBI_TYPE_DECIMAL) {
1132 _verbose_handler(RESULT->conn, "%s: field `%s` is not double type\n",
1133 __func__, dbi_result_get_field_name(Result, fieldidx+1));
1134 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1135 return my_ERROR;
1136 }
1137
1138 switch (RESULT->field_attribs[fieldidx] & DBI_DECIMAL_SIZEMASK) {
1139 case DBI_DECIMAL_SIZE4:
1140 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_float;
1141 case DBI_DECIMAL_SIZE8:
1142 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_double;
1143 default:
1144 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1145 return my_ERROR;
1146 }
1147 }
1148
dbi_result_get_string(dbi_result Result,const char * fieldname)1149 const char *dbi_result_get_string(dbi_result Result, const char *fieldname) {
1150 const char *my_ERROR = "ERROR";
1151 unsigned int fieldidx;
1152 dbi_error_flag errflag = DBI_ERROR_NONE;
1153
1154 _reset_conn_error(RESULT->conn);
1155
1156 fieldidx = _find_field(RESULT, fieldname, &errflag);
1157 if (errflag != DBI_ERROR_NONE) {
1158 dbi_conn_t *conn = RESULT->conn;
1159 _error_handler(conn, DBI_ERROR_BADNAME);
1160 return my_ERROR;
1161 }
1162 return dbi_result_get_string_idx(Result, fieldidx+1);
1163 }
1164
dbi_result_get_string_idx(dbi_result Result,unsigned int fieldidx)1165 const char *dbi_result_get_string_idx(dbi_result Result, unsigned int fieldidx) {
1166 const char *my_ERROR = "ERROR";
1167 fieldidx--;
1168
1169 _reset_conn_error(RESULT->conn);
1170
1171
1172 if (fieldidx >= RESULT->numfields) {
1173 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
1174 return my_ERROR;
1175 }
1176
1177 if (RESULT->field_types[fieldidx] != DBI_TYPE_STRING) {
1178 dbi_conn_t *conn = RESULT->conn;
1179 _verbose_handler(conn, "%s: field `%s` is not string type\n",
1180 __func__, dbi_result_get_field_name(Result, fieldidx+1));
1181 _error_handler(conn, DBI_ERROR_BADTYPE);
1182 return my_ERROR;
1183 }
1184 if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0
1185 && _get_field_flag(RESULT->rows[RESULT->currowidx], fieldidx, DBI_VALUE_NULL)) {
1186 /* string does not exist */
1187 return NULL;
1188 }
1189 /* else if field size == 0: empty string */
1190
1191 return (const char *)(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string);
1192 }
1193
dbi_result_get_binary(dbi_result Result,const char * fieldname)1194 const unsigned char *dbi_result_get_binary(dbi_result Result, const char *fieldname) {
1195 const char *my_ERROR = "ERROR";
1196 unsigned int fieldidx;
1197 dbi_error_flag errflag = DBI_ERROR_NONE;
1198
1199 _reset_conn_error(RESULT->conn);
1200
1201 fieldidx = _find_field(RESULT, fieldname, &errflag);
1202 if (errflag != DBI_ERROR_NONE) {
1203 dbi_conn_t *conn = RESULT->conn;
1204 _error_handler(conn, DBI_ERROR_BADNAME);
1205 return (const unsigned char*)my_ERROR;
1206 }
1207 return dbi_result_get_binary_idx(Result, fieldidx+1);
1208 }
1209
dbi_result_get_binary_idx(dbi_result Result,unsigned int fieldidx)1210 const unsigned char *dbi_result_get_binary_idx(dbi_result Result, unsigned int fieldidx) {
1211 const char *my_ERROR = "ERROR";
1212 fieldidx--;
1213
1214 _reset_conn_error(RESULT->conn);
1215
1216
1217 if (fieldidx >= RESULT->numfields) {
1218 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
1219 return (const unsigned char*)my_ERROR;
1220 }
1221 if (RESULT->field_types[fieldidx] != DBI_TYPE_BINARY) {
1222 _verbose_handler(RESULT->conn, "%s: field `%s` is not binary type\n",
1223 __func__, dbi_result_get_field_name(Result, fieldidx+1));
1224 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1225 return (const unsigned char*)my_ERROR;
1226 }
1227 if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0) return NULL;
1228
1229 return (const unsigned char *)(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string);
1230 }
1231
dbi_result_get_string_copy(dbi_result Result,const char * fieldname)1232 char *dbi_result_get_string_copy(dbi_result Result, const char *fieldname) {
1233 char *my_ERROR = "ERROR";
1234 unsigned int fieldidx;
1235 dbi_error_flag errflag = DBI_ERROR_NONE;
1236
1237 _reset_conn_error(RESULT->conn);
1238
1239 fieldidx = _find_field(RESULT, fieldname, &errflag);
1240 if (errflag != DBI_ERROR_NONE) {
1241 dbi_conn_t *conn = RESULT->conn;
1242 _error_handler(conn, DBI_ERROR_BADNAME);
1243 return strdup(my_ERROR);
1244 }
1245 return dbi_result_get_string_copy_idx(Result, fieldidx+1);
1246 }
1247
dbi_result_get_string_copy_idx(dbi_result Result,unsigned int fieldidx)1248 char *dbi_result_get_string_copy_idx(dbi_result Result, unsigned int fieldidx) {
1249 char *my_ERROR = "ERROR";
1250 char *newstring = NULL;
1251 fieldidx--;
1252
1253 _reset_conn_error(RESULT->conn);
1254
1255
1256 if (fieldidx >= RESULT->numfields) {
1257 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
1258 return strdup(my_ERROR);
1259 }
1260 if (RESULT->field_types[fieldidx] != DBI_TYPE_STRING) {
1261 _verbose_handler(RESULT->conn, "%s: field `%s` is not string type\n",
1262 __func__, dbi_result_get_field_name(Result, fieldidx+1));
1263 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1264 return strdup(my_ERROR);
1265 }
1266 if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0
1267 && RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string == NULL) {
1268 // mysql returns 0 for the field size of an empty string, so size==0
1269 // doesn't necessarily mean NULL
1270 return NULL;
1271 }
1272
1273 newstring = strdup(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string);
1274
1275 if (newstring) {
1276 return newstring;
1277 }
1278 else {
1279 _error_handler(RESULT->conn, DBI_ERROR_NOMEM);
1280 return strdup(my_ERROR);
1281 }
1282 }
1283
dbi_result_get_binary_copy(dbi_result Result,const char * fieldname)1284 unsigned char *dbi_result_get_binary_copy(dbi_result Result, const char *fieldname) {
1285 char *my_ERROR = "ERROR";
1286 unsigned int fieldidx;
1287 dbi_error_flag errflag = DBI_ERROR_NONE;
1288
1289 _reset_conn_error(RESULT->conn);
1290
1291 fieldidx = _find_field(RESULT, fieldname, &errflag);
1292 if (errflag != DBI_ERROR_NONE) {
1293 dbi_conn_t *conn = RESULT->conn;
1294 _error_handler(conn, DBI_ERROR_BADNAME);
1295 return (unsigned char *)strdup(my_ERROR);
1296 }
1297 return dbi_result_get_binary_copy_idx(Result, fieldidx+1);
1298 }
1299
dbi_result_get_binary_copy_idx(dbi_result Result,unsigned int fieldidx)1300 unsigned char *dbi_result_get_binary_copy_idx(dbi_result Result, unsigned int fieldidx) {
1301 char *my_ERROR = "ERROR";
1302 unsigned char *newblob = NULL;
1303 unsigned long long size;
1304 fieldidx--;
1305
1306 _reset_conn_error(RESULT->conn);
1307
1308
1309 if (fieldidx >= RESULT->numfields) {
1310 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
1311 return (unsigned char *)strdup(my_ERROR);
1312 }
1313 if (RESULT->field_types[fieldidx] != DBI_TYPE_BINARY) {
1314 _verbose_handler(RESULT->conn, "%s: field `%s` is not binary type\n",
1315 __func__, dbi_result_get_field_name(Result, fieldidx+1));
1316 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1317 return (unsigned char *)strdup(my_ERROR);
1318 }
1319 if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0) return NULL;
1320
1321 /* API function must use 1-based index */
1322 size = dbi_result_get_field_length_idx(Result, fieldidx+1);
1323 newblob = malloc(size);
1324 if (!newblob) {
1325 _error_handler(RESULT->conn, DBI_ERROR_NOMEM);
1326 return (unsigned char *)strdup(my_ERROR);
1327 }
1328 memcpy(newblob, RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string, size);
1329 return newblob;
1330 }
1331
dbi_result_get_datetime(dbi_result Result,const char * fieldname)1332 time_t dbi_result_get_datetime(dbi_result Result, const char *fieldname) {
1333 time_t my_ERROR = 0;
1334 unsigned int fieldidx;
1335 dbi_error_flag errflag = DBI_ERROR_NONE;
1336
1337 _reset_conn_error(RESULT->conn);
1338
1339 fieldidx = _find_field(RESULT, fieldname, &errflag);
1340 if (errflag != DBI_ERROR_NONE) {
1341 dbi_conn_t *conn = RESULT->conn;
1342 _error_handler(conn, DBI_ERROR_BADNAME);
1343 return my_ERROR;
1344 }
1345 return dbi_result_get_datetime_idx(Result, fieldidx+1);
1346 }
1347
dbi_result_get_datetime_idx(dbi_result Result,unsigned int fieldidx)1348 time_t dbi_result_get_datetime_idx(dbi_result Result, unsigned int fieldidx) {
1349 time_t my_ERROR = 0;
1350 fieldidx--;
1351
1352 _reset_conn_error(RESULT->conn);
1353
1354 if (fieldidx >= RESULT->numfields) {
1355 _error_handler(RESULT->conn, DBI_ERROR_BADIDX);
1356 return my_ERROR;
1357 }
1358 if (RESULT->field_types[fieldidx] != DBI_TYPE_DATETIME) {
1359 _verbose_handler(RESULT->conn, "%s: field `%s` is not datetime type\n",
1360 __func__, dbi_result_get_field_name(Result, fieldidx+1));
1361 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1362 return my_ERROR;
1363 }
1364
1365 return (time_t)(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_datetime);
1366 }
1367
1368 /* RESULT: get_as* functions */
1369
dbi_result_get_as_longlong(dbi_result Result,const char * fieldname)1370 long long dbi_result_get_as_longlong(dbi_result Result, const char *fieldname) {
1371 long long my_ERROR = 0;
1372 unsigned int fieldidx;
1373 dbi_error_flag errflag = DBI_ERROR_NONE;
1374
1375 _reset_conn_error(RESULT->conn);
1376
1377 fieldidx = _find_field(RESULT, fieldname, &errflag);
1378 if (errflag != DBI_ERROR_NONE) {
1379 dbi_conn_t *conn = RESULT->conn;
1380 _error_handler(conn, DBI_ERROR_BADNAME);
1381 return my_ERROR;
1382 }
1383 return dbi_result_get_as_longlong_idx(Result, fieldidx+1);
1384 }
1385
dbi_result_get_as_longlong_idx(dbi_result Result,unsigned int fieldidx)1386 long long dbi_result_get_as_longlong_idx(dbi_result Result, unsigned int fieldidx) {
1387 long long my_ERROR = 0;
1388 fieldidx--;
1389
1390 switch (RESULT->field_types[fieldidx]) {
1391 case DBI_TYPE_INTEGER:
1392 switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) {
1393 case DBI_INTEGER_SIZE1:
1394 return (long long)RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_char;
1395 case DBI_INTEGER_SIZE2:
1396 return (long long)RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_short;
1397 case DBI_INTEGER_SIZE3:
1398 case DBI_INTEGER_SIZE4:
1399 return (long long)RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_long;
1400 case DBI_INTEGER_SIZE8:
1401 return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_longlong;
1402 default:
1403 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1404 return my_ERROR;
1405 }
1406 case DBI_TYPE_DECIMAL:
1407 switch (RESULT->field_attribs[fieldidx] & DBI_DECIMAL_SIZEMASK) {
1408 case DBI_DECIMAL_SIZE4:
1409 return (long long)RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_float;
1410 case DBI_DECIMAL_SIZE8:
1411 return (long long)RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_double;
1412 default:
1413 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1414 return my_ERROR;
1415 }
1416 case DBI_TYPE_STRING:
1417 if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0
1418 && RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string == NULL) {
1419 /* string does not exist */
1420 return 0; /* do not raise an error */
1421 }
1422 /* else if field size == 0: empty string */
1423 /* todo: do we need strtoll() error handling? */
1424 return strtoll((const char *)(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string), NULL, 10);
1425 case DBI_TYPE_BINARY:
1426 return 0; /* do not raise an error */
1427 case DBI_TYPE_DATETIME:
1428 return (long long)(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_datetime);
1429 default:
1430 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1431 return my_ERROR;
1432 }
1433 }
1434
dbi_result_get_as_string_copy(dbi_result Result,const char * fieldname)1435 char *dbi_result_get_as_string_copy(dbi_result Result, const char *fieldname) {
1436 char *my_ERROR = "ERROR";
1437 unsigned int fieldidx;
1438 dbi_error_flag errflag = DBI_ERROR_NONE;
1439
1440 _reset_conn_error(RESULT->conn);
1441
1442 fieldidx = _find_field(RESULT, fieldname, &errflag);
1443 if (errflag != DBI_ERROR_NONE) {
1444 dbi_conn_t *conn = RESULT->conn;
1445 _error_handler(conn, DBI_ERROR_BADNAME);
1446 return strdup(my_ERROR);
1447 }
1448 return dbi_result_get_as_string_copy_idx(Result, fieldidx+1);
1449 }
1450
dbi_result_get_as_string_copy_idx(dbi_result Result,unsigned int fieldidx)1451 char *dbi_result_get_as_string_copy_idx(dbi_result Result, unsigned int fieldidx) {
1452 char *my_ERROR = "ERROR";
1453 char *newstring = NULL;
1454 char *oldstring = NULL;
1455 struct tm utctime;
1456
1457 fieldidx--;
1458
1459 newstring = malloc(32); /* sufficient for integers, decimal, and datetime */
1460
1461 if (!newstring) {
1462 _error_handler(RESULT->conn, DBI_ERROR_NOMEM);
1463 return my_ERROR;
1464 }
1465 *newstring = '\0';
1466
1467 /* output depends on: type, size, sign */
1468 switch (RESULT->field_types[fieldidx]) {
1469 case DBI_TYPE_INTEGER:
1470 switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) {
1471 case DBI_INTEGER_SIZE1:
1472 if (RESULT->field_attribs[fieldidx] & DBI_INTEGER_UNSIGNED) {
1473 snprintf(newstring, 32, "%hhu", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_char);
1474 }
1475 else {
1476 snprintf(newstring, 32, "%hhd", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_char);
1477 }
1478 break;
1479 case DBI_INTEGER_SIZE2:
1480 if (RESULT->field_attribs[fieldidx] & DBI_INTEGER_UNSIGNED) {
1481 snprintf(newstring, 32, "%hu", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_short);
1482 }
1483 else {
1484 snprintf(newstring, 32, "%hd", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_short);
1485 }
1486 break;
1487 case DBI_INTEGER_SIZE3:
1488 case DBI_INTEGER_SIZE4:
1489 if (RESULT->field_attribs[fieldidx] & DBI_INTEGER_UNSIGNED) {
1490 snprintf(newstring, 32, "%u", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_long);
1491 }
1492 else {
1493 snprintf(newstring, 32, "%d", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_long);
1494 }
1495 break;
1496 case DBI_INTEGER_SIZE8:
1497 if (RESULT->field_attribs[fieldidx] & DBI_INTEGER_UNSIGNED) {
1498 snprintf(newstring, 32, "%llu", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_longlong);
1499 }
1500 else {
1501 snprintf(newstring, 32, "%lld", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_longlong);
1502 }
1503 break;
1504 default:
1505 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1506 }
1507 break;
1508 case DBI_TYPE_DECIMAL:
1509 switch (RESULT->field_attribs[fieldidx] & DBI_DECIMAL_SIZEMASK) {
1510 case DBI_DECIMAL_SIZE4:
1511 snprintf(newstring, 32, "%e", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_float);
1512 break;
1513 case DBI_DECIMAL_SIZE8:
1514 snprintf(newstring, 32, "%e", RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_double);
1515 break;
1516 default:
1517 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1518 }
1519 break;
1520 case DBI_TYPE_STRING:
1521 if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0
1522 && RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string == NULL) {
1523 /* string does not exist */
1524 /* return an empty string instead, no error */
1525 }
1526 else {
1527 /* else if field size == 0: empty string */
1528
1529 oldstring = newstring;
1530 if ((newstring = strdup(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string)) == NULL) {
1531 _error_handler(RESULT->conn, DBI_ERROR_NOMEM);
1532 newstring = oldstring;
1533 }
1534 else {
1535 /* don't free in case of an error as we'd return a dangling pointer */
1536 free(oldstring);
1537 }
1538 }
1539 break;
1540 case DBI_TYPE_BINARY:
1541 break; /* return empty string, do not raise an error */
1542 case DBI_TYPE_DATETIME:
1543 gmtime_r(&(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_datetime), &utctime);
1544 snprintf(newstring, 32, "%04d-%02d-%02d %02d:%02d:%02d", utctime.tm_year+1900, utctime.tm_mon+1, utctime.tm_mday, utctime.tm_hour, utctime.tm_min, utctime.tm_sec);
1545 break;
1546 default:
1547 _error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
1548 }
1549
1550 return newstring; /* is still empty string in case of an error */
1551 }
1552
1553
1554 /* RESULT: bind_* functions */
1555
_setup_binding(dbi_result_t * result,const char * fieldname,void * bindto,void * helperfunc)1556 static int _setup_binding(dbi_result_t *result, const char *fieldname, void *bindto, void *helperfunc) {
1557 _field_binding_t *binding;
1558 if (!result) {
1559 _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR);
1560 return DBI_BIND_ERROR;
1561 }
1562
1563 _reset_conn_error(result->conn);
1564
1565 if (!fieldname) {
1566 _error_handler(result->conn, DBI_ERROR_BADNAME);
1567 return DBI_BIND_ERROR;
1568 }
1569 binding = _find_or_create_binding_node(result, fieldname);
1570 if (!binding) {
1571 _error_handler(result->conn, DBI_ERROR_NOMEM);
1572 return DBI_BIND_ERROR;
1573 }
1574
1575 if (bindto == NULL) {
1576 _remove_binding_node(result, binding);
1577 }
1578 else {
1579 binding->bindto = bindto;
1580 binding->helper_function = (void*)(_field_binding_t *)helperfunc;
1581 }
1582
1583 return 0;
1584 }
1585
_activate_bindings(dbi_result_t * result)1586 static void _activate_bindings(dbi_result_t *result) {
1587 _field_binding_t *binding = result->field_bindings;
1588 void (*helper_function)(_field_binding_t *);
1589
1590 while (binding) {
1591 helper_function = binding->helper_function;
1592 helper_function(binding);
1593 binding = binding->next;
1594 }
1595 return;
1596 }
1597
dbi_result_bind_char(dbi_result Result,const char * fieldname,char * bindto)1598 int dbi_result_bind_char(dbi_result Result, const char *fieldname, char *bindto) {
1599 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_char);
1600 }
1601
dbi_result_bind_uchar(dbi_result Result,const char * fieldname,unsigned char * bindto)1602 int dbi_result_bind_uchar(dbi_result Result, const char *fieldname, unsigned char *bindto) {
1603 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_uchar);
1604 }
1605
dbi_result_bind_short(dbi_result Result,const char * fieldname,short * bindto)1606 int dbi_result_bind_short(dbi_result Result, const char *fieldname, short *bindto) {
1607 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_short);
1608 }
1609
dbi_result_bind_ushort(dbi_result Result,const char * fieldname,unsigned short * bindto)1610 int dbi_result_bind_ushort(dbi_result Result, const char *fieldname, unsigned short *bindto) {
1611 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_ushort);
1612 }
1613
dbi_result_bind_int(dbi_result Result,const char * fieldname,int * bindto)1614 int dbi_result_bind_int(dbi_result Result, const char *fieldname, int *bindto) {
1615 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_int);
1616 }
1617
dbi_result_bind_long(dbi_result Result,const char * fieldname,int * bindto)1618 int dbi_result_bind_long(dbi_result Result, const char *fieldname, int *bindto) {
1619 return dbi_result_bind_int(Result, fieldname, bindto);
1620 }
1621
dbi_result_bind_uint(dbi_result Result,const char * fieldname,unsigned int * bindto)1622 int dbi_result_bind_uint(dbi_result Result, const char *fieldname, unsigned int *bindto) {
1623 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_uint);
1624 }
1625
dbi_result_bind_ulong(dbi_result Result,const char * fieldname,unsigned int * bindto)1626 int dbi_result_bind_ulong(dbi_result Result, const char *fieldname, unsigned int *bindto) {
1627 return dbi_result_bind_uint(Result, fieldname, bindto);
1628 }
1629
dbi_result_bind_longlong(dbi_result Result,const char * fieldname,long long * bindto)1630 int dbi_result_bind_longlong(dbi_result Result, const char *fieldname, long long *bindto) {
1631 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_longlong);
1632 }
1633
dbi_result_bind_ulonglong(dbi_result Result,const char * fieldname,unsigned long long * bindto)1634 int dbi_result_bind_ulonglong(dbi_result Result, const char *fieldname, unsigned long long *bindto) {
1635 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_ulonglong);
1636 }
1637
dbi_result_bind_float(dbi_result Result,const char * fieldname,float * bindto)1638 int dbi_result_bind_float(dbi_result Result, const char *fieldname, float *bindto) {
1639 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_float);
1640 }
1641
dbi_result_bind_double(dbi_result Result,const char * fieldname,double * bindto)1642 int dbi_result_bind_double(dbi_result Result, const char *fieldname, double *bindto) {
1643 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_double);
1644 }
1645
dbi_result_bind_string(dbi_result Result,const char * fieldname,const char ** bindto)1646 int dbi_result_bind_string(dbi_result Result, const char *fieldname, const char **bindto) {
1647 return _setup_binding(RESULT, fieldname, (char **)bindto, _bind_helper_string);
1648 }
1649
dbi_result_bind_binary(dbi_result Result,const char * fieldname,const unsigned char ** bindto)1650 int dbi_result_bind_binary(dbi_result Result, const char *fieldname, const unsigned char **bindto) {
1651 return _setup_binding(RESULT, fieldname, (unsigned char **)bindto, _bind_helper_binary);
1652 }
1653
dbi_result_bind_string_copy(dbi_result Result,const char * fieldname,char ** bindto)1654 int dbi_result_bind_string_copy(dbi_result Result, const char *fieldname, char **bindto) {
1655 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_string_copy);
1656 }
1657
dbi_result_bind_binary_copy(dbi_result Result,const char * fieldname,unsigned char ** bindto)1658 int dbi_result_bind_binary_copy(dbi_result Result, const char *fieldname, unsigned char **bindto) {
1659 return _setup_binding(RESULT, fieldname, bindto, _bind_helper_binary_copy);
1660 }
1661
dbi_result_bind_datetime(dbi_result Result,const char * fieldname,time_t * bindto)1662 int dbi_result_bind_datetime(dbi_result Result, const char *fieldname, time_t *bindto) {
1663 return _setup_binding(RESULT, fieldname, (time_t *)bindto, _bind_helper_datetime);
1664 }
1665
_find_or_create_binding_node(dbi_result_t * result,const char * fieldname)1666 static _field_binding_t *_find_or_create_binding_node(dbi_result_t *result, const char *fieldname) {
1667 _field_binding_t *prevbinding = NULL;
1668 _field_binding_t *binding = result->field_bindings;
1669
1670 while (binding && strcasecmp(fieldname, binding->fieldname)) {
1671 prevbinding = binding;
1672 binding = binding->next;
1673 }
1674 if (!binding) {
1675 /* allocate a new option node */
1676 binding = malloc(sizeof(_field_binding_t));
1677 if (!binding) {
1678 return NULL;
1679 }
1680 binding->result = result;
1681 binding->fieldname = strdup(fieldname);
1682 binding->next = NULL;
1683 if (result->field_bindings == NULL) {
1684 result->field_bindings = binding;
1685 }
1686 else {
1687 prevbinding->next = binding;
1688 }
1689 }
1690
1691 return binding;
1692 }
1693
_remove_binding_node(dbi_result_t * result,_field_binding_t * deadbinding)1694 static void _remove_binding_node(dbi_result_t *result, _field_binding_t *deadbinding) {
1695 _field_binding_t *prevbinding = NULL;
1696 _field_binding_t *binding = result->field_bindings;
1697
1698 while (binding && (binding != deadbinding)) {
1699 prevbinding = binding;
1700 binding = binding->next;
1701 }
1702 if (!binding) {
1703 /* this should never ever happen. silently pretend it never did. */
1704 return;
1705 }
1706 free((char *)deadbinding->fieldname);
1707 if (result->field_bindings == deadbinding) {
1708 result->field_bindings = deadbinding->next;
1709 }
1710 else {
1711 prevbinding->next = deadbinding->next;
1712 }
1713 free(deadbinding);
1714 }
1715
1716 /* returns the field index (>= 1), or 0 if no such field */
_find_field(dbi_result_t * result,const char * fieldname,dbi_error_flag * errflag)1717 static unsigned int _find_field(dbi_result_t *result, const char *fieldname, dbi_error_flag *errflag) {
1718 unsigned long i = 0;
1719 if (!result || !result->field_names) return DBI_FIELD_ERROR;
1720 while (i < result->numfields) {
1721 if (strcasecmp(result->field_names[i], fieldname) == 0) {
1722 *errflag = DBI_ERROR_NONE;
1723 return i;
1724 }
1725 i++;
1726 }
1727 _verbose_handler(result->conn, "result row has no field `%s`\n", fieldname);
1728 *errflag = DBI_ERROR_BADNAME;
1729 return 0;
1730 }
1731
_is_row_fetched(dbi_result_t * result,unsigned long long row)1732 static int _is_row_fetched(dbi_result_t *result, unsigned long long row) {
1733 /* Bull patch reported by Tom Lane */
1734 /* if (!result->rows || (row >= result->numrows_matched)) return -1; */
1735 if (!result->rows || (row > result->numrows_matched)) return -1;
1736 return !(result->rows[row] == NULL);
1737 }
1738
1739
1740 /* PRIVATE: bind helpers */
1741
_bind_helper_char(_field_binding_t * binding)1742 static void _bind_helper_char(_field_binding_t *binding) {
1743 *(char *)binding->bindto = dbi_result_get_char((dbi_result)binding->result, binding->fieldname);
1744 }
1745
_bind_helper_uchar(_field_binding_t * binding)1746 static void _bind_helper_uchar(_field_binding_t *binding) {
1747 *(unsigned char *)binding->bindto = dbi_result_get_uchar((dbi_result)binding->result, binding->fieldname);
1748 }
1749
_bind_helper_short(_field_binding_t * binding)1750 static void _bind_helper_short(_field_binding_t *binding) {
1751 *(short *)binding->bindto = dbi_result_get_short((dbi_result)binding->result, binding->fieldname);
1752 }
1753
_bind_helper_ushort(_field_binding_t * binding)1754 static void _bind_helper_ushort(_field_binding_t *binding) {
1755 *(unsigned short *)binding->bindto = dbi_result_get_ushort((dbi_result)binding->result, binding->fieldname);
1756 }
1757
_bind_helper_int(_field_binding_t * binding)1758 static void _bind_helper_int(_field_binding_t *binding) {
1759 *(int *)binding->bindto = dbi_result_get_int((dbi_result)binding->result, binding->fieldname);
1760 }
1761
_bind_helper_uint(_field_binding_t * binding)1762 static void _bind_helper_uint(_field_binding_t *binding) {
1763 *(unsigned int *)binding->bindto = dbi_result_get_uint((dbi_result)binding->result, binding->fieldname);
1764 }
1765
_bind_helper_longlong(_field_binding_t * binding)1766 static void _bind_helper_longlong(_field_binding_t *binding) {
1767 *(long long *)binding->bindto = dbi_result_get_longlong((dbi_result)binding->result, binding->fieldname);
1768 }
1769
_bind_helper_ulonglong(_field_binding_t * binding)1770 static void _bind_helper_ulonglong(_field_binding_t *binding) {
1771 *(unsigned long long *)binding->bindto = dbi_result_get_ulonglong((dbi_result)binding->result, binding->fieldname);
1772 }
1773
_bind_helper_float(_field_binding_t * binding)1774 static void _bind_helper_float(_field_binding_t *binding) {
1775 *(float *)binding->bindto = dbi_result_get_float((dbi_result)binding->result, binding->fieldname);
1776 }
1777
_bind_helper_double(_field_binding_t * binding)1778 static void _bind_helper_double(_field_binding_t *binding) {
1779 *(double *)binding->bindto = dbi_result_get_double((dbi_result)binding->result, binding->fieldname);
1780 }
1781
_bind_helper_string(_field_binding_t * binding)1782 static void _bind_helper_string(_field_binding_t *binding) {
1783 *(const char **)binding->bindto = dbi_result_get_string((dbi_result)binding->result, binding->fieldname);
1784 }
1785
_bind_helper_binary(_field_binding_t * binding)1786 static void _bind_helper_binary(_field_binding_t *binding) {
1787 *(const unsigned char **)binding->bindto = dbi_result_get_binary((dbi_result)binding->result, binding->fieldname);
1788 }
1789
_bind_helper_string_copy(_field_binding_t * binding)1790 static void _bind_helper_string_copy(_field_binding_t *binding) {
1791 *(char **)binding->bindto = dbi_result_get_string_copy((dbi_result)binding->result, binding->fieldname);
1792 }
1793
_bind_helper_binary_copy(_field_binding_t * binding)1794 static void _bind_helper_binary_copy(_field_binding_t *binding) {
1795 *(unsigned char **)binding->bindto = dbi_result_get_binary_copy((dbi_result)binding->result, binding->fieldname);
1796 }
1797
_bind_helper_datetime(_field_binding_t * binding)1798 static void _bind_helper_datetime(_field_binding_t *binding) {
1799 *(time_t *)binding->bindto = dbi_result_get_datetime((dbi_result)binding->result, binding->fieldname);
1800 }
1801
1802