gnucash maint: Refactor gnc_gen_trans_list_create_matches
John Ralls
jralls at code.gnucash.org
Tue Aug 4 12:50:40 EDT 2020
Updated via https://github.com/Gnucash/gnucash/commit/24e288ae (commit)
from https://github.com/Gnucash/gnucash/commit/67fb2576 (commit)
commit 24e288ae47284b13fa7afcf740f81f99c52a05b6
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Aug 4 09:45:30 2020 -0700
Refactor gnc_gen_trans_list_create_matches
Extracting functions query_imported_transaction_accounts and perform_matching
and eliminating the early creation and passing of several local
variables.
diff --git a/gnucash/import-export/import-main-matcher.c b/gnucash/import-export/import-main-matcher.c
index f1ff49d07..46d7db380 100644
--- a/gnucash/import-export/import-main-matcher.c
+++ b/gnucash/import-export/import-main-matcher.c
@@ -1668,30 +1668,37 @@ void gnc_gen_trans_list_add_trans_with_ref_id (GNCImportMainMatcher *gui, Transa
return;
}
-// This creates lists of all splits that could match one of the imported transactions based on their
-// account and date and organized per account
-static GHashTable*
-create_list_of_potential_matches (GNCImportMainMatcher *gui, GtkTreeModel* model, Query *query, gint match_date_hardlimit)
+
+/* Query the accounts used by the imported transactions to find a list of
+ * candidate matching transactions.
+ */
+static GList*
+query_imported_transaction_accounts (GNCImportMainMatcher *gui)
{
- GList* query_return = NULL;
- time64 import_trans_time, min_time=G_MAXINT64, max_time=0;
- GList* all_accounts = NULL;
static const int secs_per_day = 86400;
- GSList* imported_trans;
- GList* potential_match;
- GHashTable* lists_per_accounts = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_slist_free);
-
- // Go through all imported transactions, gather the list of accounts, and min/max date range.
- for (imported_trans=gui->temp_trans_list; imported_trans!=NULL; imported_trans=imported_trans->next)
+ GList* query_results = NULL;
+ GList* all_accounts = NULL;
+ GList* retval = NULL;
+ gint match_date_limit =
+ gnc_import_Settings_get_match_date_hardlimit (gui->user_settings);
+ time64 min_time=G_MAXINT64, max_time=0;
+ time64 match_timelimit = match_date_limit * secs_per_day;
+ Query *query = qof_query_create_for (GNC_ID_SPLIT);
+
+ /* Go through all imported transactions, gather the list of accounts, and
+ * min/max date range.
+ */
+ for (GSList* txn = gui->temp_trans_list; txn != NULL;
+ txn = g_slist_next (txn))
{
- Account *import_trans_account;
- GNCImportTransInfo* transaction_info;
- transaction_info = imported_trans->data;
- import_trans_account = xaccSplitGetAccount (gnc_import_TransInfo_get_fsplit (transaction_info));
- all_accounts = g_list_prepend (all_accounts, import_trans_account);
- import_trans_time = xaccTransGetDate (gnc_import_TransInfo_get_trans (transaction_info));
- min_time = MIN (min_time, import_trans_time);
- max_time = MAX (max_time, import_trans_time);
+ GNCImportTransInfo* txn_info = txn->data;
+ Account *txn_account =
+ xaccSplitGetAccount (gnc_import_TransInfo_get_fsplit (txn_info));
+ time64 txn_time =
+ xaccTransGetDate (gnc_import_TransInfo_get_trans (txn_info));
+ all_accounts = g_list_prepend (all_accounts, txn_account);
+ min_time = MIN (min_time, txn_time);
+ max_time = MAX (max_time, txn_time);
}
// Make a query to find splits with the right accounts and dates.
@@ -1699,27 +1706,41 @@ create_list_of_potential_matches (GNCImportMainMatcher *gui, GtkTreeModel* model
xaccQueryAddAccountMatch (query, all_accounts,
QOF_GUID_MATCH_ANY, QOF_QUERY_AND);
xaccQueryAddDateMatchTT (query,
- TRUE, min_time - match_date_hardlimit * secs_per_day,
- TRUE, max_time + match_date_hardlimit * secs_per_day,
+ TRUE, min_time - match_timelimit,
+ TRUE, max_time + match_timelimit,
QOF_QUERY_AND);
- query_return = qof_query_run (query);
+ query_results = qof_query_run (query);
g_list_free (all_accounts);
+ retval = g_list_copy (query_results);
+ qof_query_destroy (query);
- // Now put all potential matches into a hash table based on their account.
- for (potential_match=query_return; potential_match!=NULL; potential_match=potential_match->next)
+ return retval;
+}
+
+/* Create a hash by account of all splits that could match one of the imported
+ * transactions based on their account and date and organized per account.
+ */
+static GHashTable*
+create_hash_of_potential_matches (GList *candidate_txns,
+ GHashTable *account_hash)
+{
+ for (GList* candidate = candidate_txns; candidate != NULL;
+ candidate = g_list_next (candidate))
{
Account* split_account;
- GSList* per_account_list;
- if (gnc_import_split_has_online_id (potential_match->data))
+ GSList* split_list;
+ if (gnc_import_split_has_online_id (candidate->data))
continue;
- split_account = xaccSplitGetAccount (potential_match->data);
- // g_hash_table_steal_extended would do the two calls in one shot but is not available until 2.58
- per_account_list = g_hash_table_lookup (lists_per_accounts, split_account);
- g_hash_table_steal (lists_per_accounts, split_account);
- per_account_list = g_slist_prepend (per_account_list, potential_match->data);
- g_hash_table_insert (lists_per_accounts, split_account, per_account_list);
+ split_account = xaccSplitGetAccount (candidate->data);
+ /* g_hash_table_steal_extended would do the two calls in one shot but is
+ * not available until GLib 2.58.
+ */
+ split_list = g_hash_table_lookup (account_hash, split_account);
+ g_hash_table_steal (account_hash, split_account);
+ split_list = g_slist_prepend (split_list, candidate->data);
+ g_hash_table_insert (account_hash, split_account, split_list);
}
- return lists_per_accounts;
+ return account_hash;
}
typedef struct _match_struct
@@ -1732,60 +1753,67 @@ typedef struct _match_struct
static void
match_helper (Split* data, match_struct* s)
{
- split_find_match (s->transaction_info, data, s->display_threshold, s->fuzzy_amount);
+ split_find_match (s->transaction_info, data,
+ s->display_threshold, s->fuzzy_amount);
}
-/* This goes through the temporary list of imported transactions, runs a single query to gater potential matching
- * register transactions based on accounts and dates, then selects potential matching transactions for
- * each imported transaction. Doing a single query makes things a lot faster than doing one query per
- * imported transaction.
+/* Iterate through the imported transactions selecting matches from the
+ * potential match lists in the account hash and update the matcher with the
+ * results.
*/
-void
-gnc_gen_trans_list_create_matches (GNCImportMainMatcher *gui)
+
+static void
+perform_matching (GNCImportMainMatcher *gui, GHashTable *account_hash)
{
GtkTreeModel* model = gtk_tree_view_get_model (gui->view);
- GtkListStore* store = GTK_LIST_STORE (model);
- GtkTreeIter iter;
- GNCImportMatchInfo *selected_match;
- gboolean match_selected_manually;
- GHashTable* lists_per_accounts = NULL;
- Query *query;
- gint match_date_hardlimit = gnc_import_Settings_get_match_date_hardlimit (gui->user_settings);
- gint display_threshold = gnc_import_Settings_get_display_threshold (gui->user_settings);
- double fuzzy_amount = gnc_import_Settings_get_fuzzy_amount (gui->user_settings);
- GSList* imported_trans;
-
- query = qof_query_create_for (GNC_ID_SPLIT);
- // Gather the list of splits that could match one of the imported transactions, this return a hash table.
- lists_per_accounts = create_list_of_potential_matches (gui, model, query, match_date_hardlimit);
-
- // For each imported transaction, grab the list of potential matches corresponding to that account,
- // and evaluate how good a match they are.
- for (imported_trans=gui->temp_trans_list; imported_trans!=NULL; imported_trans=imported_trans->next)
+ gint display_threshold =
+ gnc_import_Settings_get_display_threshold (gui->user_settings);
+ double fuzzy_amount =
+ gnc_import_Settings_get_fuzzy_amount (gui->user_settings);
+
+ for (GSList *imported_txn = gui->temp_trans_list; imported_txn !=NULL;
+ imported_txn = g_slist_next (imported_txn))
{
- GNCImportTransInfo* transaction_info = imported_trans->data;
- Account *importaccount = xaccSplitGetAccount (gnc_import_TransInfo_get_fsplit (transaction_info));
- match_struct s = {transaction_info, display_threshold, fuzzy_amount};
-
- g_slist_foreach (g_hash_table_lookup (lists_per_accounts, importaccount), (GFunc) match_helper, &s);
+ GtkTreeIter iter;
+ GNCImportMatchInfo *selected_match;
+ gboolean match_selected_manually;
+ GNCImportTransInfo* txn_info = imported_txn->data;
+ Account *importaccount = xaccSplitGetAccount (gnc_import_TransInfo_get_fsplit (txn_info));
+ match_struct s = {txn_info, display_threshold, fuzzy_amount};
+
+ g_slist_foreach (g_hash_table_lookup (account_hash, importaccount),
+ (GFunc) match_helper, &s);
// Sort the matches, select the best match, and set the action.
- gnc_import_TransInfo_init_matches (transaction_info, gui->user_settings);
+ gnc_import_TransInfo_init_matches (txn_info, gui->user_settings);
- selected_match = gnc_import_TransInfo_get_selected_match (transaction_info);
- match_selected_manually = gnc_import_TransInfo_get_match_selected_manually (transaction_info);
+ selected_match = gnc_import_TransInfo_get_selected_match (txn_info);
+ match_selected_manually =
+ gnc_import_TransInfo_get_match_selected_manually (txn_info);
if (selected_match)
gnc_import_PendingMatches_add_match (gui->pending_matches,
selected_match,
match_selected_manually);
-
+
gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
- refresh_model_row (gui, model, &iter, transaction_info);
+ refresh_model_row (gui, model, &iter, txn_info);
}
-
- qof_query_destroy (query);
- g_hash_table_destroy (lists_per_accounts);
+}
+
+void
+gnc_gen_trans_list_create_matches (GNCImportMainMatcher *gui)
+{
+ GHashTable* account_hash =
+ g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
+ (GDestroyNotify)g_slist_free);
+ GList *candidate_txns = query_imported_transaction_accounts (gui);
+
+ create_hash_of_potential_matches (candidate_txns, account_hash);
+ perform_matching (gui, account_hash);
+
+ g_list_free (candidate_txns);
+ g_hash_table_destroy (account_hash);
return;
}
Summary of changes:
gnucash/import-export/import-main-matcher.c | 174 ++++++++++++++++------------
1 file changed, 101 insertions(+), 73 deletions(-)
More information about the gnucash-changes
mailing list