mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-25 10:20:18 -06:00
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:
parent
f3592f34da
commit
c67b86b470
@ -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;
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
/** @} */
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user