r18857 - gnucash/trunk/src/business/business-core/sql - Fix parent/child relationships in billterms in case the parent hasn't been loaded yet.

Phil Longstaff plongstaff at code.gnucash.org
Sat Mar 6 11:08:08 EST 2010


Author: plongstaff
Date: 2010-03-06 11:08:08 -0500 (Sat, 06 Mar 2010)
New Revision: 18857
Trac: http://svn.gnucash.org/trac/changeset/18857

Modified:
   gnucash/trunk/src/business/business-core/sql/gnc-bill-term-sql.c
   gnucash/trunk/src/business/business-core/sql/gnc-tax-table-sql.c
Log:
Fix parent/child relationships in billterms in case the parent hasn't been loaded yet.

Remove child column from billterm table because it duplicates info in the parent column and just complicates loading objects.


Modified: gnucash/trunk/src/business/business-core/sql/gnc-bill-term-sql.c
===================================================================
--- gnucash/trunk/src/business/business-core/sql/gnc-bill-term-sql.c	2010-03-06 14:54:55 UTC (rev 18856)
+++ gnucash/trunk/src/business/business-core/sql/gnc-bill-term-sql.c	2010-03-06 16:08:08 UTC (rev 18857)
@@ -51,6 +51,9 @@
 #define MAX_TYPE_LEN 2048
 
 static void set_invisible( gpointer data, gboolean value );
+static gpointer bt_get_parent( gpointer data );
+static void bt_set_parent( gpointer data, gpointer value );
+static void bt_set_parent_guid( gpointer data, gpointer value );
 
 #define TABLE_NAME "billterms"
 #define TABLE_VERSION 2
@@ -69,13 +72,15 @@
         (QofAccessFunc)gncBillTermGetInvisible, (QofSetterFunc)set_invisible
     },
     {
-        "parent",       CT_BILLTERMREF, 0,                   0,                 NULL, NULL,
-        (QofAccessFunc)gncBillTermGetParent,    (QofSetterFunc)gncBillTermSetParent
+        "parent",       CT_GUID,       0,                   0,                 NULL, NULL,
+        (QofAccessFunc)bt_get_parent,    (QofSetterFunc)bt_set_parent
     },
+#if 0
     {
         "child",        CT_BILLTERMREF, 0,                   0,                 NULL, NULL,
         (QofAccessFunc)gncBillTermReturnChild,  (QofSetterFunc)gncBillTermSetChild
     },
+#endif
     { "type",         CT_STRING,      MAX_TYPE_LEN,        COL_NNUL,          NULL, GNC_BILLTERM_TYPE },
     { "duedays",      CT_INT,         0,                   0,                 0,    GNC_BILLTERM_DUEDAYS },
     { "discountdays", CT_INT,         0,                   0,                 0,    GNC_BILLTERM_DISCDAYS },
@@ -84,6 +89,18 @@
     { NULL }
 };
 
+static GncSqlColumnTableEntry billterm_parent_col_table[] =
+{
+    { "parent", CT_GUID, 0, 0, NULL, NULL, NULL, (QofSetterFunc)bt_set_parent_guid },
+    { NULL }
+};
+
+typedef struct {
+	/*@ dependent @*/ GncBillTerm* billterm;
+	GUID guid;
+    gboolean have_guid;
+} billterm_parent_guid_struct;
+
 static void
 set_invisible( gpointer data, gboolean value )
 {
@@ -97,8 +114,66 @@
     }
 }
 
+static /*@ null @*//*@ dependent @*/ gpointer
+bt_get_parent( gpointer pObject )
+{
+    const GncBillTerm* billterm;
+    const GncBillTerm* pParent;
+    const GUID* parent_guid;
+
+	g_return_val_if_fail( pObject != NULL, NULL );
+	g_return_val_if_fail( GNC_IS_BILLTERM(pObject), NULL );
+
+    billterm = GNC_BILLTERM(pObject);
+    pParent = gncBillTermGetParent( billterm );
+    if( pParent == NULL ) {
+        parent_guid = NULL;
+    } else {
+        parent_guid = qof_instance_get_guid( QOF_INSTANCE(pParent) );
+    }
+
+    return (gpointer)parent_guid;
+}
+
+static void
+bt_set_parent( gpointer data, gpointer value )
+{
+    GncBillTerm* billterm;
+    GncBillTerm* parent;
+    QofBook* pBook;
+    GUID* guid = (GUID*)value;
+
+    g_return_if_fail( data != NULL );
+    g_return_if_fail( GNC_IS_BILLTERM(data) );
+
+    billterm = GNC_BILLTERM(data);
+    pBook = qof_instance_get_book( QOF_INSTANCE(billterm) );
+    if ( guid != NULL )
+    {
+        parent = gncBillTermLookup( pBook, guid );
+        if( parent != NULL ) {
+            gncBillTermSetParent( billterm, parent );
+            gncBillTermSetChild( parent, billterm );
+        }
+    }
+}
+
+static void
+bt_set_parent_guid( gpointer pObject, /*@ null @*/ gpointer pValue )
+{
+	billterm_parent_guid_struct* s = (billterm_parent_guid_struct*)pObject;
+    GUID* guid = (GUID*)pValue;
+
+	g_return_if_fail( pObject != NULL );
+	g_return_if_fail( pValue != NULL );
+
+	s->guid = *guid;
+    s->have_guid = TRUE;
+}
+
 static GncBillTerm*
-load_single_billterm( GncSqlBackend* be, GncSqlRow* row )
+load_single_billterm( GncSqlBackend* be, GncSqlRow* row,
+					GList** l_billterms_needing_parents )
 {
     const GUID* guid;
     GncBillTerm* pBillTerm;
@@ -113,6 +188,28 @@
         pBillTerm = gncBillTermCreate( be->primary_book );
     }
     gnc_sql_load_object( be, row, GNC_ID_BILLTERM, pBillTerm, col_table );
+
+    /* If the billterm doesn't have a parent, it might be because it hasn't been loaded yet.
+       If so, add this billterm to the list of billterms with no parent, along with the parent
+       GUID so that after they are all loaded, the parents can be fixed up. */
+    if ( gncBillTermGetParent( pBillTerm ) == NULL )
+    {
+		billterm_parent_guid_struct* s = g_malloc( (gsize)sizeof(billterm_parent_guid_struct) );
+		g_assert( s != NULL );
+
+		s->billterm = pBillTerm;
+        s->have_guid = FALSE;
+		gnc_sql_load_object( be, row, GNC_ID_TAXTABLE, s, billterm_parent_col_table );
+        if ( s->have_guid )
+        {
+		    *l_billterms_needing_parents = g_list_prepend( *l_billterms_needing_parents, s );
+        }
+        else
+        {
+            g_free( s );
+        }
+    }
+
     qof_instance_mark_clean( QOF_INSTANCE(pBillTerm) );
 
     return pBillTerm;
@@ -136,11 +233,12 @@
     {
         GncSqlRow* row;
         GList* list = NULL;
+        GList* l_billterms_needing_parents = NULL;
 
         row = gnc_sql_result_get_first_row( result );
         while ( row != NULL )
         {
-            GncBillTerm* pBillTerm = load_single_billterm( be, row );
+            GncBillTerm* pBillTerm = load_single_billterm( be, row, &l_billterms_needing_parents );
             if ( pBillTerm != NULL )
             {
                 list = g_list_append( list, pBillTerm );
@@ -153,6 +251,28 @@
         {
             gnc_sql_slots_load_for_list( be, list );
         }
+
+		/* While there are items on the list of billterms needing parents,
+		   try to see if the parent has now been loaded.  Theory says that if
+		   items are removed from the front and added to the back if the
+		   parent is still not available, then eventually, the list will
+		   shrink to size 0. */
+		if( l_billterms_needing_parents != NULL ) {
+			gboolean progress_made = TRUE;
+            GncTaxTable* root;	
+			Account* pParent;
+			GList* elem;
+				
+			while( progress_made ) {
+				progress_made = FALSE;
+				for( elem = l_billterms_needing_parents; elem != NULL; elem = g_list_next( elem ) ) {
+					billterm_parent_guid_struct* s = (billterm_parent_guid_struct*)elem->data;
+                    bt_set_parent( s->billterm, &s->guid );
+					l_billterms_needing_parents = g_list_delete_link( l_billterms_needing_parents, elem );
+					progress_made = TRUE;
+				}
+			}
+        }
     }
 }
 

Modified: gnucash/trunk/src/business/business-core/sql/gnc-tax-table-sql.c
===================================================================
--- gnucash/trunk/src/business/business-core/sql/gnc-tax-table-sql.c	2010-03-06 14:54:55 UTC (rev 18856)
+++ gnucash/trunk/src/business/business-core/sql/gnc-tax-table-sql.c	2010-03-06 16:08:08 UTC (rev 18857)
@@ -57,9 +57,9 @@
 static gpointer get_obj_guid( gpointer pObject, const QofParam* param );
 static void set_obj_guid( gpointer pObject, gpointer pValue );
 static gpointer get_child( gpointer pObject, const QofParam* param );
-static gpointer get_parent( gpointer pObject );
-static void set_parent( gpointer pObject, gpointer pValue );
-static void set_parent_guid( gpointer pObject, gpointer pValue );
+static gpointer bt_get_parent( gpointer pObject );
+static void tt_set_parent( gpointer pObject, gpointer pValue );
+static void tt_set_parent_guid( gpointer pObject, gpointer pValue );
 
 #define MAX_NAME_LEN 50
 
@@ -77,14 +77,14 @@
     /*	{ "child",     CT_TAXTABLEREF, 0,			 0,                 NULL, NULL,
     			get_child, (QofSetterFunc)gncTaxTableSetChild }, */
     { "parent",    CT_GUID,        0,			 0,                 NULL, NULL,
-                (QofAccessFunc)get_parent, set_parent
+                (QofAccessFunc)bt_get_parent, tt_set_parent
     },
     { NULL }
 };
 
 static GncSqlColumnTableEntry tt_parent_col_table[] =
 {
-    { "parent", CT_GUID, 0, 0, NULL, NULL, NULL, set_parent_guid },
+    { "parent", CT_GUID, 0, 0, NULL, NULL, NULL, tt_set_parent_guid },
     { NULL }
 };
 
@@ -169,7 +169,7 @@
 }
 
 static /*@ null @*//*@ dependent @*/ gpointer
-get_parent( gpointer pObject )
+bt_get_parent( gpointer pObject )
 {
     const GncTaxTable* tt;
     const GncTaxTable* pParent;
@@ -190,7 +190,7 @@
 }
 
 static void
-set_parent( gpointer data, gpointer value )
+tt_set_parent( gpointer data, gpointer value )
 {
     GncTaxTable* tt;
     GncTaxTable* parent;
@@ -213,7 +213,7 @@
 }
 
 static void
-set_parent_guid( gpointer pObject, /*@ null @*/ gpointer pValue )
+tt_set_parent_guid( gpointer pObject, /*@ null @*/ gpointer pValue )
 {
 	taxtable_parent_guid_struct* s = (taxtable_parent_guid_struct*)pObject;
     GUID* guid = (GUID*)pValue;
@@ -354,7 +354,7 @@
 				progress_made = FALSE;
 				for( elem = tt_needing_parents; elem != NULL; elem = g_list_next( elem ) ) {
 					taxtable_parent_guid_struct* s = (taxtable_parent_guid_struct*)elem->data;
-                    set_parent( s->tt, &s->guid );
+                    tt_set_parent( s->tt, &s->guid );
 					tt_needing_parents = g_list_delete_link( tt_needing_parents, elem );
 					progress_made = TRUE;
 				}



More information about the gnucash-changes mailing list