예제 #1
0
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;
}
예제 #2
0
/** 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;
}
예제 #3
0
static void _bind_helper_double(_field_binding_t *binding) {
  *(double *)binding->bindto = dbi_result_get_double((dbi_result)binding->result, binding->fieldname);
}