General Query Framework, an updated proposal
Derek Atkins
warlord@MIT.EDU
29 Jan 2002 23:14:04 -0500
--=-=-=
Ok, here is an updated set of headers. I've flushed out the types a
bit more as per your suggestions, and I've flushed out the model as
well.
There are now three registries:
1) core data types
2) gnucash objects' data parameters
3) gnucash objects' "parent" objects
The third registry basically allows you to register functions that
basically say: "given a split, return the account" and then perform
queries against the account object.
When you build a query term, you basically supply an object_type,
parameter_name, comparitor, predicate_data, and query_operator. When
you run the query, you tell the query what kind of object you're
looking for and it will iterate over those objects. For each term it
uses registry 3 to convert from the requested object to the querried
object, registry 2 to lookup the core type and access function, and
registry 1 to look up the match_predicate function. In this way
you can build a query that says:
Return all splits where account->account_name equals regex (name)
In this example:
- "split" is the requested object,
- "account" is the querried object,
- "account_name" is the parameter (of type QUERYCORE_STRING),
- "equals" is the comparitor,
- "regex (name)" is the predicate_data (for type QUERYCORE_STRING)
I _think_ that this API can fully implement the existing Query API.
Please send me comments.
Thanks,
-derek
--=-=-=
Content-Disposition: attachment; filename=QueryNew.h
Content-Description: Top-Level Query API
/*
* QueryNew.h -- API for finding Gnucash objects
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU>
*
*/
#ifndef GNC_QUERYNEW_H
#define GNC_QUERYNEW_H
/* A Query */
typedef struct querynew_s QueryNew;
/* Query Term Operators, for combining Query Terms */
typedef enum {
QUERY_AND=1,
QUERY_OR,
QUERY_NAND,
QUERY_NOR,
QUERY_XOR
} QueryOp;
/* Standard Query Term comparitors, for how to process a query term.
* Note that not all core types implement all comparitors
*/
typedef enum {
COMPARE_LT = 1,
COMPARE_LTE,
COMPARE_EQUAL,
COMPARE_GT,
COMPARE_GTE
} query_compare_t;
/* Types of Gnucash Queriable Objects (const char *) */
#define QUERY_TYPE_SPLIT "split"
#define QUERY_TYPE_ACCOUNT "account"
#define QUERY_TYPE_TRANSACTION "transaction"
/* Type of Query Core Objects (String, Date, Numeric, GUID, etc. */
typedef const char * QueryCoreType;
/*
* List of known core query types...
* Each core query type defines it's set of optional "comparitor qualifiers".
*/
#define QUERYCORE_STRING "string"
typedef enum {
STRING_MATCH_CASEINSENSITIVE = 1,
STRING_MATCH_REGEXP
} string_match_t;
#define QUERYCORE_DATE "date"
typedef enum {
DATE_MATCH_ROUNDED = 1
} date_match_t;
#define QUERYCORE_NUMERIC "numeric"
typedef enum {
NUMERIC_MATCH_ABS = 1,
NUMERIC_MATCH_NEG_ONLY,
NUMERIC_MATCH_POS_ONLY
} numeric_match_t;
#define QUERYCORE_GUID "guid"
typedef enum {
GUID_MATCH_ALL = 1,
GUID_MATCH_ANY
GUID_MATCH_NONE
} guid_match_t;
#define QUERYCORE_INT64 "gint64"
#define QUERYCORE_DOUBLE "double"
#define QUERYCORE_BOOLEAN "boolean"
#define QUERYCORE_KVP "kvp"
/* A CHAR type is for a RECNCell */
#define QUERYCORE_CHAR "character"
/* Basic API Functions */
/* This is the general function that adds a new Query Term to a query.
* It will find the 'obj_type' object of the search item and compare
* the 'param_name' parameter to the predicate data via the comparitor.
*
* For example:
*
* acct_name_pred_data = make_string_pred_data(STRING_MATCH_CASEINSENSITIVE,
* account_name);
* gncQueryAddTerm (query, QUERY_TYPE_ACCOUNT, QUERY_ACCOUNT_NAME,
* COMPARE_EQUAL, acct_name_pred_data, QUERY_AND);
*/
void gncQueryAddTerm (QueryNew *query,
const char *obj_type, const char *param_name,
query_compare_t comparitor, gpointer pred_data,
QueryOp op);
/* Run the query:
*
* ex: gncQueryRun (query, QUERY_TYPE_SPLIT);
*/
GList * gncQueryRun (QueryNew *query, const char *obj_type);
#endif /* GNC_QUERYNEW_H */
--=-=-=
Content-Disposition: attachment; filename=QueryCore.h
Content-Description: Core Data Type registration
/*
* QueryCore.h -- API for providing core Query data types
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU>
*
*/
#ifndef GNC_QUERYCORE_H
#define GNC_QUERYCORE_H
#include "QueryNew.h"
#include "QueryObject.h" /* for QueryAccess */
/*
* An arbitrary Query Predicate. Given the gnucash object and the
* particular parameter get-function (obtained from the registry by
* the Query internals), compare the object's parameter to the
* predicate data given the match_options
*/
typedef int (*QueryPredicate) (gpointer object,
QueryAccess get_fcn,
query_compare_t how,
gint match_options,
gpointer pdata);
/* A callback for how to destroy a query predicate's pdata */
typedef void (*QueryPredDataFree) (gpointer pdata);
/* This function registers a new Core Object with the QueryNew
* subsystem. It maps the "core_name" object to the given
* query_predicate and predicate_data_free functions.
*/
void gncQueryRegisterCoreObject (char const *core_name,
QueryPredicate pred,
QueryPredDataFree pd_free);
/* An example:
*
* gncQueryRegisterCoreObject (QUERYCORE_STRING, string_match_predicate,
* string_free_pdata);
*/
#endif /* GNC_QUERYCORE_H */
--=-=-=
Content-Disposition: attachment; filename=QueryObject.h
Content-Description: Gnucash Object registration
/*
* QueryObject.h -- API for registering queriable Gnucash objects
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU>
*
*/
#ifndef GNC_QUERYOBJECT_H
#define GNC_QUERYOBJECT_H
#include "QueryNew.h"
/* Define an arbitrary function pointer for access functions. This is
* because C doesn't have templates, so we just cast a lot. Real
* functions must be of the form:
*
* <param_type> function (object_type *obj);
*/
typedef void (*QueryAccess)(gpointer);
/* This structure is for each queriable parameter in an object */
typedef struct query_object_def {
const char * param_name;
QueryCoreType param_type;
QueryAccess param_getfcn;
} QueryObjectDef;
/* This function registers a new Gnucash Object with the QueryNew
* subsystem. It registers the "obj_name" object which provides the
* "methods" set of queriable parameters. The "methods" array must
* be a NULL-terminated array.
*/
void gncQueryRegisterObject (const char * obj_name,
const QueryObjectDef *methods[]);
/* An example:
*
* #define MY_QUERY_OBJ_MEMO "memo"
* #define MY_QUERY_OBJ_VALUE "value"
* #define MY_QUERY_OBJ_DATE "date"
*
* static QueryObjectDef myQueryObject[] = {
* { MY_QUERY_OBJ_MEMO, QUERYCORE_STRING, myMemoGetter },
* { MY_QUERY_OBJ_VALUE, QUERYCORE_NUMERIC, myValueGetter },
* { MY_QUERY_OBJ_DATE, QUERYCORE_DATE, myDateGetter },
* NULL };
*
* gncQueryRegisterObject ("myObjectName", &myQueryObject);
*/
/* This function-type will convert from one object-type to another */
typedef gpointer (*QueryConvert)(gpointer);
typedef struct query_convert_def {
const char * object_name;
QueryConvert object_getfcn;
} QueryConvertDef;
/* This function registers a new Gnucash Object and provides a
* set of methods to obtain other Gnucash objects from this one.
* The methods array much be NULL-terminated.
*/
void gncQueryRegisterConversion (const char *obj_name,
const QueryConvertDef *methods[]);
/* An example:
*
* static QueryConvertDef myQueryObjects[] = {
* { QUERY_TYPE_ACCOUNT, myAccountGetter },
* { QUERY_TYPE_TRANSACTION, myTransactionGetter },
* NULL };
*
* gncQueryRegisterConversion ("myObjectName", &myQueryObjects);
*/
#endif /* GNC_QUERYOBJECT_H */
--=-=-=
--
Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory
Member, MIT Student Information Processing Board (SIPB)
URL: http://web.mit.edu/warlord/ PP-ASEL-IA N1NWH
warlord@MIT.EDU PGP key available
--=-=-=--