27 #include <sys/types.h> 33 #include "qof-backend.hpp" 34 #include "qofbook-p.h" 35 #include "qofclass-p.h" 36 #include "qofquery-p.h" 37 #include "qofquerycore-p.h" 39 static QofLogModule log_module = QOF_MOD_QUERY;
44 QofQueryPredData *pdata;
53 QofQueryPredicateFunc pred_fcn;
70 QofCompareFunc comp_fcn;
85 QofQuerySort primary_sort;
86 QofQuerySort secondary_sort;
87 QofQuerySort tertiary_sort;
97 GHashTable* be_compiled;
106 typedef struct _QofQueryCB
114 static GList *qof_query_printSearchFor (
QofQuery * query, GList * output);
115 static GList *qof_query_printTerms (
QofQuery * query, GList * output);
116 static GList *qof_query_printSorts (QofQuerySort *s[],
const gint numSorts,
118 static GList *qof_query_printAndTerms (GList * terms, GList * output);
121 static const char *qof_query_printDateMatch (
QofDateMatch d);
123 static const char *qof_query_printGuidMatch (
QofGuidMatch g);
124 static const char *qof_query_printCharMatch (
QofCharMatch c);
125 static GList *qof_query_printPredData (QofQueryPredData *pd, GList *lst);
127 static void qof_query_printValueForParam (QofQueryPredData *pd, GString * gs);
128 static void qof_query_printOutput (GList * output);
129 static void qof_query_print (
QofQuery * query);
133 static void query_init (
QofQuery *q, QofQueryTerm *initial_term)
135 GList * _or_ =
nullptr;
136 GList *_and_ =
nullptr;
141 _or_ = g_list_alloc ();
142 _and_ = g_list_alloc ();
143 _and_->data = initial_term;
150 g_list_free (q->results);
151 g_list_free (q->books);
153 g_slist_free (q->primary_sort.param_list);
154 g_slist_free (q->secondary_sort.param_list);
155 g_slist_free (q->tertiary_sort.param_list);
157 g_slist_free (q->primary_sort.param_fcns);
158 g_slist_free (q->secondary_sort.param_fcns);
159 g_slist_free (q->tertiary_sort.param_fcns);
162 memset (q, 0,
sizeof (*q));
169 q->primary_sort.param_list = g_slist_prepend (static_cast<GSList*>(
nullptr),
171 q->primary_sort.increasing = TRUE;
172 q->secondary_sort.increasing = TRUE;
173 q->tertiary_sort.increasing = TRUE;
180 if (!q1 || !q2)
return;
183 q1->terms = q2->terms;
187 q1->books = q2->books;
194 static void free_query_term (QofQueryTerm *qt)
199 g_slist_free (qt->param_list);
200 g_slist_free (qt->param_fcns);
204 static QofQueryTerm * copy_query_term (
const QofQueryTerm *qt)
206 QofQueryTerm *new_qt;
207 if (!qt)
return nullptr;
209 new_qt = g_new0 (QofQueryTerm, 1);
211 new_qt->param_list = g_slist_copy (qt->param_list);
212 new_qt->param_fcns = g_slist_copy (qt->param_fcns);
217 static GList * copy_and_terms (
const GList *and_terms)
219 GList *_and_ =
nullptr;
220 const GList *cur_and;
222 for (cur_and = and_terms; cur_and; cur_and = cur_and->next)
224 _and_ = g_list_prepend(_and_, copy_query_term (static_cast<QofQueryTerm*>(cur_and->data)));
227 return g_list_reverse(_and_);
231 copy_or_terms(
const GList * or_terms)
233 GList * _or_ =
nullptr;
234 const GList * cur_or;
236 for (cur_or = or_terms; cur_or; cur_or = cur_or->next)
238 _or_ = g_list_prepend(_or_, copy_and_terms(static_cast<GList*>(cur_or->data)));
241 return g_list_reverse(_or_);
244 static void copy_sort (QofQuerySort *dst,
const QofQuerySort *src)
247 dst->param_list = g_slist_copy (src->param_list);
248 dst->param_fcns = g_slist_copy (src->param_fcns);
251 static void free_sort (QofQuerySort *s)
253 g_slist_free (s->param_list);
254 s->param_list =
nullptr;
256 g_slist_free (s->param_fcns);
257 s->param_fcns =
nullptr;
260 static void free_members (
QofQuery *q)
264 if (q ==
nullptr)
return;
266 for (cur_or = q->terms; cur_or; cur_or = cur_or->next)
270 for (cur_and = static_cast<GList*>(cur_or->data); cur_and;
271 cur_and = static_cast<GList*>(cur_and->next))
273 free_query_term(static_cast<QofQueryTerm*>(cur_and->data));
274 cur_and->data =
nullptr;
277 g_list_free(static_cast<GList*>(cur_or->data));
278 cur_or->data =
nullptr;
281 free_sort (&(q->primary_sort));
282 free_sort (&(q->secondary_sort));
283 free_sort (&(q->tertiary_sort));
285 g_list_free(q->terms);
288 g_list_free(q->books);
291 g_list_free(q->results);
292 q->results =
nullptr;
295 static int cmp_func (
const QofQuerySort *sort,
QofSortFunc default_sort,
296 const gconstpointer a,
const gconstpointer b)
298 QofParam *param =
nullptr;
300 gpointer conva, convb;
302 g_return_val_if_fail (sort, 0);
305 if (sort->use_default)
307 if (default_sort)
return default_sort (a, b);
312 if (!sort->param_fcns)
return 0;
315 if (!sort->comp_fcn && !sort->obj_cmp)
return 0;
320 for (node = static_cast<GSList*>(sort->param_fcns); node;
321 node =
static_cast<GSList*
>(node->next))
323 param =
static_cast<QofParam*
>(node->data);
327 if (!node->next && !sort->obj_cmp)
331 conva = (param->param_getfcn) (conva, param);
332 convb = (param->param_getfcn) (convb, param);
338 int rc = sort->comp_fcn (conva, convb, sort->options, param);
342 return sort->obj_cmp (conva, convb);
346 sort_func (
const gconstpointer a,
const gconstpointer b,
const gpointer q)
351 g_return_val_if_fail (sortQuery, 0);
353 retval = cmp_func (&(sortQuery->primary_sort), sortQuery->defaultSort, a, b);
356 retval = cmp_func (&(sortQuery->secondary_sort), sortQuery->defaultSort,
360 retval = cmp_func (&(sortQuery->tertiary_sort), sortQuery->defaultSort,
362 return sortQuery->tertiary_sort.increasing ? retval : -retval;
366 return sortQuery->secondary_sort.increasing ? retval : -retval;
371 return sortQuery->primary_sort.increasing ? retval : -retval;
382 check_object (
const QofQuery *q, gpointer
object)
384 const GList * and_ptr;
385 const GList * or_ptr;
386 const QofQueryTerm * qt;
387 int and_terms_ok = 1;
389 for (or_ptr = q->terms; or_ptr; or_ptr = or_ptr->next)
392 for (and_ptr = static_cast<GList*>(or_ptr->data); and_ptr;
393 and_ptr = static_cast<GList*>(and_ptr->next))
395 qt = (QofQueryTerm *)(and_ptr->data);
396 if (qt->param_fcns && qt->pred_fcn)
399 QofParam *param =
nullptr;
400 gpointer conv_obj = object;
403 for (node = qt->param_fcns; node; node = node->next)
405 param =
static_cast<QofParam*
>(node->data);
408 if (!node->next)
break;
410 conv_obj = param->param_getfcn (conv_obj, param);
413 if (((qt->pred_fcn)(conv_obj, param, qt->pdata)) == qt->invert)
435 if (
nullptr == q->terms)
return 1;
447 QofParam
const **
final)
449 const QofParam *objDef =
nullptr;
450 GSList *fcns =
nullptr;
452 ENTER (
"param_list=%p id=%s", param_list, start_obj);
453 g_return_val_if_fail (param_list,
nullptr);
454 g_return_val_if_fail (start_obj,
nullptr);
455 g_return_val_if_fail (
final,
nullptr);
457 for (; param_list; param_list = param_list->next)
466 fcns = g_slist_prepend (fcns, (gpointer) objDef);
472 start_obj = (
QofIdType) objDef->param_type;
475 LEAVE (
"fcns=%p", fcns);
476 return (g_slist_reverse (fcns));
480 compile_sort (QofQuerySort *sort,
QofIdType obj)
482 const QofParam *resObj =
nullptr;
484 ENTER (
"sort=%p id=%s params=%p", sort, obj, sort->param_list);
485 sort->use_default = FALSE;
487 g_slist_free (sort->param_fcns);
488 sort->param_fcns =
nullptr;
489 sort->comp_fcn =
nullptr;
490 sort->obj_cmp =
nullptr;
493 if (!sort->param_list)
500 sort->param_fcns = compile_params (sort->param_list, obj, &resObj);
505 if (sort->param_fcns && resObj)
510 if (resObj->param_compfcn)
511 sort->comp_fcn = resObj->param_compfcn;
513 sort->comp_fcn = qof_query_core_get_compare (resObj->param_type);
516 if (sort->comp_fcn ==
nullptr)
517 sort->obj_cmp = qof_class_get_default_sort (resObj->param_type);
519 else if (!g_strcmp0 (static_cast<char*>(sort->param_list->data),
522 sort->use_default = TRUE;
524 LEAVE (
"sort=%p id=%s", sort, obj);
527 static void compile_terms (
QofQuery *q)
529 GList *or_ptr, *and_ptr;
531 ENTER (
" query=%p", q);
535 for (or_ptr = q->terms; or_ptr; or_ptr = or_ptr->next)
537 for (and_ptr = static_cast<GList*>(or_ptr->data); and_ptr;
538 and_ptr = static_cast<GList*>(and_ptr->next))
540 QofQueryTerm* qt =
static_cast<QofQueryTerm*
>(and_ptr->data);
541 const QofParam* resObj =
nullptr;
543 g_slist_free (qt->param_fcns);
544 qt->param_fcns =
nullptr;
547 qt->param_fcns = compile_params (qt->param_list, q->search_for,
554 if (qt->param_fcns && resObj)
555 qt->pred_fcn = qof_query_core_get_predicate (resObj->param_type);
557 qt->pred_fcn =
nullptr;
562 compile_sort (&(q->primary_sort), q->search_for);
563 compile_sort (&(q->secondary_sort), q->search_for);
564 compile_sort (&(q->tertiary_sort), q->search_for);
566 q->defaultSort = qof_class_get_default_sort (q->search_for);
567 #ifdef QOF_BACKEND_QUERY 569 for (node = q->books; node; node = node->next)
571 QofBook* book =
static_cast<QofBook*
>(node->data);
574 if (be && be->compile_query)
576 gpointer result = (be->compile_query)(be, q);
578 g_hash_table_insert (q->be_compiled, book, result);
583 LEAVE (
" query=%p", q);
586 static void check_item_cb (gpointer
object, gpointer user_data)
590 if (!
object || !ql)
return;
592 if (check_object (ql->query,
object))
594 ql->list = g_list_prepend (ql->list,
object);
608 if (!l1 && !l2)
return 0;
609 if (!l1 && l2)
return -1;
610 if (l1 && !l2)
return 1;
612 ret = g_strcmp0 (static_cast<char*>(l1->data),
613 static_cast<char*>(l2->data));
623 static GList * merge_books (GList *l1, GList *l2)
625 GList *res =
nullptr;
628 res = g_list_copy (l1);
630 for (node = l2; node; node = node->next)
632 if (g_list_index (res, node->data) == -1)
633 res = g_list_prepend (res, node->data);
640 query_free_compiled (gpointer key, gpointer value, gpointer not_used)
642 #ifdef QOF_BACKEND_QUERY 643 QofBook* book =
static_cast<QofBook*
>(key);
646 if (be && be->free_query)
647 (be->free_query)(be, value);
653 static void query_clear_compiles (
QofQuery *q)
655 g_hash_table_foreach_remove (q->be_compiled, query_free_compiled,
nullptr);
662 qof_query_build_param_list (
char const *param, ...)
665 char const *this_param;
671 va_start (ap, param);
673 for (this_param = param; this_param; this_param = va_arg (ap,
const char *))
674 param_list = g_slist_prepend (param_list, (gpointer)this_param);
678 return g_slist_reverse (param_list);
687 if (!q || !param_list || !pred_data)
return;
689 qt = g_new0 (QofQueryTerm, 1);
690 qt->param_list = param_list;
691 qt->pdata = pred_data;
695 if (q->terms !=
nullptr)
710 if (!q || !param_list)
return;
712 for (_or_ = q->terms; _or_; _or_ = _or_->next)
714 for (_and_ = static_cast<GList*>(_or_->data); _and_;
715 _and_ = static_cast<GList*>(_and_->next))
717 qt =
static_cast<QofQueryTerm*
>(_and_->data);
718 if (!param_list_cmp (qt->param_list, param_list))
720 auto or_list =
static_cast<GList*
> (_or_->data);
721 if (or_list && !or_list->next)
723 q->terms = g_list_remove_link (static_cast<GList*>(q->terms), _or_);
724 g_list_free_1 (_or_);
730 _or_->data = g_list_remove_link (or_list, _and_);
731 g_list_free_1 (_and_);
732 _and_ =
static_cast<GList*
>(_or_->data);
736 free_query_term (qt);
743 static GList * qof_query_run_internal (
QofQuery *q,
747 GList *matching_objects =
nullptr;
748 int object_count = 0;
750 if (!q)
return nullptr;
751 g_return_val_if_fail (q->search_for,
nullptr);
752 g_return_val_if_fail (q->books,
nullptr);
753 g_return_val_if_fail (run_cb,
nullptr);
761 query_clear_compiles (q);
773 memset (&qcb, 0,
sizeof (qcb));
777 run_cb(&qcb, cb_arg);
779 matching_objects = qcb.list;
780 object_count = qcb.count;
782 PINFO (
"matching objects=%p count=%d", matching_objects, object_count);
790 matching_objects = g_list_reverse(matching_objects);
793 if (q->primary_sort.comp_fcn || q->primary_sort.obj_cmp ||
794 (q->primary_sort.use_default && q->defaultSort))
796 matching_objects = g_list_sort_with_data(matching_objects, sort_func, q);
800 if ((object_count > q->max_results) && (q->max_results > -1))
802 if (q->max_results > 0)
807 mptr = g_list_nth(matching_objects, object_count - q->max_results);
811 if (mptr->prev !=
nullptr) mptr->prev->next =
nullptr;
812 mptr->prev =
nullptr;
814 g_list_free(matching_objects);
815 matching_objects = mptr;
820 g_list_free(matching_objects);
821 matching_objects =
nullptr;
827 g_list_free(q->results);
828 q->results = matching_objects;
831 return matching_objects;
834 static void qof_query_run_cb(
QofQueryCB* qcb, gpointer cb_arg)
839 g_return_if_fail(qcb);
841 for (node = qcb->query->books; node; node = node->next)
843 QofBook* book =
static_cast<QofBook*
>(node->data);
844 #ifdef QOF_BACKEND_QUERY 850 gpointer compiled_query = g_hash_table_lookup (qcb->query->be_compiled,
853 if (compiled_query && be->run_query)
855 (be->run_query) (be, compiled_query);
868 return qof_query_run_internal(q, qof_query_run_cb,
nullptr);
871 static void qof_query_run_subq_cb(
QofQueryCB* qcb, gpointer cb_arg)
875 g_return_if_fail(pq);
882 if (!subq)
return nullptr;
883 if (!primaryq)
return nullptr;
886 g_return_val_if_fail (subq->search_for,
nullptr);
887 g_return_val_if_fail (primaryq->search_for,
nullptr);
888 g_return_val_if_fail(!g_strcmp0(subq->search_for, primaryq->search_for),
892 return qof_query_run_internal(subq, qof_query_run_subq_cb,
902 return query->results;
908 swap_terms (query, q2);
911 g_list_free (query->books);
912 query->books =
nullptr;
913 g_list_free (query->results);
914 query->results =
nullptr;
921 qp->be_compiled = g_hash_table_new (g_direct_hash, g_direct_equal);
922 query_init (qp,
nullptr);
931 if (g_strcmp0 (q->search_for, obj_type))
951 return g_list_length (q->terms);
959 for (o = q->terms; o; o = o->next)
960 n += g_list_length(static_cast<GList*>(o->data));
969 if (!q || !term_param)
972 for (_or_ = q->terms; _or_; _or_ = _or_->next)
974 for (_and_ = static_cast<GList*>(_or_->data); _and_;
975 _and_ = static_cast<GList*>(_and_->next))
977 QofQueryTerm* qt =
static_cast<QofQueryTerm*
>(_and_->data);
978 if (!param_list_cmp (term_param, qt->param_list))
990 GSList *results =
nullptr;
992 if (!q || !term_param)
995 for (_or_ = q->terms; _or_; _or_ = _or_->next)
997 for (_and_ = static_cast<GList*>(_or_->data); _and_;
998 _and_ = static_cast<GList*>(_and_->next))
1000 QofQueryTerm *qt =
static_cast<QofQueryTerm*
>(_and_->data);
1001 if (!param_list_cmp (term_param, qt->param_list))
1002 results = g_slist_prepend (results, qt->pdata);
1006 return g_slist_reverse (results);
1013 query_clear_compiles (q);
1014 g_hash_table_destroy (q->be_compiled);
1023 if (!q)
return nullptr;
1025 ht = copy->be_compiled;
1026 free_members (copy);
1030 copy->be_compiled = ht;
1031 copy->terms = copy_or_terms (q->terms);
1032 copy->books = g_list_copy (q->books);
1033 copy->results = g_list_copy (q->results);
1035 copy_sort (&(copy->primary_sort), &(q->primary_sort));
1036 copy_sort (&(copy->secondary_sort), &(q->secondary_sort));
1037 copy_sort (&(copy->tertiary_sort), &(q->tertiary_sort));
1053 QofQuery * right, * left, * iright, * ileft;
1063 num_or_terms = g_list_length(q->terms);
1065 switch (num_or_terms)
1069 retval->max_results = q->max_results;
1076 retval->max_results = q->max_results;
1077 retval->books = g_list_copy (q->books);
1078 retval->search_for = q->search_for;
1079 retval->changed = 1;
1081 aterms =
static_cast<GList*
>(g_list_nth_data(q->terms, 0));
1082 new_oterm =
nullptr;
1083 for (cur = aterms; cur; cur = cur->next)
1085 qt = copy_query_term(static_cast<QofQueryTerm*>(cur->data));
1086 qt->invert = !(qt->invert);
1087 new_oterm = g_list_append(
nullptr, qt);
1088 retval->terms = g_list_prepend(retval->terms, new_oterm);
1090 retval->terms = g_list_reverse(retval->terms);
1098 right->terms = copy_or_terms(g_list_nth(q->terms, 1));
1101 left->terms = g_list_append(
nullptr,
1102 copy_and_terms(static_cast<GList*>(g_list_nth_data(q->terms, 0))));
1108 retval->books = g_list_copy (q->books);
1109 retval->max_results = q->max_results;
1110 retval->search_for = q->search_for;
1111 retval->changed = 1;
1141 if (q1->search_for && q2->search_for)
1142 g_return_val_if_fail (g_strcmp0 (q1->search_for, q2->search_for) == 0,
1145 search_for = (q1->search_for ? q1->search_for : q2->search_for);
1156 if ((QOF_QUERY_AND == op) &&
1157 (q1->terms ==
nullptr || q2->terms ==
nullptr))
1167 g_list_concat(copy_or_terms(q1->terms), copy_or_terms(q2->terms));
1168 retval->books = merge_books (q1->books, q2->books);
1169 retval->max_results = q1->max_results;
1170 retval->changed = 1;
1175 retval->books = merge_books (q1->books, q2->books);
1176 retval->max_results = q1->max_results;
1177 retval->changed = 1;
1183 for (i = q1->terms; i; i = i->next)
1185 for (j = q2->terms; j; j = j->next)
1188 g_list_prepend(retval->terms,
1190 (copy_and_terms(static_cast<GList*>(i->data)),
1191 copy_and_terms(static_cast<GList*>(j->data))));
1194 retval->terms = g_list_reverse(retval->terms);
1197 case QOF_QUERY_NAND:
1231 retval->search_for = search_for;
1244 swap_terms (q1, tmp_q);
1253 if (q->primary_sort.param_list)
1254 g_slist_free (q->primary_sort.param_list);
1255 q->primary_sort.param_list = params1;
1256 q->primary_sort.options = 0;
1258 if (q->secondary_sort.param_list)
1259 g_slist_free (q->secondary_sort.param_list);
1260 q->secondary_sort.param_list = params2;
1261 q->secondary_sort.options = 0;
1263 if (q->tertiary_sort.param_list)
1264 g_slist_free (q->tertiary_sort.param_list);
1265 q->tertiary_sort.param_list = params3;
1266 q->tertiary_sort.options = 0;
1271 void qof_query_set_sort_options (
QofQuery *q, gint prim_op, gint sec_op,
1275 q->primary_sort.options = prim_op;
1276 q->secondary_sort.options = sec_op;
1277 q->tertiary_sort.options = tert_op;
1281 gboolean sec_inc, gboolean tert_inc)
1284 q->primary_sort.increasing = prim_inc;
1285 q->secondary_sort.increasing = sec_inc;
1286 q->tertiary_sort.increasing = tert_inc;
1299 QofQueryPredData *pdata;
1301 if (!q || !param_list)
return;
1304 g_return_if_fail (options == QOF_GUID_MATCH_NULL);
1306 pdata = qof_query_guid_predicate (options, guid_list);
1315 if (!q || !param_list)
return;
1318 g = g_list_prepend (g, (gpointer)guid);
1329 if (!q || !book)
return;
1332 if (g_list_index (q->books, book) == -1)
1333 q->books = g_list_prepend (q->books, book);
1335 slist = g_slist_prepend (slist, static_cast<void*>(const_cast<char*>(QOF_PARAM_GUID)));
1336 slist = g_slist_prepend (slist, static_cast<void*>(const_cast<char*>(
QOF_PARAM_BOOK)));
1343 if (!q)
return nullptr;
1350 QofQueryPredData *pdata;
1351 if (!q || !param_list)
return;
1353 pdata = qof_query_boolean_predicate (QOF_COMPARE_EQUAL, value);
1363 qof_query_core_init ();
1365 LEAVE (
"Completed initialization of QofQuery");
1368 void qof_query_shutdown (
void)
1370 qof_class_shutdown ();
1371 qof_query_core_shutdown ();
1374 int qof_query_get_max_results (
const QofQuery *q)
1377 return q->max_results;
1382 if (!q)
return nullptr;
1383 return q->search_for;
1386 GList * qof_query_get_terms (
const QofQuery *q)
1388 if (!q)
return nullptr;
1396 return qt->param_list;
1399 QofQueryPredData *qof_query_term_get_pred_data (
const QofQueryTerm *qt)
1406 gboolean qof_query_term_is_inverted (
const QofQueryTerm *qt)
1413 void qof_query_get_sorts (
QofQuery *q, QofQuerySort **primary,
1414 QofQuerySort **secondary, QofQuerySort **tertiary)
1419 *primary = &(q->primary_sort);
1421 *secondary = &(q->secondary_sort);
1423 *tertiary = &(q->tertiary_sort);
1430 return qs->param_list;
1433 gint qof_query_sort_get_sort_options (
const QofQuerySort *qs)
1440 gboolean qof_query_sort_get_increasing (
const QofQuerySort *qs)
1444 return qs->increasing;
1448 qof_query_term_equal (
const QofQueryTerm *qt1,
const QofQueryTerm *qt2)
1450 if (qt1 == qt2)
return TRUE;
1451 if (!qt1 || !qt2)
return FALSE;
1453 if (qt1->invert != qt2->invert)
return FALSE;
1454 if (param_list_cmp (qt1->param_list, qt2->param_list))
return FALSE;
1455 return qof_query_core_predicate_equal (qt1->pdata, qt2->pdata);
1459 qof_query_sort_equal (
const QofQuerySort* qs1,
const QofQuerySort* qs2)
1461 if (qs1 == qs2)
return TRUE;
1462 if (!qs1 || !qs2)
return FALSE;
1465 if (!qs1->param_list && !qs2->param_list)
return TRUE;
1467 if (qs1->options != qs2->options)
return FALSE;
1468 if (qs1->increasing != qs2->increasing)
return FALSE;
1469 return (param_list_cmp (qs1->param_list, qs2->param_list) == 0);
1476 if (q1 == q2)
return TRUE;
1477 if (!q1 || !q2)
return FALSE;
1479 if (q1->max_results != q2->max_results)
return FALSE;
1481 for (or1 = q1->terms, or2 = q2->terms; or1 || or2;
1482 or1 = or1->next, or2 = or2->next)
1488 and1 =
static_cast<GList*
>(or1->data);
1489 and2 =
static_cast<GList*
>(or2->data);
1491 for (; and1 || and2; and1 = and1->next, and2 = and2->next)
1495 if (!qof_query_term_equal (static_cast<QofQueryTerm*>(and1->data),
1496 static_cast<QofQueryTerm*
>(and2->data)))
1501 if (!qof_query_sort_equal (&(q1->primary_sort), &(q2->primary_sort)))
1503 if (!qof_query_sort_equal (&(q1->secondary_sort), &(q2->secondary_sort)))
1505 if (!qof_query_sort_equal (&(q1->tertiary_sort), &(q2->tertiary_sort)))
1521 gint maxResults = 0, numSorts = 3;
1527 LEAVE(
"query is (null)");
1533 maxResults = qof_query_get_max_results (query);
1535 output = qof_query_printSearchFor (query, output);
1536 output = qof_query_printTerms (query, output);
1538 qof_query_get_sorts (query, &s[0], &s[1], &s[2]);
1542 output = qof_query_printSorts (s, numSorts, output);
1545 str = g_string_new (
" ");
1546 g_string_printf (str,
"Maximum number of results: %d", maxResults);
1547 output = g_list_append (output, str);
1549 qof_query_printOutput (output);
1554 qof_query_printOutput (GList * output)
1558 for (lst = output; lst; lst = lst->next)
1560 GString *line = (GString *) lst->data;
1562 DEBUG (
" %s", line->str);
1563 g_string_free (line, TRUE);
1573 qof_query_printSearchFor (
QofQuery * query, GList * output)
1579 gs = g_string_new (
"Query Object Type: ");
1580 g_string_append (gs, (
nullptr == searchFor) ?
"(null)" : searchFor);
1581 output = g_list_append (output, gs);
1592 qof_query_printTerms (
QofQuery * query, GList * output)
1597 terms = qof_query_get_terms (query);
1599 for (lst = terms; lst; lst = lst->next)
1601 output = g_list_append (output, g_string_new (
"OR and AND Terms:"));
1605 output = qof_query_printAndTerms (static_cast<GList*>(lst->data),
1611 g_list_append (output, g_string_new (
" No data for AND terms"));
1624 qof_query_printSorts (QofQuerySort *s[],
const gint numSorts, GList * output)
1628 GString *gs = g_string_new (
"Sort Parameters: ");
1630 for (curSort = 0; curSort < numSorts; curSort++)
1632 gboolean increasing;
1637 increasing = qof_query_sort_get_increasing (s[curSort]);
1639 gsl = qof_query_sort_get_param_path (s[curSort]);
1640 if (gsl) g_string_append_printf (gs,
" Param: ");
1641 for (n = gsl; n; n = n->next)
1644 if (gsl != n) g_string_append_printf (gs,
" ");
1645 g_string_append_printf (gs,
"%s", param_name);
1649 g_string_append_printf (gs,
" %s ", increasing ?
"DESC" :
"ASC");
1650 g_string_append_printf (gs,
" Options: 0x%x ", s[curSort]->options);
1654 output = g_list_append (output, gs);
1664 qof_query_printAndTerms (GList * terms, GList * output)
1666 const char *prefix =
"AND Terms:";
1668 QofQueryPredData *pd;
1673 output = g_list_append (output, g_string_new (prefix));
1674 for (lst = terms; lst; lst = lst->next)
1676 qt = (QofQueryTerm *) lst->data;
1677 pd = qof_query_term_get_pred_data (qt);
1678 path = qof_query_term_get_param_path (qt);
1679 invert = qof_query_term_is_inverted (qt);
1681 if (invert) output = g_list_append (output,
1682 g_string_new(
" INVERT SENSE "));
1683 output = g_list_append (output, qof_query_printParamPath (path));
1684 output = qof_query_printPredData (pd, output);
1698 GString *gs = g_string_new (
"Param List: ");
1699 g_string_append (gs,
" ");
1700 for (list = parmList; list; list = list->next)
1702 g_string_append (gs, (gchar *) list->data);
1704 g_string_append (gs,
"->");
1714 qof_query_printPredData (QofQueryPredData *pd, GList *lst)
1718 gs = g_string_new (
"Pred Data: ");
1719 g_string_append (gs, (gchar *) pd->type_name);
1722 if (g_strcmp0 (pd->type_name, QOF_TYPE_CHAR) &&
1723 g_strcmp0 (pd->type_name, QOF_TYPE_GUID))
1725 g_string_append_printf (gs,
" how: %s",
1726 qof_query_printStringForHow (pd->how));
1728 lst = g_list_append(lst, gs);
1729 gs = g_string_new (
"");
1730 qof_query_printValueForParam (pd, gs);
1731 lst = g_list_append(lst, gs);
1745 case QOF_COMPARE_LT:
1746 return "QOF_COMPARE_LT";
1747 case QOF_COMPARE_LTE:
1748 return "QOF_COMPARE_LTE";
1749 case QOF_COMPARE_EQUAL:
1750 return "QOF_COMPARE_EQUAL";
1751 case QOF_COMPARE_GT:
1752 return "QOF_COMPARE_GT";
1753 case QOF_COMPARE_GTE:
1754 return "QOF_COMPARE_GTE";
1755 case QOF_COMPARE_NEQ:
1756 return "QOF_COMPARE_NEQ";
1757 case QOF_COMPARE_CONTAINS:
1758 return "QOF_COMPARE_CONTAINS";
1759 case QOF_COMPARE_NCONTAINS:
1760 return "QOF_COMPARE_NCONTAINS";
1763 return "INVALID HOW";
1768 qof_query_printValueForParam (QofQueryPredData *pd, GString * gs)
1771 if (!g_strcmp0 (pd->type_name, QOF_TYPE_GUID))
1775 g_string_append_printf (gs,
"Match type %s",
1776 qof_query_printGuidMatch (pdata->options));
1777 for (node = pdata->guids; node; node = node->next)
1781 g_string_append_printf (gs,
", guids: %s",guidstr);
1785 if (!g_strcmp0 (pd->type_name, QOF_TYPE_STRING))
1788 g_string_append_printf (gs,
" Match type %s",
1789 qof_query_printStringMatch (pdata->options));
1790 g_string_append_printf (gs,
" %s string: %s",
1791 pdata->is_regex ?
"Regex" :
"Not regex",
1792 pdata->matchstring);
1795 if (!g_strcmp0 (pd->type_name, QOF_TYPE_NUMERIC))
1798 g_string_append_printf (gs,
" Match type %s",
1799 qof_query_printNumericMatch (pdata->options));
1800 g_string_append_printf (gs,
" gnc_numeric: %s",
1804 if (!g_strcmp0 (pd->type_name, QOF_TYPE_INT64))
1807 g_string_append_printf (gs,
" int64: %" G_GINT64_FORMAT, pdata->val);
1810 if (!g_strcmp0 (pd->type_name, QOF_TYPE_INT32))
1813 g_string_append_printf (gs,
" int32: %d", pdata->val);
1816 if (!g_strcmp0 (pd->type_name, QOF_TYPE_DOUBLE))
1819 g_string_append_printf (gs,
" double: %.18g", pdata->val);
1822 if (!g_strcmp0 (pd->type_name, QOF_TYPE_DATE))
1826 memset (datebuff, 0,
sizeof(datebuff));
1828 g_string_append_printf (gs,
" Match type %s",
1829 qof_query_printDateMatch (pdata->options));
1830 g_string_append_printf (gs,
" query_date: %s", datebuff);
1833 if (!g_strcmp0 (pd->type_name, QOF_TYPE_CHAR))
1836 g_string_append_printf (gs,
" Match type %s",
1837 qof_query_printCharMatch (pdata->options));
1838 g_string_append_printf (gs,
" char list: %s", pdata->char_list);
1841 if (!g_strcmp0 (pd->type_name, QOF_TYPE_BOOLEAN))
1844 g_string_append_printf (gs,
" boolean: %s", pdata->val ?
"TRUE" :
"FALSE");
1860 case QOF_STRING_MATCH_NORMAL:
1861 return "QOF_STRING_MATCH_NORMAL";
1862 case QOF_STRING_MATCH_CASEINSENSITIVE:
1863 return "QOF_STRING_MATCH_CASEINSENSITIVE";
1865 return "UNKNOWN MATCH TYPE";
1877 case QOF_DATE_MATCH_NORMAL:
1878 return "QOF_DATE_MATCH_NORMAL";
1879 case QOF_DATE_MATCH_DAY:
1880 return "QOF_DATE_MATCH_DAY";
1882 return "UNKNOWN MATCH TYPE";
1894 case QOF_NUMERIC_MATCH_DEBIT:
1895 return "QOF_NUMERIC_MATCH_DEBIT";
1896 case QOF_NUMERIC_MATCH_CREDIT:
1897 return "QOF_NUMERIC_MATCH_CREDIT";
1898 case QOF_NUMERIC_MATCH_ANY:
1899 return "QOF_NUMERIC_MATCH_ANY";
1901 return "UNKNOWN MATCH TYPE";
1914 return "QOF_GUID_MATCH_ANY";
1916 return "QOF_GUID_MATCH_ALL";
1917 case QOF_GUID_MATCH_NONE:
1918 return "QOF_GUID_MATCH_NONE";
1919 case QOF_GUID_MATCH_NULL:
1920 return "QOF_GUID_MATCH_NULL";
1922 return "QOF_GUID_MATCH_LIST_ANY";
1925 return "UNKNOWN MATCH TYPE";
1937 case QOF_CHAR_MATCH_ANY:
1938 return "QOF_CHAR_MATCH_ANY";
1939 case QOF_CHAR_MATCH_NONE:
1940 return "QOF_CHAR_MATCH_NONE";
1942 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.
#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.