gnucash maint: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Sun Nov 19 14:42:28 EST 2017


Updated	 via  https://github.com/Gnucash/gnucash/commit/af1bc450 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/23f25d74 (commit)
	from  https://github.com/Gnucash/gnucash/commit/ff76db28 (commit)



commit af1bc45021aaa9c844a9e204ead402f155835e36
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Nov 19 09:36:44 2017 -0800

    A better way to handle MySQL's 0000-00-00 invalid date indicator.

diff --git a/src/backend/sql/gnc-backend-sql.c b/src/backend/sql/gnc-backend-sql.c
index e9dfc75..7d169d1 100644
--- a/src/backend/sql/gnc-backend-sql.c
+++ b/src/backend/sql/gnc-backend-sql.c
@@ -30,6 +30,7 @@
 #include "config.h"
 
 #include <errno.h>
+#include <stdint.h>
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
@@ -1904,27 +1905,43 @@ load_timespec( const GncSqlBackend* be, GncSqlRow* row,
     }
     else
     {
+        /* MySQL's TIMESTAMP type is not compliant with the SQL
+         * standard in that it is valid only from 1970-01-01 00:00:01
+         * to 2038-01-15 23:59:59. Times outside that range are set to
+         * "0000-00-00 00:00:00"; depending on the libdbi version we
+         * may get either the string value or the time64 representing
+         * it. In either case leave the timespec at 0.
+         */
         if ( G_VALUE_HOLDS_INT64( val ) )
         {
-	    timespecFromTime64 (&ts, (time64)(g_value_get_int64 (val)));
-	    isOK = TRUE;
+            const time64 MINTIME = INT64_C(-62135596800);
+            const time64 MAXTIME = INT64_C(253402300799);
+            const time64 t = (time64)(g_value_get_int64 (val));
+            if (t >= MINTIME && t <= MAXTIME)
+            {
+                timespecFromTime64 (&ts, t);
+            }
+            isOK = TRUE;
 	}
 	else if (G_VALUE_HOLDS_STRING (val))
 	{
             const gchar* s = g_value_get_string( val );
             if ( s != NULL )
             {
-                gchar* buf;
-                buf = g_strdup_printf( "%c%c%c%c-%c%c-%c%c %c%c:%c%c:%c%c",
-                                       s[0], s[1], s[2], s[3],
-                                       s[4], s[5],
-                                       s[6], s[7],
-                                       s[8], s[9],
-                                       s[10], s[11],
-                                       s[12], s[13] );
-                ts = gnc_iso8601_to_timespec_gmt( buf );
-                g_free( buf );
-                isOK = TRUE;
+                 if (! g_str_has_prefix (s, "0000-00-00"))
+                 {
+                      gchar* buf;
+                      buf = g_strdup_printf( "%c%c%c%c-%c%c-%c%c %c%c:%c%c:%c%c",
+                                             s[0], s[1], s[2], s[3],
+                                             s[4], s[5],
+                                             s[6], s[7],
+                                             s[8], s[9],
+                                             s[10], s[11],
+                                             s[12], s[13] );
+                      ts = gnc_iso8601_to_timespec_gmt( buf );
+                      g_free( buf );
+                 }
+                 isOK = TRUE;
             }
         }
         else
diff --git a/src/libqof/qof/gnc-date.c b/src/libqof/qof/gnc-date.c
index 3af9be9..1c652de 100644
--- a/src/libqof/qof/gnc-date.c
+++ b/src/libqof/qof/gnc-date.c
@@ -73,17 +73,6 @@
 #  define GNC_T_FMT "%r"
 #endif
 
-/* t < MINTIME is probably from a bad conversion from t 0 to
- * 0000-00-00, so restore it to the Unix Epoch. t anywhere near
- * MAXTIME is obviously an error, but we don't want to crash with a
- * bad date-time so just clamp it to MAXTIME.
- */
-static inline time64
-clamp_time(time64 t)
-{
-    return  t < MINTIME ? 0 : t > MAXTIME ? MAXTIME : t;
-}
-
 const char *gnc_default_strftime_date_format =
 #ifdef G_OS_WIN32
     /* The default date format for use with strftime in Win32. */
@@ -152,7 +141,7 @@ GDateTime*
 gnc_g_date_time_new_from_unix_local (time64 time)
 {
     GTimeZone *tz = gnc_g_time_zone_new_local ();
-    GDateTime *gdt = g_date_time_new_from_unix_utc (clamp_time (time));
+    GDateTime *gdt = g_date_time_new_from_unix_utc (time);
     if (gdt)
 	gdt = gnc_g_date_time_adjust_for_dst (gdt, tz);
     return gdt;
@@ -260,7 +249,7 @@ struct tm*
 gnc_localtime_r (const time64 *secs, struct tm* time)
 {
      guint index = 0;
-     GDateTime *gdt = gnc_g_date_time_new_from_unix_local (clamp_time (*secs));
+     GDateTime *gdt = gnc_g_date_time_new_from_unix_local (*secs);
      g_return_val_if_fail (gdt != NULL, NULL);
 
      gnc_g_date_time_fill_struct_tm (gdt, time);
@@ -282,7 +271,7 @@ struct tm*
 gnc_gmtime (const time64 *secs)
 {
      struct tm *time;
-     GDateTime *gdt = g_date_time_new_from_unix_utc (clamp_time (*secs));
+     GDateTime *gdt = g_date_time_new_from_unix_utc (*secs);
      g_return_val_if_fail (gdt != NULL, NULL);
      time = g_slice_alloc0 (sizeof (struct tm));
      gnc_g_date_time_fill_struct_tm (gdt, time);
@@ -400,10 +389,10 @@ gnc_timegm (struct tm* time)
 gchar*
 gnc_ctime (const time64 *secs)
 {
-    GDateTime *gdt = gnc_g_date_time_new_from_unix_local (clamp_time (*secs));
-    gchar *string = g_date_time_format (gdt, "%a %b %e %H:%M:%S %Y");
-    g_date_time_unref (gdt);
-    return string;
+     GDateTime *gdt = gnc_g_date_time_new_from_unix_local (*secs);
+     gchar *string = g_date_time_format (gdt, "%a %b %e %H:%M:%S %Y");
+     g_date_time_unref (gdt);
+     return string;
 }
 
 time64
@@ -898,7 +887,7 @@ size_t
 qof_print_date_buff (char * buff, size_t len, time64 t)
 {
     struct tm theTime;
-    time64 bt = clamp_time (t);
+    time64 bt = t;
     size_t actual;
     if (!buff) return 0 ;
     if (!gnc_localtime_r(&bt, &theTime))
@@ -1646,7 +1635,7 @@ gnc_timezone (const struct tm *tm)
 void
 timespecFromTime64 ( Timespec *ts, time64 t )
 {
-    ts->tv_sec = clamp_time (t);
+    ts->tv_sec = t;
     ts->tv_nsec = 0;
 }
 
diff --git a/src/libqof/qof/gnc-date.h b/src/libqof/qof/gnc-date.h
index ad5bcf0..acdbe65 100644
--- a/src/libqof/qof/gnc-date.h
+++ b/src/libqof/qof/gnc-date.h
@@ -70,7 +70,7 @@
 
 #include <glib-object.h>
 #include <time.h>
-#include <stdint.h>
+
 /**
  * Many systems, including Microsoft Windows and BSD-derived Unixes
  * like Darwin, are retaining the int-32 typedef for time_t. Since
@@ -100,8 +100,7 @@ extern const char *gnc_default_strftime_date_format;
 
 /** The maximum length of a string created by the date printers */
 #define MAX_DATE_LENGTH 34
-#define MAXTIME INT64_C(253402300799)
-#define MINTIME INT64_C(-62135596800)
+
 /** Constants *******************************************************/
 /** \brief UTC date format string.
 
diff --git a/src/libqof/qof/test/test-gnc-date.c b/src/libqof/qof/test/test-gnc-date.c
index c54d2f0..acd48f9 100644
--- a/src/libqof/qof/test/test-gnc-date.c
+++ b/src/libqof/qof/test/test-gnc-date.c
@@ -58,17 +58,6 @@ typedef struct
 static _GncDateTime gncdt;
 extern void _gnc_date_time_init (_GncDateTime *);
 
-/* t < MINTIME is probably from a bad conversion from t 0 to
- * 0000-00-00, so restore it to the Unix Epoch. t anywhere near
- * MAXTIME is obviously an error, but we don't want to crash with a
- * bad date-time so just clamp it to MAXTIME.
- */
-static inline time64
-clamp_time(time64 t)
-{
-    return  t < MINTIME ? 0 : t > MAXTIME ? MAXTIME : t;
-}
-
 /* gnc_localtime just creates a tm on the heap and calls
  * gnc_localtime_r with it, so this suffices to test both.
  */
@@ -81,6 +70,18 @@ test_gnc_localtime (void)
                       // difference between g_date_time and tm->tm_wday)
                      };
     guint ind;
+#if defined(__clang__) && __clang_major__ < 6
+#define _func "struct tm *gnc_localtime_r(const time64 *, struct tm *)"
+#else
+#define _func "gnc_localtime_r"
+#endif
+    gchar *msg = _func ": assertion " _Q "gdt != NULL' failed";
+#undef _func
+    gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
+    gchar *logdomain = "qof";
+    TestErrorStruct check = {loglevel, logdomain, msg, 0};
+    GLogFunc hdlr = g_log_set_default_handler ((GLogFunc)test_null_handler, &check);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check);
 
     for (ind = 0; ind < G_N_ELEMENTS (secs); ind++)
     {
@@ -111,6 +112,8 @@ test_gnc_localtime (void)
         g_date_time_unref (gdt);
         gnc_tm_free (time);
     }
+    g_assert_cmpint (check.hits, ==, 1);
+    g_log_set_default_handler (hdlr, NULL);
 }
 
 static void
@@ -126,23 +129,35 @@ test_gnc_gmtime (void)
         { 48, 51, 23, 18, 11, 69, 4, 352, 0, 0, NULL },
         { 41, 12, 0, 6, 0, 70, 2, 6, 0, 0, NULL },
         { 32, 30, 2, 3, 11, 92, 4, 338, 0, 0, NULL },
-        { 59, 59, 23, 31, 11, 8099, 5, 365, 0, 0, NULL },
+        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL },
         { 6, 47, 16, 7, 3, 107, 6, 97, 0, 0, NULL },
 #else
         { 6, 41, 2, 24, 9, -1301, 4, 297, 0 },
         { 48, 51, 23, 18, 11, 69, 4, 352, 0 },
         { 41, 12, 0, 6, 0, 70, 2, 6, 0 },
         { 32, 30, 2, 3, 11, 92, 4, 338, 0 },
-        { 59, 50, 23, 31, 11, 8099, 5, 365, 0 },
+        { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
         { 6, 47, 16, 7, 3, 107, 6, 97, 0 },
 #endif
     };
     guint ind;
+#if defined(__clang__) && __clang_major__ < 6
+#define _func "struct tm *gnc_gmtime(const time64 *)"
+#else
+#define _func "gnc_gmtime"
+#endif
+    gchar *msg = _func ": assertion " _Q "gdt != NULL' failed";
+#undef _func
+    gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
+    gchar *logdomain = "qof";
+    TestErrorStruct check = {loglevel, logdomain, msg, 0};
+    GLogFunc hdlr = g_log_set_default_handler ((GLogFunc)test_null_handler, &check);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check);
 
     for (ind = 0; ind < G_N_ELEMENTS (secs); ind++)
     {
         struct tm* time = gnc_gmtime (&secs[ind]);
-        GDateTime *gdt = g_date_time_new_from_unix_utc (clamp_time (secs[ind]));
+        GDateTime *gdt = g_date_time_new_from_unix_utc (secs[ind]);
         if (gdt == NULL)
         {
             g_assert (time == NULL);
@@ -163,6 +178,8 @@ test_gnc_gmtime (void)
         g_date_time_unref (gdt);
         gnc_tm_free (time);
     }
+    g_assert_cmpint (check.hits, ==, 1);
+    g_log_set_default_handler (hdlr, NULL);
 }
 
 static void
@@ -2020,23 +2037,14 @@ gnc_timezone (const struct tm *tm)// C: 5 in 2  Local: 2:0:0
 test_gnc_timezone (void)
 {
 }*/
-/* timespecFromTime64
+/* timespecFromtime64
 void
-timespecFromTime64( Timespec *ts, time64 t )// C: 22 in 11  Local: 0:0:0
+timespecFromtime64( Timespec *ts, time64 t )// C: 22 in 11  Local: 0:0:0
 */
-static void
-test_timespecFromTime64 (void)
-{
-     Timespec ts = {-9999, 0};
-     timespecFromTime64 (&ts, MINTIME - 1);
-     g_assert_cmpint (0, ==, ts.tv_sec);
-     timespecFromTime64 (&ts, MINTIME + 1);
-     g_assert_cmpint (MINTIME + 1, ==, ts.tv_sec);
-     timespecFromTime64 (&ts, MAXTIME + 1);
-     g_assert_cmpint (MAXTIME, ==, ts.tv_sec);
-     timespecFromTime64 (&ts, MAXTIME - 1);
-     g_assert_cmpint (MAXTIME - 1, ==, ts.tv_sec);
-}
+/* static void
+test_timespecFromtime64 (void)
+{
+}*/
 /* timespec_now
 Timespec
 timespec_now()// C: 2 in 2  Local: 0:0:0
@@ -2466,7 +2474,7 @@ test_suite_gnc_date (void)
     GNC_TEST_ADD_FUNC (suitename, "gnc dmy2timespec end", test_gnc_dmy2timespec_end);
     GNC_TEST_ADD_FUNC (suitename, "gnc dmy2timespec Neutral", test_gnc_dmy2timespec_neutral);
 // GNC_TEST_ADD_FUNC (suitename, "gnc timezone", test_gnc_timezone);
-    GNC_TEST_ADD_FUNC (suitename, "timespecFromTime64", test_timespecFromTime64);
+// GNC_TEST_ADD_FUNC (suitename, "timespecFromTime t", test_timespecFromtime64);
 // GNC_TEST_ADD_FUNC (suitename, "timespec now", test_timespec_now);
 // GNC_TEST_ADD_FUNC (suitename, "timespecToTime t", test_timespecTotime64);
     GNC_TEST_ADD_FUNC (suitename, "timespec to gdate", test_timespec_to_gdate);

commit 23f25d74d99c4f2b1b2371e1824fde93ef8127b4
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Nov 19 09:35:08 2017 -0800

    Don't try to unref a NULL GDateTime*.

diff --git a/src/libqof/qof/gnc-date.c b/src/libqof/qof/gnc-date.c
index d0ded97..3af9be9 100644
--- a/src/libqof/qof/gnc-date.c
+++ b/src/libqof/qof/gnc-date.c
@@ -1503,8 +1503,8 @@ gnc_iso8601_to_timespec_gmt(const char *str)
     {
 	time.tv_sec = g_date_time_to_unix (gdt);
 	time.tv_nsec = g_date_time_get_microsecond (gdt) * 1000;
+        g_date_time_unref (gdt);
     }
-    g_date_time_unref (gdt);
     return time;
 }
 



Summary of changes:
 src/backend/sql/gnc-backend-sql.c   | 43 ++++++++++++++++-------
 src/libqof/qof/gnc-date.c           | 31 ++++++-----------
 src/libqof/qof/gnc-date.h           |  5 ++-
 src/libqof/qof/test/test-gnc-date.c | 68 +++++++++++++++++++++----------------
 4 files changed, 80 insertions(+), 67 deletions(-)



More information about the gnucash-changes mailing list