GnuCash  2.6.16
Files | Data Structures | Macros | Typedefs | Enumerations
Query: Querying for Objects

Files

file  qofquery.h
 find objects that match a certain expression.
 
file  qofquerycore.h
 API for providing core Query data types.
 

Data Structures

struct  QofQueryPredData
 

Macros

#define QOF_MOD_QUERY   "qof.query"
 
#define QOF_QUERY_FIRST_TERM   QOF_QUERY_AND
 
#define QUERY_DEFAULT_SORT   "QofQueryDefaultSort"
 
#define QOF_PARAM_BOOK   "book"
 
#define QOF_PARAM_GUID   "guid"
 
#define QOF_PARAM_KVP   "kvp"
 
#define QOF_PARAM_ACTIVE   "active"
 
#define QOF_PARAM_VERSION   "version"
 

Typedefs

typedef GSList QofQueryParamList
 

Enumerations

enum  QofQueryOp {
  QOF_QUERY_AND = 1, QOF_QUERY_OR, QOF_QUERY_NAND, QOF_QUERY_NOR,
  QOF_QUERY_XOR
}
 
enum  QofQueryCompare {
  QOF_COMPARE_LT = 1, QOF_COMPARE_LTE, QOF_COMPARE_EQUAL, QOF_COMPARE_GT,
  QOF_COMPARE_GTE, QOF_COMPARE_NEQ
}
 
enum  QofStringMatch { QOF_STRING_MATCH_NORMAL = 1, QOF_STRING_MATCH_CASEINSENSITIVE }
 
enum  QofDateMatch { QOF_DATE_MATCH_NORMAL = 1, QOF_DATE_MATCH_DAY }
 
enum  QofNumericMatch { QOF_NUMERIC_MATCH_DEBIT = 1, QOF_NUMERIC_MATCH_CREDIT, QOF_NUMERIC_MATCH_ANY }
 
enum  QofGuidMatch {
  QOF_GUID_MATCH_ANY = 1, QOF_GUID_MATCH_NONE, QOF_GUID_MATCH_NULL, QOF_GUID_MATCH_ALL,
  QOF_GUID_MATCH_LIST_ANY
}
 
enum  QofCharMatch { QOF_CHAR_MATCH_ANY = 1, QOF_CHAR_MATCH_NONE }
 

Query Subsystem Initialization and Shudown

void qof_query_init (void)
 
void qof_query_shutdown (void)
 

Low-Level API Functions

QofQueryParamListqof_query_build_param_list (char const *param,...)
 
QofQuery * qof_query_create (void)
 
QofQuery * qof_query_create_for (QofIdTypeConst obj_type)
 
void qof_query_destroy (QofQuery *q)
 
void qof_query_search_for (QofQuery *query, QofIdTypeConst obj_type)
 
void qof_query_set_book (QofQuery *q, QofBook *book)
 
void qof_query_add_term (QofQuery *query, QofQueryParamList *param_list, QofQueryPredData *pred_data, QofQueryOp op)
 
void qof_query_add_guid_match (QofQuery *q, QofQueryParamList *param_list, const GncGUID *guid, QofQueryOp op)
 
void qof_query_add_guid_list_match (QofQuery *q, QofQueryParamList *param_list, GList *guid_list, QofGuidMatch options, QofQueryOp op)
 
void qof_query_add_boolean_match (QofQuery *q, QofQueryParamList *param_list, gboolean value, QofQueryOp op)
 
GList * qof_query_run (QofQuery *query)
 
GList * qof_query_last_run (QofQuery *query)
 
GList * qof_query_run_subquery (QofQuery *subquery, const QofQuery *primary_query)
 
void qof_query_clear (QofQuery *query)
 
void qof_query_purge_terms (QofQuery *q, QofQueryParamList *param_list)
 
int qof_query_has_terms (QofQuery *q)
 
int qof_query_num_terms (QofQuery *q)
 
gboolean qof_query_has_term_type (QofQuery *q, QofQueryParamList *term_param)
 
GSList * qof_query_get_term_type (QofQuery *q, QofQueryParamList *term_param)
 
QofQuery * qof_query_copy (QofQuery *q)
 
QofQuery * qof_query_invert (QofQuery *q)
 
QofQuery * qof_query_merge (QofQuery *q1, QofQuery *q2, QofQueryOp op)
 
void qof_query_merge_in_place (QofQuery *q1, QofQuery *q2, QofQueryOp op)
 
void qof_query_set_sort_order (QofQuery *q, QofQueryParamList *primary_sort_params, QofQueryParamList *secondary_sort_params, QofQueryParamList *tertiary_sort_params)
 
void qof_query_set_sort_options (QofQuery *q, gint prim_op, gint sec_op, gint tert_op)
 
void qof_query_set_sort_increasing (QofQuery *q, gboolean prim_inc, gboolean sec_inc, gboolean tert_inc)
 
void qof_query_set_max_results (QofQuery *q, int n)
 
gboolean qof_query_equal (const QofQuery *q1, const QofQuery *q2)
 
void qof_query_print (QofQuery *query)
 
QofIdType qof_query_get_search_for (const QofQuery *q)
 
GList * qof_query_get_books (QofQuery *q)
 

Core Data Type Predicates

QofQueryPredData * qof_query_string_predicate (QofQueryCompare how, const gchar *str, QofStringMatch options, gboolean is_regex)
 
QofQueryPredData * qof_query_date_predicate (QofQueryCompare how, QofDateMatch options, Timespec date)
 
QofQueryPredData * qof_query_numeric_predicate (QofQueryCompare how, QofNumericMatch options, gnc_numeric value)
 
QofQueryPredData * qof_query_guid_predicate (QofGuidMatch options, GList *guids)
 
QofQueryPredData * qof_query_int32_predicate (QofQueryCompare how, gint32 val)
 
QofQueryPredData * qof_query_int64_predicate (QofQueryCompare how, gint64 val)
 
QofQueryPredData * qof_query_double_predicate (QofQueryCompare how, double val)
 
QofQueryPredData * qof_query_boolean_predicate (QofQueryCompare how, gboolean val)
 
QofQueryPredData * qof_query_char_predicate (QofCharMatch options, const gchar *chars)
 
QofQueryPredData * qof_query_collect_predicate (QofGuidMatch options, QofCollection *coll)
 
QofQueryPredData * qof_query_choice_predicate (QofGuidMatch options, GList *guids)
 
QofQueryPredData * qof_query_kvp_predicate (QofQueryCompare how, QofQueryParamList *path, const KvpValue *value)
 
QofQueryPredData * qof_query_kvp_predicate_path (QofQueryCompare how, const gchar *path, const KvpValue *value)
 
QofQueryPredData * qof_query_core_predicate_copy (const QofQueryPredData *pdata)
 
void qof_query_core_predicate_free (QofQueryPredData *pdata)
 
gboolean qof_query_date_predicate_get_date (const QofQueryPredData *pd, Timespec *date)
 
char * qof_query_core_to_string (QofType, gpointer object, QofParam *getter)
 
int qof_string_number_compare_func (gpointer a, gpointer b, gint options, QofParam *this_param)
 

Detailed Description

BASIC QUERY API: With this API you can create arbitrary logical queries to find sets of arbitrary object. To make simple queries (1 term, such as a search for a parameter with one value), create the appropriate QueryTerm structure and stick it in a Query object using xaccInitQuery. The QueryTerm should be malloc'd but the Query object will handle freeing it. To make compound queries, make multiple simple queries and combine them using qof_query_merge() and the logical operations of your choice.

SQL QUERY API: As an alternative to building queries one predicate at a time, you can use the SQL query interface. This interface will accept a string containing an SQL query, parse it, convert it into the core representation, and execute it.

STRUCTURE OF A QUERY: A Query is a logical function of any number of QueryTerms. A QueryTerm consists of a C function pointer (the Predicate) and a PredicateData structure containing data passed to the predicate function. The PredicateData structure is a constant associated with the Term and is identical for every object that is tested.

The terms of the Query may represent any logical function and are stored in canonical form, i.e. the function is expressed as a logical sum of logical products. So if you have QueryTerms a, b, c, d, e and you have the logical function a(b+c) + !(c(d+e)), it gets stored as ab + ac + !c + !c!e +!d!c + !d!e. This may not be optimal for evaluation of some functions but it's easy to store, easy to manipulate, and it doesn't require a complete algebra system to deal with.

The representation is of a GList of GLists of QueryTerms. The "backbone" GList q->terms represents the OR-chain, and every item on the backbone is a GList of QueryTerms representing an AND-chain corresponding to a single product-term in the canonical representation. QueryTerms are duplicated when necessary to fill out the canonical form, and the same predicate may be evaluated multiple times per split for complex queries. This is a place where we could probably optimize.

Macro Definition Documentation

◆ QOF_PARAM_BOOK

#define QOF_PARAM_BOOK   "book"

"Known" Object Parameters – all objects must support these

Definition at line 104 of file qofquery.h.

◆ QOF_PARAM_KVP

#define QOF_PARAM_KVP   "kvp"

"Known" Object Parameters – some objects might support these

Definition at line 108 of file qofquery.h.

◆ QOF_QUERY_FIRST_TERM

#define QOF_QUERY_FIRST_TERM   QOF_QUERY_AND

First/only term is same as 'and'

Definition at line 98 of file qofquery.h.

◆ QUERY_DEFAULT_SORT

#define QUERY_DEFAULT_SORT   "QofQueryDefaultSort"

Default sort object type

Definition at line 101 of file qofquery.h.

Typedef Documentation

◆ QofQueryParamList

typedef GSList QofQueryParamList

A list of parameters (QofIdType) used to describe a parameter to use in a predicate or when sorting

Definition at line 145 of file qofquerycore.h.

Enumeration Type Documentation

◆ QofCharMatch

A CHAR type is for a RECNCell, Comparisons for QOF_TYPE_CHAR 'ANY' will match any character in the string.

Match 'ANY' is a convenience/performance-enhanced predicate for the compound statement (value==char1) || (value==char2) || etc. Match 'NONE' is equivalent to (value != char1) && (value != char2) && etc.

Definition at line 126 of file qofquerycore.h.

127 {
128  QOF_CHAR_MATCH_ANY = 1,
129  QOF_CHAR_MATCH_NONE
130 } QofCharMatch;
QofCharMatch
Definition: qofquerycore.h:126

◆ QofDateMatch

Comparisons for QOF_TYPE_DATE The QOF_DATE_MATCH_DAY comparison rounds the two time values to mid-day and then compares these rounded values. The QOF_DATE_MATCH_NORMAL comparison matches the time values, down to the second.

Definition at line 77 of file qofquerycore.h.

78 {
79  QOF_DATE_MATCH_NORMAL = 1,
80  QOF_DATE_MATCH_DAY
81 } QofDateMatch;
QofDateMatch
Definition: qofquerycore.h:77

◆ QofGuidMatch

Enumerator
QOF_GUID_MATCH_ANY 

These expect a single object and expect the QofAccessFunc returns GncGUID*

QOF_GUID_MATCH_ALL 

These expect a GList* of objects and calls the QofAccessFunc routine on each item in the list to obtain a GncGUID* for each object

QOF_GUID_MATCH_LIST_ANY 

These expect a single object and expect the QofAccessFunc function to return a GList* of GncGUID* (the list is the property of the caller)

Definition at line 103 of file qofquerycore.h.

104 {
107  QOF_GUID_MATCH_ANY = 1,
108  QOF_GUID_MATCH_NONE,
109  QOF_GUID_MATCH_NULL,
116 } QofGuidMatch;
QofGuidMatch
Definition: qofquerycore.h:103

◆ QofNumericMatch

Comparisons for QOF_TYPE_NUMERIC, QOF_TYPE_DEBCRED

XXX Should be deprecated, or at least wrapped up as a convenience function, this is based on the old bill gribble code, which assumed the amount was always positive, and then specified a funds-flow direction (credit, debit, or either).

The point being that 'match credit' is equivalent to the compound predicate (amount >= 0) && (amount 'op' value) while the 'match debit' predicate is equivalent to (amount <= 0) && (abs(amount) 'op' value)

Definition at line 95 of file qofquerycore.h.

96 {
97  QOF_NUMERIC_MATCH_DEBIT = 1,
98  QOF_NUMERIC_MATCH_CREDIT,
99  QOF_NUMERIC_MATCH_ANY
QofNumericMatch
Definition: qofquerycore.h:95

◆ QofQueryCompare

Standard Query comparators, for how to compare objects in a predicate. Note that not all core types implement all comparators

Definition at line 50 of file qofquerycore.h.

51 {
52  QOF_COMPARE_LT = 1,
53  QOF_COMPARE_LTE,
54  QOF_COMPARE_EQUAL,
55  QOF_COMPARE_GT,
56  QOF_COMPARE_GTE,
57  QOF_COMPARE_NEQ
QofQueryCompare
Definition: qofquerycore.h:50

◆ QofQueryOp

enum QofQueryOp

Query Term Operators, for combining Query Terms

Definition at line 88 of file qofquery.h.

89 {
90  QOF_QUERY_AND = 1,
91  QOF_QUERY_OR,
92  QOF_QUERY_NAND,
93  QOF_QUERY_NOR,
94  QOF_QUERY_XOR
95 } QofQueryOp;
QofQueryOp
Definition: qofquery.h:88

◆ QofStringMatch

List of known core query data-types... Each core query type defines it's set of optional "comparator qualifiers".

Definition at line 64 of file qofquerycore.h.

65 {
66  QOF_STRING_MATCH_NORMAL = 1,
67  QOF_STRING_MATCH_CASEINSENSITIVE
QofStringMatch
Definition: qofquerycore.h:64

Function Documentation

◆ qof_query_add_boolean_match()

void qof_query_add_boolean_match ( QofQuery *  q,
QofQueryParamList param_list,
gboolean  value,
QofQueryOp  op 
)

Handy-dandy convenience routines, avoids having to create a separate predicate for boolean matches. We might want to create handy-dandy sugar routines for the other predicate types as well.

Definition at line 1312 of file qofquery.c.

1314 {
1315  QofQueryPredData *pdata;
1316  if (!q || !param_list) return;
1317 
1318  pdata = qof_query_boolean_predicate (QOF_COMPARE_EQUAL, value);
1319  qof_query_add_term (q, param_list, pdata, op);
1320 }
void qof_query_add_term(QofQuery *q, QofQueryParamList *param_list, QofQueryPredData *pred_data, QofQueryOp op)
Definition: qofquery.c:651

◆ qof_query_add_guid_list_match()

void qof_query_add_guid_list_match ( QofQuery *  q,
QofQueryParamList param_list,
GList *  guid_list,
QofGuidMatch  options,
QofQueryOp  op 
)

DOCUMENT ME !!

Definition at line 1260 of file qofquery.c.

1263 {
1264  QofQueryPredData *pdata;
1265 
1266  if (!q || !param_list) return;
1267 
1268  if (!guid_list)
1269  g_return_if_fail (options == QOF_GUID_MATCH_NULL);
1270 
1271  pdata = qof_query_guid_predicate (options, guid_list);
1272  qof_query_add_term (q, param_list, pdata, op);
1273 }
void qof_query_add_term(QofQuery *q, QofQueryParamList *param_list, QofQueryPredData *pred_data, QofQueryOp op)
Definition: qofquery.c:651

◆ qof_query_add_guid_match()

void qof_query_add_guid_match ( QofQuery *  q,
QofQueryParamList param_list,
const GncGUID guid,
QofQueryOp  op 
)

DOCUMENT ME !!

Definition at line 1275 of file qofquery.c.

1277 {
1278  GList *g = NULL;
1279 
1280  if (!q || !param_list) return;
1281 
1282  if (guid)
1283  g = g_list_prepend (g, (gpointer)guid);
1284 
1285  qof_query_add_guid_list_match (q, param_list, g,
1286  g ? QOF_GUID_MATCH_ANY : QOF_GUID_MATCH_NULL, op);
1287 
1288  g_list_free (g);
1289 }
void qof_query_add_guid_list_match(QofQuery *q, QofQueryParamList *param_list, GList *guid_list, QofGuidMatch options, QofQueryOp op)
Definition: qofquery.c:1260

◆ qof_query_add_term()

void qof_query_add_term ( QofQuery *  query,
QofQueryParamList param_list,
QofQueryPredData *  pred_data,
QofQueryOp  op 
)

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_list' parameter to the predicate data via the comparator.

The param_list is a recursive list of parameters. For example, you can say 'split->memo' by creating a list of one element, "SPLIT_MEMO". You can say 'split->account->name' by creating a list of two elements, "SPLIT_ACCOUNT" and "ACCOUNT_NAME". The list becomes the property of the Query.

For example:

acct_name_pred_data = make_string_pred_data(QOF_STRING_MATCH_CASEINSENSITIVE, account_name); param_list = make_list (SPLIT_ACCOUNT, ACCOUNT_NAME, NULL); qof_query_add_term (query, param_list, QOF_COMPARE_EQUAL, acct_name_pred_data, QOF_QUERY_AND);

Please note that QofQuery does not, at this time, support joins. That is, one cannot specify a predicate that is a parameter list. Put another way, one cannot search for objects where obja->thingy == objb->stuff

Definition at line 651 of file qofquery.c.

653 {
654  QofQueryTerm *qt;
655  QofQuery *qr, *qs;
656 
657  if (!q || !param_list || !pred_data) return;
658 
659  qt = g_new0 (QofQueryTerm, 1);
660  qt->param_list = param_list;
661  qt->pdata = pred_data;
662  qs = qof_query_create ();
663  query_init (qs, qt);
664 
665  if (qof_query_has_terms (q))
666  qr = qof_query_merge (q, qs, op);
667  else
668  qr = qof_query_merge (q, qs, QOF_QUERY_OR);
669 
670  swap_terms (q, qr);
671  qof_query_destroy (qs);
672  qof_query_destroy (qr);
673 }
void qof_query_destroy(QofQuery *q)
Definition: qofquery.c:975
QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
Definition: qofquery.c:1095
int qof_query_has_terms(QofQuery *q)
Definition: qofquery.c:916
QofQuery * qof_query_create(void)
Definition: qofquery.c:886

◆ qof_query_clear()

void qof_query_clear ( QofQuery *  query)

Remove all query terms from query. query matches nothing after qof_query_clear().

Definition at line 873 of file qofquery.c.

874 {
875  QofQuery *q2 = qof_query_create ();
876  swap_terms (query, q2);
877  qof_query_destroy (q2);
878 
879  g_list_free (query->books);
880  query->books = NULL;
881  g_list_free (query->results);
882  query->results = NULL;
883  query->changed = 1;
884 }
void qof_query_destroy(QofQuery *q)
Definition: qofquery.c:975
QofQuery * qof_query_create(void)
Definition: qofquery.c:886

◆ qof_query_copy()

QofQuery* qof_query_copy ( QofQuery *  q)

Make a copy of the indicated query

Definition at line 984 of file qofquery.c.

985 {
986  QofQuery *copy;
987  GHashTable *ht;
988 
989  if (!q) return NULL;
990  copy = qof_query_create ();
991  ht = copy->be_compiled;
992  free_members (copy);
993 
994  memcpy (copy, q, sizeof (QofQuery));
995 
996  copy->be_compiled = ht;
997  copy->terms = copy_or_terms (q->terms);
998  copy->books = g_list_copy (q->books);
999  copy->results = g_list_copy (q->results);
1000 
1001  copy_sort (&(copy->primary_sort), &(q->primary_sort));
1002  copy_sort (&(copy->secondary_sort), &(q->secondary_sort));
1003  copy_sort (&(copy->tertiary_sort), &(q->tertiary_sort));
1004 
1005  copy->changed = 1;
1006 
1007  return copy;
1008 }
QofQuery * qof_query_create(void)
Definition: qofquery.c:886

◆ qof_query_core_predicate_copy()

QofQueryPredData* qof_query_core_predicate_copy ( const QofQueryPredData *  pdata)

Copy a predicate.

Definition at line 1895 of file qofquerycore.c.

1896 {
1897  QueryPredicateCopyFunc copy;
1898 
1899  g_return_val_if_fail (pdata, NULL);
1900  g_return_val_if_fail (pdata->type_name, NULL);
1901 
1902  copy = qof_query_copy_predicate (pdata->type_name);
1903  return (copy (pdata));
1904 }

◆ qof_query_core_predicate_free()

void qof_query_core_predicate_free ( QofQueryPredData *  pdata)

Destroy a predicate.

Definition at line 1883 of file qofquerycore.c.

1884 {
1885  QueryPredDataFree free_fcn;
1886 
1887  g_return_if_fail (pdata);
1888  g_return_if_fail (pdata->type_name);
1889 
1890  free_fcn = qof_query_predicate_free (pdata->type_name);
1891  free_fcn (pdata);
1892 }

◆ qof_query_core_to_string()

char* qof_query_core_to_string ( QofType  ,
gpointer  object,
QofParam *  getter 
)

Return a printable string for a core data object. Caller needs to g_free() the returned string.

Definition at line 1907 of file qofquerycore.c.

1909 {
1910  QueryToString toString;
1911 
1912  g_return_val_if_fail (type, NULL);
1913  g_return_val_if_fail (object, NULL);
1914  g_return_val_if_fail (getter, NULL);
1915 
1916  toString = g_hash_table_lookup (toStringTable, type);
1917  g_return_val_if_fail (toString, NULL);
1918 
1919  return toString (object, getter);
1920 }

◆ qof_query_create()

QofQuery* qof_query_create ( void  )

Create a new query. Before running the query, a 'search-for' type must be set otherwise nothing will be returned. The results of the query is a list of the indicated search-for type.

Allocates and initializes a Query structure which must be freed by the user with qof_query_destroy(). A newly-allocated QofQuery object matches nothing (qof_query_run() will return NULL).

Definition at line 886 of file qofquery.c.

887 {
888  QofQuery *qp = g_new0 (QofQuery, 1);
889  qp->be_compiled = g_hash_table_new (g_direct_hash, g_direct_equal);
890  query_init (qp, NULL);
891  return qp;
892 }

◆ qof_query_date_predicate_get_date()

gboolean qof_query_date_predicate_get_date ( const QofQueryPredData *  pd,
Timespec *  date 
)

Retrieve a predicate.

Definition at line 422 of file qofquerycore.c.

423 {
424  const query_date_t pdata = (const query_date_t)pd;
425 
426  if (pdata->pd.type_name != query_date_type)
427  return FALSE;
428  *date = pdata->date;
429  return TRUE;
430 }

◆ qof_query_destroy()

void qof_query_destroy ( QofQuery *  q)

Frees the resources associate with a Query object.

Definition at line 975 of file qofquery.c.

976 {
977  if (!q) return;
978  free_members (q);
979  query_clear_compiles (q);
980  g_hash_table_destroy (q->be_compiled);
981  g_free (q);
982 }

◆ qof_query_equal()

gboolean qof_query_equal ( const QofQuery *  q1,
const QofQuery *  q2 
)

Compare two queries for equality. Query terms are compared each to each. This is a simplistic implementation – logical equivalences between different and/or trees are ignored.

Definition at line 1437 of file qofquery.c.

1438 {
1439  GList *or1, *or2;
1440 
1441  if (q1 == q2) return TRUE;
1442  if (!q1 || !q2) return FALSE;
1443 
1444  if (g_list_length (q1->terms) != g_list_length (q2->terms)) return FALSE;
1445  if (q1->max_results != q2->max_results) return FALSE;
1446 
1447  for (or1 = q1->terms, or2 = q2->terms; or1;
1448  or1 = or1->next, or2 = or2->next)
1449  {
1450  GList *and1, *and2;
1451 
1452  and1 = or1->data;
1453  and2 = or2->data;
1454 
1455  if (g_list_length (and1) != g_list_length (and2)) return FALSE;
1456 
1457  for ( ; and1; and1 = and1->next, and2 = and2->next)
1458  if (!qof_query_term_equal (and1->data, and2->data))
1459  return FALSE;
1460  }
1461 
1462  if (!qof_query_sort_equal (&(q1->primary_sort), &(q2->primary_sort)))
1463  return FALSE;
1464  if (!qof_query_sort_equal (&(q1->secondary_sort), &(q2->secondary_sort)))
1465  return FALSE;
1466  if (!qof_query_sort_equal (&(q1->tertiary_sort), &(q2->tertiary_sort)))
1467  return FALSE;
1468 
1469  return TRUE;
1470 }

◆ qof_query_get_books()

GList* qof_query_get_books ( QofQuery *  q)

Return the list of books we're using

Definition at line 1306 of file qofquery.c.

1307 {
1308  if (!q) return NULL;
1309  return q->books;
1310 }

◆ qof_query_get_search_for()

QofIdType qof_query_get_search_for ( const QofQuery *  q)

Return the type of data we're querying for

Definition at line 1345 of file qofquery.c.

1346 {
1347  if (!q) return NULL;
1348  return q->search_for;
1349 }

◆ qof_query_has_term_type()

gboolean qof_query_has_term_type ( QofQuery *  q,
QofQueryParamList term_param 
)

DOCUMENT ME !!

Definition at line 932 of file qofquery.c.

933 {
934  GList *or;
935  GList *and;
936 
937  if (!q || !term_param)
938  return FALSE;
939 
940  for (or = q->terms; or; or = or->next)
941  {
942  for (and = or->data; and; and = and->next)
943  {
944  QofQueryTerm *qt = and->data;
945  if (!param_list_cmp (term_param, qt->param_list))
946  return TRUE;
947  }
948  }
949 
950  return FALSE;
951 }

◆ qof_query_has_terms()

int qof_query_has_terms ( QofQuery *  q)

Return boolean FALSE if there are no terms in the query Can be used as a predicate to see if the query has been initialized (return value > 0) or is "blank" (return value == 0).

Definition at line 916 of file qofquery.c.

917 {
918  if (!q) return 0;
919  return g_list_length (q->terms);
920 }

◆ qof_query_init()

void qof_query_init ( void  )

Subsystem initialization and shutdown. Call init() once to initialize the query subsystem; call shutdown() to free up any resources associated with the query subsystem. Typically called during application startup, shutdown.

Definition at line 1325 of file qofquery.c.

1326 {
1327  ENTER (" ");
1328  qof_query_core_init ();
1329  qof_class_init ();
1330  LEAVE ("Completed initialization of QofQuery");
1331 }
#define ENTER(format, args...)
Definition: qoflog.h:256
#define LEAVE(format, args...)
Definition: qoflog.h:266

◆ qof_query_invert()

QofQuery* qof_query_invert ( QofQuery *  q)

Make a copy of the indicated query, inverting the sense of the search. In other words, if the original query search for all objects with a certain condition, the inverted query will search for all object with NOT that condition. The union of the results returned by the original and inverted queries equals the set of all searched objects. These to sets are disjoint (share no members in common).

This will return a newly allocated QofQuery object, or NULL on error. Free it with qof_query_destroy() when no longer needed.

Definition at line 1016 of file qofquery.c.

1017 {
1018  QofQuery * retval;
1019  QofQuery * right, * left, * iright, * ileft;
1020  QofQueryTerm * qt;
1021  GList * aterms;
1022  GList * cur;
1023  GList * new_oterm;
1024  int num_or_terms;
1025 
1026  if (!q)
1027  return NULL;
1028 
1029  num_or_terms = g_list_length(q->terms);
1030 
1031  switch (num_or_terms)
1032  {
1033  case 0:
1034  retval = qof_query_create();
1035  retval->max_results = q->max_results;
1036  break;
1037 
1038  /* This is the DeMorgan expansion for a single AND expression. */
1039  /* !(abc) = !a + !b + !c */
1040  case 1:
1041  retval = qof_query_create();
1042  retval->max_results = q->max_results;
1043  retval->books = g_list_copy (q->books);
1044  retval->search_for = q->search_for;
1045  retval->changed = 1;
1046 
1047  aterms = g_list_nth_data(q->terms, 0);
1048  new_oterm = NULL;
1049  for (cur = aterms; cur; cur = cur->next)
1050  {
1051  qt = copy_query_term(cur->data);
1052  qt->invert = !(qt->invert);
1053  new_oterm = g_list_append(NULL, qt);
1054  retval->terms = g_list_prepend(retval->terms, new_oterm);
1055  }
1056  retval->terms = g_list_reverse(retval->terms);
1057  break;
1058 
1059  /* If there are multiple OR-terms, we just recurse by
1060  * breaking it down to !(a + b + c) =
1061  * !a * !(b + c) = !a * !b * !c. */
1062  default:
1063  right = qof_query_create();
1064  right->terms = copy_or_terms(g_list_nth(q->terms, 1));
1065 
1066  left = qof_query_create();
1067  left->terms = g_list_append(NULL,
1068  copy_and_terms(g_list_nth_data(q->terms, 0)));
1069 
1070  iright = qof_query_invert(right);
1071  ileft = qof_query_invert(left);
1072 
1073  retval = qof_query_merge(iright, ileft, QOF_QUERY_AND);
1074  retval->books = g_list_copy (q->books);
1075  retval->max_results = q->max_results;
1076  retval->search_for = q->search_for;
1077  retval->changed = 1;
1078 
1079  qof_query_destroy(iright);
1080  qof_query_destroy(ileft);
1081  qof_query_destroy(right);
1082  qof_query_destroy(left);
1083  break;
1084  }
1085 
1086  return retval;
1087 }
void qof_query_destroy(QofQuery *q)
Definition: qofquery.c:975
QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
Definition: qofquery.c:1095
QofQuery * qof_query_invert(QofQuery *q)
Definition: qofquery.c:1016
QofQuery * qof_query_create(void)
Definition: qofquery.c:886

◆ qof_query_kvp_predicate()

QofQueryPredData* qof_query_kvp_predicate ( QofQueryCompare  how,
QofQueryParamList path,
const KvpValue *  value 
)

The qof_query_kvp_predicate() matches the object that has the value 'value' located at the path 'path'. In a certain sense, the 'path' is handled as if it were a parameter.

Definition at line 1291 of file qofquerycore.c.

1293 {
1294  query_kvp_t pdata;
1295  QofQueryParamList *node;
1296 
1297  g_return_val_if_fail (path && value, NULL);
1298 
1299  pdata = g_new0 (query_kvp_def, 1);
1300  pdata->pd.type_name = query_kvp_type;
1301  pdata->pd.how = how;
1302  pdata->value = kvp_value_copy (value);
1303  pdata->path = g_slist_copy (path);
1304  for (node = pdata->path; node; node = node->next)
1305  node->data = g_strdup (node->data);
1306 
1307  return ((QofQueryPredData*)pdata);
1308 }
GSList QofQueryParamList
Definition: qofquerycore.h:145
KvpValue * kvp_value_copy(const KvpValue *value)
Definition: kvp_frame.c:1277

◆ qof_query_kvp_predicate_path()

QofQueryPredData* qof_query_kvp_predicate_path ( QofQueryCompare  how,
const gchar *  path,
const KvpValue *  value 
)

Same predicate as above, except that 'path' is assumed to be a string containing slash-separated pathname.

◆ qof_query_last_run()

GList* qof_query_last_run ( QofQuery *  query)

Return the results of the last query, without causing the query to be re-run. Do NOT free the resulting list. This list is managed internally by QofQuery.

Definition at line 865 of file qofquery.c.

866 {
867  if (!query)
868  return NULL;
869 
870  return query->results;
871 }

◆ qof_query_merge()

QofQuery* qof_query_merge ( QofQuery *  q1,
QofQuery *  q2,
QofQueryOp  op 
)

Combine two queries together using the Boolean set (logical) operator 'op'. For example, if the operator 'op' is set to QUERY_AND, then the set of results returned by the query will will be the Boolean set intersection of the results returned by q1 and q2. Similarly, QUERY_OR maps to set union, etc.

Both queries must have compatible search-types. If both queries are set, they must search for the same object type. If only one is set, the resulting query will search for the set type. If neither query has the search-type set, the result will be unset as well.

This will return a newly allocated QofQuery object, or NULL on error. Free it with qof_query_destroy() when no longer needed. Note that if either input query is NULL then the returned query is NOT newly allocated – it will return the non-NULL query. You only need to call this function when both q1 and q2 are non-NULL.

Definition at line 1095 of file qofquery.c.

1096 {
1097 
1098  QofQuery * retval = NULL;
1099  QofQuery * i1, * i2;
1100  QofQuery * t1, * t2;
1101  GList * i, * j;
1102  QofIdType search_for;
1103 
1104  if (!q1) return q2;
1105  if (!q2) return q1;
1106 
1107  if (q1->search_for && q2->search_for)
1108  g_return_val_if_fail (g_strcmp0 (q1->search_for, q2->search_for) == 0,
1109  NULL);
1110 
1111  search_for = (q1->search_for ? q1->search_for : q2->search_for);
1112 
1113  /* Avoid merge surprises if op==QOF_QUERY_AND but q1 is empty.
1114  * The goal of this tweak is to allow the user to start with
1115  * an empty q1 and then append to it recursively
1116  * (and q1 (and q2 (and q3 (and q4 ....))))
1117  * without bombing out because the append started with an
1118  * empty list.
1119  * We do essentially the same check in qof_query_add_term()
1120  * so that the first term added to an empty query doesn't screw up.
1121  */
1122  if ((QOF_QUERY_AND == op) &&
1123  ( (0 == qof_query_has_terms (q1)) || (0 == qof_query_has_terms (q2)) ))
1124  {
1125  op = QOF_QUERY_OR;
1126  }
1127 
1128  switch (op)
1129  {
1130  case QOF_QUERY_OR:
1131  retval = qof_query_create();
1132  retval->terms =
1133  g_list_concat(copy_or_terms(q1->terms), copy_or_terms(q2->terms));
1134  retval->books = merge_books (q1->books, q2->books);
1135  retval->max_results = q1->max_results;
1136  retval->changed = 1;
1137  break;
1138 
1139  case QOF_QUERY_AND:
1140  retval = qof_query_create();
1141  retval->books = merge_books (q1->books, q2->books);
1142  retval->max_results = q1->max_results;
1143  retval->changed = 1;
1144 
1145  /* g_list_append() can take forever, so let's build the list in
1146  * reverse and then reverse it at the end, to deal better with
1147  * "large" queries.
1148  */
1149  for (i = q1->terms; i; i = i->next)
1150  {
1151  for (j = q2->terms; j; j = j->next)
1152  {
1153  retval->terms =
1154  g_list_prepend(retval->terms,
1155  g_list_concat
1156  (copy_and_terms(i->data),
1157  copy_and_terms(j->data)));
1158  }
1159  }
1160  retval->terms = g_list_reverse(retval->terms);
1161  break;
1162 
1163  case QOF_QUERY_NAND:
1164  /* !(a*b) = (!a + !b) */
1165  i1 = qof_query_invert(q1);
1166  i2 = qof_query_invert(q2);
1167  retval = qof_query_merge(i1, i2, QOF_QUERY_OR);
1168  qof_query_destroy(i1);
1169  qof_query_destroy(i2);
1170  break;
1171 
1172  case QOF_QUERY_NOR:
1173  /* !(a+b) = (!a*!b) */
1174  i1 = qof_query_invert(q1);
1175  i2 = qof_query_invert(q2);
1176  retval = qof_query_merge(i1, i2, QOF_QUERY_AND);
1177  qof_query_destroy(i1);
1178  qof_query_destroy(i2);
1179  break;
1180 
1181  case QOF_QUERY_XOR:
1182  /* a xor b = (a * !b) + (!a * b) */
1183  i1 = qof_query_invert(q1);
1184  i2 = qof_query_invert(q2);
1185  t1 = qof_query_merge(q1, i2, QOF_QUERY_AND);
1186  t2 = qof_query_merge(i1, q2, QOF_QUERY_AND);
1187  retval = qof_query_merge(t1, t2, QOF_QUERY_OR);
1188 
1189  qof_query_destroy(i1);
1190  qof_query_destroy(i2);
1191  qof_query_destroy(t1);
1192  qof_query_destroy(t2);
1193  break;
1194  }
1195 
1196  retval->search_for = search_for;
1197  return retval;
1198 }
const gchar * QofIdType
Definition: qofid.h:80
void qof_query_destroy(QofQuery *q)
Definition: qofquery.c:975
QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
Definition: qofquery.c:1095
QofQuery * qof_query_invert(QofQuery *q)
Definition: qofquery.c:1016
int qof_query_has_terms(QofQuery *q)
Definition: qofquery.c:916
QofQuery * qof_query_create(void)
Definition: qofquery.c:886

◆ qof_query_merge_in_place()

void qof_query_merge_in_place ( QofQuery *  q1,
QofQuery *  q2,
QofQueryOp  op 
)

Like qof_query_merge, but this will merge a copy of q2 into q1. q2 remains unchanged.

Definition at line 1201 of file qofquery.c.

1202 {
1203  QofQuery *tmp_q;
1204 
1205  if (!q1 || !q2)
1206  return;
1207 
1208  tmp_q = qof_query_merge (q1, q2, op);
1209  swap_terms (q1, tmp_q);
1210  qof_query_destroy (tmp_q);
1211 }
void qof_query_destroy(QofQuery *q)
Definition: qofquery.c:975
QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
Definition: qofquery.c:1095

◆ qof_query_num_terms()

int qof_query_num_terms ( QofQuery *  q)

Return the number of terms in the canonical form of the query.

Definition at line 922 of file qofquery.c.

923 {
924  GList *o;
925  int n = 0;
926  if (!q) return 0;
927  for (o = q->terms; o; o = o->next)
928  n += g_list_length(o->data);
929  return n;
930 }

◆ qof_query_print()

void qof_query_print ( QofQuery *  query)

Log the Query

Deprecated:
Do not call directly, use the standard log module code: ::qof_log_set_level(QOF_MOD_QUERY, QOF_LOG_DEBUG); or ::qof_log_set_default(QOF_LOG_DEBUG);
Deprecated:
access via qof_log instead. The query will be logged automatically if qof_log_set_default or qof_log_set_level(QOF_MOD_QUERY, ...) are set to QOF_LOG_DEBUG or higher.

This function cycles through a QofQuery object, and prints out the values of the various members of the query

Definition at line 1502 of file qofquery.c.

1503 {
1504  GList *output;
1505  GString *str;
1506  QofQuerySort *s[3];
1507  gint maxResults = 0, numSorts = 3;
1508 
1509  ENTER (" ");
1510 
1511  if (!query)
1512  {
1513  LEAVE("query is (null)");
1514  return;
1515  }
1516 
1517  output = NULL;
1518  str = NULL;
1519  maxResults = qof_query_get_max_results (query);
1520 
1521  output = qof_query_printSearchFor (query, output);
1522  output = qof_query_printTerms (query, output);
1523 
1524  qof_query_get_sorts (query, &s[0], &s[1], &s[2]);
1525 
1526  if (s[0])
1527  {
1528  output = qof_query_printSorts (s, numSorts, output);
1529  }
1530 
1531  str = g_string_new (" ");
1532  g_string_printf (str, "Maximum number of results: %d", maxResults);
1533  output = g_list_append (output, str);
1534 
1535  qof_query_printOutput (output);
1536  LEAVE (" ");
1537 }
#define ENTER(format, args...)
Definition: qoflog.h:256
#define LEAVE(format, args...)
Definition: qoflog.h:266

◆ qof_query_purge_terms()

void qof_query_purge_terms ( QofQuery *  q,
QofQueryParamList param_list 
)

Remove query terms of a particular type from q. The "type" of a term is determined by the type of data that gets passed to the predicate function. XXX ??? Huh? remove anything of that predicate type, or just the particular predicate ?

Definition at line 675 of file qofquery.c.

676 {
677  QofQueryTerm *qt;
678  GList *or, *and;
679 
680  if (!q || !param_list) return;
681 
682  for (or = q->terms; or; or = or->next)
683  {
684  for (and = or->data; and; and = and->next)
685  {
686  qt = and->data;
687  if (!param_list_cmp (qt->param_list, param_list))
688  {
689  if (g_list_length (or->data) == 1)
690  {
691  q->terms = g_list_remove_link (q->terms, or);
692  g_list_free_1 (or);
693  or = q->terms;
694  break;
695  }
696  else
697  {
698  or->data = g_list_remove_link (or->data, and);
699  g_list_free_1 (and);
700  and = or->data;
701  if (!and) break;
702  }
703  q->changed = 1;
704  free_query_term (qt);
705  }
706  }
707  if (!or) break;
708  }
709 }

◆ qof_query_run()

GList* qof_query_run ( QofQuery *  query)

Perform the query, return the results. The returned list is a list of the 'search-for' type that was previously set with the qof_query_search_for() or the qof_query_create_for() routines. The returned list will have been sorted using the indicated sort order, and trimmed to the max_results length.

Do NOT free the resulting list. This list is managed internally by QofQuery.

Definition at line 833 of file qofquery.c.

834 {
835  /* Just a wrapper */
836  return qof_query_run_internal(q, qof_query_run_cb, NULL);
837 }

◆ qof_query_run_subquery()

GList* qof_query_run_subquery ( QofQuery *  subquery,
const QofQuery *  primary_query 
)

Perform a subquery, return the results. Instead of running over a book, the subquery runs over the results of the primary query.

Do NOT free the resulting list. This list is managed internally by QofQuery.

Definition at line 848 of file qofquery.c.

849 {
850  if (!subq) return NULL;
851  if (!primaryq) return NULL;
852 
853  /* Make sure we're searching for the same thing */
854  g_return_val_if_fail (subq->search_for, NULL);
855  g_return_val_if_fail (primaryq->search_for, NULL);
856  g_return_val_if_fail(!g_strcmp0(subq->search_for, primaryq->search_for),
857  NULL);
858 
859  /* Perform the subquery */
860  return qof_query_run_internal(subq, qof_query_run_subq_cb,
861  (gpointer)primaryq);
862 }

◆ qof_query_search_for()

void qof_query_search_for ( QofQuery *  query,
QofIdTypeConst  obj_type 
)

Set the object type to be searched for. The results of performing the query will be a list of this obj_type.

Definition at line 894 of file qofquery.c.

895 {
896  if (!q || !obj_type)
897  return;
898 
899  if (g_strcmp0 (q->search_for, obj_type))
900  {
901  q->search_for = (QofIdType) obj_type;
902  q->changed = 1;
903  }
904 }
const gchar * QofIdType
Definition: qofid.h:80

◆ qof_query_set_book()

void qof_query_set_book ( QofQuery *  q,
QofBook *  book 
)

Set the book to be searched. Books contain/identify collections of objects; the search will be performed over those books specified with this function. If no books are set, no results will be returned (since there is nothing to search over).

You can search multiple books. To specify multiple books, call this function multiple times with different arguments. XXX needed qof_query_clear_books() to reset the list ...

Definition at line 1291 of file qofquery.c.

1292 {
1293  QofQueryParamList *slist = NULL;
1294  if (!q || !book) return;
1295 
1296  /* Make sure this book is only in the list once */
1297  if (g_list_index (q->books, book) == -1)
1298  q->books = g_list_prepend (q->books, book);
1299 
1300  slist = g_slist_prepend (slist, QOF_PARAM_GUID);
1301  slist = g_slist_prepend (slist, QOF_PARAM_BOOK);
1302  qof_query_add_guid_match (q, slist,
1303  qof_instance_get_guid(book), QOF_QUERY_AND);
1304 }
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Definition: qofinstance.c:473
#define QOF_PARAM_BOOK
Definition: qofquery.h:104
GSList QofQueryParamList
Definition: qofquerycore.h:145
void qof_query_add_guid_match(QofQuery *q, QofQueryParamList *param_list, const GncGUID *guid, QofQueryOp op)
Definition: qofquery.c:1275

◆ qof_query_set_max_results()

void qof_query_set_max_results ( QofQuery *  q,
int  n 
)

Set the maximum number of results that should be returned. If 'max-results' is set to -1, then all of the results are returned. If there are more results than 'max-results', then the result list is trimmed. Note that there is an important interplay between 'max-results' and the sort order: only the last bit of results are returned. For example, if the sort order is set to be increasing date order, then only the objects with the most recent dates will be returned.

Definition at line 1254 of file qofquery.c.

1255 {
1256  if (!q) return;
1257  q->max_results = n;
1258 }

◆ qof_query_set_sort_increasing()

void qof_query_set_sort_increasing ( QofQuery *  q,
gboolean  prim_inc,
gboolean  sec_inc,
gboolean  tert_inc 
)

When a query is run, the results are sorted before being returned. This routine can be used to control the direction of the ordering. A value of TRUE indicates the sort will be in increasing order, a value of FALSE will order results in decreasing order.

Note that if there are more results than the 'max-results' value, then only the last max-results will be returned. For example, if the sort is set to be increasing date order, then only the objects with the most recent dates will be returned.

Definition at line 1245 of file qofquery.c.

1247 {
1248  if (!q) return;
1249  q->primary_sort.increasing = prim_inc;
1250  q->secondary_sort.increasing = sec_inc;
1251  q->tertiary_sort.increasing = tert_inc;
1252 }

◆ qof_query_set_sort_order()

void qof_query_set_sort_order ( QofQuery *  q,
QofQueryParamList primary_sort_params,
QofQueryParamList secondary_sort_params,
QofQueryParamList tertiary_sort_params 
)

When a query is run, the results are sorted before being returned. This routine can be used to set the parameters on which the sort will be performed. Two objects in the result list will be compared using the 'primary_sort_params', and sorted based on that order. If the comparison shows that they are equal, then the 'secondary_sort_params' will be used. If still equal, then the tertiary parameters will be compared. Any or all of these parameter lists may be NULL. Any of these parameter lists may be set to QUERY_DEFAULT_SORT.

Note that if there are more results than the 'max-results' value, then only the last max-results will be returned. For example, if the sort is set to be increasing date order, then only the objects with the most recent dates will be returned.

The input lists become the property of QofQuery and are managed by it. They will be freed when the query is destroyed (or when new lists are set).

Definition at line 1214 of file qofquery.c.

1216 {
1217  if (!q) return;
1218  if (q->primary_sort.param_list)
1219  g_slist_free (q->primary_sort.param_list);
1220  q->primary_sort.param_list = params1;
1221  q->primary_sort.options = 0;
1222 
1223  if (q->secondary_sort.param_list)
1224  g_slist_free (q->secondary_sort.param_list);
1225  q->secondary_sort.param_list = params2;
1226  q->secondary_sort.options = 0;
1227 
1228  if (q->tertiary_sort.param_list)
1229  g_slist_free (q->tertiary_sort.param_list);
1230  q->tertiary_sort.param_list = params3;
1231  q->tertiary_sort.options = 0;
1232 
1233  q->changed = 1;
1234 }

◆ qof_string_number_compare_func()

int qof_string_number_compare_func ( gpointer  a,
gpointer  b,
gint  options,
QofParam *  this_param 
)

Compare two parameter(strings) as if they are numbers! the two objects, a and b, are the objects being compared this_param is the QofParam for this parameter in the objects

Definition at line 193 of file qofquerycore.c.

195 {
196  const char *s1, *s2;
197  char *sr1, *sr2;
198  long i1, i2;
199  g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
200 
201  s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
202  s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
203 
204  // Deal with NULL strings
205  if (s1 == s2) return 0;
206  if (!s1 && s2) return -1;
207  if (s1 && !s2) return 1;
208 
209  // Convert to integers and test
210  i1 = strtol(s1, &sr1, 10);
211  i2 = strtol(s2, &sr2, 10);
212  if (i1 < i2) return -1;
213  if (i1 > i2) return 1;
214 
215  // If the integers match, then test the REST of the string as text.
216  if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
217  return safe_strcasecmp (sr1, sr2);
218 
219  return g_strcmp0 (sr1, sr2);
220 }
gint safe_strcasecmp(const gchar *da, const gchar *db)
Definition: qofutil.c:100