/* ----------------------------------------------------------------- */ static void load_tx_guid( const GncSqlBackend* be, GncSqlRow* row, /*@ null @*/ QofSetterFunc setter, gpointer pObject, const GncSqlColumnTableEntry* table_row ) { const GValue* val; GncGUID guid; Transaction* tx; const gchar* guid_str; 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 ); val = gnc_sql_row_get_value_at_col_name( row, table_row->col_name ); g_assert( val != NULL ); guid_str = g_value_get_string(val); if ( guid_str != NULL ) { (void)string_to_guid( guid_str, &guid ); tx = xaccTransLookup( &guid, be->book ); // If the transaction is not found, try loading it if ( tx == NULL ) { gchar* buf; GncSqlStatement* stmt; buf = g_strdup_printf( "SELECT * FROM %s WHERE guid='%s'", TRANSACTION_TABLE, guid_str ); stmt = gnc_sql_create_statement_from_sql( (GncSqlBackend*)be, buf ); g_free( buf ); query_transactions( (GncSqlBackend*)be, stmt ); tx = xaccTransLookup( &guid, be->book ); } if ( tx != NULL ) { if ( table_row->gobj_param_name != NULL ) { qof_instance_increase_editlevel (pObject); g_object_set( pObject, table_row->gobj_param_name, tx, NULL ); qof_instance_decrease_editlevel (pObject); } else { g_return_if_fail( setter != NULL ); (*setter)( pObject, (const gpointer)tx ); } } } }
/* ================================================================= */ static void load_account_guid (const GncSqlBackend* be, GncSqlRow* row, QofSetterFunc setter, gpointer pObject, const GncSqlColumnTableEntry* table_row) { const GValue* val; GncGUID guid; Account* account = NULL; 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); val = gnc_sql_row_get_value_at_col_name (row, table_row->col_name); if (val != NULL && G_VALUE_HOLDS_STRING (val) && g_value_get_string (val) != NULL) { (void)string_to_guid (g_value_get_string (val), &guid); account = xaccAccountLookup (&guid, be->book); if (account != NULL) { if (table_row->gobj_param_name != NULL) { qof_instance_increase_editlevel (pObject); g_object_set (pObject, table_row->gobj_param_name, account, NULL); qof_instance_decrease_editlevel (pObject); } else { g_return_if_fail (setter != NULL); (*setter) (pObject, (const gpointer)account); } } else { PWARN ("Account ref '%s' not found", g_value_get_string (val)); } } }
/* ================================================================= */ static void load_billterm_guid (const GncSqlBackend* be, GncSqlRow* row, QofSetterFunc setter, gpointer pObject, const GncSqlColumnTableEntry* table_row) { const GValue* val; GncGUID guid; GncBillTerm* term = NULL; 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); val = gnc_sql_row_get_value_at_col_name (row, table_row->col_name); if (val != NULL && G_VALUE_HOLDS_STRING (val) && g_value_get_string (val) != NULL) { string_to_guid (g_value_get_string (val), &guid); term = gncBillTermLookup (be->book, &guid); if (term != NULL) { if (table_row->gobj_param_name != NULL) { qof_instance_increase_editlevel (pObject); g_object_set (pObject, table_row->gobj_param_name, term, NULL); qof_instance_decrease_editlevel (pObject); } else { (*setter) (pObject, (const gpointer)term); } } else { PWARN ("Billterm ref '%s' not found", g_value_get_string (val)); } } }
static void load_commodity_guid( const GncSqlBackend* be, GncSqlRow* row, /*@ null @*/ QofSetterFunc setter, gpointer pObject, const GncSqlColumnTableEntry* table_row ) { const GValue* val; GncGUID guid; gnc_commodity* commodity = NULL; 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 ); val = gnc_sql_row_get_value_at_col_name( row, table_row->col_name ); if ( val != NULL && G_VALUE_HOLDS_STRING( val ) && g_value_get_string( val ) != NULL ) { (void)string_to_guid( g_value_get_string( val ), &guid ); commodity = gnc_commodity_find_commodity_by_guid( &guid, be->book ); if ( commodity != NULL ) { if ( table_row->gobj_param_name != NULL ) { qof_instance_increase_editlevel (pObject); g_object_set( pObject, table_row->gobj_param_name, commodity, NULL ); qof_instance_decrease_editlevel (pObject); } else if ( setter != NULL ) { (*setter)( pObject, (const gpointer)commodity ); } } else { PWARN( "Commodity ref '%s' not found", g_value_get_string( val ) ); } } }
void GncSqlAccountBackend::load_all (GncSqlBackend* sql_be) { QofBook* pBook; ParentGuidVec l_accounts_needing_parents; g_return_if_fail (sql_be != NULL); ENTER (""); pBook = sql_be->book(); std::stringstream sql; sql << "SELECT * FROM " << TABLE_NAME; auto stmt = sql_be->create_statement_from_sql(sql.str()); auto result = sql_be->execute_select_statement(stmt); for (auto row : *result) load_single_account (sql_be, row, l_accounts_needing_parents); sql.str(""); sql << "SELECT DISTINCT guid FROM " << TABLE_NAME; gnc_sql_slots_load_for_sql_subquery (sql_be, sql.str().c_str(), (BookLookupFn)xaccAccountLookup); /* While there are items on the list of accounts 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 (!l_accounts_needing_parents.empty()) { auto progress_made = true; std::reverse(l_accounts_needing_parents.begin(), l_accounts_needing_parents.end()); auto end = l_accounts_needing_parents.end(); while (progress_made) { progress_made = false; end = std::remove_if(l_accounts_needing_parents.begin(), end, [&](ParentGuidPtr s) { auto pParent = xaccAccountLookup (&s->guid, sql_be->book()); if (pParent != nullptr) { gnc_account_append_child (pParent, s->pAccount); progress_made = true; delete s; return true; } return false; }); } /* Any non-ROOT accounts left over must be parented by the root account */ auto root = gnc_book_get_root_account (pBook); end = std::remove_if(l_accounts_needing_parents.begin(), end, [&](ParentGuidPtr s) { if (xaccAccountGetType (s->pAccount) != ACCT_TYPE_ROOT) gnc_account_append_child (root, s->pAccount); delete s; return true; }); } #if LOAD_TRANSACTIONS_AS_NEEDED /* Load starting balances */ auto bal_slist = gnc_sql_get_account_balances_slist (sql_be); for (auto bal = bal_slist; bal != NULL; bal = bal->next) { acct_balances_t* balances = (acct_balances_t*)bal->data; qof_instance_increase_editlevel (balances->acct); g_object_set (balances->acct, "start-balance", &balances->balance, "start-cleared-balance", &balances->cleared_balance, "start-reconciled-balance", &balances->reconciled_balance, NULL); qof_instance_decrease_editlevel (balances->acct); } if (bal_slist != NULL) { g_slist_free (bal_slist); } #endif LEAVE (""); }
static void load_all_accounts (GncSqlBackend* be) { GncSqlStatement* stmt = NULL; GncSqlResult* result; QofBook* pBook; GList* l_accounts_needing_parents = NULL; GSList* bal_slist; GSList* bal; g_return_if_fail (be != NULL); ENTER (""); pBook = be->book; stmt = gnc_sql_create_select_statement (be, TABLE_NAME); if (stmt == NULL) { LEAVE ("stmt == NULL"); return; } result = gnc_sql_execute_select_statement (be, stmt); gnc_sql_statement_dispose (stmt); if (result != NULL) { GncSqlRow* row = gnc_sql_result_get_first_row (result); gchar* sql; while (row != NULL) { load_single_account (be, row, &l_accounts_needing_parents); row = gnc_sql_result_get_next_row (result); } gnc_sql_result_dispose (result); sql = g_strdup_printf ("SELECT DISTINCT guid FROM %s", TABLE_NAME); gnc_sql_slots_load_for_sql_subquery (be, sql, (BookLookupFn)xaccAccountLookup); g_free (sql); /* While there are items on the list of accounts 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 (l_accounts_needing_parents != NULL) { gboolean progress_made = TRUE; Account* root; Account* pParent; GList* elem; while (progress_made) { progress_made = FALSE; for (elem = l_accounts_needing_parents; elem != NULL;) { account_parent_guid_struct* s = (account_parent_guid_struct*)elem->data; pParent = xaccAccountLookup (&s->guid, be->book); if (pParent != NULL) { GList* next_elem; gnc_account_append_child (pParent, s->pAccount); next_elem = g_list_next (elem); l_accounts_needing_parents = g_list_delete_link (l_accounts_needing_parents, elem); g_free (s); elem = next_elem; progress_made = TRUE; } else { /* Can't be up in the for loop because the 'then' clause reads inside a node freed by g_list_delete_link(). */ elem = g_list_next (elem); } } } /* Any non-ROOT accounts left over must be parented by the root account */ root = gnc_book_get_root_account (pBook); while (l_accounts_needing_parents != NULL) { account_parent_guid_struct* s = (account_parent_guid_struct*) l_accounts_needing_parents->data; if (xaccAccountGetType (s->pAccount) != ACCT_TYPE_ROOT) { gnc_account_append_child (root, s->pAccount); } g_free (s); l_accounts_needing_parents = g_list_delete_link (l_accounts_needing_parents, l_accounts_needing_parents); } } /* Load starting balances */ bal_slist = gnc_sql_get_account_balances_slist (be); for (bal = bal_slist; bal != NULL; bal = bal->next) { acct_balances_t* balances = (acct_balances_t*)bal->data; qof_instance_increase_editlevel (balances->acct); g_object_set (balances->acct, "start-balance", &balances->balance, "start-cleared-balance", &balances->cleared_balance, "start-reconciled-balance", &balances->reconciled_balance, NULL); qof_instance_decrease_editlevel (balances->acct); } if (bal_slist != NULL) { g_slist_free (bal_slist); } } LEAVE (""); }
/** * Executes a transaction query statement and loads the transactions and all * of the splits. * * @param be SQL backend * @param stmt SQL statement */ static void query_transactions( GncSqlBackend* be, GncSqlStatement* stmt ) { GncSqlResult* result; g_return_if_fail( be != NULL ); g_return_if_fail( stmt != NULL ); result = gnc_sql_execute_select_statement( be, stmt ); if ( result != NULL ) { GList* tx_list = NULL; GList* node; GncSqlRow* row; Transaction* tx; #if LOAD_TRANSACTIONS_AS_NEEDED GSList* bal_list = NULL; GSList* nextbal; Account* root = gnc_book_get_root_account( be->book ); qof_event_suspend(); xaccAccountBeginEdit( root ); // Save the start/ending balances (balance, cleared and reconciled) for // every account. gnc_account_foreach_descendant( gnc_book_get_root_account( be->primary_book ), save_account_balances, &bal_list ); #endif // Load the transactions row = gnc_sql_result_get_first_row( result ); while ( row != NULL ) { tx = load_single_tx( be, row ); if ( tx != NULL ) { tx_list = g_list_prepend( tx_list, tx ); } row = gnc_sql_result_get_next_row( result ); } gnc_sql_result_dispose( result ); // Load all splits and slots for the transactions if ( tx_list != NULL ) { gnc_sql_slots_load_for_list( be, tx_list ); load_splits_for_tx_list( be, tx_list ); } // Commit all of the transactions for ( node = tx_list; node != NULL; node = node->next ) { Transaction* pTx = GNC_TRANSACTION(node->data); xaccTransCommitEdit( pTx ); } g_list_free( tx_list ); #if LOAD_TRANSACTIONS_AS_NEEDED // Update the account balances based on the loaded splits. If the end // balance has changed, update the start balance so that the end // balance is the same as it was before the splits were loaded. // Repeat for cleared and reconciled balances. for ( nextbal = bal_list; nextbal != NULL; nextbal = nextbal->next ) { full_acct_balances_t* balns = (full_acct_balances_t*)nextbal->data; gnc_numeric* pnew_end_bal; gnc_numeric* pnew_end_c_bal; gnc_numeric* pnew_end_r_bal; gnc_numeric adj; g_object_get( balns->acc, "end-balance", &pnew_end_bal, "end-cleared-balance", &pnew_end_c_bal, "end-reconciled-balance", &pnew_end_r_bal, NULL ); qof_instance_increase_editlevel (balns-acc); 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 ); balns->start_bal = gnc_numeric_add( balns->start_bal, adj, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD ); g_object_set( balns->acc, "start-balance", &balns->start_bal, NULL ); qof_instance_decrease_editlevel (balns-acc); } if ( !gnc_numeric_eq( *pnew_end_c_bal, balns->end_cleared_bal ) ) { adj = gnc_numeric_sub( balns->end_cleared_bal, *pnew_end_c_bal, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD ); balns->start_cleared_bal = gnc_numeric_add( balns->start_cleared_bal, adj, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD ); g_object_set( balns->acc, "start-cleared-balance", &balns->start_cleared_bal, NULL ); } if ( !gnc_numeric_eq( *pnew_end_r_bal, balns->end_reconciled_bal ) ) { adj = gnc_numeric_sub( balns->end_reconciled_bal, *pnew_end_r_bal, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD ); balns->start_reconciled_bal = gnc_numeric_add( balns->start_reconciled_bal, adj, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD ); g_object_set( balns->acc, "start-reconciled-balance", &balns->start_reconciled_bal, NULL ); } qof_instance_decrease_editlevel (balns-acc); xaccAccountRecomputeBalance( balns->acc ); g_free( pnew_end_bal ); g_free( pnew_end_c_bal ); g_free( pnew_end_r_bal ); g_free( balns ); } if ( bal_list != NULL ) { g_slist_free( bal_list ); } xaccAccountCommitEdit( root ); qof_event_resume(); #endif } }