AUDIT: r23174 - gnucash/trunk/src/backend - Bug 674862 - 2038 bug in libdbi

John Ralls jralls at code.gnucash.org
Tue Sep 17 19:26:11 EDT 2013


Author: jralls
Date: 2013-09-17 19:26:10 -0400 (Tue, 17 Sep 2013)
New Revision: 23174
Trac: http://svn.gnucash.org/trac/changeset/23174

Modified:
   gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c
   gnucash/trunk/src/backend/sql/gnc-backend-sql.c
Log:
Bug 674862 - 2038 bug in libdbi

Retrieve the numerical value directly from the dbi_result and use
it to create the Timespec or GDate.
BP

Modified: gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c
===================================================================
--- gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c	2013-09-17 23:25:43 UTC (rev 23173)
+++ gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c	2013-09-17 23:26:10 UTC (rev 23174)
@@ -65,6 +65,9 @@
 #define GETPID() getpid()
 #endif
 
+/* For direct access to dbi data structs, sadly needed for datetime */
+#include <dbi/dbi-dev.h>
+
 #define GNC_HOST_NAME_MAX 255
 #define TRANSACTION_NAME "trans"
 
@@ -2008,7 +2011,6 @@
     gushort type;
     guint attrs;
     GValue* value;
-    time64 time;
 
     type = dbi_result_get_field_type( dbi_row->result, col_name );
     attrs = dbi_result_get_field_attribs( dbi_row->result, col_name );
@@ -2048,27 +2050,20 @@
         {
             return NULL;
         }
-	time = dbi_result_get_datetime( dbi_row->result, col_name );
-	/* Protect gmtime from time values < 0 to work around a mingw
-	   bug that fills struct_tm with garbage values which in turn
-	   creates a string that GDate can't parse. */
-	if (time >= 0)
-	  {
-            struct tm *tm_struct = gnc_gmtime (&time);
-            (void)g_value_init (value, G_TYPE_STRING);
-            g_value_take_string (value,
-                                 g_strdup_printf ("%d%02d%02d%02d%02d%02d",
-                                                  1900 + tm_struct->tm_year,
-						  tm_struct->tm_mon + 1,
-						  tm_struct->tm_mday,
-                                                  tm_struct->tm_hour,
-						  tm_struct->tm_min,
-						  tm_struct->tm_sec));
-	    gnc_tm_free (tm_struct);
-	  }
 	else
-	  g_value_take_string (value, "19691231235959");
-
+	{
+	    /* A seriously evil hack to work around libdbi bug #15
+	     * https://sourceforge.net/p/libdbi/bugs/15/. When libdbi
+	     * v0.9 is widely available this can be replaced with
+	     * dbi_result_get_as_longlong.
+	     */
+	    dbi_result_t *result = (dbi_result_t*)(dbi_row->result);
+	    guint64 row = dbi_result_get_currow (result);
+	    guint idx = dbi_result_get_field_idx (result, col_name) - 1;
+	    time64 time = result->rows[row]->field_values[idx].d_datetime;
+	    (void)g_value_init( value, G_TYPE_INT64 );
+	    g_value_set_int64 (value, time);
+	}
         break;
     default:
         PERR( "Field %s: unknown DBI_TYPE: %d\n", col_name, type );

Modified: gnucash/trunk/src/backend/sql/gnc-backend-sql.c
===================================================================
--- gnucash/trunk/src/backend/sql/gnc-backend-sql.c	2013-09-17 23:25:43 UTC (rev 23173)
+++ gnucash/trunk/src/backend/sql/gnc-backend-sql.c	2013-09-17 23:26:10 UTC (rev 23174)
@@ -1938,8 +1938,13 @@
     }
     else
     {
-        if ( G_VALUE_HOLDS_STRING( val ) )
+        if ( G_VALUE_HOLDS_INT64( val ) )
         {
+	    timespecFromTime64 (&ts, (time64)(g_value_get_int64 (val)));
+	    isOK = TRUE;
+	}
+	else if (G_VALUE_HOLDS_STRING (val))
+	{
             const gchar* s = g_value_get_string( val );
             if ( s != NULL )
             {
@@ -1955,7 +1960,6 @@
                 g_free( buf );
                 isOK = TRUE;
             }
-
         }
         else
         {
@@ -2047,7 +2051,6 @@
            const GncSqlColumnTableEntry* table_row )
 {
     const GValue* val;
-    GDate* date;
 
     g_return_if_fail( be != NULL );
     g_return_if_fail( row != NULL );
@@ -2058,11 +2061,30 @@
     val = gnc_sql_row_get_value_at_col_name( row, table_row->col_name );
     if ( val != NULL )
     {
-        if ( G_VALUE_HOLDS_STRING( val ) )
+	if (G_VALUE_HOLDS_INT64 (val))
+	{
+	    gint64 time = g_value_get_int64 (val);
+	    GDateTime *gdt = g_date_time_new_from_unix_utc (time);
+	    gint day, month, year;
+	    GDate *date;
+	    g_date_time_get_ymd (gdt, &year, &month, &day);
+	    date = g_date_new_dmy (day, month, year);
+	    g_date_time_unref (gdt);
+	    if ( table_row->gobj_param_name != NULL )
+	    {
+		g_object_set( pObject, table_row->gobj_param_name, date, NULL );
+	    }
+	    else
+	    {
+		(*setter)( pObject, date );
+	    }
+	    g_date_free( date );
+	}
+        else if ( G_VALUE_HOLDS_STRING( val ) )
         {
             // Format of date is YYYYMMDD
             const gchar* s = g_value_get_string( val );
-
+	    GDate *date;
             if ( s != NULL )
             {
                 gchar buf[5];



More information about the gnucash-changes mailing list