rendered paste body/* * libdbi - database independent abstraction layer for C. * Copyright (C) 2001-2003, David Parker and Mark Tobenkin. * http://libdbi.sourceforge.net * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: dbi_result.c,v 1.47 2008/01/23 16:37:36 mhoenicka Exp $ * * (anything that has to do with row seeking or fetching fields goes in this file) */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <unistd.h>#include <math.h>#include <limits.h>#include <dbi/dbi.h>#include <dbi/dbi-dev.h>#ifdef __MINGW32__#define strtok_r(s1,s2,s3) strtok(s1,s2)#endif// cast the opaque parameter to our struct pointer#define RESULT ((dbi_result_t*)Result)/* declarations for internal functions -- anything declared as static won't be accessible by name from client programs */static _field_binding_t *_find_or_create_binding_node(dbi_result_t *result, const char *fieldname);static void _remove_binding_node(dbi_result_t *result, _field_binding_t *deadbinding);static unsigned int _find_field(dbi_result_t *result, const char *fieldname, dbi_error_flag* errflag);static int _is_row_fetched(dbi_result_t *result, unsigned long long row);static int _setup_binding(dbi_result_t *result, const char *fieldname, void *bindto, void *helperfunc);static void _activate_bindings(dbi_result_t *result);static unsigned int _parse_field_formatstr(const char *format, char ***tokens_dest, char ***fieldnames_dest);static void _free_string_list(char **ptrs, int total);static void _free_result_rows(dbi_result_t *result);int _disjoin_from_conn(dbi_result_t *result);static void _bind_helper_char(_field_binding_t *binding);static void _bind_helper_uchar(_field_binding_t *binding);static void _bind_helper_short(_field_binding_t *binding);static void _bind_helper_ushort(_field_binding_t *binding);static void _bind_helper_int(_field_binding_t *binding);static void _bind_helper_uint(_field_binding_t *binding);static void _bind_helper_longlong(_field_binding_t *binding);static void _bind_helper_ulonglong(_field_binding_t *binding);static void _bind_helper_float(_field_binding_t *binding);static void _bind_helper_double(_field_binding_t *binding);static void _bind_helper_string(_field_binding_t *binding);static void _bind_helper_binary(_field_binding_t *binding);static void _bind_helper_string_copy(_field_binding_t *binding);static void _bind_helper_binary_copy(_field_binding_t *binding);static void _bind_helper_datetime(_field_binding_t *binding);/* XXX ROW SEEKING AND FETCHING XXX *//* returns 1 if ok, 0 on error */int dbi_result_seek_row(dbi_result Result, unsigned long long rowidx) { int retval; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return 0; } _reset_conn_error(RESULT->conn); if (RESULT->result_state == NOTHING_RETURNED || rowidx <= 0 || rowidx > RESULT->numrows_matched) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return 0; } if (_is_row_fetched(RESULT, rowidx) == 1) { /* jump right to it */ RESULT->currowidx = rowidx; _activate_bindings(RESULT); return 1; } /* row is one-based for the user, but zero-based to the dbd conn */ retval = RESULT->conn->driver->functions->goto_row(RESULT, rowidx-1); if (retval == -1) { _error_handler(RESULT->conn, DBI_ERROR_DBD); return 0; } retval = RESULT->conn->driver->functions->fetch_row(RESULT, rowidx-1); if (retval == 0) { _error_handler(RESULT->conn, DBI_ERROR_DBD); return 0; } RESULT->currowidx = rowidx; _activate_bindings(RESULT); return retval;}int dbi_result_first_row(dbi_result Result) { return dbi_result_seek_row(Result, 1);}int dbi_result_last_row(dbi_result Result) { return dbi_result_seek_row(Result, dbi_result_get_numrows(Result));}int dbi_result_has_prev_row(dbi_result Result) { if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return 0; } _reset_conn_error(RESULT->conn); return RESULT->result_state != NOTHING_RETURNED && RESULT->currowidx > 1;}int dbi_result_prev_row(dbi_result Result) { if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return 0; } _reset_conn_error(RESULT->conn); if (!dbi_result_has_prev_row(Result)) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return 0; } return dbi_result_seek_row(Result, RESULT->currowidx-1);}int dbi_result_has_next_row(dbi_result Result) { if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return 0; } _reset_conn_error(RESULT->conn); return RESULT->result_state != NOTHING_RETURNED && RESULT->currowidx < dbi_result_get_numrows(Result);}int dbi_result_next_row(dbi_result Result) { if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return 0; } _reset_conn_error(RESULT->conn); if (!dbi_result_has_next_row(Result)) {/* _error_handler(RESULT->conn, DBI_ERROR_BADIDX); */ return 0; } return dbi_result_seek_row(Result, RESULT->currowidx+1);}unsigned long long dbi_result_get_currow(dbi_result Result) { if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return 0; } _reset_conn_error(RESULT->conn); return RESULT->currowidx;}unsigned long long dbi_result_get_numrows(dbi_result Result) { if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_ROW_ERROR; } _reset_conn_error(RESULT->conn); return RESULT->numrows_matched;}unsigned long long dbi_result_get_numrows_affected(dbi_result Result) { if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_ROW_ERROR; } _reset_conn_error(RESULT->conn); return RESULT->numrows_affected;}/* returns the length of the string or binary, excluding a trailing \0 */size_t dbi_result_get_field_length(dbi_result Result, const char *fieldname) { unsigned int fieldidx = 0; dbi_error_flag errflag; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_LENGTH_ERROR; } _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { _error_handler(RESULT->conn, errflag); return DBI_LENGTH_ERROR; } return dbi_result_get_field_length_idx(Result, fieldidx+1);}size_t dbi_result_get_field_length_idx(dbi_result Result, unsigned int fieldidx) { unsigned long long currowidx; /* user-visible indexes start at 1 */ fieldidx--; if (!RESULT || !RESULT->rows) { _error_handler(RESULT ? RESULT->conn : NULL, DBI_ERROR_BADPTR); return DBI_LENGTH_ERROR; } _reset_conn_error(RESULT->conn); currowidx = RESULT->currowidx; if (!RESULT->rows[currowidx] || !RESULT->rows[currowidx]->field_sizes) { _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT); return DBI_LENGTH_ERROR; } if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return DBI_LENGTH_ERROR; } return RESULT->rows[currowidx]->field_sizes[fieldidx];}/* the "field_size" functions are merely kept to support legacy code. Their purpose was, er, unclear, their implementations were, er, broke, and the name "field_length" is more appropriate to what these functions do anyway. Support for the "field_size" functions is likely to be dropped in the next release */size_t dbi_result_get_field_size(dbi_result Result, const char *fieldname) { return dbi_result_get_field_length(Result, fieldname);}size_t dbi_result_get_field_size_idx(dbi_result Result, unsigned int fieldidx) { return dbi_result_get_field_length_idx(Result, fieldidx);}unsigned int dbi_result_get_field_idx(dbi_result Result, const char *fieldname) { unsigned int fieldidx = 0; dbi_error_flag errflag; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return 0; } _reset_conn_error(RESULT->conn); /* user-visible indexes start at 1 */ fieldidx = _find_field(RESULT, fieldname, &errflag)+1; if (errflag != DBI_ERROR_NONE) { _error_handler(RESULT->conn, errflag); return 0; } return fieldidx;}const char *dbi_result_get_field_name(dbi_result Result, unsigned int fieldidx) { if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return NULL; } _reset_conn_error(RESULT->conn); if (fieldidx > RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return NULL; } else if (RESULT->field_names == NULL) { _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT); return NULL; } return (const char *) RESULT->field_names[fieldidx-1];}unsigned int dbi_result_get_numfields(dbi_result Result) { if (!RESULT) return DBI_FIELD_ERROR; _reset_conn_error(RESULT->conn); return RESULT->numfields;}unsigned short dbi_result_get_field_type(dbi_result Result, const char *fieldname) { unsigned int fieldidx = 0; dbi_error_flag errflag; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_TYPE_ERROR; } _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { _error_handler(RESULT->conn, errflag); return DBI_TYPE_ERROR; } return dbi_result_get_field_type_idx(Result, fieldidx+1);}unsigned short dbi_result_get_field_type_idx(dbi_result Result, unsigned int fieldidx) { fieldidx--; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_TYPE_ERROR; } _reset_conn_error(RESULT->conn); if (!RESULT->field_types) { _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT); return DBI_TYPE_ERROR; } else if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return DBI_TYPE_ERROR; } return RESULT->field_types[fieldidx];}unsigned int dbi_result_get_field_attrib(dbi_result Result, const char *fieldname, unsigned int attribmin, unsigned int attribmax) { unsigned int fieldidx = 0; dbi_error_flag errflag; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_ATTRIBUTE_ERROR; } _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { _error_handler(RESULT->conn, errflag); return DBI_ATTRIBUTE_ERROR; } return dbi_result_get_field_attrib_idx(Result, fieldidx+1, attribmin, attribmax);}unsigned int dbi_result_get_field_attrib_idx(dbi_result Result, unsigned int fieldidx, unsigned int attribmin, unsigned int attribmax) { fieldidx--; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_ATTRIBUTE_ERROR; } _reset_conn_error(RESULT->conn); if (!RESULT->field_attribs) { _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT); return DBI_ATTRIBUTE_ERROR; } else if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return DBI_ATTRIBUTE_ERROR; } return _isolate_attrib(RESULT->field_attribs[fieldidx], attribmin, attribmax);}unsigned int dbi_result_get_field_attribs(dbi_result Result, const char *fieldname) { unsigned int fieldidx = 0; dbi_error_flag errflag; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_ATTRIBUTE_ERROR; } _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { _error_handler(RESULT->conn, errflag); return DBI_ATTRIBUTE_ERROR; } return dbi_result_get_field_attribs_idx(Result, fieldidx+1);}unsigned int dbi_result_get_field_attribs_idx(dbi_result Result, unsigned int fieldidx) { fieldidx--; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_ATTRIBUTE_ERROR; } _reset_conn_error(RESULT->conn); if (!RESULT->field_attribs) { _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT); return DBI_ATTRIBUTE_ERROR; } else if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return DBI_ATTRIBUTE_ERROR; } return RESULT->field_attribs[fieldidx];}void _set_field_flag(dbi_row_t *row, unsigned int fieldidx, unsigned char flag, unsigned char value) { unsigned char *flags = &row->field_flags[fieldidx]; if (value) *flags |= flag; // if value = 1, set the flag else *flags &= ~flag; // set that bit to 0}int _get_field_flag(dbi_row_t *row, unsigned int fieldidx, unsigned char flag) { return (row->field_flags[fieldidx] & flag) != 0;}int dbi_result_field_is_null(dbi_result Result, const char *fieldname) { unsigned int fieldidx = 0; dbi_error_flag errflag; if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_FIELD_FLAG_ERROR; } _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { _error_handler(RESULT->conn, errflag); return DBI_FIELD_FLAG_ERROR; } return dbi_result_field_is_null_idx(Result, fieldidx+1);}int dbi_result_field_is_null_idx(dbi_result Result, unsigned int fieldidx) { unsigned long long currowidx; fieldidx--; if (!RESULT || !RESULT->rows) { _error_handler(RESULT ? RESULT->conn : NULL, DBI_ERROR_BADPTR); return DBI_FIELD_FLAG_ERROR; } _reset_conn_error(RESULT->conn); currowidx = RESULT->currowidx; if (!RESULT->rows[currowidx] || !RESULT->rows[currowidx]->field_flags) { _error_handler(RESULT->conn, DBI_ERROR_BADOBJECT); return DBI_FIELD_FLAG_ERROR; } if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return DBI_FIELD_FLAG_ERROR; } return _get_field_flag(RESULT->rows[currowidx], fieldidx, DBI_VALUE_NULL);}int _disjoin_from_conn(dbi_result_t *result) { /* todo: is int enough? */ int idx; int found = -1; int retval; retval = result->conn->driver->functions->free_query(result); for (idx = 0; idx < result->conn->results_used; idx++) { if (found < 0) { /* keep looking */ if (result->conn->results[idx] == result) { found = idx; result->conn->results[idx] = NULL; } } else { /* already found, shift remaining elements back one */ result->conn->results[idx-1] = result->conn->results[idx]; } } if (found >= 0) { result->conn->results[result->conn->results_used-1] = NULL; result->conn->results_used--; } result->conn = NULL; return retval;}int dbi_result_disjoin(dbi_result Result) { return RESULT ? _disjoin_from_conn(RESULT) : -1;}int dbi_result_free(dbi_result Result) { int retval = 0; if (!RESULT) return -1; if (RESULT->conn) { retval = _disjoin_from_conn(RESULT); } _reset_conn_error(RESULT->conn); while (RESULT->field_bindings) { _remove_binding_node(RESULT, RESULT->field_bindings); } if (RESULT->rows) { _free_result_rows(RESULT); } if (RESULT->numfields) { _free_string_list(RESULT->field_names, RESULT->numfields); free(RESULT->field_types); free(RESULT->field_attribs); } if (retval == -1) { _error_handler(RESULT->conn, DBI_ERROR_DBD); } free(RESULT); return retval;}dbi_conn dbi_result_get_conn(dbi_result Result) { if (!RESULT) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return NULL; } return RESULT->conn;}/* RESULT: mass retrieval functions */static unsigned int _parse_field_formatstr(const char *format, char ***tokens_dest, char ***fieldnames_dest) { unsigned int found = 0; unsigned int cur = 0; char **tokens = NULL; char **fieldnames = NULL; char *chunk; char *fieldtype; char *fieldname; char *temp1; char *temp2; char *line = strdup(format); temp1 = line; while (temp1 && (temp1 = strchr(temp1, '.')) != NULL) { temp1++; found++; } tokens = calloc(found, sizeof(char *)); fieldnames = calloc(found, sizeof(char *)); if (!tokens || !fieldnames) return DBI_FIELD_ERROR; chunk = strtok_r(line, " ", &temp1); do { temp2 = strchr(chunk, '.'); if (!temp2) continue; fieldname = chunk; *temp2 = '\0'; fieldtype = (temp2+2); /* ignore the % */ tokens[cur] = strdup(fieldtype); fieldnames[cur] = strdup(fieldname); cur++; } while ((chunk = strtok_r(NULL, " ", &temp1))); *tokens_dest = tokens; *fieldnames_dest = fieldnames; free(line); return found;}static void _free_string_list(char **ptrs, int total) { int i; if (ptrs == NULL) return; for (i = 0; i < total; ++i) if (ptrs[i]) free(ptrs[i]); free(ptrs); return;}static void _free_result_rows(dbi_result_t *result) { unsigned long long rowidx = 0; unsigned int fieldidx = 0; for (rowidx = 0; rowidx <= result->numrows_matched; rowidx++) { if (!result->rows[rowidx]) continue; for (fieldidx = 0; fieldidx < result->numfields; fieldidx++) { if ((result->field_types[fieldidx] == DBI_TYPE_STRING || result->field_types[fieldidx] == DBI_TYPE_BINARY) && result->rows[rowidx]->field_values[fieldidx].d_string) { free(result->rows[rowidx]->field_values[fieldidx].d_string); } } free(result->rows[rowidx]->field_values); free(result->rows[rowidx]->field_sizes); free(result->rows[rowidx]->field_flags); free(result->rows[rowidx]); } free(result->rows);}unsigned int dbi_result_get_fields(dbi_result Result, const char *format, ...) { char **tokens, **fieldnames; unsigned int curidx = 0, numtokens = 0, uflag; va_list ap; if (!RESULT) return DBI_FIELD_ERROR; numtokens = _parse_field_formatstr(format, &tokens, &fieldnames); if (numtokens == DBI_FIELD_ERROR) { return numtokens; } va_start(ap, format); while (curidx < numtokens) { uflag = strlen(tokens[curidx]) > 1 && tokens[curidx][0] == 'u'; switch (tokens[curidx][strlen(tokens[curidx])-1]) { case 'c': /* char */ if (uflag) /* unsigned */ *va_arg(ap, unsigned char *) = dbi_result_get_uchar(Result, fieldnames[curidx]); else *va_arg(ap, char *) = dbi_result_get_char(Result, fieldnames[curidx]); break; case 'h': /* sHort ("S"tring was taken) */ if (uflag) /* unsigned */ *va_arg(ap, unsigned short *) = dbi_result_get_ushort(Result, fieldnames[curidx]); else *va_arg(ap, short *) = dbi_result_get_short(Result, fieldnames[curidx]); break; case 'l': /* 4-byte integer (both l and i work) */ case 'i': if (uflag) /* unsigned */ *va_arg(ap, unsigned int *) = dbi_result_get_uint(Result, fieldnames[curidx]); else *va_arg(ap, int *) = dbi_result_get_int(Result, fieldnames[curidx]); break; case 'L': /* long long */ if (uflag) /* unsigned */ *va_arg(ap, unsigned long long *) = dbi_result_get_ulonglong(Result, fieldnames[curidx]); else *va_arg(ap, long long *) = dbi_result_get_longlong(Result, fieldnames[curidx]); break; case 'f': /* float */ *va_arg(ap, float *) = dbi_result_get_float(Result, fieldnames[curidx]); break; case 'd': /* double */ *va_arg(ap, double *) = dbi_result_get_double(Result, fieldnames[curidx]); break; case 's': /* string */ *va_arg(ap, const char **) = dbi_result_get_string(Result, fieldnames[curidx]); break; case 'b': /* binary */ *va_arg(ap, const unsigned char **) = dbi_result_get_binary(Result, fieldnames[curidx]); break; case 'S': /* string copy */ *va_arg(ap, char **) = dbi_result_get_string_copy(Result, fieldnames[curidx]); break; case 'B': /* binary copy */ *va_arg(ap, unsigned char **) = dbi_result_get_binary_copy(Result, fieldnames[curidx]); break; case 'm': /* datetiMe (what... you have any better ideas?? */ *va_arg(ap, time_t *) = dbi_result_get_datetime(Result, fieldnames[curidx]); break; } curidx++; } va_end(ap); _free_string_list(tokens, numtokens); _free_string_list(fieldnames, numtokens); return numtokens;}unsigned int dbi_result_bind_fields(dbi_result Result, const char *format, ...) { char **tokens, **fieldnames; unsigned int curidx = 0, numtokens = 0, uflag; va_list ap; if (!RESULT) return DBI_FIELD_ERROR; numtokens = _parse_field_formatstr(format, &tokens, &fieldnames); if (numtokens == DBI_FIELD_ERROR) { return numtokens; } va_start(ap, format); while (curidx < numtokens) { uflag = strlen(tokens[curidx]) > 1 && tokens[curidx][0] == 'u'; switch (tokens[curidx][strlen(tokens[curidx])-1]) { case 'c': /* char */ if (uflag) /* unsigned */ dbi_result_bind_uchar(Result, fieldnames[curidx], va_arg(ap, unsigned char *)); else dbi_result_bind_char(Result, fieldnames[curidx], va_arg(ap, char *)); break; case 'h': /* sHort ("S"tring was taken) */ if (uflag) /* unsigned */ dbi_result_bind_ushort(Result, fieldnames[curidx], va_arg(ap, unsigned short *)); else dbi_result_bind_short(Result, fieldnames[curidx], va_arg(ap, short *)); break; case 'l': /* 4-byte integer (both l and i work) */ case 'i': if (uflag) /* unsigned */ dbi_result_bind_uint(Result, fieldnames[curidx], va_arg(ap, unsigned int *)); else dbi_result_bind_int(Result, fieldnames[curidx], va_arg(ap, int *)); break; case 'L': /* long long */ if (uflag) /* unsigned */ dbi_result_bind_ulonglong(Result, fieldnames[curidx], va_arg(ap, unsigned long long *)); else dbi_result_bind_longlong(Result, fieldnames[curidx], va_arg(ap, long long *)); break; case 'f': /* float */ dbi_result_bind_float(Result, fieldnames[curidx], va_arg(ap, float *)); break; case 'd': /* double */ dbi_result_bind_double(Result, fieldnames[curidx], va_arg(ap, double *)); break; case 's': /* string */ dbi_result_bind_string(Result, fieldnames[curidx], va_arg(ap, const char **)); break; case 'b': /* binary */ dbi_result_bind_binary(Result, fieldnames[curidx], va_arg(ap, const unsigned char **)); break; case 'S': /* string copy */ dbi_result_bind_string_copy(Result, fieldnames[curidx], va_arg(ap, char **)); break; case 'B': /* binary copy */ dbi_result_bind_binary_copy(Result, fieldnames[curidx], va_arg(ap, unsigned char **)); break; case 'm': /* datetiMe (what... you have any better ideas?? */ dbi_result_bind_datetime(Result, fieldnames[curidx], va_arg(ap, time_t *)); break; } curidx++; } va_end(ap); _free_string_list(tokens, numtokens); _free_string_list(fieldnames, numtokens); return numtokens;}/* RESULT: get_* functions */signed char dbi_result_get_char(dbi_result Result, const char *fieldname) { signed char ERROR = 0; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, errflag); return ERROR; } return dbi_result_get_char_idx(Result, fieldidx+1);}signed char dbi_result_get_char_idx(dbi_result Result, unsigned int fieldidx) { signed char ERROR = 0; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return ERROR; } if (RESULT->field_types[fieldidx] != DBI_TYPE_INTEGER) { _verbose_handler(RESULT->conn, "%s: field `%s` is not integer type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; } switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) { case DBI_INTEGER_SIZE1: return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_char; case DBI_INTEGER_SIZE2: case DBI_INTEGER_SIZE3: case DBI_INTEGER_SIZE4: case DBI_INTEGER_SIZE8: _verbose_handler(RESULT->conn, "%s: field `%s` is more than 1 byte wide\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); default: _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; }}short dbi_result_get_short(dbi_result Result, const char *fieldname) { short ERROR = 0; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return ERROR; } return dbi_result_get_short_idx(Result, fieldidx+1);}short dbi_result_get_short_idx(dbi_result Result, unsigned int fieldidx) { short ERROR = 0; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return ERROR; } if (RESULT->field_types[fieldidx] != DBI_TYPE_INTEGER) { _verbose_handler(RESULT->conn, "%s: field `%s` is not integer type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; } switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) { case DBI_INTEGER_SIZE1: case DBI_INTEGER_SIZE2: return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_short; case DBI_INTEGER_SIZE3: case DBI_INTEGER_SIZE4: case DBI_INTEGER_SIZE8: _verbose_handler(RESULT->conn, "%s: field `%s` is more than 2 bytes wide\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); default: _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; }}int dbi_result_get_long(dbi_result Result, const char *fieldname) { return dbi_result_get_int(Result, fieldname);}int dbi_result_get_int(dbi_result Result, const char *fieldname) { long ERROR = 0; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return ERROR; } return dbi_result_get_int_idx(Result, fieldidx+1);}int dbi_result_get_long_idx(dbi_result Result, unsigned int fieldidx) { return dbi_result_get_int_idx(Result, fieldidx);}int dbi_result_get_int_idx(dbi_result Result, unsigned int fieldidx) { long ERROR = 0; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return ERROR; } if (RESULT->field_types[fieldidx] != DBI_TYPE_INTEGER) { _verbose_handler(RESULT->conn, "%s: field `%s` is not integer type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; } switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) { case DBI_INTEGER_SIZE1: case DBI_INTEGER_SIZE2: case DBI_INTEGER_SIZE3: case DBI_INTEGER_SIZE4: return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_long; case DBI_INTEGER_SIZE8: _verbose_handler(RESULT->conn, "%s: field `%s` is more than 4 bytes wide\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); default: _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; }}long long dbi_result_get_longlong(dbi_result Result, const char *fieldname) { long long ERROR = 0; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return ERROR; } return dbi_result_get_longlong_idx(Result, fieldidx+1);}long long dbi_result_get_longlong_idx(dbi_result Result, unsigned int fieldidx) { long long ERROR = 0; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return ERROR; } if (RESULT->field_types[fieldidx] != DBI_TYPE_INTEGER) { _verbose_handler(RESULT->conn, "%s: field `%s` is not integer type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; } switch (RESULT->field_attribs[fieldidx] & DBI_INTEGER_SIZEMASK) { case DBI_INTEGER_SIZE1: case DBI_INTEGER_SIZE2: case DBI_INTEGER_SIZE3: case DBI_INTEGER_SIZE4: case DBI_INTEGER_SIZE8: return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_longlong; default: _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; }}unsigned char dbi_result_get_uchar(dbi_result Result, const char *fieldname) { return (unsigned char)dbi_result_get_char(Result, fieldname);}unsigned char dbi_result_get_uchar_idx(dbi_result Result, unsigned int fieldidx) { return (unsigned char)dbi_result_get_char_idx(Result, fieldidx);}unsigned short dbi_result_get_ushort(dbi_result Result, const char *fieldname) { return (unsigned short)dbi_result_get_short(Result, fieldname);}unsigned short dbi_result_get_ushort_idx(dbi_result Result, unsigned int fieldidx) { return (unsigned short)dbi_result_get_short_idx(Result, fieldidx);}unsigned int dbi_result_get_uint(dbi_result Result, const char *fieldname) { return (unsigned int)dbi_result_get_int(Result, fieldname);}unsigned int dbi_result_get_ulong(dbi_result Result, const char *fieldname) { return dbi_result_get_uint(Result, fieldname);}unsigned int dbi_result_get_uint_idx(dbi_result Result, unsigned int fieldidx) { return (unsigned int)dbi_result_get_int_idx(Result, fieldidx);}unsigned int dbi_result_get_ulong_idx(dbi_result Result, unsigned int fieldidx) { return dbi_result_get_uint_idx(Result, fieldidx);}unsigned long long dbi_result_get_ulonglong(dbi_result Result, const char *fieldname) { return (unsigned long long)dbi_result_get_longlong(Result, fieldname);}unsigned long long dbi_result_get_ulonglong_idx(dbi_result Result, unsigned int fieldidx) { return (unsigned long long)dbi_result_get_longlong_idx(Result, fieldidx);}float dbi_result_get_float(dbi_result Result, const char *fieldname) { float ERROR = 0.0; dbi_error_flag errflag; unsigned int fieldidx; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return ERROR; } return dbi_result_get_float_idx(Result, fieldidx+1);}float dbi_result_get_float_idx(dbi_result Result, unsigned int fieldidx) { float ERROR = 0.0; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return ERROR; } if (RESULT->field_types[fieldidx] != DBI_TYPE_DECIMAL) { _verbose_handler(RESULT->conn, "%s: field `%s` is not float type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; } switch (RESULT->field_attribs[fieldidx] & DBI_DECIMAL_SIZEMASK) { case DBI_DECIMAL_SIZE4: return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_float; case DBI_DECIMAL_SIZE8: _verbose_handler(RESULT->conn, "%s: field `%s` is double, not float\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); default: _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; }}double dbi_result_get_double(dbi_result Result, const char *fieldname) { double ERROR = 0.0; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return ERROR; } return dbi_result_get_double_idx(Result, fieldidx+1);} double dbi_result_get_double_idx(dbi_result Result, unsigned int fieldidx) { double ERROR = 0.0; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return ERROR; } if (RESULT->field_types[fieldidx] != DBI_TYPE_DECIMAL) { _verbose_handler(RESULT->conn, "%s: field `%s` is not double type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; } switch (RESULT->field_attribs[fieldidx] & DBI_DECIMAL_SIZEMASK) { case DBI_DECIMAL_SIZE4: case DBI_DECIMAL_SIZE8: return RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_double; default: _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; }}const char *dbi_result_get_string(dbi_result Result, const char *fieldname) { const char *ERROR = "ERROR"; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return ERROR; } return dbi_result_get_string_idx(Result, fieldidx+1);} const char *dbi_result_get_string_idx(dbi_result Result, unsigned int fieldidx) { const char *ERROR = "ERROR"; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return ERROR; } if (RESULT->field_types[fieldidx] != DBI_TYPE_STRING) { dbi_conn_t *conn = RESULT->conn; _verbose_handler(conn, "%s: field `%s` is not string type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(conn, DBI_ERROR_BADTYPE); return ERROR; } if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0 && _get_field_flag(RESULT->rows[RESULT->currowidx], fieldidx, DBI_VALUE_NULL)) { /* string does not exist */ return NULL; } /* else if field size == 0: empty string */ return (const char *)(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string);}const unsigned char *dbi_result_get_binary(dbi_result Result, const char *fieldname) { const char *ERROR = "ERROR"; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return (const unsigned char*)ERROR; } return dbi_result_get_binary_idx(Result, fieldidx+1);} const unsigned char *dbi_result_get_binary_idx(dbi_result Result, unsigned int fieldidx) { const char *ERROR = "ERROR"; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return (const unsigned char*)ERROR; } if (RESULT->field_types[fieldidx] != DBI_TYPE_BINARY) { _verbose_handler(RESULT->conn, "%s: field `%s` is not binary type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return (const unsigned char*)ERROR; } if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0) return NULL; return (const unsigned char *)(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string);}char *dbi_result_get_string_copy(dbi_result Result, const char *fieldname) { char *ERROR = "ERROR"; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return strdup(ERROR); } return dbi_result_get_string_copy_idx(Result, fieldidx+1);} char *dbi_result_get_string_copy_idx(dbi_result Result, unsigned int fieldidx) { char *ERROR = "ERROR"; char *newstring = NULL; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return strdup(ERROR); } if (RESULT->field_types[fieldidx] != DBI_TYPE_STRING) { _verbose_handler(RESULT->conn, "%s: field `%s` is not string type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return strdup(ERROR); } if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0 && RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string == NULL) { // mysql returns 0 for the field size of an empty string, so size==0 // doesn't necessarily mean NULL return NULL; } newstring = strdup(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string); if (newstring) { return newstring; } else { _error_handler(RESULT->conn, DBI_ERROR_NOMEM); return strdup(ERROR); }}unsigned char *dbi_result_get_binary_copy(dbi_result Result, const char *fieldname) { char *ERROR = "ERROR"; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return (unsigned char *)strdup(ERROR); } return dbi_result_get_binary_copy_idx(Result, fieldidx+1);} unsigned char *dbi_result_get_binary_copy_idx(dbi_result Result, unsigned int fieldidx) { char *ERROR = "ERROR"; unsigned char *newblob = NULL; unsigned long long size; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return (unsigned char *)strdup(ERROR); } if (RESULT->field_types[fieldidx] != DBI_TYPE_BINARY) { _verbose_handler(RESULT->conn, "%s: field `%s` is not binary type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return (unsigned char *)strdup(ERROR); } if (RESULT->rows[RESULT->currowidx]->field_sizes[fieldidx] == 0) return NULL; /* API function must use 1-based index */ size = dbi_result_get_field_length_idx(Result, fieldidx+1); newblob = malloc(size); if (!newblob) { _error_handler(RESULT->conn, DBI_ERROR_NOMEM); return (unsigned char *)strdup(ERROR); } memcpy(newblob, RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_string, size); return newblob;}time_t dbi_result_get_datetime(dbi_result Result, const char *fieldname) { time_t ERROR = 0; unsigned int fieldidx; dbi_error_flag errflag; _reset_conn_error(RESULT->conn); fieldidx = _find_field(RESULT, fieldname, &errflag); if (errflag != DBI_ERROR_NONE) { dbi_conn_t *conn = RESULT->conn; _error_handler(conn, DBI_ERROR_BADNAME); return ERROR; } return dbi_result_get_datetime_idx(Result, fieldidx+1);} time_t dbi_result_get_datetime_idx(dbi_result Result, unsigned int fieldidx) { time_t ERROR = 0; fieldidx--; _reset_conn_error(RESULT->conn); if (fieldidx >= RESULT->numfields) { _error_handler(RESULT->conn, DBI_ERROR_BADIDX); return ERROR; } if (RESULT->field_types[fieldidx] != DBI_TYPE_DATETIME) { _verbose_handler(RESULT->conn, "%s: field `%s` is not datetime type\n", __func__, dbi_result_get_field_name(Result, fieldidx+1)); _error_handler(RESULT->conn, DBI_ERROR_BADTYPE); return ERROR; } return (time_t)(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_datetime);}/* RESULT: bind_* functions */static int _setup_binding(dbi_result_t *result, const char *fieldname, void *bindto, void *helperfunc) { _field_binding_t *binding; if (!result) { _error_handler(/*RESULT->conn*/ NULL, DBI_ERROR_BADPTR); return DBI_BIND_ERROR; } _reset_conn_error(result->conn); if (!fieldname) { _error_handler(result->conn, DBI_ERROR_BADNAME); return DBI_BIND_ERROR; } binding = _find_or_create_binding_node(result, fieldname); if (!binding) { _error_handler(result->conn, DBI_ERROR_NOMEM); return DBI_BIND_ERROR; } if (bindto == NULL) { _remove_binding_node(result, binding); } else { binding->bindto = bindto; binding->helper_function = (void*)(_field_binding_t *)helperfunc; } return 0;}static void _activate_bindings(dbi_result_t *result) { _field_binding_t *binding = result->field_bindings; void (*helper_function)(_field_binding_t *); while (binding) { helper_function = binding->helper_function; helper_function(binding); binding = binding->next; } return;}int dbi_result_bind_char(dbi_result Result, const char *fieldname, char *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_char);}int dbi_result_bind_uchar(dbi_result Result, const char *fieldname, unsigned char *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_uchar);}int dbi_result_bind_short(dbi_result Result, const char *fieldname, short *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_short);}int dbi_result_bind_ushort(dbi_result Result, const char *fieldname, unsigned short *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_ushort);}int dbi_result_bind_int(dbi_result Result, const char *fieldname, int *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_int);}int dbi_result_bind_long(dbi_result Result, const char *fieldname, int *bindto) { return dbi_result_bind_int(Result, fieldname, bindto);}int dbi_result_bind_uint(dbi_result Result, const char *fieldname, unsigned int *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_uint);}int dbi_result_bind_ulong(dbi_result Result, const char *fieldname, unsigned int *bindto) { return dbi_result_bind_uint(Result, fieldname, bindto);}int dbi_result_bind_longlong(dbi_result Result, const char *fieldname, long long *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_longlong);}int dbi_result_bind_ulonglong(dbi_result Result, const char *fieldname, unsigned long long *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_ulonglong);}int dbi_result_bind_float(dbi_result Result, const char *fieldname, float *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_float);}int dbi_result_bind_double(dbi_result Result, const char *fieldname, double *bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_double);}int dbi_result_bind_string(dbi_result Result, const char *fieldname, const char **bindto) { return _setup_binding(RESULT, fieldname, (char **)bindto, _bind_helper_string);}int dbi_result_bind_binary(dbi_result Result, const char *fieldname, const unsigned char **bindto) { return _setup_binding(RESULT, fieldname, (unsigned char **)bindto, _bind_helper_binary);}int dbi_result_bind_string_copy(dbi_result Result, const char *fieldname, char **bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_string_copy);}int dbi_result_bind_binary_copy(dbi_result Result, const char *fieldname, unsigned char **bindto) { return _setup_binding(RESULT, fieldname, bindto, _bind_helper_binary_copy);}int dbi_result_bind_datetime(dbi_result Result, const char *fieldname, time_t *bindto) { return _setup_binding(RESULT, fieldname, (time_t *)bindto, _bind_helper_datetime);}static _field_binding_t *_find_or_create_binding_node(dbi_result_t *result, const char *fieldname) { _field_binding_t *prevbinding = NULL; _field_binding_t *binding = result->field_bindings; while (binding && strcasecmp(fieldname, binding->fieldname)) { prevbinding = binding; binding = binding->next; } if (!binding) { /* allocate a new option node */ binding = malloc(sizeof(_field_binding_t)); if (!binding) { return NULL; } binding->result = result; binding->fieldname = strdup(fieldname); binding->next = NULL; if (result->field_bindings == NULL) { result->field_bindings = binding; } else { prevbinding->next = binding; } } return binding;}static void _remove_binding_node(dbi_result_t *result, _field_binding_t *deadbinding) { _field_binding_t *prevbinding = NULL; _field_binding_t *binding = result->field_bindings; while (binding && (binding != deadbinding)) { prevbinding = binding; binding = binding->next; } if (!binding) { /* this should never ever happen. silently pretend it never did. */ return; } free((char *)deadbinding->fieldname); if (result->field_bindings == deadbinding) { result->field_bindings = deadbinding->next; } else { prevbinding->next = deadbinding->next; } free(deadbinding);}/* returns the field index (>= 1), or 0 if no such field */static unsigned int _find_field(dbi_result_t *result, const char *fieldname, dbi_error_flag *errflag) { unsigned long i = 0; if (!result || !result->field_names) return DBI_FIELD_ERROR; while (i < result->numfields) { if (strcasecmp(result->field_names[i], fieldname) == 0) { *errflag = DBI_ERROR_NONE; return i; } i++; } _verbose_handler(result->conn, "result row has no field `%s`\n", fieldname); *errflag = DBI_ERROR_BADNAME; return 0;}static int _is_row_fetched(dbi_result_t *result, unsigned long long row) { if (!result->rows || (row >= result->numrows_matched)) return -1; return !(result->rows[row] == NULL);}/* PRIVATE: bind helpers */static void _bind_helper_char(_field_binding_t *binding) { *(char *)binding->bindto = dbi_result_get_char((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_uchar(_field_binding_t *binding) { *(unsigned char *)binding->bindto = dbi_result_get_uchar((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_short(_field_binding_t *binding) { *(short *)binding->bindto = dbi_result_get_short((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_ushort(_field_binding_t *binding) { *(unsigned short *)binding->bindto = dbi_result_get_ushort((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_int(_field_binding_t *binding) { *(int *)binding->bindto = dbi_result_get_int((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_uint(_field_binding_t *binding) { *(unsigned int *)binding->bindto = dbi_result_get_uint((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_longlong(_field_binding_t *binding) { *(long long *)binding->bindto = dbi_result_get_longlong((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_ulonglong(_field_binding_t *binding) { *(unsigned long long *)binding->bindto = dbi_result_get_ulonglong((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_float(_field_binding_t *binding) { *(float *)binding->bindto = dbi_result_get_float((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_double(_field_binding_t *binding) { *(double *)binding->bindto = dbi_result_get_double((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_string(_field_binding_t *binding) { *(const char **)binding->bindto = dbi_result_get_string((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_binary(_field_binding_t *binding) { *(const unsigned char **)binding->bindto = dbi_result_get_binary((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_string_copy(_field_binding_t *binding) { *(char **)binding->bindto = dbi_result_get_string_copy((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_binary_copy(_field_binding_t *binding) { *(unsigned char **)binding->bindto = dbi_result_get_binary_copy((dbi_result)binding->result, binding->fieldname);}static void _bind_helper_datetime(_field_binding_t *binding) { *(time_t *)binding->bindto = dbi_result_get_datetime((dbi_result)binding->result, binding->fieldname);}