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.  


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@17925 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Phil Longstaff 2009-02-15 19:26:38 +00:00
parent f3592f34da
commit c67b86b470
10 changed files with 97 additions and 97 deletions

View File

@ -449,7 +449,7 @@ returns NULL on error, otherwise a pointer to the QofBook. Use
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;

View File

@ -283,6 +283,11 @@ struct QofBackendProvider_s
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 @@ struct QofBackend_s
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 *);

View File

@ -317,6 +317,20 @@ qof_session_get_url (const QofSession *session)
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 @@ qof_session_load (QofSession *session,
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);
}
}

View File

@ -441,5 +441,9 @@ gboolean qof_session_export (QofSession *tmp_session,
*/
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 */
/** @} */

View File

@ -333,7 +333,7 @@ gnc_dbi_destroy_backend( QofBackend *be )
/* ================================================================= */
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 @@ gnc_dbi_load( QofBackend* qbe, QofBook *book )
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 @@ row_get_value_at_col_name( GncSqlRow* row, const gchar* col_name )
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 );

View File

@ -907,12 +907,14 @@ file_commit_edit (QofBackend *be, QofInstance *inst)
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;

View File

@ -151,7 +151,7 @@ initial_load_cb( const gchar* type, gpointer data_p, gpointer be_p )
}
void
gnc_sql_load( GncSqlBackend* be, QofBook *book )
gnc_sql_load( GncSqlBackend* be, QofBook *book, QofBackendLoadType loadType )
{
GncSqlObjectBackend* pData;
int i;
@ -163,26 +163,30 @@ gnc_sql_load( GncSqlBackend* be, QofBook *book )
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;
@ -1136,7 +1140,7 @@ load_boolean( const GncSqlBackend* be, GncSqlRow* row,
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 @@ gnc_sql_load_tx_guid( const GncSqlBackend* be, GncSqlRow* row )
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 @@ gnc_sql_init_version_info( GncSqlBackend* be )
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 );

View File

@ -90,7 +90,7 @@ void gnc_sql_init( GncSqlBackend* be );
* @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.

View File

@ -327,10 +327,13 @@ load_single_tx( GncSqlBackend* be, GncSqlRow* row )
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,22 +392,6 @@ save_account_balances( Account* acc, gpointer pData )
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
}
/**
@ -478,36 +465,11 @@ query_transactions( GncSqlBackend* be, GncSqlStatement* stmt )
"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 @@ void gnc_sql_transaction_load_tx_for_account( GncSqlBackend* be, Account* accoun
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 @@ load_all_tx_helper( Account* a, gpointer data )
*/
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 {

View File

@ -1072,6 +1072,9 @@ gnc_file_do_save_as (const char* filename)
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.