r17925 - gnucash/trunk - 1) Before saving file contents via save-as, ensure that all data has been loaded. This

Phil Longstaff plongstaff at cvs.gnucash.org
Sun Feb 15 14:26:39 EST 2009


Author: plongstaff
Date: 2009-02-15 14:26:38 -0500 (Sun, 15 Feb 2009)
New Revision: 17925
Trac: http://svn.gnucash.org/trac/changeset/17925

Modified:
   gnucash/trunk/lib/libqof/backend/file/qsf-backend.c
   gnucash/trunk/lib/libqof/qof/qofbackend-p.h
   gnucash/trunk/lib/libqof/qof/qofsession.c
   gnucash/trunk/lib/libqof/qof/qofsession.h
   gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c
   gnucash/trunk/src/backend/file/gnc-backend-file.c
   gnucash/trunk/src/backend/sql/gnc-backend-sql.c
   gnucash/trunk/src/backend/sql/gnc-backend-sql.h
   gnucash/trunk/src/backend/sql/gnc-transaction-sql.c
   gnucash/trunk/src/gnome-utils/gnc-file.c
Log:
1) Before saving file contents via save-as, ensure that all data has been loaded. This 
doesn't matter for the file backend, but does for the SQL backend, because the SQL backend 
only loads transactions/splits as needed.
2) Partially solve problem where int64 values are loaded incorrectly.  This started because 
num and denom for prices were seen to be limited to 32 bits.  libdbi provides a 
libdbi_result_get_longlong() routine, but unfortunately, on my system (with libdbi 0.8.2-3), 
it seems to have some bugs a) it returns negative values unsigned and b) it seems limited to 
a 32 bit value even when the correct value is in the db.  


Modified: gnucash/trunk/lib/libqof/backend/file/qsf-backend.c
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qsf-backend.c	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-backend.c	2009-02-15 19:26:38 UTC (rev 17925)
@@ -449,7 +449,7 @@
 	QofBook. 
 */
 static void
-qsf_file_type(QofBackend *be, QofBook *book)
+qsf_file_type(QofBackend *be, QofBook *book, QofBackendLoadType loadType)
 {
 	QSFBackend *qsf_be;
 	qsf_param *params;

Modified: gnucash/trunk/lib/libqof/qof/qofbackend-p.h
===================================================================
--- gnucash/trunk/lib/libqof/qof/qofbackend-p.h	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/lib/libqof/qof/qofbackend-p.h	2009-02-15 19:26:38 UTC (rev 17925)
@@ -283,6 +283,11 @@
   void (*provider_free) (QofBackendProvider *);
 };
 
+typedef enum {
+  LOAD_TYPE_INITIAL_LOAD,
+  LOAD_TYPE_LOAD_ALL
+} QofBackendLoadType;
+
 struct QofBackend_s
 {
   void (*session_begin) (QofBackend *be,
@@ -293,7 +298,7 @@
   void (*session_end) (QofBackend *);
   void (*destroy_backend) (QofBackend *);
 
-  void (*load) (QofBackend *, QofBook *);
+  void (*load) (QofBackend *, QofBook *, QofBackendLoadType);
 
   void (*begin) (QofBackend *, QofInstance *);
   void (*commit) (QofBackend *, QofInstance *);

Modified: gnucash/trunk/lib/libqof/qof/qofsession.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/qofsession.c	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/lib/libqof/qof/qofsession.c	2009-02-15 19:26:38 UTC (rev 17925)
@@ -317,6 +317,20 @@
    return session->book_id;
 }
 
+void
+qof_session_ensure_all_data_loaded (QofSession *session)
+{
+    QofBackend* backend;
+
+	if (session == NULL) return;
+    backend = qof_session_get_backend(session);
+	if (backend == NULL) return;
+
+	if (backend->load == NULL) return;
+	backend->load(backend, qof_session_get_book(session), LOAD_TYPE_LOAD_ALL);
+	qof_session_push_error (session, qof_backend_get_error(backend), NULL);
+}
+
 /* =============================================================== */
 
 typedef struct qof_instance_copy_data {
@@ -1150,7 +1164,7 @@
 		
 		if (be->load) 
 		{
-			be->load (be, newbook);
+			be->load (be, newbook, LOAD_TYPE_INITIAL_LOAD);
 			qof_session_push_error (session, qof_backend_get_error(be), NULL);
 		}
 	}

Modified: gnucash/trunk/lib/libqof/qof/qofsession.h
===================================================================
--- gnucash/trunk/lib/libqof/qof/qofsession.h	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/lib/libqof/qof/qofsession.h	2009-02-15 19:26:38 UTC (rev 17925)
@@ -441,5 +441,9 @@
  */
 GList* qof_backend_get_registered_access_method_list(void);
 
+/** Ensure all of the data is loaded from the session.
+ */
+void qof_session_ensure_all_data_loaded(QofSession* session);
+
 #endif /* QOF_SESSION_H */
 /** @} */

Modified: gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c
===================================================================
--- gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c	2009-02-15 19:26:38 UTC (rev 17925)
@@ -333,7 +333,7 @@
 /* ================================================================= */
 
 static void
-gnc_dbi_load( QofBackend* qbe, QofBook *book )
+gnc_dbi_load( QofBackend* qbe, QofBook *book, QofBackendLoadType loadType )
 {
     GncDbiBackend *be = (GncDbiBackend*)qbe;
     GncSqlObjectBackend* pData;
@@ -345,16 +345,18 @@
 
     ENTER( "be=%p, book=%p", be, book );
 
-    g_assert( be->primary_book == NULL );
-    be->primary_book = book;
+	if( loadType == LOAD_TYPE_INITIAL_LOAD ) {
+    	g_assert( be->primary_book == NULL );
+    	be->primary_book = book;
 
-	// Set up table version information
-	gnc_sql_init_version_info( &be->sql_be );
+		// Set up table version information
+		gnc_sql_init_version_info( &be->sql_be );
 
-    // Call all object backends to create any required tables
-    qof_object_foreach_backend( GNC_SQL_BACKEND, create_tables_cb, be );
+    	// Call all object backends to create any required tables
+    	qof_object_foreach_backend( GNC_SQL_BACKEND, create_tables_cb, be );
+	}
 
-	gnc_sql_load( &be->sql_be, book );
+	gnc_sql_load( &be->sql_be, book, loadType );
 
     LEAVE( "" );
 }
@@ -674,13 +676,22 @@
 	GncDbiSqlRow* dbi_row = (GncDbiSqlRow*)row;
 	gushort type;
 	GValue* value;
+	gint64 raw_int64_value;
+	gint raw_int_value;
 
 	type = dbi_result_get_field_type( dbi_row->result, col_name );
 	value = g_new0( GValue, 1 );
 	switch( type ) {
 		case DBI_TYPE_INTEGER:
-			g_value_init( value, G_TYPE_INT );
-			g_value_set_int( value, dbi_result_get_int( dbi_row->result, col_name ) );
+			g_value_init( value, G_TYPE_INT64 );
+
+			// FIXME: Bug in LibDBI: 64 bit int values returned incorrectly
+			raw_int64_value = dbi_result_get_longlong( dbi_row->result, col_name );
+			raw_int_value = dbi_result_get_int( dbi_row->result, col_name );
+			if( raw_int_value < 0 && raw_int64_value > 0 ) {
+				raw_int64_value = raw_int_value;
+			}
+			g_value_set_int64( value, raw_int64_value );
 			break;
 		case DBI_TYPE_DECIMAL:
 			g_value_init( value, G_TYPE_DOUBLE );

Modified: gnucash/trunk/src/backend/file/gnc-backend-file.c
===================================================================
--- gnucash/trunk/src/backend/file/gnc-backend-file.c	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/src/backend/file/gnc-backend-file.c	2009-02-15 19:26:38 UTC (rev 17925)
@@ -907,12 +907,14 @@
    way. */
 
 static void
-gnc_file_be_load_from_file (QofBackend *bend, QofBook *book)
+gnc_file_be_load_from_file (QofBackend *bend, QofBook *book, QofBackendLoadType loadType)
 {
     QofBackendError error;
     gboolean rc;
     FileBackend *be = (FileBackend *) bend;
 
+	if (loadType != LOAD_TYPE_INITIAL_LOAD) return;
+
     error = ERR_BACKEND_NO_ERR;
     be->primary_book = book;
 

Modified: gnucash/trunk/src/backend/sql/gnc-backend-sql.c
===================================================================
--- gnucash/trunk/src/backend/sql/gnc-backend-sql.c	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/src/backend/sql/gnc-backend-sql.c	2009-02-15 19:26:38 UTC (rev 17925)
@@ -151,7 +151,7 @@
 }
 
 void
-gnc_sql_load( GncSqlBackend* be, QofBook *book )
+gnc_sql_load( GncSqlBackend* be, QofBook *book, QofBackendLoadType loadType )
 {
     GncSqlObjectBackend* pData;
 	int i;
@@ -163,27 +163,31 @@
 
     ENTER( "be=%p, book=%p", be, book );
 
-    g_assert( be->primary_book == NULL );
-    be->primary_book = book;
-
-    /* Load any initial stuff */
     be->loading = TRUE;
     
-    /* Some of this needs to happen in a certain order */
-	for( i = 0; fixed_load_order[i] != NULL; i++ ) {
-    	pData = qof_object_lookup_backend( fixed_load_order[i], GNC_SQL_BACKEND );
-    	if( pData->initial_load != NULL ) {
-        	(pData->initial_load)( be );
-		}
-    }
+	if( loadType == LOAD_TYPE_INITIAL_LOAD ) {
+    	g_assert( be->primary_book == NULL );
+    	be->primary_book = book;
 
-	root = gnc_book_get_root_account( book );
-	gnc_account_foreach_descendant( root, (AccountCb)xaccAccountBeginEdit, NULL );
+    	/* Load any initial stuff. Some of this needs to happen in a certain order */
+		for( i = 0; fixed_load_order[i] != NULL; i++ ) {
+    		pData = qof_object_lookup_backend( fixed_load_order[i], GNC_SQL_BACKEND );
+    		if( pData->initial_load != NULL ) {
+        		(pData->initial_load)( be );
+			}
+    	}
 
-    qof_object_foreach_backend( GNC_SQL_BACKEND, initial_load_cb, be );
+		root = gnc_book_get_root_account( book );
+		gnc_account_foreach_descendant( root, (AccountCb)xaccAccountBeginEdit, NULL );
 
-	gnc_account_foreach_descendant( root, (AccountCb)xaccAccountCommitEdit, NULL );
+    	qof_object_foreach_backend( GNC_SQL_BACKEND, initial_load_cb, be );
 
+		gnc_account_foreach_descendant( root, (AccountCb)xaccAccountCommitEdit, NULL );
+	} else if( loadType == LOAD_TYPE_LOAD_ALL ) {
+		// Load all transactions
+		gnc_sql_transaction_load_all_tx( be );
+	}
+
     be->loading = FALSE;
 
 	// Mark the book as clean
@@ -1136,7 +1140,7 @@
     if( val == NULL ) {
         int_value = 0;
     } else {
-        int_value = g_value_get_int( val );
+        int_value = g_value_get_int64( val );
     }
     if( table_row->gobj_param_name != NULL ) {
 		g_object_set( pObject, table_row->gobj_param_name, int_value, NULL );
@@ -1888,28 +1892,28 @@
 void
 gnc_sql_load_object( const GncSqlBackend* be, GncSqlRow* row,
                     QofIdTypeConst obj_name, gpointer pObject,
-                    const GncSqlColumnTableEntry* table_row )
+                    const GncSqlColumnTableEntry* table )
 {
-    int col;
     QofSetterFunc setter;
     GncSqlColumnTypeHandler* pHandler;
+	const GncSqlColumnTableEntry* table_row;
 
 	g_return_if_fail( be != NULL );
 	g_return_if_fail( row != NULL );
 	g_return_if_fail( pObject != NULL );
-	g_return_if_fail( table_row != NULL );
+	g_return_if_fail( table != NULL );
 
-    for( col = 0; table_row[col].col_name != NULL; col++ ) {
-		if( (table_row[col].flags & COL_AUTOINC) != 0 ) {
+    for( table_row = table; table_row->col_name != NULL; table_row++ ) {
+		if( (table_row->flags & COL_AUTOINC) != 0 ) {
 			setter = set_autoinc_id;
-        } else if( table_row[col].qof_param_name != NULL ) {
+        } else if( table_row->qof_param_name != NULL ) {
             setter = qof_class_get_parameter_setter( obj_name,
-                                                table_row[col].qof_param_name );
+                                                table_row->qof_param_name );
         } else {
-            setter = table_row[col].setter;
+            setter = table_row->setter;
         }
-        pHandler = get_handler( &table_row[col] );
-        pHandler->load_fn( be, row, setter, pObject, &table_row[col] );
+        pHandler = get_handler( table_row );
+        pHandler->load_fn( be, row, setter, pObject, table_row );
     }
 }
 
@@ -2493,7 +2497,7 @@
 				version = gnc_sql_row_get_value_at_col_name( row, VERSION_COL_NAME );
 				g_hash_table_insert( be->versions,
 									g_strdup( g_value_get_string( name ) ),
-									GINT_TO_POINTER(g_value_get_int( version )) );
+									GINT_TO_POINTER((gint)g_value_get_int64( version )) );
 				row = gnc_sql_result_get_next_row( result );
 			}
 			gnc_sql_result_dispose( result );

Modified: gnucash/trunk/src/backend/sql/gnc-backend-sql.h
===================================================================
--- gnucash/trunk/src/backend/sql/gnc-backend-sql.h	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/src/backend/sql/gnc-backend-sql.h	2009-02-15 19:26:38 UTC (rev 17925)
@@ -90,7 +90,7 @@
  * @param be SQL backend
  * @param book Book to be loaded
  */
-void gnc_sql_load( GncSqlBackend* be, QofBook *book );
+void gnc_sql_load( GncSqlBackend* be, QofBook *book, QofBackendLoadType loadType );
 
 /**
  * Save the contents of a book to an SQL database.

Modified: gnucash/trunk/src/backend/sql/gnc-transaction-sql.c
===================================================================
--- gnucash/trunk/src/backend/sql/gnc-transaction-sql.c	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/src/backend/sql/gnc-transaction-sql.c	2009-02-15 19:26:38 UTC (rev 17925)
@@ -327,10 +327,13 @@
     guid = gnc_sql_load_guid( be, row );
     tx_guid = *guid;
 
+	// Don't overwrite the transaction if it's already been loaded (and possibly modified).
     pTx = xaccTransLookup( &tx_guid, be->primary_book );
-    if( pTx == NULL ) {
-        pTx = xaccMallocTransaction( be->primary_book );
+    if( pTx != NULL ) {
+		return NULL;
     }
+
+    pTx = xaccMallocTransaction( be->primary_book );
     xaccTransBeginEdit( pTx );
     gnc_sql_load_object( be, row, GNC_ID_TRANS, pTx, tx_col_table );
 
@@ -389,23 +392,7 @@
 	newbal->start_reconciled_bal = *pstart_r;
 	newbal->end_reconciled_bal = *pend_r;
 	*pBal_list = g_slist_append( *pBal_list, newbal );
-
-#if 0
-{
-	if( g_acct == NULL ) {
-		const gchar* name = xaccAccountGetName( acc );
-		if( strcmp( name, "Dividend Income" ) == 0 ) {
-			g_acct = acc;
-		}
-	}
-	if( g_acct != NULL && g_acct == acc ) {
-		printf( "save_account_balance: baln = %s: %s\n",
-				gnc_numeric_to_string( newbal->start_bal ),
-				gnc_numeric_to_string( newbal->end_bal ) );
-	}
 }
-#endif
-}
 
 /**
  * Executes a transaction query statement and loads the transactions and all
@@ -478,36 +465,11 @@
 					"end-reconciled-balance", &pnew_end_r_bal,
 					NULL );
 
-#if 0
-{
-	if( g_acct != NULL && balns->acc == g_acct ) {
-		printf( "Before: %s after %s\n",
-				gnc_numeric_to_string( balns->end_bal ),
-				gnc_numeric_to_string( *pnew_end_bal ) );
-	}
-}
-#endif
-
 			if( !gnc_numeric_eq( *pnew_end_bal, balns->end_bal ) ) {
 				adj = gnc_numeric_sub( balns->end_bal, *pnew_end_bal,
 									GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
-#if 0
-{
-	if( g_acct != NULL && balns->acc == g_acct ) {
-		printf( "adj: %s start (before) = %s", gnc_numeric_to_string( adj ), gnc_numeric_to_string( balns->start_bal ) );
-	}
-}
-#endif
-
 				balns->start_bal = gnc_numeric_add( balns->start_bal, adj,
 									GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
-#if 0
-{
-	if( g_acct != NULL && balns->acc == g_acct ) {
-		printf( " start (after) = %s\n", gnc_numeric_to_string( balns->start_bal ) );
-	}
-}
-#endif
 				g_object_set( balns->acc, "start-balance", &balns->start_bal, NULL );
 			}
 			if( !gnc_numeric_eq( *pnew_end_c_bal, balns->end_cleared_bal ) ) {
@@ -775,14 +737,6 @@
 	gnc_sql_statement_dispose( stmt );
 }
 
-static void
-load_all_tx_helper( Account* a, gpointer data )
-{
-    GncSqlBackend* be = (GncSqlBackend*)data;
-
-	gnc_sql_transaction_load_tx_for_account( be, a );
-}
-
 /**
  * Loads all transactions.  This might be used during a save-as operation to ensure that
  * all data is in memory and ready to be saved.
@@ -791,12 +745,15 @@
  */
 void gnc_sql_transaction_load_all_tx( GncSqlBackend* be )
 {
-	Account* root;
+	gchar* query_sql;
+    GncSqlStatement* stmt;
 
 	g_return_if_fail( be != NULL );
 
-	root = gnc_book_get_root_account( be->primary_book );
-	gnc_account_foreach_descendant( root, load_all_tx_helper, be );
+	query_sql = g_strdup_printf( "SELECT * FROM %s", TRANSACTION_TABLE );
+	stmt = gnc_sql_create_statement_from_sql( be, query_sql );
+    query_transactions( be, stmt );
+	gnc_sql_statement_dispose( stmt );
 }
 
 typedef struct {

Modified: gnucash/trunk/src/gnome-utils/gnc-file.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-file.c	2009-02-15 17:28:29 UTC (rev 17924)
+++ gnucash/trunk/src/gnome-utils/gnc-file.c	2009-02-15 19:26:38 UTC (rev 17925)
@@ -1072,6 +1072,9 @@
     return;
   }
 
+  /* Make sure all of the data from the old file is loaded */
+  qof_session_ensure_all_data_loaded(session);
+
   /* -- this session code is NOT identical in FileOpen and FileSaveAs -- */
 
   xaccLogSetBaseName(newfile); //FIXME: This is premature.



More information about the gnucash-changes mailing list