29 #include <sys/types.h> 36 #include "qof-backend.hpp" 37 #include "qofbook-p.h" 38 #include "qofclass-p.h" 39 #include "qofquery-p.h" 40 #include "qofquerycore-p.h" 42 static QofLogModule log_module = QOF_MOD_QUERY;
47 QofQueryPredData *pdata;
56 QofQueryPredicateFunc pred_fcn;
73 QofCompareFunc comp_fcn;
88 QofQuerySort primary_sort;
89 QofQuerySort secondary_sort;
90 QofQuerySort tertiary_sort;
100 GHashTable* be_compiled;
109 typedef struct _QofQueryCB
117 static void query_init (
QofQuery *q, QofQueryTerm *initial_term)
125 _or_ = g_list_alloc ();
126 _and_ = g_list_alloc ();
127 _and_->data = initial_term;
134 g_list_free (q->results);
135 g_list_free (q->books);
137 g_slist_free (q->primary_sort.param_list);
138 g_slist_free (q->secondary_sort.param_list);
139 g_slist_free (q->tertiary_sort.param_list);
141 g_slist_free (q->primary_sort.param_fcns);
142 g_slist_free (q->secondary_sort.param_fcns);
143 g_slist_free (q->tertiary_sort.param_fcns);
146 memset (q, 0,
sizeof (*q));
153 q->primary_sort.param_list = g_slist_prepend (static_cast<GSList*>(NULL),
155 q->primary_sort.increasing = TRUE;
156 q->secondary_sort.increasing = TRUE;
157 q->tertiary_sort.increasing = TRUE;
164 if (!q1 || !q2)
return;
167 q1->terms = q2->terms;
171 q1->books = q2->books;
178 static void free_query_term (QofQueryTerm *qt)
183 g_slist_free (qt->param_list);
184 g_slist_free (qt->param_fcns);
188 static QofQueryTerm * copy_query_term (
const QofQueryTerm *qt)
190 QofQueryTerm *new_qt;
191 if (!qt)
return NULL;
193 new_qt = g_new0 (QofQueryTerm, 1);
194 memcpy (new_qt, qt,
sizeof(QofQueryTerm));
195 new_qt->param_list = g_slist_copy (qt->param_list);
196 new_qt->param_fcns = g_slist_copy (qt->param_fcns);
201 static GList * copy_and_terms (
const GList *and_terms)
204 const GList *cur_and;
206 for (cur_and = and_terms; cur_and; cur_and = cur_and->next)
208 _and_ = g_list_prepend(_and_, copy_query_term (static_cast<QofQueryTerm*>(cur_and->data)));
211 return g_list_reverse(_and_);
215 copy_or_terms(
const GList * or_terms)
218 const GList * cur_or;
220 for (cur_or = or_terms; cur_or; cur_or = cur_or->next)
222 _or_ = g_list_prepend(_or_, copy_and_terms(static_cast<GList*>(cur_or->data)));
225 return g_list_reverse(_or_);
228 static void copy_sort (QofQuerySort *dst,
const QofQuerySort *src)
230 memcpy (dst, src,
sizeof (*dst));
231 dst->param_list = g_slist_copy (src->param_list);
232 dst->param_fcns = g_slist_copy (src->param_fcns);
235 static void free_sort (QofQuerySort *s)
237 g_slist_free (s->param_list);
238 s->param_list = NULL;
240 g_slist_free (s->param_fcns);
241 s->param_fcns = NULL;
244 static void free_members (
QofQuery *q)
248 if (q == NULL)
return;
250 for (cur_or = q->terms; cur_or; cur_or = cur_or->next)
254 for (cur_and = static_cast<GList*>(cur_or->data); cur_and;
255 cur_and = static_cast<GList*>(cur_and->next))
257 free_query_term(static_cast<QofQueryTerm*>(cur_and->data));
258 cur_and->data = NULL;
261 g_list_free(static_cast<GList*>(cur_or->data));
265 free_sort (&(q->primary_sort));
266 free_sort (&(q->secondary_sort));
267 free_sort (&(q->tertiary_sort));
269 g_list_free(q->terms);
272 g_list_free(q->books);
275 g_list_free(q->results);
279 static int cmp_func (
const QofQuerySort *sort,
QofSortFunc default_sort,
280 const gconstpointer a,
const gconstpointer b)
282 QofParam *param = NULL;
284 gpointer conva, convb;
286 g_return_val_if_fail (sort, 0);
289 if (sort->use_default)
291 if (default_sort)
return default_sort (a, b);
296 if (!sort->param_fcns)
return 0;
299 if (!sort->comp_fcn && !sort->obj_cmp)
return 0;
304 for (node = static_cast<GSList*>(sort->param_fcns); node;
305 node =
static_cast<GSList*
>(node->next))
307 param =
static_cast<QofParam*
>(node->data);
311 if (!node->next && !sort->obj_cmp)
315 conva = (param->param_getfcn) (conva, param);
316 convb = (param->param_getfcn) (convb, param);
322 int rc = sort->comp_fcn (conva, convb, sort->options, param);
326 return sort->obj_cmp (conva, convb);
330 sort_func (
const gconstpointer a,
const gconstpointer b,
const gpointer q)
335 g_return_val_if_fail (sortQuery, 0);
337 retval = cmp_func (&(sortQuery->primary_sort), sortQuery->defaultSort, a, b);
340 retval = cmp_func (&(sortQuery->secondary_sort), sortQuery->defaultSort,
344 retval = cmp_func (&(sortQuery->tertiary_sort), sortQuery->defaultSort,
346 return sortQuery->tertiary_sort.increasing ? retval : -retval;
350 return sortQuery->secondary_sort.increasing ? retval : -retval;
355 return sortQuery->primary_sort.increasing ? retval : -retval;
366 check_object (
const QofQuery *q, gpointer
object)
368 const GList * and_ptr;
369 const GList * or_ptr;
370 const QofQueryTerm * qt;
371 int and_terms_ok = 1;
373 for (or_ptr = q->terms; or_ptr; or_ptr = or_ptr->next)
376 for (and_ptr = static_cast<GList*>(or_ptr->data); and_ptr;
377 and_ptr = static_cast<GList*>(and_ptr->next))
379 qt = (QofQueryTerm *)(and_ptr->data);
380 if (qt->param_fcns && qt->pred_fcn)
383 QofParam *param = NULL;
384 gpointer conv_obj = object;
387 for (node = qt->param_fcns; node; node = node->next)
389 param =
static_cast<QofParam*
>(node->data);
392 if (!node->next)
break;
394 conv_obj = param->param_getfcn (conv_obj, param);
397 if (((qt->pred_fcn)(conv_obj, param, qt->pdata)) == qt->invert)
419 if (NULL == q->terms)
return 1;
431 QofParam
const **
final)
433 const QofParam *objDef = NULL;
436 ENTER (
"param_list=%p id=%s", param_list, start_obj);
437 g_return_val_if_fail (param_list, NULL);
438 g_return_val_if_fail (start_obj, NULL);
439 g_return_val_if_fail (
final, NULL);
441 for (; param_list; param_list = param_list->next)
450 fcns = g_slist_prepend (fcns, (gpointer) objDef);
456 start_obj = (
QofIdType) objDef->param_type;
459 LEAVE (
"fcns=%p", fcns);
460 return (g_slist_reverse (fcns));
464 compile_sort (QofQuerySort *sort,
QofIdType obj)
466 const QofParam *resObj = NULL;
468 ENTER (
"sort=%p id=%s params=%p", sort, obj, sort->param_list);
469 sort->use_default = FALSE;
471 g_slist_free (sort->param_fcns);
472 sort->param_fcns = NULL;
473 sort->comp_fcn = NULL;
474 sort->obj_cmp = NULL;
477 if (!sort->param_list)
484 sort->param_fcns = compile_params (sort->param_list, obj, &resObj);
489 if (sort->param_fcns && resObj)
494 if (resObj->param_compfcn)
495 sort->comp_fcn = resObj->param_compfcn;
497 sort->comp_fcn = qof_query_core_get_compare (resObj->param_type);
500 if (sort->comp_fcn == NULL)
501 sort->obj_cmp = qof_class_get_default_sort (resObj->param_type);
503 else if (!g_strcmp0 (static_cast<char*>(sort->param_list->data),
506 sort->use_default = TRUE;
508 LEAVE (
"sort=%p id=%s", sort, obj);
511 static void compile_terms (
QofQuery *q)
513 GList *or_ptr, *and_ptr, *node;
515 ENTER (
" query=%p", q);
519 for (or_ptr = q->terms; or_ptr; or_ptr = or_ptr->next)
521 for (and_ptr = static_cast<GList*>(or_ptr->data); and_ptr;
522 and_ptr = static_cast<GList*>(and_ptr->next))
524 QofQueryTerm* qt =
static_cast<QofQueryTerm*
>(and_ptr->data);
525 const QofParam* resObj = NULL;
527 g_slist_free (qt->param_fcns);
528 qt->param_fcns = NULL;
531 qt->param_fcns = compile_params (qt->param_list, q->search_for,
538 if (qt->param_fcns && resObj)
539 qt->pred_fcn = qof_query_core_get_predicate (resObj->param_type);
546 compile_sort (&(q->primary_sort), q->search_for);
547 compile_sort (&(q->secondary_sort), q->search_for);
548 compile_sort (&(q->tertiary_sort), q->search_for);
550 q->defaultSort = qof_class_get_default_sort (q->search_for);
551 #ifdef QOF_BACKEND_QUERY 553 for (node = q->books; node; node = node->next)
555 QofBook* book =
static_cast<QofBook*
>(node->data);
558 if (be && be->compile_query)
560 gpointer result = (be->compile_query)(be, q);
562 g_hash_table_insert (q->be_compiled, book, result);
567 LEAVE (
" query=%p", q);
570 static void check_item_cb (gpointer
object, gpointer user_data)
574 if (!
object || !ql)
return;
576 if (check_object (ql->query,
object))
578 ql->list = g_list_prepend (ql->list,
object);
592 if (!l1 && !l2)
return 0;
593 if (!l1 && l2)
return -1;
594 if (l1 && !l2)
return 1;
596 ret = g_strcmp0 (static_cast<char*>(l1->data),
597 static_cast<char*>(l2->data));
607 static GList * merge_books (GList *l1, GList *l2)
612 res = g_list_copy (l1);
614 for (node = l2; node; node = node->next)
616 if (g_list_index (res, node->data) == -1)
617 res = g_list_prepend (res, node->data);
624 query_free_compiled (gpointer key, gpointer value, gpointer not_used)
626 #ifdef QOF_BACKEND_QUERY 627 QofBook* book =
static_cast<QofBook*
>(key);
630 if (be && be->free_query)
631 (be->free_query)(be, value);
637 static void query_clear_compiles (
QofQuery *q)
639 g_hash_table_foreach_remove (q->be_compiled, query_free_compiled, NULL);
646 qof_query_build_param_list (
char const *param, ...)
649 char const *this_param;
655 va_start (ap, param);
657 for (this_param = param; this_param; this_param = va_arg (ap,
const char *))
658 param_list = g_slist_prepend (param_list, (gpointer)this_param);
662 return g_slist_reverse (param_list);
671 if (!q || !param_list || !pred_data)
return;
673 qt = g_new0 (QofQueryTerm, 1);
674 qt->param_list = param_list;
675 qt->pdata = pred_data;
679 if (q->terms != NULL)
694 if (!q || !param_list)
return;
696 for (_or_ = q->terms; _or_; _or_ = _or_->next)
698 for (_and_ = static_cast<GList*>(_or_->data); _and_;
699 _and_ = static_cast<GList*>(_and_->next))
701 qt =
static_cast<QofQueryTerm*
>(_and_->data);
702 if (!param_list_cmp (qt->param_list, param_list))
704 auto or_list =
static_cast<GList*
> (_or_->data);
705 if (or_list && !or_list->next)
707 q->terms = g_list_remove_link (static_cast<GList*>(q->terms), _or_);
708 g_list_free_1 (_or_);
714 _or_->data = g_list_remove_link (or_list, _and_);
715 g_list_free_1 (_and_);
716 _and_ =
static_cast<GList*
>(_or_->data);
720 free_query_term (qt);
727 static GList * qof_query_run_internal (
QofQuery *q,
731 GList *matching_objects = NULL;
732 int object_count = 0;
735 g_return_val_if_fail (q->search_for, NULL);
736 g_return_val_if_fail (q->books, NULL);
737 g_return_val_if_fail (run_cb, NULL);
745 query_clear_compiles (q);
757 memset (&qcb, 0,
sizeof (qcb));
761 run_cb(&qcb, cb_arg);
763 matching_objects = qcb.list;
764 object_count = qcb.count;
766 PINFO (
"matching objects=%p count=%d", matching_objects, object_count);
774 matching_objects = g_list_reverse(matching_objects);
777 if (q->primary_sort.comp_fcn || q->primary_sort.obj_cmp ||
778 (q->primary_sort.use_default && q->defaultSort))
780 matching_objects = g_list_sort_with_data(matching_objects, sort_func, q);
784 if ((object_count > q->max_results) && (q->max_results > -1))
786 if (q->max_results > 0)
791 mptr = g_list_nth(matching_objects, object_count - q->max_results);
795 if (mptr->prev != NULL) mptr->prev->next = NULL;
798 g_list_free(matching_objects);
799 matching_objects = mptr;
804 g_list_free(matching_objects);
805 matching_objects = NULL;
811 g_list_free(q->results);
812 q->results = matching_objects;
815 return matching_objects;
818 static void qof_query_run_cb(
QofQueryCB* qcb, gpointer cb_arg)
823 g_return_if_fail(qcb);
825 for (node = qcb->query->books; node; node = node->next)
827 QofBook* book =
static_cast<QofBook*
>(node->data);
828 #ifdef QOF_BACKEND_QUERY 834 gpointer compiled_query = g_hash_table_lookup (qcb->query->be_compiled,
837 if (compiled_query && be->run_query)
839 (be->run_query) (be, compiled_query);
852 return qof_query_run_internal(q, qof_query_run_cb, NULL);
855 static void qof_query_run_subq_cb(
QofQueryCB* qcb, gpointer cb_arg)
859 g_return_if_fail(pq);
866 if (!subq)
return NULL;
867 if (!primaryq)
return NULL;
870 g_return_val_if_fail (subq->search_for, NULL);
871 g_return_val_if_fail (primaryq->search_for, NULL);
872 g_return_val_if_fail(!g_strcmp0(subq->search_for, primaryq->search_for),
876 return qof_query_run_internal(subq, qof_query_run_subq_cb,
886 return query->results;
892 swap_terms (query, q2);
895 g_list_free (query->books);
897 g_list_free (query->results);
898 query->results = NULL;
905 qp->be_compiled = g_hash_table_new (g_direct_hash, g_direct_equal);
906 query_init (qp, NULL);
915 if (g_strcmp0 (q->search_for, obj_type))
935 return g_list_length (q->terms);
943 for (o = q->terms; o; o = o->next)
944 n += g_list_length(static_cast<GList*>(o->data));
953 if (!q || !term_param)
956 for (_or_ = q->terms; _or_; _or_ = _or_->next)
958 for (_and_ = static_cast<GList*>(_or_->data); _and_;
959 _and_ = static_cast<GList*>(_and_->next))
961 QofQueryTerm* qt =
static_cast<QofQueryTerm*
>(_and_->data);
962 if (!param_list_cmp (term_param, qt->param_list))
974 GSList *results = NULL;
976 if (!q || !term_param)
979 for (_or_ = q->terms; _or_; _or_ = _or_->next)
981 for (_and_ = static_cast<GList*>(_or_->data); _and_;
982 _and_ = static_cast<GList*>(_and_->next))
984 QofQueryTerm *qt =
static_cast<QofQueryTerm*
>(_and_->data);
985 if (!param_list_cmp (term_param, qt->param_list))
986 results = g_slist_prepend (results, qt->pdata);
990 return g_slist_reverse (results);
997 query_clear_compiles (q);
998 g_hash_table_destroy (q->be_compiled);
1007 if (!q)
return NULL;
1009 ht = copy->be_compiled;
1010 free_members (copy);
1012 memcpy (copy, q,
sizeof (
QofQuery));
1014 copy->be_compiled = ht;
1015 copy->terms = copy_or_terms (q->terms);
1016 copy->books = g_list_copy (q->books);
1017 copy->results = g_list_copy (q->results);
1019 copy_sort (&(copy->primary_sort), &(q->primary_sort));
1020 copy_sort (&(copy->secondary_sort), &(q->secondary_sort));
1021 copy_sort (&(copy->tertiary_sort), &(q->tertiary_sort));
1037 QofQuery * right, * left, * iright, * ileft;
1047 num_or_terms = g_list_length(q->terms);
1049 switch (num_or_terms)
1053 retval->max_results = q->max_results;
1060 retval->max_results = q->max_results;
1061 retval->books = g_list_copy (q->books);
1062 retval->search_for = q->search_for;
1063 retval->changed = 1;
1065 aterms =
static_cast<GList*
>(g_list_nth_data(q->terms, 0));
1067 for (cur = aterms; cur; cur = cur->next)
1069 qt = copy_query_term(static_cast<QofQueryTerm*>(cur->data));
1070 qt->invert = !(qt->invert);
1071 new_oterm = g_list_append(NULL, qt);
1072 retval->terms = g_list_prepend(retval->terms, new_oterm);
1074 retval->terms = g_list_reverse(retval->terms);
1082 right->terms = copy_or_terms(g_list_nth(q->terms, 1));
1085 left->terms = g_list_append(NULL,
1086 copy_and_terms(static_cast<GList*>(g_list_nth_data(q->terms, 0))));
1092 retval->books = g_list_copy (q->books);
1093 retval->max_results = q->max_results;
1094 retval->search_for = q->search_for;
1095 retval->changed = 1;
1125 if (q1->search_for && q2->search_for)
1126 g_return_val_if_fail (g_strcmp0 (q1->search_for, q2->search_for) == 0,
1129 search_for = (q1->search_for ? q1->search_for : q2->search_for);
1140 if ((QOF_QUERY_AND == op) &&
1141 (q1->terms == NULL || q2->terms == NULL))
1151 g_list_concat(copy_or_terms(q1->terms), copy_or_terms(q2->terms));
1152 retval->books = merge_books (q1->books, q2->books);
1153 retval->max_results = q1->max_results;
1154 retval->changed = 1;
1159 retval->books = merge_books (q1->books, q2->books);
1160 retval->max_results = q1->max_results;
1161 retval->changed = 1;
1167 for (i = q1->terms; i; i = i->next)
1169 for (j = q2->terms; j; j = j->next)
1172 g_list_prepend(retval->terms,
1174 (copy_and_terms(static_cast<GList*>(i->data)),
1175 copy_and_terms(static_cast<GList*>(j->data))));
1178 retval->terms = g_list_reverse(retval->terms);
1181 case QOF_QUERY_NAND:
1214 retval->search_for = search_for;
1227 swap_terms (q1, tmp_q);
1236 if (q->primary_sort.param_list)
1237 g_slist_free (q->primary_sort.param_list);
1238 q->primary_sort.param_list = params1;
1239 q->primary_sort.options = 0;
1241 if (q->secondary_sort.param_list)
1242 g_slist_free (q->secondary_sort.param_list);
1243 q->secondary_sort.param_list = params2;
1244 q->secondary_sort.options = 0;
1246 if (q->tertiary_sort.param_list)
1247 g_slist_free (q->tertiary_sort.param_list);
1248 q->tertiary_sort.param_list = params3;
1249 q->tertiary_sort.options = 0;
1254 void qof_query_set_sort_options (
QofQuery *q, gint prim_op, gint sec_op,
1258 q->primary_sort.options = prim_op;
1259 q->secondary_sort.options = sec_op;
1260 q->tertiary_sort.options = tert_op;
1264 gboolean sec_inc, gboolean tert_inc)
1267 q->primary_sort.increasing = prim_inc;
1268 q->secondary_sort.increasing = sec_inc;
1269 q->tertiary_sort.increasing = tert_inc;
1282 QofQueryPredData *pdata;
1284 if (!q || !param_list)
return;
1287 g_return_if_fail (options == QOF_GUID_MATCH_NULL);
1289 pdata = qof_query_guid_predicate (options, guid_list);
1298 if (!q || !param_list)
return;
1301 g = g_list_prepend (g, (gpointer)guid);
1312 if (!q || !book)
return;
1315 if (g_list_index (q->books, book) == -1)
1316 q->books = g_list_prepend (q->books, book);
1318 slist = g_slist_prepend (slist, static_cast<void*>(const_cast<char*>(QOF_PARAM_GUID)));
1319 slist = g_slist_prepend (slist, static_cast<void*>(const_cast<char*>(
QOF_PARAM_BOOK)));
1326 if (!q)
return NULL;
1333 QofQueryPredData *pdata;
1334 if (!q || !param_list)
return;
1336 pdata = qof_query_boolean_predicate (QOF_COMPARE_EQUAL, value);
1346 qof_query_core_init ();
1348 LEAVE (
"Completed initialization of QofQuery");
1351 void qof_query_shutdown (
void)
1353 qof_class_shutdown ();
1354 qof_query_core_shutdown ();
1357 int qof_query_get_max_results (
const QofQuery *q)
1360 return q->max_results;
1365 if (!q)
return NULL;
1366 return q->search_for;
1369 GList * qof_query_get_terms (
const QofQuery *q)
1371 if (!q)
return NULL;
1379 return qt->param_list;
1382 QofQueryPredData *qof_query_term_get_pred_data (
const QofQueryTerm *qt)
1389 gboolean qof_query_term_is_inverted (
const QofQueryTerm *qt)
1396 void qof_query_get_sorts (
QofQuery *q, QofQuerySort **primary,
1397 QofQuerySort **secondary, QofQuerySort **tertiary)
1402 *primary = &(q->primary_sort);
1404 *secondary = &(q->secondary_sort);
1406 *tertiary = &(q->tertiary_sort);
1413 return qs->param_list;
1416 gint qof_query_sort_get_sort_options (
const QofQuerySort *qs)
1423 gboolean qof_query_sort_get_increasing (
const QofQuerySort *qs)
1427 return qs->increasing;
1431 qof_query_term_equal (
const QofQueryTerm *qt1,
const QofQueryTerm *qt2)
1433 if (qt1 == qt2)
return TRUE;
1434 if (!qt1 || !qt2)
return FALSE;
1436 if (qt1->invert != qt2->invert)
return FALSE;
1437 if (param_list_cmp (qt1->param_list, qt2->param_list))
return FALSE;
1438 return qof_query_core_predicate_equal (qt1->pdata, qt2->pdata);
1442 qof_query_sort_equal (
const QofQuerySort* qs1,
const QofQuerySort* qs2)
1444 if (qs1 == qs2)
return TRUE;
1445 if (!qs1 || !qs2)
return FALSE;
1448 if (!qs1->param_list && !qs2->param_list)
return TRUE;
1450 if (qs1->options != qs2->options)
return FALSE;
1451 if (qs1->increasing != qs2->increasing)
return FALSE;
1452 return (param_list_cmp (qs1->param_list, qs2->param_list) == 0);
1459 if (q1 == q2)
return TRUE;
1460 if (!q1 || !q2)
return FALSE;
1462 if (q1->max_results != q2->max_results)
return FALSE;
1464 for (or1 = q1->terms, or2 = q2->terms; or1 || or2;
1465 or1 = or1->next, or2 = or2->next)
1471 and1 =
static_cast<GList*
>(or1->data);
1472 and2 =
static_cast<GList*
>(or2->data);
1474 for (; and1 || and2; and1 = and1->next, and2 = and2->next)
1478 if (!qof_query_term_equal (static_cast<QofQueryTerm*>(and1->data),
1479 static_cast<QofQueryTerm*
>(and2->data)))
1484 if (!qof_query_sort_equal (&(q1->primary_sort), &(q2->primary_sort)))
1486 if (!qof_query_sort_equal (&(q1->secondary_sort), &(q2->secondary_sort)))
1488 if (!qof_query_sort_equal (&(q1->tertiary_sort), &(q2->tertiary_sort)))
1499 static GList *qof_query_printSearchFor (
QofQuery * query, GList * output);
1500 static GList *qof_query_printTerms (
QofQuery * query, GList * output);
1501 static GList *qof_query_printSorts (QofQuerySort *s[],
const gint numSorts,
1503 static GList *qof_query_printAndTerms (GList * terms, GList * output);
1505 static const char *qof_query_printStringMatch (
QofStringMatch s);
1506 static const char *qof_query_printDateMatch (
QofDateMatch d);
1508 static const char *qof_query_printGuidMatch (
QofGuidMatch g);
1509 static const char *qof_query_printCharMatch (
QofCharMatch c);
1510 static GList *qof_query_printPredData (QofQueryPredData *pd, GList *lst);
1512 static void qof_query_printValueForParam (QofQueryPredData *pd, GString * gs);
1513 static void qof_query_printOutput (GList * output);
1528 gint maxResults = 0, numSorts = 3;
1534 LEAVE(
"query is (null)");
1540 maxResults = qof_query_get_max_results (query);
1542 output = qof_query_printSearchFor (query, output);
1543 output = qof_query_printTerms (query, output);
1545 qof_query_get_sorts (query, &s[0], &s[1], &s[2]);
1549 output = qof_query_printSorts (s, numSorts, output);
1552 str = g_string_new (
" ");
1553 g_string_printf (str,
"Maximum number of results: %d", maxResults);
1554 output = g_list_append (output, str);
1556 qof_query_printOutput (output);
1561 qof_query_printOutput (GList * output)
1565 for (lst = output; lst; lst = lst->next)
1567 GString *line = (GString *) lst->data;
1569 DEBUG (
" %s", line->str);
1570 g_string_free (line, TRUE);
1580 qof_query_printSearchFor (
QofQuery * query, GList * output)
1586 gs = g_string_new (
"Query Object Type: ");
1587 g_string_append (gs, (NULL == searchFor) ?
"(null)" : searchFor);
1588 output = g_list_append (output, gs);
1599 qof_query_printTerms (
QofQuery * query, GList * output)
1604 terms = qof_query_get_terms (query);
1606 for (lst = terms; lst; lst = lst->next)
1608 output = g_list_append (output, g_string_new (
"OR and AND Terms:"));
1612 output = qof_query_printAndTerms (static_cast<GList*>(lst->data),
1618 g_list_append (output, g_string_new (
" No data for AND terms"));
1631 qof_query_printSorts (QofQuerySort *s[],
const gint numSorts, GList * output)
1635 GString *gs = g_string_new (
"Sort Parameters: ");
1637 for (curSort = 0; curSort < numSorts; curSort++)
1639 gboolean increasing;
1644 increasing = qof_query_sort_get_increasing (s[curSort]);
1646 gsl = qof_query_sort_get_param_path (s[curSort]);
1647 if (gsl) g_string_append_printf (gs,
" Param: ");
1648 for (n = gsl; n; n = n->next)
1651 if (gsl != n) g_string_append_printf (gs,
" ");
1652 g_string_append_printf (gs,
"%s", param_name);
1656 g_string_append_printf (gs,
" %s ", increasing ?
"DESC" :
"ASC");
1657 g_string_append_printf (gs,
" Options: 0x%x ", s[curSort]->options);
1661 output = g_list_append (output, gs);
1671 qof_query_printAndTerms (GList * terms, GList * output)
1673 const char *prefix =
"AND Terms:";
1675 QofQueryPredData *pd;
1680 output = g_list_append (output, g_string_new (prefix));
1681 for (lst = terms; lst; lst = lst->next)
1683 qt = (QofQueryTerm *) lst->data;
1684 pd = qof_query_term_get_pred_data (qt);
1685 path = qof_query_term_get_param_path (qt);
1686 invert = qof_query_term_is_inverted (qt);
1688 if (invert) output = g_list_append (output,
1689 g_string_new(
" INVERT SENSE "));
1690 output = g_list_append (output, qof_query_printParamPath (path));
1691 output = qof_query_printPredData (pd, output);
1705 GString *gs = g_string_new (
"Param List: ");
1706 g_string_append (gs,
" ");
1707 for (list = parmList; list; list = list->next)
1709 g_string_append (gs, (gchar *) list->data);
1711 g_string_append (gs,
"->");
1721 qof_query_printPredData (QofQueryPredData *pd, GList *lst)
1725 gs = g_string_new (
"Pred Data: ");
1726 g_string_append (gs, (gchar *) pd->type_name);
1729 if (g_strcmp0 (pd->type_name, QOF_TYPE_CHAR) &&
1730 g_strcmp0 (pd->type_name, QOF_TYPE_GUID))
1732 g_string_append_printf (gs,
" how: %s",
1733 qof_query_printStringForHow (pd->how));
1735 lst = g_list_append(lst, gs);
1736 gs = g_string_new (
"");
1737 qof_query_printValueForParam (pd, gs);
1738 lst = g_list_append(lst, gs);
1752 case QOF_COMPARE_LT:
1753 return "QOF_COMPARE_LT";
1754 case QOF_COMPARE_LTE:
1755 return "QOF_COMPARE_LTE";
1756 case QOF_COMPARE_EQUAL:
1757 return "QOF_COMPARE_EQUAL";
1758 case QOF_COMPARE_GT:
1759 return "QOF_COMPARE_GT";
1760 case QOF_COMPARE_GTE:
1761 return "QOF_COMPARE_GTE";
1762 case QOF_COMPARE_NEQ:
1763 return "QOF_COMPARE_NEQ";
1764 case QOF_COMPARE_CONTAINS:
1765 return "QOF_COMPARE_CONTAINS";
1766 case QOF_COMPARE_NCONTAINS:
1767 return "QOF_COMPARE_NCONTAINS";
1770 return "INVALID HOW";
1775 qof_query_printValueForParam (QofQueryPredData *pd, GString * gs)
1778 if (!g_strcmp0 (pd->type_name, QOF_TYPE_GUID))
1782 g_string_append_printf (gs,
"Match type %s",
1783 qof_query_printGuidMatch (pdata->options));
1784 for (node = pdata->guids; node; node = node->next)
1788 g_string_append_printf (gs,
", guids: %s",guidstr);
1792 if (!g_strcmp0 (pd->type_name, QOF_TYPE_STRING))
1795 g_string_append_printf (gs,
" Match type %s",
1796 qof_query_printStringMatch (pdata->options));
1797 g_string_append_printf (gs,
" %s string: %s",
1798 pdata->is_regex ?
"Regex" :
"Not regex",
1799 pdata->matchstring);
1802 if (!g_strcmp0 (pd->type_name, QOF_TYPE_NUMERIC))
1805 g_string_append_printf (gs,
" Match type %s",
1806 qof_query_printNumericMatch (pdata->options));
1807 g_string_append_printf (gs,
" gnc_numeric: %s",
1811 if (!g_strcmp0 (pd->type_name, QOF_TYPE_INT64))
1814 g_string_append_printf (gs,
" int64: %" G_GINT64_FORMAT, pdata->val);
1817 if (!g_strcmp0 (pd->type_name, QOF_TYPE_INT32))
1820 g_string_append_printf (gs,
" int32: %d", pdata->val);
1823 if (!g_strcmp0 (pd->type_name, QOF_TYPE_DOUBLE))
1826 g_string_append_printf (gs,
" double: %.18g", pdata->val);
1829 if (!g_strcmp0 (pd->type_name, QOF_TYPE_DATE))
1833 memset (datebuff, 0,
sizeof(datebuff));
1835 g_string_append_printf (gs,
" Match type %s",
1836 qof_query_printDateMatch (pdata->options));
1837 g_string_append_printf (gs,
" query_date: %s", datebuff);
1840 if (!g_strcmp0 (pd->type_name, QOF_TYPE_CHAR))
1843 g_string_append_printf (gs,
" Match type %s",
1844 qof_query_printCharMatch (pdata->options));
1845 g_string_append_printf (gs,
" char list: %s", pdata->char_list);
1848 if (!g_strcmp0 (pd->type_name, QOF_TYPE_BOOLEAN))
1851 g_string_append_printf (gs,
" boolean: %s", pdata->val ?
"TRUE" :
"FALSE");
1867 case QOF_STRING_MATCH_NORMAL:
1868 return "QOF_STRING_MATCH_NORMAL";
1869 case QOF_STRING_MATCH_CASEINSENSITIVE:
1870 return "QOF_STRING_MATCH_CASEINSENSITIVE";
1872 return "UNKNOWN MATCH TYPE";
1884 case QOF_DATE_MATCH_NORMAL:
1885 return "QOF_DATE_MATCH_NORMAL";
1886 case QOF_DATE_MATCH_DAY:
1887 return "QOF_DATE_MATCH_DAY";
1889 return "UNKNOWN MATCH TYPE";
1901 case QOF_NUMERIC_MATCH_DEBIT:
1902 return "QOF_NUMERIC_MATCH_DEBIT";
1903 case QOF_NUMERIC_MATCH_CREDIT:
1904 return "QOF_NUMERIC_MATCH_CREDIT";
1905 case QOF_NUMERIC_MATCH_ANY:
1906 return "QOF_NUMERIC_MATCH_ANY";
1908 return "UNKNOWN MATCH TYPE";
1921 return "QOF_GUID_MATCH_ANY";
1923 return "QOF_GUID_MATCH_ALL";
1924 case QOF_GUID_MATCH_NONE:
1925 return "QOF_GUID_MATCH_NONE";
1926 case QOF_GUID_MATCH_NULL:
1927 return "QOF_GUID_MATCH_NULL";
1929 return "QOF_GUID_MATCH_LIST_ANY";
1932 return "UNKNOWN MATCH TYPE";
1944 case QOF_CHAR_MATCH_ANY:
1945 return "QOF_CHAR_MATCH_ANY";
1946 case QOF_CHAR_MATCH_NONE:
1947 return "QOF_CHAR_MATCH_NONE";
1949 return "UNKNOWN MATCH TYPE";
void qof_query_add_term(QofQuery *q, QofQueryParamList *param_list, QofQueryPredData *pred_data, QofQueryOp op)
This is the general function that adds a new Query Term to a query.
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
#define PINFO(format, args...)
Print an informational note.
void qof_query_core_predicate_free(QofQueryPredData *pdata)
Destroy a predicate.
void qof_query_set_sort_order(QofQuery *q, QofQueryParamList *params1, QofQueryParamList *params2, QofQueryParamList *params3)
When a query is run, the results are sorted before being returned.
void qof_query_purge_terms(QofQuery *q, QofQueryParamList *param_list)
Remove query terms of a particular type from q.
const gchar * QofIdTypeConst
QofIdTypeConst declaration.
void qof_query_print(QofQuery *query)
Log the Query.
#define DEBUG(format, args...)
Print a debugging message.
void(* QofInstanceForeachCB)(QofInstance *, gpointer user_data)
Callback type for qof_collection_foreach.
QofQuery * qof_query_copy(QofQuery *q)
Make a copy of the indicated query.
gboolean qof_query_equal(const QofQuery *q1, const QofQuery *q2)
Compare two queries for equality.
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
QofStringMatch
List of known core query data-types...
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
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.
These expect a single object and expect the QofAccessFunc returns GncGUID*.
#define ENTER(format, args...)
Print a function entry debugging message.
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
GSList QofQueryParamList
A list of parameters (QofIdType) used to describe a parameter to use in a predicate or when sorting...
void qof_query_set_max_results(QofQuery *q, int n)
Set the maximum number of results that should be returned.
gboolean qof_log_check(QofLogModule domain, QofLogLevel level)
Check to see if the given log_module is configured to log at the given log_level. ...
const gchar * QofIdType
QofIdType declaration.
int qof_query_num_terms(QofQuery *q)
Return the number of terms in the canonical form of the query.
const QofParam * qof_class_get_parameter(QofIdTypeConst obj_name, const char *parameter)
Return the registered Parameter Definition for the requested parameter.
GList * qof_query_run_subquery(QofQuery *subq, const QofQuery *primaryq)
Perform a subquery, return the results.
void qof_query_destroy(QofQuery *q)
Frees the resources associate with a Query object.
void qof_query_init(void)
Subsystem initialization and shutdown.
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
void qof_query_set_book(QofQuery *q, QofBook *book)
Set the book to be searched.
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
Invoke the callback 'cb' on every instance ov a particular object type.
QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
Combine two queries together using the Boolean set (logical) operator 'op'.
QofQueryCompare
Standard Query comparators, for how to compare objects in a predicate.
QofCharMatch
A CHAR type is for a RECNCell, Comparisons for QOF_TYPE_CHAR 'ANY' will match any character in the st...
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
These expect a single object and expect the QofAccessFunc function to return a GList* of GncGUID* (th...
QofQuery * qof_query_invert(QofQuery *q)
Make a copy of the indicated query, inverting the sense of the search.
void qof_query_clear(QofQuery *query)
Remove all query terms from query.
gboolean qof_query_has_term_type(QofQuery *q, QofQueryParamList *term_param)
DOCUMENT ME !!
These expect a GList* of objects and calls the QofAccessFunc routine on each item in the list to obta...
void qof_query_add_guid_match(QofQuery *q, QofQueryParamList *param_list, const GncGUID *guid, QofQueryOp op)
DOCUMENT ME !!
GList * qof_query_last_run(QofQuery *query)
Return the results of the last query, without causing the query to be re-run.
QofQueryOp
Query Term Operators, for combining Query Terms.
GList * qof_query_run(QofQuery *q)
Perform the query, return the results.
QofIdType qof_query_get_search_for(const QofQuery *q)
Return the type of data we're querying for.
QofDateMatch
Comparisons for QOF_TYPE_DATE The QOF_DATE_MATCH_DAY comparison rounds the two time values to mid-day...
#define LEAVE(format, args...)
Print a function exit debugging message.
#define QUERY_DEFAULT_SORT
Default sort object type.
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 quer...
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...
QofQueryPredData * qof_query_core_predicate_copy(const QofQueryPredData *pdata)
Copy a predicate.
The type used to store guids in C.
QofNumericMatch
Comparisons for QOF_TYPE_NUMERIC, QOF_TYPE_DEBCRED.
QofQuery * qof_query_create(void)
Create a new query.
void qof_query_add_guid_list_match(QofQuery *q, QofQueryParamList *param_list, GList *guid_list, QofGuidMatch options, QofQueryOp op)
DOCUMENT ME !!
void qof_query_search_for(QofQuery *q, QofIdTypeConst obj_type)
Set the object type to be searched for.
size_t qof_print_date_buff(char *buff, size_t buflen, time64 secs)
Convenience: calls through to qof_print_date_dmy_buff().
GList * qof_query_get_books(QofQuery *q)
Return the list of books we're using.
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.