diff --git a/src/engine/Query.c b/src/engine/Query.c index 71bb81c523..f8d3142917 100644 --- a/src/engine/Query.c +++ b/src/engine/Query.c @@ -41,6 +41,7 @@ #include "Query.h" #include "Transaction.h" #include "TransactionP.h" +#include "gnc-lot.h" static short module = MOD_QUERY; @@ -170,6 +171,72 @@ xaccQueryGetTransactions (Query * q, query_txn_match_t runtype) return retval; } +/******************************************************************** + * xaccQueryGetLots + * Get lots matching the query terms, specifying whether + * we require some or all splits to match + ********************************************************************/ + +static void +query_match_all_lot_filter_func(gpointer key, gpointer value, gpointer user_data) +{ + GNCLot * l = key; + int num_matches = GPOINTER_TO_INT(value); + GList ** matches = user_data; + + if(num_matches == gnc_lot_count_splits(l)) { + *matches = g_list_prepend(*matches, l); + } +} + +static void +query_match_any_lot_filter_func(gpointer key, gpointer value, gpointer user_data) +{ + GNCLot * t = key; + GList ** matches = user_data; + *matches = g_list_prepend(*matches, t); +} + +LotList * +xaccQueryGetLots (Query * q, query_txn_match_t runtype) +{ + GList * splits = xaccQueryGetSplits(q); + GList * current = NULL; + GList * retval = NULL; + GHashTable * lot_hash = g_hash_table_new(g_direct_hash, g_direct_equal); + GNCLot * lot = NULL; + gpointer val = NULL; + int count = 0; + + /* iterate over matching splits, incrementing a match-count in + * the hash table */ + for(current = splits; current; current=current->next) { + lot = xaccSplitGetLot((Split *)(current->data)); + + /* don't waste time looking up unless we need the count + * information */ + if(runtype == QUERY_TXN_MATCH_ALL) { + val = g_hash_table_lookup(lot_hash, lot); + count = GPOINTER_TO_INT(val); + } + g_hash_table_insert(lot_hash, lot, GINT_TO_POINTER(count + 1)); + } + + /* now pick out the transactions that match */ + if(runtype == QUERY_TXN_MATCH_ALL) { + g_hash_table_foreach(lot_hash, query_match_all_lot_filter_func, + &retval); + } + else { + g_hash_table_foreach(lot_hash, query_match_any_lot_filter_func, + &retval); + } + + g_hash_table_destroy(lot_hash); + + return retval; +} + /******************************************************************* * match-adding API *******************************************************************/ diff --git a/src/engine/Query.h b/src/engine/Query.h index 6cb28c16fb..1335a5fc50 100644 --- a/src/engine/Query.h +++ b/src/engine/Query.h @@ -97,6 +97,9 @@ typedef enum { * the caller. The query_run_t argument is used to provide account * matching in the following way: * + * The xaccQueryGetLots() routine is just like GetTransactions() except + * it returns a list of Lots. + * * query_txn_match_t describes how to match accounts when querying * for transactions with xaccQueryGetTransactions(). * What is the difference between 'ANY' and 'ALL', you @@ -115,6 +118,7 @@ typedef enum { #define xaccQueryGetSplits gncQueryRun SplitList * xaccQueryGetSplitsUniqueTrans(Query *q); TransList * xaccQueryGetTransactions(Query * q, query_txn_match_t type); +LotList * xaccQueryGetLots(Query * q, query_txn_match_t type); /******************************************************************* * match-adding API