00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026
00027 #include <sys/types.h>
00028 #include <time.h>
00029 #include <glib.h>
00030 #include <regex.h>
00031 #include <string.h>
00032
00033 #include "qof.h"
00034 #include "qofbackend-p.h"
00035 #include "qofbook-p.h"
00036 #include "qofclass-p.h"
00037 #include "qofquery-p.h"
00038 #include "qofquerycore-p.h"
00039
00040 static QofLogModule log_module = QOF_MOD_QUERY;
00041
00042 struct _QofQueryTerm
00043 {
00044 GSList *param_list;
00045 QofQueryPredData *pdata;
00046 gboolean invert;
00047
00048
00049
00050
00051
00052
00053 GSList *param_fcns;
00054 QofQueryPredicateFunc pred_fcn;
00055 };
00056
00057 struct _QofQuerySort
00058 {
00059 GSList *param_list;
00060 gint options;
00061 gboolean increasing;
00062
00063
00064
00065
00066
00067
00068 gboolean use_default;
00069 GSList *param_fcns;
00070 QofSortFunc obj_cmp;
00071 QofCompareFunc comp_fcn;
00072 };
00073
00074
00075 struct _QofQuery
00076 {
00077
00078 QofIdType search_for;
00079
00080
00081
00082 GList *terms;
00083
00084
00085
00086 QofQuerySort primary_sort;
00087 QofQuerySort secondary_sort;
00088 QofQuerySort tertiary_sort;
00089 QofSortFunc defaultSort;
00090
00091
00092 gint max_results;
00093
00094
00095 GList *books;
00096
00097
00098 GHashTable *be_compiled;
00099
00100
00101
00102 gint changed;
00103
00104 GList *results;
00105 };
00106
00107 typedef struct _QofQueryCB
00108 {
00109 QofQuery *query;
00110 GList *list;
00111 gint count;
00112 } QofQueryCB;
00113
00114
00115 static void
00116 query_init (QofQuery * q, QofQueryTerm * initial_term)
00117 {
00118 GList *or = NULL;
00119 GList *and = NULL;
00120 GHashTable *ht;
00121
00122 if (initial_term)
00123 {
00124 or = g_list_alloc ();
00125 and = g_list_alloc ();
00126 and->data = initial_term;
00127 or->data = and;
00128 }
00129
00130 if (q->terms)
00131 qof_query_clear (q);
00132
00133 g_list_free (q->results);
00134 g_list_free (q->books);
00135
00136 g_slist_free (q->primary_sort.param_list);
00137 g_slist_free (q->secondary_sort.param_list);
00138 g_slist_free (q->tertiary_sort.param_list);
00139
00140 g_slist_free (q->primary_sort.param_fcns);
00141 g_slist_free (q->secondary_sort.param_fcns);
00142 g_slist_free (q->tertiary_sort.param_fcns);
00143
00144 ht = q->be_compiled;
00145 memset (q, 0, sizeof (*q));
00146 q->be_compiled = ht;
00147
00148 q->terms = or;
00149 q->changed = 1;
00150 q->max_results = -1;
00151
00152 q->primary_sort.param_list =
00153 g_slist_prepend (NULL, QUERY_DEFAULT_SORT);
00154 q->primary_sort.increasing = TRUE;
00155 q->secondary_sort.increasing = TRUE;
00156 q->tertiary_sort.increasing = TRUE;
00157 }
00158
00159 static void
00160 swap_terms (QofQuery * q1, QofQuery * q2)
00161 {
00162 GList *g;
00163
00164 if (!q1 || !q2)
00165 return;
00166
00167 g = q1->terms;
00168 q1->terms = q2->terms;
00169 q2->terms = g;
00170
00171 g = q1->books;
00172 q1->books = q2->books;
00173 q2->books = g;
00174
00175 q1->changed = 1;
00176 q2->changed = 1;
00177 }
00178
00179 static void
00180 free_query_term (QofQueryTerm * qt)
00181 {
00182 if (!qt)
00183 return;
00184
00185 qof_query_core_predicate_free (qt->pdata);
00186 g_slist_free (qt->param_list);
00187 g_slist_free (qt->param_fcns);
00188 g_free (qt);
00189 }
00190
00191 static QofQueryTerm *
00192 copy_query_term (QofQueryTerm * qt)
00193 {
00194 QofQueryTerm *new_qt;
00195 if (!qt)
00196 return NULL;
00197
00198 new_qt = g_new0 (QofQueryTerm, 1);
00199 memcpy (new_qt, qt, sizeof (QofQueryTerm));
00200 new_qt->param_list = g_slist_copy (qt->param_list);
00201 new_qt->param_fcns = g_slist_copy (qt->param_fcns);
00202 new_qt->pdata = qof_query_core_predicate_copy (qt->pdata);
00203 return new_qt;
00204 }
00205
00206 static GList *
00207 copy_and_terms (GList * and_terms)
00208 {
00209 GList *and = NULL;
00210 GList *cur_and;
00211
00212 for (cur_and = and_terms; cur_and; cur_and = cur_and->next)
00213 {
00214 and = g_list_prepend (and, copy_query_term (cur_and->data));
00215 }
00216
00217 return g_list_reverse (and);
00218 }
00219
00220 static GList *
00221 copy_or_terms (GList * or_terms)
00222 {
00223 GList *or = NULL;
00224 GList *cur_or;
00225
00226 for (cur_or = or_terms; cur_or; cur_or = cur_or->next)
00227 {
00228 or = g_list_prepend (or, copy_and_terms (cur_or->data));
00229 }
00230
00231 return g_list_reverse (or);
00232 }
00233
00234 static void
00235 copy_sort (QofQuerySort * dst, const QofQuerySort * src)
00236 {
00237 memcpy (dst, src, sizeof (*dst));
00238 dst->param_list = g_slist_copy (src->param_list);
00239 dst->param_fcns = g_slist_copy (src->param_fcns);
00240 }
00241
00242 static void
00243 free_sort (QofQuerySort * s)
00244 {
00245 g_slist_free (s->param_list);
00246 s->param_list = NULL;
00247
00248 g_slist_free (s->param_fcns);
00249 s->param_fcns = NULL;
00250 }
00251
00252 static void
00253 free_members (QofQuery * q)
00254 {
00255 GList *cur_or;
00256
00257 if (q == NULL)
00258 return;
00259
00260 for (cur_or = q->terms; cur_or; cur_or = cur_or->next)
00261 {
00262 GList *cur_and;
00263
00264 for (cur_and = cur_or->data; cur_and; cur_and = cur_and->next)
00265 {
00266 free_query_term (cur_and->data);
00267 cur_and->data = NULL;
00268 }
00269
00270 g_list_free (cur_or->data);
00271 cur_or->data = NULL;
00272 }
00273
00274 free_sort (&(q->primary_sort));
00275 free_sort (&(q->secondary_sort));
00276 free_sort (&(q->tertiary_sort));
00277
00278 g_list_free (q->terms);
00279 q->terms = NULL;
00280
00281 g_list_free (q->books);
00282 q->books = NULL;
00283
00284 g_list_free (q->results);
00285 q->results = NULL;
00286 }
00287
00288 static gint
00289 cmp_func (QofQuerySort * sort, QofSortFunc default_sort,
00290 gconstpointer a, gconstpointer b)
00291 {
00292 QofParam *param = NULL;
00293 GSList *node;
00294 gpointer conva, convb;
00295
00296 g_return_val_if_fail (sort, 0);
00297
00298
00299 if (sort->use_default)
00300 {
00301 if (default_sort)
00302 return default_sort (a, b);
00303 return 0;
00304 }
00305
00306
00307 if (!sort->param_fcns)
00308 return 0;
00309
00310
00311 if (!sort->comp_fcn && !sort->obj_cmp)
00312 return 0;
00313
00314
00315 conva = (gpointer) a;
00316 convb = (gpointer) b;
00317 for (node = sort->param_fcns; node; node = node->next)
00318 {
00319 param = node->data;
00320
00321
00322
00323 if (!node->next && !sort->obj_cmp)
00324 break;
00325
00326
00327 conva = (param->param_getfcn) (conva, param);
00328 convb = (param->param_getfcn) (convb, param);
00329 }
00330
00331
00332 if (sort->comp_fcn)
00333 {
00334 gint rc = sort->comp_fcn (conva, convb, sort->options, param);
00335 return rc;
00336 }
00337
00338 return sort->obj_cmp (conva, convb);
00339 }
00340
00341 static QofQuery *sortQuery = NULL;
00342
00343 static gint
00344 sort_func (gconstpointer a, gconstpointer b)
00345 {
00346 gint retval;
00347
00348 g_return_val_if_fail (sortQuery, 0);
00349
00350 retval =
00351 cmp_func (&(sortQuery->primary_sort), sortQuery->defaultSort, a,
00352 b);
00353 if (retval == 0)
00354 {
00355 retval =
00356 cmp_func (&(sortQuery->secondary_sort),
00357 sortQuery->defaultSort,
00358 a, b);
00359 if (retval == 0)
00360 {
00361 retval =
00362 cmp_func (&(sortQuery->tertiary_sort),
00363 sortQuery->defaultSort, a, b);
00364 return sortQuery->tertiary_sort.increasing ?
00365 retval : -retval;
00366 }
00367 else
00368 {
00369 return sortQuery->secondary_sort.increasing ?
00370 retval : -retval;
00371 }
00372 }
00373 else
00374 {
00375 return sortQuery->primary_sort.increasing ? retval : -retval;
00376 }
00377 }
00378
00379
00380
00381
00382
00383
00384
00385 static gint
00386 check_object (QofQuery * q, gpointer object)
00387 {
00388 GList *and_ptr;
00389 GList *or_ptr;
00390 QofQueryTerm *qt;
00391 gint and_terms_ok = 1;
00392
00393 for (or_ptr = q->terms; or_ptr; or_ptr = or_ptr->next)
00394 {
00395 and_terms_ok = 1;
00396 for (and_ptr = or_ptr->data; and_ptr; and_ptr = and_ptr->next)
00397 {
00398 qt = (QofQueryTerm *) (and_ptr->data);
00399 if (qt->param_fcns && qt->pred_fcn)
00400 {
00401 GSList *node;
00402 QofParam *param = NULL;
00403 gpointer conv_obj = object;
00404
00405
00406 for (node = qt->param_fcns; node; node = node->next)
00407 {
00408 param = node->data;
00409
00410
00411 if (!node->next)
00412 break;
00413
00414 conv_obj = param->param_getfcn (conv_obj, param);
00415 }
00416
00417 if (((qt->pred_fcn) (conv_obj, param,
00418 qt->pdata)) == qt->invert)
00419 {
00420 and_terms_ok = 0;
00421 break;
00422 }
00423 }
00424 else
00425 {
00426
00427 }
00428 }
00429 if (and_terms_ok)
00430 {
00431 return 1;
00432 }
00433 }
00434
00435
00436
00437
00438
00439
00440 if (NULL == q->terms)
00441 return 1;
00442 return 0;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451 static GSList *
00452 compile_params (GSList * param_list, QofIdType start_obj,
00453 QofParam const **final)
00454 {
00455 const QofParam *objDef = NULL;
00456 GSList *fcns = NULL;
00457
00458 ENTER ("param_list=%p id=%s", param_list, start_obj);
00459 g_return_val_if_fail (param_list, NULL);
00460 g_return_val_if_fail (start_obj, NULL);
00461 g_return_val_if_fail (final, NULL);
00462
00463 for (; param_list; param_list = param_list->next)
00464 {
00465 QofIdType param_name = param_list->data;
00466 objDef = qof_class_get_parameter (start_obj, param_name);
00467
00468
00469 if (!objDef)
00470 break;
00471
00472
00473 fcns = g_slist_prepend (fcns, (gpointer) objDef);
00474
00475
00476 *final = objDef;
00477
00478
00479 start_obj = (QofIdType) objDef->param_type;
00480 }
00481
00482 LEAVE ("fcns=%p", fcns);
00483 return (g_slist_reverse (fcns));
00484 }
00485
00486 static void
00487 compile_sort (QofQuerySort * sort, QofIdType obj)
00488 {
00489 const QofParam *resObj = NULL;
00490
00491 ENTER ("sort=%p id=%s params=%p", sort, obj, sort->param_list);
00492 sort->use_default = FALSE;
00493
00494 g_slist_free (sort->param_fcns);
00495 sort->param_fcns = NULL;
00496 sort->comp_fcn = NULL;
00497 sort->obj_cmp = NULL;
00498
00499
00500 if (!sort->param_list)
00501 {
00502 LEAVE (" ");
00503 return;
00504 }
00505
00506
00507 sort->param_fcns = compile_params (sort->param_list, obj, &resObj);
00508
00509
00510
00511
00512 if (sort->param_fcns)
00513 {
00514 sort->comp_fcn = qof_query_core_get_compare (resObj->param_type);
00515
00516
00517 if (sort->comp_fcn == NULL)
00518 {
00519 sort->obj_cmp =
00520 qof_class_get_default_sort (resObj->param_type);
00521 }
00522 }
00523 else if (!safe_strcmp (sort->param_list->data, QUERY_DEFAULT_SORT))
00524 {
00525 sort->use_default = TRUE;
00526 }
00527 LEAVE ("sort=%p id=%s", sort, obj);
00528 }
00529
00530 static void
00531 compile_terms (QofQuery * q)
00532 {
00533 GList *or_ptr, *and_ptr, *node;
00534
00535 ENTER (" query=%p", q);
00536
00537
00538
00539 for (or_ptr = q->terms; or_ptr; or_ptr = or_ptr->next)
00540 {
00541 for (and_ptr = or_ptr->data; and_ptr; and_ptr = and_ptr->next)
00542 {
00543 QofQueryTerm *qt = and_ptr->data;
00544 const QofParam *resObj = NULL;
00545
00546 g_slist_free (qt->param_fcns);
00547 qt->param_fcns = NULL;
00548
00549
00550 qt->param_fcns = compile_params (qt->param_list, q->search_for,
00551 &resObj);
00552
00553
00554
00555
00556
00557 if (qt->param_fcns)
00558 qt->pred_fcn =
00559 qof_query_core_get_predicate (resObj->param_type);
00560 else
00561 qt->pred_fcn = NULL;
00562 }
00563 }
00564
00565
00566 compile_sort (&(q->primary_sort), q->search_for);
00567 compile_sort (&(q->secondary_sort), q->search_for);
00568 compile_sort (&(q->tertiary_sort), q->search_for);
00569
00570 q->defaultSort = qof_class_get_default_sort (q->search_for);
00571
00572
00573 for (node = q->books; node; node = node->next)
00574 {
00575 QofBook *book = node->data;
00576 QofBackend *be = book->backend;
00577
00578 if (be && be->compile_query)
00579 {
00580 gpointer result = (be->compile_query) (be, q);
00581 if (result)
00582 g_hash_table_insert (q->be_compiled, book, result);
00583 }
00584 }
00585 LEAVE (" query=%p", q);
00586 }
00587
00588 static void
00589 check_item_cb (gpointer object, gpointer user_data)
00590 {
00591 QofQueryCB *ql = user_data;
00592
00593 if (!object || !ql)
00594 return;
00595
00596 if (check_object (ql->query, object))
00597 {
00598 ql->list = g_list_prepend (ql->list, object);
00599 ql->count++;
00600 }
00601 return;
00602 }
00603
00604 static int
00605 param_list_cmp (GSList * l1, GSList * l2)
00606 {
00607 while (1)
00608 {
00609 int ret;
00610
00611
00612 if (!l1 && !l2)
00613 return 0;
00614 if (!l1 && l2)
00615 return -1;
00616 if (l1 && !l2)
00617 return 1;
00618
00619 ret = safe_strcmp (l1->data, l2->data);
00620 if (ret)
00621 return ret;
00622
00623 l1 = l1->next;
00624 l2 = l2->next;
00625 }
00626 }
00627
00628 static GList *
00629 merge_books (GList * l1, GList * l2)
00630 {
00631 GList *res = NULL;
00632 GList *node;
00633
00634 res = g_list_copy (l1);
00635
00636 for (node = l2; node; node = node->next)
00637 {
00638 if (g_list_index (res, node->data) == -1)
00639 res = g_list_prepend (res, node->data);
00640 }
00641
00642 return res;
00643 }
00644
00645 static gboolean
00646 query_free_compiled (gpointer key, gpointer value,
00647 gpointer user_data __attribute__ ((unused)))
00648 {
00649 QofBook *book = key;
00650 QofBackend *be = book->backend;
00651
00652 if (be && be->free_query)
00653 (be->free_query) (be, value);
00654
00655 return TRUE;
00656 }
00657
00658
00659 static void
00660 query_clear_compiles (QofQuery * q)
00661 {
00662 g_hash_table_foreach_remove (q->be_compiled, query_free_compiled,
00663 NULL);
00664 }
00665
00666
00667
00668
00669 GSList *
00670 qof_query_build_param_list (gchar const *param, ...)
00671 {
00672 GSList *param_list = NULL;
00673 gchar const *this_param;
00674 va_list ap;
00675
00676 if (!param)
00677 return NULL;
00678
00679 va_start (ap, param);
00680
00681 for (this_param = param; this_param;
00682 this_param = va_arg (ap, const gchar *))
00683 param_list = g_slist_prepend (param_list, (gpointer) this_param);
00684
00685 va_end (ap);
00686
00687 return g_slist_reverse (param_list);
00688 }
00689
00690 void
00691 qof_query_add_term (QofQuery * q, GSList * param_list,
00692 QofQueryPredData * pred_data, QofQueryOp op)
00693 {
00694 QofQueryTerm *qt;
00695 QofQuery *qr, *qs;
00696
00697 if (!q || !param_list || !pred_data)
00698 return;
00699
00700 qt = g_new0 (QofQueryTerm, 1);
00701 qt->param_list = param_list;
00702 qt->pdata = pred_data;
00703 qs = qof_query_create ();
00704 query_init (qs, qt);
00705
00706 if (qof_query_has_terms (q))
00707 qr = qof_query_merge (q, qs, op);
00708 else
00709 qr = qof_query_merge (q, qs, QOF_QUERY_OR);
00710
00711 swap_terms (q, qr);
00712 qof_query_destroy (qs);
00713 qof_query_destroy (qr);
00714 }
00715
00716 void
00717 qof_query_purge_terms (QofQuery * q, GSList * param_list)
00718 {
00719 QofQueryTerm *qt;
00720 GList *or, *and;
00721
00722 if (!q || !param_list)
00723 return;
00724
00725 for (or = q->terms; or; or = or->next)
00726 {
00727 for (and = or->data; and; and = and->next)
00728 {
00729 qt = and->data;
00730 if (!param_list_cmp (qt->param_list, param_list))
00731 {
00732 if (g_list_length (or->data) == 1)
00733 {
00734 q->terms = g_list_remove_link (q->terms, or);
00735 g_list_free_1 (or);
00736 or = q->terms;
00737 break;
00738 }
00739 else
00740 {
00741 or->data = g_list_remove_link (or->data, and);
00742 g_list_free_1 (and);
00743 and = or->data;
00744 if (!and)
00745 break;
00746 }
00747 q->changed = 1;
00748 free_query_term (qt);
00749 }
00750 }
00751 if (!or)
00752 break;
00753 }
00754 }
00755
00756 GList *
00757 qof_query_run (QofQuery * q)
00758 {
00759 GList *matching_objects = NULL;
00760 GList *node;
00761 gint object_count = 0;
00762
00763 if (!q)
00764 return NULL;
00765 g_return_val_if_fail (q->search_for, NULL);
00766 g_return_val_if_fail (q->books, NULL);
00767 ENTER (" q=%p", q);
00768
00769
00770
00771
00772 if (q->changed)
00773 {
00774 query_clear_compiles (q);
00775 compile_terms (q);
00776 }
00777
00778
00779 if (qof_log_check (log_module, QOF_LOG_DETAIL))
00780 qof_query_print (q);
00781
00782
00783 {
00784 QofQueryCB qcb;
00785
00786 memset (&qcb, 0, sizeof (qcb));
00787 qcb.query = q;
00788
00789
00790 for (node = q->books; node; node = node->next)
00791 {
00792 QofBook *book = node->data;
00793 QofBackend *be = book->backend;
00794
00795
00796 if (be)
00797 {
00798 gpointer compiled_query =
00799 g_hash_table_lookup (q->be_compiled, book);
00800
00801 if (compiled_query && be->run_query)
00802 {
00803 (be->run_query) (be, compiled_query);
00804 }
00805 }
00806
00807
00808 qof_object_foreach (q->search_for, book,
00809 (QofEntityForeachCB) check_item_cb, &qcb);
00810 }
00811
00812 matching_objects = qcb.list;
00813 object_count = qcb.count;
00814 }
00815 PINFO ("matching objects=%p count=%d", matching_objects, object_count);
00816
00817
00818
00819
00820
00821
00822
00823 matching_objects = g_list_reverse (matching_objects);
00824
00825
00826
00827
00828
00829 if (q->primary_sort.comp_fcn || q->primary_sort.obj_cmp ||
00830 (q->primary_sort.use_default && q->defaultSort))
00831 {
00832 sortQuery = q;
00833 matching_objects = g_list_sort (matching_objects, sort_func);
00834 sortQuery = NULL;
00835 }
00836
00837
00838 if ((object_count > q->max_results) && (q->max_results > -1))
00839 {
00840 if (q->max_results > 0)
00841 {
00842 GList *mptr;
00843
00844
00845 mptr =
00846 g_list_nth (matching_objects,
00847 object_count - q->max_results);
00848
00849 if (mptr != NULL)
00850 {
00851 if (mptr->prev != NULL)
00852 mptr->prev->next = NULL;
00853 mptr->prev = NULL;
00854 }
00855 g_list_free (matching_objects);
00856 matching_objects = mptr;
00857 }
00858 else
00859 {
00860
00861 g_list_free (matching_objects);
00862 matching_objects = NULL;
00863 }
00864 object_count = q->max_results;
00865 }
00866
00867 q->changed = 0;
00868
00869 g_list_free (q->results);
00870 q->results = matching_objects;
00871
00872 LEAVE (" q=%p", q);
00873 return matching_objects;
00874 }
00875
00876 GList *
00877 qof_query_last_run (QofQuery * query)
00878 {
00879 if (!query)
00880 return NULL;
00881
00882 return query->results;
00883 }
00884
00885 void
00886 qof_query_clear (QofQuery * query)
00887 {
00888 QofQuery *q2 = qof_query_create ();
00889 swap_terms (query, q2);
00890 qof_query_destroy (q2);
00891
00892 g_list_free (query->books);
00893 query->books = NULL;
00894 g_list_free (query->results);
00895 query->results = NULL;
00896 query->changed = 1;
00897 }
00898
00899 QofQuery *
00900 qof_query_create (void)
00901 {
00902 QofQuery *qp = g_new0 (QofQuery, 1);
00903 qp->be_compiled = g_hash_table_new (g_direct_hash, g_direct_equal);
00904 query_init (qp, NULL);
00905 return qp;
00906 }
00907
00908 void
00909 qof_query_search_for (QofQuery * q, QofIdTypeConst obj_type)
00910 {
00911 if (!q || !obj_type)
00912 return;
00913
00914 if (safe_strcmp (q->search_for, obj_type))
00915 {
00916 q->search_for = (QofIdType) obj_type;
00917 q->changed = 1;
00918 }
00919 }
00920
00921 QofQuery *
00922 qof_query_create_for (QofIdTypeConst obj_type)
00923 {
00924 QofQuery *q;
00925 if (!obj_type)
00926 return NULL;
00927 q = qof_query_create ();
00928 qof_query_search_for (q, obj_type);
00929 return q;
00930 }
00931
00932 gint
00933 qof_query_has_terms (QofQuery * q)
00934 {
00935 if (!q)
00936 return 0;
00937 return g_list_length (q->terms);
00938 }
00939
00940 gint
00941 qof_query_num_terms (QofQuery * q)
00942 {
00943 GList *o;
00944 gint n = 0;
00945 if (!q)
00946 return 0;
00947 for (o = q->terms; o; o = o->next)
00948 n += g_list_length (o->data);
00949 return n;
00950 }
00951
00952 gboolean
00953 qof_query_has_term_type (QofQuery * q, GSList * term_param)
00954 {
00955 GList *or;
00956 GList *and;
00957
00958 if (!q || !term_param)
00959 return FALSE;
00960
00961 for (or = q->terms; or; or = or->next)
00962 {
00963 for (and = or->data; and; and = and->next)
00964 {
00965 QofQueryTerm *qt = and->data;
00966 if (!param_list_cmp (term_param, qt->param_list))
00967 return TRUE;
00968 }
00969 }
00970
00971 return FALSE;
00972 }
00973
00974 GSList *
00975 qof_query_get_term_type (QofQuery * q, GSList * term_param)
00976 {
00977 GList *or;
00978 GList *and;
00979 GSList *results = NULL;
00980
00981 if (!q || !term_param)
00982 return FALSE;
00983
00984 for (or = q->terms; or; or = or->next)
00985 {
00986 for (and = or->data; and; and = and->next)
00987 {
00988 QofQueryTerm *qt = and->data;
00989 if (!param_list_cmp (term_param, qt->param_list))
00990 results = g_slist_append (results, qt->pdata);
00991 }
00992 }
00993
00994 return results;
00995 }
00996
00997 void
00998 qof_query_destroy (QofQuery * q)
00999 {
01000 if (!q)
01001 return;
01002 free_members (q);
01003 query_clear_compiles (q);
01004 g_hash_table_destroy (q->be_compiled);
01005 g_free (q);
01006 }
01007
01008 QofQuery *
01009 qof_query_copy (QofQuery * q)
01010 {
01011 QofQuery *copy;
01012 GHashTable *ht;
01013
01014 if (!q)
01015 return NULL;
01016 copy = qof_query_create ();
01017 ht = copy->be_compiled;
01018 free_members (copy);
01019
01020 memcpy (copy, q, sizeof (QofQuery));
01021
01022 copy->be_compiled = ht;
01023 copy->terms = copy_or_terms (q->terms);
01024 copy->books = g_list_copy (q->books);
01025 copy->results = g_list_copy (q->results);
01026
01027 copy_sort (&(copy->primary_sort), &(q->primary_sort));
01028 copy_sort (&(copy->secondary_sort), &(q->secondary_sort));
01029 copy_sort (&(copy->tertiary_sort), &(q->tertiary_sort));
01030
01031 copy->changed = 1;
01032
01033 return copy;
01034 }
01035
01036
01037
01038
01039
01040
01041
01042 QofQuery *
01043 qof_query_invert (QofQuery * q)
01044 {
01045 QofQuery *retval;
01046 QofQuery *right, *left, *iright, *ileft;
01047 QofQueryTerm *qt;
01048 GList *aterms;
01049 GList *cur;
01050 GList *new_oterm;
01051 gint num_or_terms;
01052
01053 if (!q)
01054 return NULL;
01055
01056 num_or_terms = g_list_length (q->terms);
01057
01058 switch (num_or_terms)
01059 {
01060 case 0:
01061 retval = qof_query_create ();
01062 retval->max_results = q->max_results;
01063 break;
01064
01065
01066
01067 case 1:
01068 retval = qof_query_create ();
01069 retval->max_results = q->max_results;
01070 retval->books = g_list_copy (q->books);
01071 retval->search_for = q->search_for;
01072 retval->changed = 1;
01073
01074 aterms = g_list_nth_data (q->terms, 0);
01075 new_oterm = NULL;
01076 for (cur = aterms; cur; cur = cur->next)
01077 {
01078 qt = copy_query_term (cur->data);
01079 qt->invert = !(qt->invert);
01080 new_oterm = g_list_append (NULL, qt);
01081
01082
01083
01084
01085 retval->terms = g_list_reverse (retval->terms);
01086 retval->terms = g_list_prepend (retval->terms, new_oterm);
01087 retval->terms = g_list_reverse (retval->terms);
01088 }
01089 break;
01090
01091
01092
01093
01094 default:
01095 right = qof_query_create ();
01096 right->terms = copy_or_terms (g_list_nth (q->terms, 1));
01097
01098 left = qof_query_create ();
01099 left->terms = g_list_append (NULL,
01100 copy_and_terms (g_list_nth_data (q->terms, 0)));
01101
01102 iright = qof_query_invert (right);
01103 ileft = qof_query_invert (left);
01104
01105 retval = qof_query_merge (iright, ileft, QOF_QUERY_AND);
01106 retval->books = g_list_copy (q->books);
01107 retval->max_results = q->max_results;
01108 retval->search_for = q->search_for;
01109 retval->changed = 1;
01110
01111 qof_query_destroy (iright);
01112 qof_query_destroy (ileft);
01113 qof_query_destroy (right);
01114 qof_query_destroy (left);
01115 break;
01116 }
01117
01118 return retval;
01119 }
01120
01121
01122
01123
01124
01125
01126 QofQuery *
01127 qof_query_merge (QofQuery * q1, QofQuery * q2, QofQueryOp op)
01128 {
01129
01130 QofQuery *retval = NULL;
01131 QofQuery *i1, *i2;
01132 QofQuery *t1, *t2;
01133 GList *i, *j;
01134 QofIdType search_for;
01135
01136 if (!q1)
01137 return q2;
01138 if (!q2)
01139 return q1;
01140
01141 if (q1->search_for && q2->search_for)
01142 g_return_val_if_fail (safe_strcmp (q1->search_for,
01143 q2->search_for) == 0, NULL);
01144
01145 search_for = (q1->search_for ? q1->search_for : q2->search_for);
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 if ((QOF_QUERY_AND == op) && (0 == qof_query_has_terms (q1)))
01157 {
01158 op = QOF_QUERY_OR;
01159 }
01160
01161 switch (op)
01162 {
01163 case QOF_QUERY_OR:
01164 retval = qof_query_create ();
01165 retval->terms =
01166 g_list_concat (copy_or_terms (q1->terms),
01167 copy_or_terms (q2->terms));
01168 retval->books = merge_books (q1->books, q2->books);
01169 retval->max_results = q1->max_results;
01170 retval->changed = 1;
01171 break;
01172
01173 case QOF_QUERY_AND:
01174 retval = qof_query_create ();
01175 retval->books = merge_books (q1->books, q2->books);
01176 retval->max_results = q1->max_results;
01177 retval->changed = 1;
01178
01179
01180
01181
01182
01183 for (i = q1->terms; i; i = i->next)
01184 {
01185 for (j = q2->terms; j; j = j->next)
01186 {
01187 retval->terms =
01188 g_list_prepend (retval->terms,
01189 g_list_concat
01190 (copy_and_terms (i->data), copy_and_terms (j->data)));
01191 }
01192 }
01193 retval->terms = g_list_reverse (retval->terms);
01194 break;
01195
01196 case QOF_QUERY_NAND:
01197
01198 i1 = qof_query_invert (q1);
01199 i2 = qof_query_invert (q2);
01200 retval = qof_query_merge (i1, i2, QOF_QUERY_OR);
01201 qof_query_destroy (i1);
01202 qof_query_destroy (i2);
01203 break;
01204
01205 case QOF_QUERY_NOR:
01206
01207 i1 = qof_query_invert (q1);
01208 i2 = qof_query_invert (q2);
01209 retval = qof_query_merge (i1, i2, QOF_QUERY_AND);
01210 qof_query_destroy (i1);
01211 qof_query_destroy (i2);
01212 break;
01213
01214 case QOF_QUERY_XOR:
01215
01216 i1 = qof_query_invert (q1);
01217 i2 = qof_query_invert (q2);
01218 t1 = qof_query_merge (q1, i2, QOF_QUERY_AND);
01219 t2 = qof_query_merge (i1, q2, QOF_QUERY_AND);
01220 retval = qof_query_merge (t1, t2, QOF_QUERY_OR);
01221
01222 qof_query_destroy (i1);
01223 qof_query_destroy (i2);
01224 qof_query_destroy (t1);
01225 qof_query_destroy (t2);
01226 break;
01227 }
01228
01229 retval->search_for = search_for;
01230 return retval;
01231 }
01232
01233 void
01234 qof_query_merge_in_place (QofQuery * q1, QofQuery * q2, QofQueryOp op)
01235 {
01236 QofQuery *tmp_q;
01237
01238 if (!q1 || !q2)
01239 return;
01240
01241 tmp_q = qof_query_merge (q1, q2, op);
01242 swap_terms (q1, tmp_q);
01243 qof_query_destroy (tmp_q);
01244 }
01245
01246 void
01247 qof_query_set_sort_order (QofQuery * q,
01248 GSList * params1, GSList * params2, GSList * params3)
01249 {
01250 if (!q)
01251 return;
01252 if (q->primary_sort.param_list)
01253 g_slist_free (q->primary_sort.param_list);
01254 q->primary_sort.param_list = params1;
01255 q->primary_sort.options = 0;
01256
01257 if (q->secondary_sort.param_list)
01258 g_slist_free (q->secondary_sort.param_list);
01259 q->secondary_sort.param_list = params2;
01260 q->secondary_sort.options = 0;
01261
01262 if (q->tertiary_sort.param_list)
01263 g_slist_free (q->tertiary_sort.param_list);
01264 q->tertiary_sort.param_list = params3;
01265 q->tertiary_sort.options = 0;
01266
01267 q->changed = 1;
01268 }
01269
01270 void
01271 qof_query_set_sort_options (QofQuery * q, gint prim_op, gint sec_op,
01272 gint tert_op)
01273 {
01274 if (!q)
01275 return;
01276 q->primary_sort.options = prim_op;
01277 q->secondary_sort.options = sec_op;
01278 q->tertiary_sort.options = tert_op;
01279 }
01280
01281 void
01282 qof_query_set_sort_increasing (QofQuery * q, gboolean prim_inc,
01283 gboolean sec_inc, gboolean tert_inc)
01284 {
01285 if (!q)
01286 return;
01287 q->primary_sort.increasing = prim_inc;
01288 q->secondary_sort.increasing = sec_inc;
01289 q->tertiary_sort.increasing = tert_inc;
01290 }
01291
01292 void
01293 qof_query_set_max_results (QofQuery * q, gint n)
01294 {
01295 if (!q)
01296 return;
01297 q->max_results = n;
01298 }
01299
01300 void
01301 qof_query_add_guid_list_match (QofQuery * q, GSList * param_list,
01302 GList * guid_list, QofGuidMatch options, QofQueryOp op)
01303 {
01304 QofQueryPredData *pdata;
01305
01306 if (!q || !param_list)
01307 return;
01308
01309 if (!guid_list)
01310 g_return_if_fail (options == QOF_GUID_MATCH_NULL);
01311
01312 pdata = qof_query_guid_predicate (options, guid_list);
01313 qof_query_add_term (q, param_list, pdata, op);
01314 }
01315
01316 void
01317 qof_query_add_guid_match (QofQuery * q, GSList * param_list,
01318 const GUID * guid, QofQueryOp op)
01319 {
01320 GList *g = NULL;
01321
01322 if (!q || !param_list)
01323 return;
01324
01325 if (guid)
01326 g = g_list_prepend (g, (gpointer) guid);
01327
01328 qof_query_add_guid_list_match (q, param_list, g,
01329 g ? QOF_GUID_MATCH_ANY : QOF_GUID_MATCH_NULL, op);
01330
01331 g_list_free (g);
01332 }
01333
01334 void
01335 qof_query_set_book (QofQuery * q, QofBook * book)
01336 {
01337 GSList *slist = NULL;
01338 if (!q || !book)
01339 return;
01340
01341
01342 if (g_list_index (q->books, book) == -1)
01343 q->books = g_list_prepend (q->books, book);
01344
01345 slist = g_slist_prepend (slist, QOF_PARAM_GUID);
01346 slist = g_slist_prepend (slist, QOF_PARAM_BOOK);
01347 qof_query_add_guid_match (q, slist,
01348 qof_entity_get_guid ((QofEntity*)book), QOF_QUERY_AND);
01349 }
01350
01351 GList *
01352 qof_query_get_books (QofQuery * q)
01353 {
01354 if (!q)
01355 return NULL;
01356 return q->books;
01357 }
01358
01359 void
01360 qof_query_add_boolean_match (QofQuery * q, GSList * param_list,
01361 gboolean value, QofQueryOp op)
01362 {
01363 QofQueryPredData *pdata;
01364 if (!q || !param_list)
01365 return;
01366
01367 pdata = qof_query_boolean_predicate (QOF_COMPARE_EQUAL, value);
01368 qof_query_add_term (q, param_list, pdata, op);
01369 }
01370
01371
01372
01373
01374 void
01375 qof_query_init (void)
01376 {
01377 ENTER (" ");
01378 qof_query_core_init ();
01379 qof_class_init ();
01380 qof_date_init ();
01381 LEAVE ("Completed initialization of QofQuery");
01382 }
01383
01384 void
01385 qof_query_shutdown (void)
01386 {
01387 qof_class_shutdown ();
01388 qof_query_core_shutdown ();
01389 }
01390
01391 gint
01392 qof_query_get_max_results (QofQuery * q)
01393 {
01394 if (!q)
01395 return 0;
01396 return q->max_results;
01397 }
01398
01399 QofIdType
01400 qof_query_get_search_for (QofQuery * q)
01401 {
01402 if (!q)
01403 return NULL;
01404 return q->search_for;
01405 }
01406
01407 GList *
01408 qof_query_get_terms (QofQuery * q)
01409 {
01410 if (!q)
01411 return NULL;
01412 return q->terms;
01413 }
01414
01415 GSList *
01416 qof_query_term_get_param_path (QofQueryTerm * qt)
01417 {
01418 if (!qt)
01419 return NULL;
01420 return qt->param_list;
01421 }
01422
01423 QofQueryPredData *
01424 qof_query_term_get_pred_data (QofQueryTerm * qt)
01425 {
01426 if (!qt)
01427 return NULL;
01428 return qt->pdata;
01429 }
01430
01431 gboolean
01432 qof_query_term_is_inverted (QofQueryTerm * qt)
01433 {
01434 if (!qt)
01435 return FALSE;
01436 return qt->invert;
01437 }
01438
01439 void
01440 qof_query_get_sorts (QofQuery * q, QofQuerySort ** primary,
01441 QofQuerySort ** secondary, QofQuerySort ** tertiary)
01442 {
01443 if (!q)
01444 return;
01445 if (primary)
01446 *primary = &(q->primary_sort);
01447 if (secondary)
01448 *secondary = &(q->secondary_sort);
01449 if (tertiary)
01450 *tertiary = &(q->tertiary_sort);
01451 }
01452
01453 GSList *
01454 qof_query_sort_get_param_path (QofQuerySort * qs)
01455 {
01456 if (!qs)
01457 return NULL;
01458 return qs->param_list;
01459 }
01460
01461 gint
01462 qof_query_sort_get_sort_options (QofQuerySort * qs)
01463 {
01464 if (!qs)
01465 return 0;
01466 return qs->options;
01467 }
01468
01469 gboolean
01470 qof_query_sort_get_increasing (QofQuerySort * qs)
01471 {
01472 if (!qs)
01473 return FALSE;
01474 return qs->increasing;
01475 }
01476
01477 static gboolean
01478 qof_query_term_equal (QofQueryTerm * qt1, QofQueryTerm * qt2)
01479 {
01480 if (qt1 == qt2)
01481 return TRUE;
01482 if (!qt1 || !qt2)
01483 return FALSE;
01484
01485 if (qt1->invert != qt2->invert)
01486 return FALSE;
01487 if (param_list_cmp (qt1->param_list, qt2->param_list))
01488 return FALSE;
01489 return qof_query_core_predicate_equal (qt1->pdata, qt2->pdata);
01490 }
01491
01492 static gboolean
01493 qof_query_sort_equal (QofQuerySort * qs1, QofQuerySort * qs2)
01494 {
01495 if (qs1 == qs2)
01496 return TRUE;
01497 if (!qs1 || !qs2)
01498 return FALSE;
01499
01500
01501 if (!qs1->param_list && !qs2->param_list)
01502 return TRUE;
01503
01504 if (qs1->options != qs2->options)
01505 return FALSE;
01506 if (qs1->increasing != qs2->increasing)
01507 return FALSE;
01508 return (param_list_cmp (qs1->param_list, qs2->param_list) == 0);
01509 }
01510
01511 gboolean
01512 qof_query_equal (QofQuery * q1, QofQuery * q2)
01513 {
01514 GList *or1, *or2;
01515
01516 if (q1 == q2)
01517 return TRUE;
01518 if (!q1 || !q2)
01519 return FALSE;
01520
01521 if (g_list_length (q1->terms) != g_list_length (q2->terms))
01522 return FALSE;
01523 if (q1->max_results != q2->max_results)
01524 return FALSE;
01525
01526 for (or1 = q1->terms, or2 = q2->terms; or1;
01527 or1 = or1->next, or2 = or2->next)
01528 {
01529 GList *and1, *and2;
01530
01531 and1 = or1->data;
01532 and2 = or2->data;
01533
01534 if (g_list_length (and1) != g_list_length (and2))
01535 return FALSE;
01536
01537 for (; and1; and1 = and1->next, and2 = and2->next)
01538 if (!qof_query_term_equal (and1->data, and2->data))
01539 return FALSE;
01540 }
01541
01542 if (!qof_query_sort_equal (&(q1->primary_sort), &(q2->primary_sort)))
01543 return FALSE;
01544 if (!qof_query_sort_equal (&(q1->secondary_sort),
01545 &(q2->secondary_sort)))
01546 return FALSE;
01547 if (!qof_query_sort_equal (&(q1->tertiary_sort), &(q2->tertiary_sort)))
01548 return FALSE;
01549
01550 return TRUE;
01551 }
01552
01553
01554
01555
01556
01557
01558 static GList *qof_query_printSearchFor (QofQuery * query, GList * output);
01559 static GList *qof_query_printTerms (QofQuery * query, GList * output);
01560 static GList *qof_query_printSorts (QofQuerySort * s[],
01561 const gint numSorts, GList * output);
01562 static GList *qof_query_printAndTerms (GList * terms, GList * output);
01563 static gchar *qof_query_printStringForHow (QofQueryCompare how);
01564 static gchar *qof_query_printStringMatch (QofStringMatch s);
01565 static gchar *qof_query_printDateMatch (QofDateMatch d);
01566 static gchar *qof_query_printNumericMatch (QofNumericMatch n);
01567 static gchar *qof_query_printGuidMatch (QofGuidMatch g);
01568 static gchar *qof_query_printCharMatch (QofCharMatch c);
01569 static GList *qof_query_printPredData (QofQueryPredData * pd, GList * lst);
01570 static GString *qof_query_printParamPath (GSList * parmList);
01571 static void qof_query_printValueForParam (QofQueryPredData * pd,
01572 GString * gs);
01573 static void qof_query_printOutput (GList * output);
01574
01576 void
01577 qof_query_print (QofQuery * query)
01578 {
01579 GList *output;
01580 GString *str;
01581 QofQuerySort *s[3];
01582 gint maxResults = 0, numSorts = 3;
01583
01584 ENTER (" ");
01585
01586 if (!query)
01587 {
01588 LEAVE ("query is (null)");
01589 return;
01590 }
01591
01592 output = NULL;
01593 str = NULL;
01594 maxResults = qof_query_get_max_results (query);
01595
01596 output = qof_query_printSearchFor (query, output);
01597 output = qof_query_printTerms (query, output);
01598
01599 qof_query_get_sorts (query, &s[0], &s[1], &s[2]);
01600
01601 if (s[0])
01602 {
01603 output = qof_query_printSorts (s, numSorts, output);
01604 }
01605
01606 str = g_string_new (" ");
01607 g_string_printf (str, "Maximum number of results: %d", maxResults);
01608 output = g_list_append (output, str);
01609
01610 qof_query_printOutput (output);
01611 LEAVE (" ");
01612 }
01613
01614 static void
01615 qof_query_printOutput (GList * output)
01616 {
01617 GList *lst;
01618
01619 for (lst = output; lst; lst = lst->next)
01620 {
01621 GString *line = (GString *) lst->data;
01622
01623 DEBUG (" %s", line->str);
01624 g_string_free (line, TRUE);
01625 line = NULL;
01626 }
01627 }
01628
01629
01630
01631
01632
01633 static GList *
01634 qof_query_printSearchFor (QofQuery * query, GList * output)
01635 {
01636 QofIdType searchFor;
01637 GString *gs;
01638
01639 searchFor = qof_query_get_search_for (query);
01640 gs = g_string_new ("Query Object Type: ");
01641 g_string_append (gs, (NULL == searchFor) ? "(null)" : searchFor);
01642 output = g_list_append (output, gs);
01643
01644 return output;
01645 }
01646
01647
01648
01649
01650
01651
01652 static GList *
01653 qof_query_printTerms (QofQuery * query, GList * output)
01654 {
01655
01656 GList *terms, *lst;
01657
01658 terms = qof_query_get_terms (query);
01659
01660 for (lst = terms; lst; lst = lst->next)
01661 {
01662 output =
01663 g_list_append (output, g_string_new ("OR Terms:"));
01664
01665 if (lst->data)
01666 {
01667 output = qof_query_printAndTerms (lst->data, output);
01668 }
01669 else
01670 {
01671 output =
01672 g_list_append (output,
01673 g_string_new (" No data for AND terms"));
01674 }
01675 }
01676
01677 return output;
01678 }
01679
01680
01681
01682
01683
01684
01685 static GList *
01686 qof_query_printSorts (QofQuerySort * s[], const gint numSorts,
01687 GList * output)
01688 {
01689 GSList *gsl, *n = NULL;
01690 gint curSort;
01691 GString *gs = g_string_new ("Sort Parameters: ");
01692
01693 for (curSort = 0; curSort < numSorts; curSort++)
01694 {
01695 gboolean increasing;
01696 if (!s[curSort])
01697 {
01698 break;
01699 }
01700 increasing = qof_query_sort_get_increasing (s[curSort]);
01701
01702 gsl = qof_query_sort_get_param_path (s[curSort]);
01703 if (gsl)
01704 g_string_append_printf (gs, " Param: ");
01705 for (n = gsl; n; n = n->next)
01706 {
01707 QofIdType param_name = n->data;
01708 if (gsl != n)
01709 g_string_append_printf (gs, " ");
01710 g_string_append_printf (gs, "%s", param_name);
01711 }
01712 if (gsl)
01713 {
01714 g_string_append_printf (gs, " %s ",
01715 increasing ? "DESC" : "ASC");
01716 g_string_append_printf (gs, " Options: 0x%x ",
01717 s[curSort]->options);
01718 }
01719 }
01720
01721 output = g_list_append (output, gs);
01722 return output;
01723
01724 }
01725
01726
01727
01728
01729
01730 static GList *
01731 qof_query_printAndTerms (GList * terms, GList * output)
01732 {
01733 const gchar *prefix = "AND Terms:";
01734 QofQueryTerm *qt;
01735 QofQueryPredData *pd;
01736 GSList *path;
01737 GList *lst;
01738 gboolean invert;
01739
01740 output = g_list_append (output, g_string_new (prefix));
01741 for (lst = terms; lst; lst = lst->next)
01742 {
01743 qt = (QofQueryTerm *) lst->data;
01744 pd = qof_query_term_get_pred_data (qt);
01745 path = qof_query_term_get_param_path (qt);
01746 invert = qof_query_term_is_inverted (qt);
01747
01748 if (invert)
01749 output =
01750 g_list_append (output, g_string_new (" INVERT SENSE "));
01751 output = g_list_append (output, qof_query_printParamPath (path));
01752 output = qof_query_printPredData (pd, output);
01753
01754 }
01755
01756 return output;
01757 }
01758
01759
01760
01761
01762 static GString *
01763 qof_query_printParamPath (GSList * parmList)
01764 {
01765 GSList *list = NULL;
01766 GString *gs = g_string_new ("Param List: ");
01767 g_string_append (gs, " ");
01768 for (list = parmList; list; list = list->next)
01769 {
01770 g_string_append (gs, (gchar *) list->data);
01771 if (list->next)
01772 g_string_append (gs, ", ");
01773 }
01774
01775 return gs;
01776 }
01777
01778
01779
01780
01781 static GList *
01782 qof_query_printPredData (QofQueryPredData * pd, GList * lst)
01783 {
01784 GString *gs;
01785
01786 gs = g_string_new ("Pred Data: ");
01787 g_string_append (gs, (gchar *) pd->type_name);
01788
01789
01790 if (safe_strcmp (pd->type_name, QOF_TYPE_CHAR) &&
01791 safe_strcmp (pd->type_name, QOF_TYPE_GUID))
01792 {
01793 g_string_append_printf (gs, " how: %s",
01794 qof_query_printStringForHow (pd->how));
01795 }
01796 lst = g_list_append (lst, gs);
01797 gs = g_string_new ("");
01798 qof_query_printValueForParam (pd, gs);
01799 lst = g_list_append (lst, gs);
01800 return lst;
01801 }
01802
01803
01804
01805
01806
01807 static gchar *
01808 qof_query_printStringForHow (QofQueryCompare how)
01809 {
01810
01811 switch (how)
01812 {
01813 AS_STRING_CASE(QOF_COMPARE_LT,)
01814 AS_STRING_CASE(QOF_COMPARE_LTE,)
01815 AS_STRING_CASE(QOF_COMPARE_EQUAL,)
01816 AS_STRING_CASE(QOF_COMPARE_GT,)
01817 AS_STRING_CASE(QOF_COMPARE_GTE,)
01818 AS_STRING_CASE(QOF_COMPARE_NEQ,)
01819 }
01820 return "INVALID HOW";
01821 }
01822
01823
01824 static void
01825 qof_query_printValueForParam (QofQueryPredData * pd, GString * gs)
01826 {
01827
01828 if (!safe_strcmp (pd->type_name, QOF_TYPE_GUID))
01829 {
01830 GList *node;
01831 query_guid_t pdata = (query_guid_t) pd;
01832 g_string_append_printf (gs, "Match type %s ",
01833 qof_query_printGuidMatch (pdata->options));
01834 for (node = pdata->guids; node; node = node->next)
01835 {
01836
01837 g_string_append_printf (gs, ", guids: %s",
01838 guid_to_string ((GUID *) node->data));
01839 }
01840 return;
01841 }
01842 if (!safe_strcmp (pd->type_name, QOF_TYPE_STRING))
01843 {
01844 query_string_t pdata = (query_string_t) pd;
01845 g_string_append_printf (gs, "Match type %s ",
01846 qof_query_printStringMatch (pdata->options));
01847 g_string_append_printf (gs, " %s string: %s",
01848 pdata->is_regex ? "Regex" : "Not regex", pdata->matchstring);
01849 return;
01850 }
01851 if (!safe_strcmp (pd->type_name, QOF_TYPE_NUMERIC))
01852 {
01853 query_numeric_t pdata = (query_numeric_t) pd;
01854 g_string_append_printf (gs, "Match type %s ",
01855 qof_query_printNumericMatch (pdata->options));
01856 g_string_append_printf (gs, " numeric: %s",
01857 qof_numeric_dbg_to_string (pdata->amount));
01858 return;
01859 }
01860 if (!safe_strcmp (pd->type_name, QOF_TYPE_KVP))
01861 {
01862 GSList *node;
01863 query_kvp_t pdata = (query_kvp_t) pd;
01864 g_string_append_printf (gs, " kvp path: ");
01865 for (node = pdata->path; node; node = node->next)
01866 {
01867 g_string_append_printf (gs, "/%s", (gchar *) node->data);
01868 }
01869 g_string_append_printf (gs, " kvp value: %s ",
01870 kvp_value_to_string (pdata->value));
01871 return;
01872 }
01873 if (!safe_strcmp (pd->type_name, QOF_TYPE_INT64))
01874 {
01875 query_int64_t pdata = (query_int64_t) pd;
01876 g_string_append_printf (gs, " int64: %" G_GINT64_FORMAT,
01877 pdata->val);
01878 return;
01879 }
01880 if (!safe_strcmp (pd->type_name, QOF_TYPE_INT32))
01881 {
01882 query_int32_t pdata = (query_int32_t) pd;
01883 g_string_append_printf (gs, " int32: %d", pdata->val);
01884 return;
01885 }
01886 if (!safe_strcmp (pd->type_name, QOF_TYPE_DOUBLE))
01887 {
01888 query_double_t pdata = (query_double_t) pd;
01889 g_string_append_printf (gs, " double: %.18g", pdata->val);
01890 return;
01891 }
01892 if (!safe_strcmp (pd->type_name, QOF_TYPE_TIME))
01893 {
01894 query_time_t pdata;
01895 QofDate *qd;
01896
01897 pdata = (query_time_t) pd;
01898 qd = qof_date_from_qtime (pdata->qt);
01899 g_string_append_printf (gs, "Match type %s " ,
01900 qof_query_printDateMatch (pdata->options));
01901 g_string_append_printf (gs, "query date: %s",
01902 qof_date_print (qd, QOF_DATE_FORMAT_UTC));
01903 qof_date_free (qd);
01904 }
01905 #ifndef QOF_DISABLE_DEPRECATED
01906 if (!safe_strcmp (pd->type_name, QOF_TYPE_DATE))
01907 {
01908 query_date_t pdata;
01909
01910 pdata = (query_date_t) pd;
01911 g_string_append_printf (gs, "Match type %s ",
01912 qof_query_printDateMatch (pdata->options));
01913 g_string_append_printf (gs, " query_date: %s",
01914 gnc_print_date (pdata->date));
01915 return;
01916 }
01917 #endif
01918 if (!safe_strcmp (pd->type_name, QOF_TYPE_CHAR))
01919 {
01920 query_char_t pdata = (query_char_t) pd;
01921 g_string_append_printf (gs, "Match type %s ",
01922 qof_query_printCharMatch (pdata->options));
01923 g_string_append_printf (gs, " char list: %s",
01924 pdata->char_list);
01925 return;
01926 }
01927 if (!safe_strcmp (pd->type_name, QOF_TYPE_BOOLEAN))
01928 {
01929 query_boolean_t pdata = (query_boolean_t) pd;
01930 g_string_append_printf (gs, " boolean: %s",
01931 pdata->val ? "TRUE" : "FALSE");
01932 return;
01933 }
01935 return;
01936 }
01937
01938
01939
01940
01941
01942 static gchar *
01943 qof_query_printStringMatch (QofStringMatch s)
01944 {
01945 switch (s)
01946 {
01947 AS_STRING_CASE(QOF_STRING_MATCH_NORMAL,)
01948 AS_STRING_CASE(QOF_STRING_MATCH_CASEINSENSITIVE,)
01949 }
01950 return "UNKNOWN MATCH TYPE";
01951 }
01952
01953
01954
01955
01956
01957 static gchar *
01958 qof_query_printDateMatch (QofDateMatch d)
01959 {
01960 switch (d)
01961 {
01962 AS_STRING_CASE(QOF_DATE_MATCH_NORMAL,)
01963 AS_STRING_CASE(QOF_DATE_MATCH_DAY,)
01964 }
01965 return "UNKNOWN MATCH TYPE";
01966 }
01967
01968
01969
01970
01971
01972 static gchar *
01973 qof_query_printNumericMatch (QofNumericMatch n)
01974 {
01975 switch (n)
01976 {
01977 AS_STRING_CASE(QOF_NUMERIC_MATCH_DEBIT,)
01978 AS_STRING_CASE(QOF_NUMERIC_MATCH_CREDIT,)
01979 AS_STRING_CASE(QOF_NUMERIC_MATCH_ANY,)
01980 }
01981 return "UNKNOWN MATCH TYPE";
01982 }
01983
01984
01985
01986
01987
01988 static gchar *
01989 qof_query_printGuidMatch (QofGuidMatch g)
01990 {
01991 switch (g)
01992 {
01993 AS_STRING_CASE(QOF_GUID_MATCH_ANY,)
01994 AS_STRING_CASE(QOF_GUID_MATCH_ALL,)
01995 AS_STRING_CASE(QOF_GUID_MATCH_NONE,)
01996 AS_STRING_CASE(QOF_GUID_MATCH_NULL,)
01997 AS_STRING_CASE(QOF_GUID_MATCH_LIST_ANY,)
01998 }
01999
02000 return "UNKNOWN MATCH TYPE";
02001 }
02002
02003
02004
02005
02006
02007 static gchar *
02008 qof_query_printCharMatch (QofCharMatch c)
02009 {
02010 switch (c)
02011 {
02012 AS_STRING_CASE(QOF_CHAR_MATCH_ANY,)
02013 AS_STRING_CASE(QOF_CHAR_MATCH_NONE,)
02014 }
02015 return "UNKNOWN MATCH TYPE";
02016 }
02017
02018