mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Implement "GUID_MATCH_ALL" (to enable support for the old ACCT_MATCH_ALL).
Note that this allows a user to shoot themselves in the foot if they don't supply a parameter that returns a list. Right now the only valid use of this option is: (Trans)->TRANS_SPLITLIST->SPLIT_ACCOUNTGUID git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6690 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
8615b3d40a
commit
8a96da9c0d
@ -406,11 +406,43 @@ static int guid_match_predicate (gpointer object, QueryAccess get_fcn,
|
||||
|
||||
VERIFY_PREDICATE (query_guid_type);
|
||||
|
||||
/* See if the guid is in the list */
|
||||
guid = ((query_guid_getter)get_fcn) (object);
|
||||
for (node = pdata->guids; node; node = node->next) {
|
||||
if (guid_equal (node->data, guid))
|
||||
break;
|
||||
/* object is a GList of objects; get_gcn must be called on each one.
|
||||
* See if every guid in the predicate is accounted-for in the
|
||||
* object list
|
||||
*/
|
||||
if (pdata->options == GUID_MATCH_ALL) {
|
||||
for (node = pdata->guids; node; node = node->next) {
|
||||
GList *o_list;
|
||||
|
||||
/* See if this GUID matches the object's guid */
|
||||
for (o_list = object; o_list; o_list = o_list->next) {
|
||||
guid = ((query_guid_getter)get_fcn) (o_list->data);
|
||||
if (guid_equal (node->data, guid))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If o_list is NULL, we've walked the whole list without finding
|
||||
* a match. Therefore break out now, the match has failed.
|
||||
*/
|
||||
if (o_list == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The match is complete. If node == NULL then we've succesfully
|
||||
* found a match for all the guids in the predicate. Return
|
||||
* appropriately below.
|
||||
*/
|
||||
|
||||
} else { /* ! MATCH_ALL */
|
||||
|
||||
/* See if the guid is in the list */
|
||||
guid = ((query_guid_getter)get_fcn) (object);
|
||||
for (node = pdata->guids; node; node = node->next) {
|
||||
if (guid_equal (node->data, guid))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (pdata->options) {
|
||||
@ -423,6 +455,9 @@ static int guid_match_predicate (gpointer object, QueryAccess get_fcn,
|
||||
case GUID_MATCH_NULL:
|
||||
return (guid == NULL);
|
||||
break;
|
||||
case GUID_MATCH_ALL:
|
||||
return (node == NULL);
|
||||
break;
|
||||
default:
|
||||
PWARN ("bad match type");
|
||||
return 0;
|
||||
|
@ -43,15 +43,16 @@ typedef struct {
|
||||
GSList * param_list;
|
||||
gint options;
|
||||
gboolean increasing;
|
||||
gboolean use_default;
|
||||
|
||||
/* These values are filled in during "compilation" of the query
|
||||
* term, based upon the obj_name, param_name, and searched-for
|
||||
* object type. If conv_fcn is NULL, then we don't know how to
|
||||
* convert types.
|
||||
*/
|
||||
gboolean use_default;
|
||||
GSList * param_fcns;
|
||||
QueryCompare comp_fcn;
|
||||
QuerySort obj_cmp; /* In case you are comparing objects */
|
||||
QueryCompare comp_fcn; /* When you are comparing core types */
|
||||
} QuerySort_t;
|
||||
|
||||
/* The QUERY structure */
|
||||
@ -249,7 +250,7 @@ static int cmp_func (QuerySort_t *sort, QuerySort default_sort,
|
||||
{
|
||||
GSList *node;
|
||||
gpointer conva, convb;
|
||||
QueryAccess get_fcn;
|
||||
QueryAccess get_fcn = NULL; /* to appease the compiler */
|
||||
|
||||
g_return_val_if_fail (sort, 0);
|
||||
g_return_val_if_fail (default_sort, 0);
|
||||
@ -264,8 +265,8 @@ static int cmp_func (QuerySort_t *sort, QuerySort default_sort,
|
||||
/* If no parameters, consider them equal */
|
||||
if (!sort->param_fcns) return 0;
|
||||
|
||||
/* no compare function, consider them equal */
|
||||
if (!sort->comp_fcn) return 0;
|
||||
/* no compare function, consider the two objects equal */
|
||||
if (!sort->comp_fcn && !sort->obj_cmp) return 0;
|
||||
|
||||
/* Do the list of conversions */
|
||||
conva = (gpointer)a;
|
||||
@ -273,8 +274,9 @@ static int cmp_func (QuerySort_t *sort, QuerySort default_sort,
|
||||
for (node = sort->param_fcns; node; node = node->next) {
|
||||
get_fcn = node->data;
|
||||
|
||||
/* The last term is really the "parameter getter" */
|
||||
if (!node->next)
|
||||
/* The last term is really the "parameter getter",
|
||||
* unless we're comparing objects ;) */
|
||||
if (!node->next && !sort->obj_cmp)
|
||||
break;
|
||||
|
||||
/* Do the converstions */
|
||||
@ -282,8 +284,11 @@ static int cmp_func (QuerySort_t *sort, QuerySort default_sort,
|
||||
convb = get_fcn (convb);
|
||||
}
|
||||
|
||||
/* And now return the compare */
|
||||
return sort->comp_fcn (conva, convb, sort->options, get_fcn);
|
||||
/* And now return the (appropriate) compare */
|
||||
if (sort->comp_fcn)
|
||||
return sort->comp_fcn (conva, convb, sort->options, get_fcn);
|
||||
|
||||
return sort->obj_cmp (conva, convb);
|
||||
}
|
||||
|
||||
static QueryNew * sortQuery = NULL;
|
||||
@ -398,6 +403,8 @@ static void compile_sort (QuerySort_t *sort, GNCIdType obj)
|
||||
|
||||
g_slist_free (sort->param_fcns);
|
||||
sort->param_fcns = NULL;
|
||||
sort->comp_fcn = NULL;
|
||||
sort->obj_cmp = NULL;
|
||||
|
||||
/* An empty param_list implies "no sort" */
|
||||
if (!sort->param_list)
|
||||
@ -407,12 +414,16 @@ static void compile_sort (QuerySort_t *sort, GNCIdType obj)
|
||||
sort->param_fcns = compile_params (sort->param_list, obj, &resObj);
|
||||
|
||||
/* If we have valid parameters, grab the compare function,
|
||||
* If not, see if this is the default sort.
|
||||
* If not, check if this is the default sort.
|
||||
*/
|
||||
if (sort->param_fcns)
|
||||
if (sort->param_fcns) {
|
||||
sort->comp_fcn = gncQueryCoreGetCompare (resObj->param_type);
|
||||
|
||||
else if (!safe_strcmp (sort->param_list->data, QUERY_DEFAULT_SORT))
|
||||
/* Hrm, perhaps this is an object compare, not a core compare? */
|
||||
if (sort->comp_fcn == NULL)
|
||||
sort->obj_cmp = gncQueryObjectDefaultSort (resObj->param_type);
|
||||
|
||||
} else if (!safe_strcmp (sort->param_list->data, QUERY_DEFAULT_SORT))
|
||||
sort->use_default = TRUE;
|
||||
}
|
||||
|
||||
@ -935,10 +946,24 @@ int gncQueryGetMaxResults (QueryNew *q)
|
||||
return q->max_results;
|
||||
}
|
||||
|
||||
void gncQueryAddGUIDListMatch (QueryNew *q, GSList *param_list,
|
||||
GList *guid_list, guid_match_t options,
|
||||
QueryOp op)
|
||||
{
|
||||
QueryPredData_t pdata;
|
||||
|
||||
if (!q || !param_list) return;
|
||||
|
||||
if (!guid_list)
|
||||
g_return_if_fail (options == GUID_MATCH_NULL);
|
||||
|
||||
pdata = gncQueryGUIDPredicate (options, guid_list);
|
||||
gncQueryAddTerm (q, param_list, COMPARE_EQUAL, pdata, op);
|
||||
}
|
||||
|
||||
void gncQueryAddGUIDMatch (QueryNew *q, GSList *param_list,
|
||||
const GUID *guid, QueryOp op)
|
||||
{
|
||||
QueryPredData_t pdata;
|
||||
GList *g = NULL;
|
||||
|
||||
if (!q || !param_list) return;
|
||||
@ -946,10 +971,10 @@ void gncQueryAddGUIDMatch (QueryNew *q, GSList *param_list,
|
||||
if (guid)
|
||||
g = g_list_prepend (g, (gpointer)guid);
|
||||
|
||||
pdata = gncQueryGUIDPredicate (guid ? GUID_MATCH_ANY : GUID_MATCH_NULL, g);
|
||||
g_list_free (g);
|
||||
gncQueryAddGUIDListMatch (q, param_list, g,
|
||||
g ? GUID_MATCH_ANY : GUID_MATCH_NULL, op);
|
||||
|
||||
gncQueryAddTerm (q, param_list, COMPARE_EQUAL, pdata, op);
|
||||
g_list_free (g);
|
||||
}
|
||||
|
||||
void gncQuerySetBook (QueryNew *q, GNCBook *book)
|
||||
|
@ -55,6 +55,7 @@ typedef enum {
|
||||
#define SPLIT_VOIDED_VALUE "voided-value"
|
||||
#define SPLIT_TRANS "trans"
|
||||
#define SPLIT_ACCOUNT "account"
|
||||
#define SPLIT_ACCOUNT_GUID "account-guid" /* for guid_match_all */
|
||||
|
||||
#define TRANS_KVP "kvp"
|
||||
#define TRANS_GUID "guid"
|
||||
@ -67,6 +68,7 @@ typedef enum {
|
||||
#define TRANS_VOID_STATUS "void-p"
|
||||
#define TRANS_VOID_REASON "void-reason"
|
||||
#define TRANS_VOID_TIME "void-time"
|
||||
#define TRANS_SPLITLIST "split-list" /* for guid_match_all */
|
||||
|
||||
#define ACCOUNT_KVP "kvp"
|
||||
#define ACCOUNT_GUID "guid"
|
||||
@ -112,7 +114,8 @@ typedef enum {
|
||||
typedef enum {
|
||||
GUID_MATCH_ANY = 1,
|
||||
GUID_MATCH_NONE,
|
||||
GUID_MATCH_NULL
|
||||
GUID_MATCH_NULL,
|
||||
GUID_MATCH_ALL /* You _must_ pass a GList of objects! */
|
||||
} guid_match_t;
|
||||
|
||||
#define QUERYCORE_INT64 "gint64"
|
||||
@ -156,6 +159,9 @@ void gncQueryAddTerm (QueryNew *query, GSList *param_list,
|
||||
void gncQuerySetBook (QueryNew *q, GNCBook *book);
|
||||
void gncQueryAddGUIDMatch (QueryNew *q, GSList *param_list,
|
||||
const GUID *guid, QueryOp op);
|
||||
void gncQueryAddGUIDListMatch (QueryNew *q, GSList *param_list,
|
||||
GList *guid_list, guid_match_t options,
|
||||
QueryOp op);
|
||||
|
||||
/* Run the query:
|
||||
*
|
||||
|
@ -25,6 +25,17 @@ static GHashTable *paramTable = NULL;
|
||||
static GHashTable *sortTable = NULL;
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
static gpointer split_account_guid_getter (gpointer obj)
|
||||
{
|
||||
Split *s = obj;
|
||||
Account *acc;
|
||||
|
||||
if (!s) return NULL;
|
||||
acc = xaccSplitGetAccount (s);
|
||||
if (!acc) return NULL;
|
||||
return ((gpointer)xaccAccountGetGUID (acc));
|
||||
}
|
||||
|
||||
static void init_split (void)
|
||||
{
|
||||
static const QueryObjectDef params[] = {
|
||||
@ -51,6 +62,7 @@ static void init_split (void)
|
||||
(QueryAccess)xaccSplitVoidFormerValue },
|
||||
{ SPLIT_TRANS, GNC_ID_TRANS, (QueryAccess)xaccSplitGetParent },
|
||||
{ SPLIT_ACCOUNT, GNC_ID_ACCOUNT, (QueryAccess)xaccSplitGetAccount },
|
||||
{ SPLIT_ACCOUNT_GUID, QUERYCORE_GUID, split_account_guid_getter },
|
||||
{ QUERY_PARAM_BOOK, GNC_ID_BOOK, (QueryAccess)xaccSplitGetBook },
|
||||
{ NULL },
|
||||
};
|
||||
@ -72,6 +84,7 @@ static void init_txn (void)
|
||||
{ TRANS_VOID_STATUS, QUERYCORE_BOOLEAN, (QueryAccess)xaccTransGetVoidStatus },
|
||||
{ TRANS_VOID_REASON, QUERYCORE_STRING, (QueryAccess)xaccTransGetVoidReason },
|
||||
{ TRANS_VOID_TIME, QUERYCORE_DATE, (QueryAccess)xaccTransGetVoidTime },
|
||||
{ TRANS_SPLITLIST, GNC_ID_SPLIT, (QueryAccess)xaccTransGetSplitList },
|
||||
{ QUERY_PARAM_BOOK, GNC_ID_BOOK, (QueryAccess)xaccTransGetBook },
|
||||
{ NULL },
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user