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; }
/** Users discovered a bug in some distributions of libdbi, where if * it is compiled on certain versions of gcc with the -ffast-math * compiler option it fails to correctly handle saving of 64-bit * values. This function tests for the problem. * @param: conn: The just-opened dbi_conn * @returns: GNC_DBI_PASS if the dbi library is safe to use, * GNC_DBI_FAIL_SETUP if the test could not be completed, or * GNC_DBI_FAIL_TEST if the bug was found. */ static GncDbiTestResult dbi_library_test (dbi_conn conn) { int64_t testlonglong = -9223372036854775807LL, resultlonglong = 0; uint64_t testulonglong = 9223372036854775807LLU, resultulonglong = 0; double testdouble = 1.7976921348623157E+307, resultdouble = 0.0; dbi_result result; GncDbiTestResult retval = GNC_DBI_PASS; result = dbi_conn_query (conn, "CREATE TEMPORARY TABLE numtest " "( test_int BIGINT, test_unsigned BIGINT," " test_double FLOAT8 )"); if (result == nullptr) { PWARN ("Test_DBI_Library: Create table failed"); return GNC_DBI_FAIL_SETUP; } dbi_result_free (result); std::stringstream querystr; querystr << "INSERT INTO numtest VALUES (" << testlonglong << ", " << testulonglong << ", " << std::setprecision(12) << testdouble << ")"; auto query = querystr.str(); result = dbi_conn_query (conn, query.c_str()); if (result == nullptr) { PWARN ("Test_DBI_Library: Failed to insert test row into table"); return GNC_DBI_FAIL_SETUP; } dbi_result_free (result); gnc_push_locale (LC_NUMERIC, "C"); result = dbi_conn_query (conn, "SELECT * FROM numtest"); if (result == nullptr) { const char* errmsg; dbi_conn_error (conn, &errmsg); PWARN ("Test_DBI_Library: Failed to retrieve test row into table: %s", errmsg); dbi_conn_query (conn, "DROP TABLE numtest"); gnc_pop_locale (LC_NUMERIC); return GNC_DBI_FAIL_SETUP; } while (dbi_result_next_row (result)) { resultlonglong = dbi_result_get_longlong (result, "test_int"); resultulonglong = dbi_result_get_ulonglong (result, "test_unsigned"); resultdouble = dbi_result_get_double (result, "test_double"); } gnc_pop_locale (LC_NUMERIC); if (testlonglong != resultlonglong) { PWARN ("Test_DBI_Library: LongLong Failed %" PRId64 " != % " PRId64, testlonglong, resultlonglong); retval = GNC_DBI_FAIL_TEST; } if (testulonglong != resultulonglong) { PWARN ("Test_DBI_Library: Unsigned longlong Failed %" PRIu64 " != %" PRIu64, testulonglong, resultulonglong); retval = GNC_DBI_FAIL_TEST; } /* A bug in libdbi stores only 7 digits of precision */ if (testdouble >= resultdouble + 0.000001e307 || testdouble <= resultdouble - 0.000001e307) { PWARN ("Test_DBI_Library: Double Failed %17e != %17e", testdouble, resultdouble); retval = GNC_DBI_FAIL_TEST; } return retval; }
static void _bind_helper_double(_field_binding_t *binding) { *(double *)binding->bindto = dbi_result_get_double((dbi_result)binding->result, binding->fieldname); }