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:
Derek Atkins 2002-02-05 16:39:21 +00:00
parent 8615b3d40a
commit 8a96da9c0d
4 changed files with 101 additions and 22 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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:
*

View File

@ -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 },
};