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