r23177 - gnucash/branches/2.4/src/backend - [r23174]Bug #674862 - 2038 bug in libdbi

John Ralls jralls at code.gnucash.org
Thu Sep 19 12:32:26 EDT 2013


Author: jralls
Date: 2013-09-19 12:32:25 -0400 (Thu, 19 Sep 2013)
New Revision: 23177
Trac: http://svn.gnucash.org/trac/changeset/23177

Modified:
   gnucash/branches/2.4/src/backend/dbi/gnc-backend-dbi.c
   gnucash/branches/2.4/src/backend/sql/gnc-backend-sql.c
Log:
[r23174]Bug #674862 - 2038 bug in libdbi

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

NB: In Gnucash 2.4 there are plenty of other 2038 bugs due to reliance
on the libc time functions. This has been corrected in trunk.

Modified: gnucash/branches/2.4/src/backend/dbi/gnc-backend-dbi.c
===================================================================
--- gnucash/branches/2.4/src/backend/dbi/gnc-backend-dbi.c	2013-09-18 10:13:14 UTC (rev 23176)
+++ gnucash/branches/2.4/src/backend/dbi/gnc-backend-dbi.c	2013-09-19 16:32:25 UTC (rev 23177)
@@ -66,6 +66,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"
 
@@ -2007,8 +2010,6 @@
     gushort type;
     guint attrs;
     GValue* value;
-    time_t time;
-    struct tm tm_struct;
 
     type = dbi_result_get_field_type( dbi_row->result, col_name );
     attrs = dbi_result_get_field_attribs( dbi_row->result, col_name );
@@ -2048,26 +2049,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)
-	  {
-	    (void)gmtime_r( &time, &tm_struct );
-	    (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 ) );
-	  }
 	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;
+	    gint64 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/branches/2.4/src/backend/sql/gnc-backend-sql.c
===================================================================
--- gnucash/branches/2.4/src/backend/sql/gnc-backend-sql.c	2013-09-18 10:13:14 UTC (rev 23176)
+++ gnucash/branches/2.4/src/backend/sql/gnc-backend-sql.c	2013-09-19 16:32:25 UTC (rev 23177)
@@ -1951,8 +1951,13 @@
     }
     else
     {
-        if ( G_VALUE_HOLDS_STRING( val ) )
+        if ( G_VALUE_HOLDS_INT64( val ) )
         {
+	    ts.tv_sec = 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 )
             {
@@ -1968,7 +1973,6 @@
                 g_free( buf );
                 isOK = TRUE;
             }
-
         }
         else
         {
@@ -2060,7 +2064,6 @@
            const GncSqlColumnTableEntry* table_row )
 {
     const GValue* val;
-    GDate* date;
 
     g_return_if_fail( be != NULL );
     g_return_if_fail( row != NULL );
@@ -2071,11 +2074,28 @@
     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))
+	{
+	    Timespec ts = {0, 0};
+	    GDate date;
+	    ts.tv_sec = g_value_get_int64 (val);
+	    date = timespec_to_gdate (ts);
+
+	    if ( table_row->gobj_param_name != NULL )
+	    {
+		g_object_set( pObject, table_row->gobj_param_name,
+			      &date, NULL );
+	    }
+	    else
+	    {
+		(*setter)( pObject, &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