r18856 - gnucash/trunk/src/business/business-core/sql - Fix parent/child links for tax tables. If a tax table's parent table has not been loaded yet, remember the relationship, and after all tables have been loaded, fix up the rest of the parent/child links.

Phil Longstaff plongstaff at code.gnucash.org
Sat Mar 6 09:54:55 EST 2010


Author: plongstaff
Date: 2010-03-06 09:54:55 -0500 (Sat, 06 Mar 2010)
New Revision: 18856
Trac: http://svn.gnucash.org/trac/changeset/18856

Modified:
   gnucash/trunk/src/business/business-core/sql/gnc-tax-table-sql.c
Log:
Fix parent/child links for tax tables.  If a tax table's parent table has not been loaded yet, remember the relationship, and after all tables have been loaded, fix up the rest of the parent/child links.


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:32:26 UTC (rev 18855)
+++ gnucash/trunk/src/business/business-core/sql/gnc-tax-table-sql.c	2010-03-06 14:54:55 UTC (rev 18856)
@@ -57,7 +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 );
 
 #define MAX_NAME_LEN 50
 
@@ -69,19 +71,23 @@
     { "guid",      CT_GUID,        0,            COL_NNUL | COL_PKEY, "guid" },
     { "name",      CT_STRING,      MAX_NAME_LEN, COL_NNUL,          "name" },
     { "refcount",  CT_INT64,       0,            COL_NNUL,          NULL, GNC_TT_REFCOUNT },
-    {
-        "invisible", CT_BOOLEAN,     0,            COL_NNUL,          NULL, NULL,
+    { "invisible", CT_BOOLEAN,     0,            COL_NNUL,          NULL, NULL,
         (QofAccessFunc)gncTaxTableGetInvisible, (QofSetterFunc)set_invisible
     },
     /*	{ "child",     CT_TAXTABLEREF, 0,			 0,                 NULL, NULL,
     			get_child, (QofSetterFunc)gncTaxTableSetChild }, */
-    {
-        "parent",    CT_TAXTABLEREF, 0,			 0,                 NULL, NULL,
-        (QofAccessFunc)gncTaxTableGetParent, set_parent
+    { "parent",    CT_GUID,        0,			 0,                 NULL, NULL,
+                (QofAccessFunc)get_parent, set_parent
     },
     { NULL }
 };
 
+static GncSqlColumnTableEntry tt_parent_col_table[] =
+{
+    { "parent", CT_GUID, 0, 0, NULL, NULL, NULL, set_parent_guid },
+    { NULL }
+};
+
 #define TTENTRIES_TABLE_NAME "taxtable_entries"
 #define TTENTRIES_TABLE_VERSION 3
 
@@ -115,6 +121,12 @@
     { NULL }
 };
 
+typedef struct {
+	/*@ dependent @*/ GncTaxTable* tt;
+	GUID guid;
+    gboolean have_guid;
+} taxtable_parent_guid_struct;
+
 static gpointer
 get_obj_guid( gpointer pObject, const QofParam* param )
 {
@@ -156,24 +168,64 @@
     return gncTaxTableGetChild( tt );
 }
 
+static /*@ null @*//*@ dependent @*/ gpointer
+get_parent( gpointer pObject )
+{
+    const GncTaxTable* tt;
+    const GncTaxTable* pParent;
+    const GUID* parent_guid;
+
+	g_return_val_if_fail( pObject != NULL, NULL );
+	g_return_val_if_fail( GNC_IS_TAXTABLE(pObject), NULL );
+
+    tt = GNC_TAXTABLE(pObject);
+    pParent = gncTaxTableGetParent( tt );
+    if( pParent == NULL ) {
+        parent_guid = NULL;
+    } else {
+        parent_guid = qof_instance_get_guid( QOF_INSTANCE(pParent) );
+    }
+
+    return (gpointer)parent_guid;
+}
+
 static void
 set_parent( gpointer data, gpointer value )
 {
-    GncTaxTable* tt = GNC_TAXTABLE(data);
+    GncTaxTable* tt;
     GncTaxTable* parent;
+    QofBook* pBook;
+    GUID* guid = (GUID*)value;
 
     g_return_if_fail( data != NULL );
     g_return_if_fail( GNC_IS_TAXTABLE(data) );
 
-    if ( value != NULL )
+    tt = GNC_TAXTABLE(data);
+    pBook = qof_instance_get_book( QOF_INSTANCE(tt) );
+    if ( guid != NULL )
     {
-        parent = GNC_TAXTABLE(value);
-        gncTaxTableSetParent( tt, parent );
-        gncTaxTableSetChild( parent, tt );
+        parent = gncTaxTableLookup( pBook, guid );
+        if( parent != NULL ) {
+            gncTaxTableSetParent( tt, parent );
+            gncTaxTableSetChild( parent, tt );
+        }
     }
 }
 
 static void
+set_parent_guid( gpointer pObject, /*@ null @*/ gpointer pValue )
+{
+	taxtable_parent_guid_struct* s = (taxtable_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 void
 load_single_ttentry( GncSqlBackend* be, GncSqlRow* row, GncTaxTable* tt )
 {
     GncTaxTableEntry* e = gncTaxTableEntryCreate();
@@ -223,7 +275,8 @@
 }
 
 static void
-load_single_taxtable( GncSqlBackend* be, GncSqlRow* row )
+load_single_taxtable( GncSqlBackend* be, GncSqlRow* row,
+					GList** l_tt_needing_parents )
 {
     const GUID* guid;
     GncTaxTable* tt;
@@ -241,6 +294,23 @@
     gnc_sql_slots_load( be, QOF_INSTANCE(tt) );
     load_taxtable_entries( be, tt );
 
+    /* If the tax table doesn't have a parent, it might be because it hasn't been loaded yet.
+       If so, add this tax table to the list of tax tables with no parent, along with the parent
+       GUID so that after they are all loaded, the parents can be fixed up. */
+    if( gncTaxTableGetParent( tt ) == NULL ) {
+		taxtable_parent_guid_struct* s = g_malloc( (gsize)sizeof(taxtable_parent_guid_struct) );
+		g_assert( s != NULL );
+
+		s->tt = tt;
+        s->have_guid = FALSE;
+		gnc_sql_load_object( be, row, GNC_ID_TAXTABLE, s, tt_parent_col_table );
+        if( s->have_guid ) {
+		    *l_tt_needing_parents = g_list_prepend( *l_tt_needing_parents, s );
+        } else {
+            g_free( s );
+        }
+    }
+
     qof_instance_mark_clean( QOF_INSTANCE(tt) );
 }
 
@@ -259,14 +329,37 @@
     if ( result != NULL )
     {
         GncSqlRow* row;
+        GList* tt_needing_parents = NULL;
 
         row = gnc_sql_result_get_first_row( result );
         while ( row != NULL )
         {
-            load_single_taxtable( be, row );
+            load_single_taxtable( be, row, &tt_needing_parents );
             row = gnc_sql_result_get_next_row( result );
         }
         gnc_sql_result_dispose( result );
+
+		/* While there are items on the list of taxtables 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( tt_needing_parents != NULL ) {
+			gboolean progress_made = TRUE;
+            GncTaxTable* root;	
+			Account* pParent;
+			GList* elem;
+				
+			while( progress_made ) {
+				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_needing_parents = g_list_delete_link( tt_needing_parents, elem );
+					progress_made = TRUE;
+				}
+			}
+        }
     }
 }
 



More information about the gnucash-changes mailing list