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, gpointer not_used)
00647 {
00648 QofBook *book = key;
00649 QofBackend *be = book->backend;
00650
00651 if (be && be->free_query)
00652 (be->free_query) (be, value);
00653
00654 return TRUE;
00655 }
00656
00657
00658 static void
00659 query_clear_compiles (QofQuery * q)
00660 {
00661 g_hash_table_foreach_remove (q->be_compiled, query_free_compiled,
00662 NULL);
00663 }
00664
00665
00666
00667
00668 GSList *
00669 qof_query_build_param_list (gchar const *param, ...)
00670 {
00671 GSList *param_list = NULL;
00672 gchar const *this_param;
00673 va_list ap;
00674
00675 if (!param)
00676 return NULL;
00677
00678 va_start (ap, param);
00679
00680 for (this_param = param; this_param;
00681 this_param = va_arg (ap, const gchar *))
00682 param_list = g_slist_prepend (param_list, (gpointer) this_param);
00683
00684 va_end (ap);
00685
00686 return g_slist_reverse (param_list);
00687 }
00688
00689 void
00690 qof_query_add_term (QofQuery * q, GSList * param_list,
00691 QofQueryPredData * pred_data, QofQueryOp op)
00692 {
00693 QofQueryTerm *qt;
00694 QofQuery *qr, *qs;
00695
00696 if (!q || !param_list || !pred_data)
00697 return;
00698
00699 qt = g_new0 (QofQueryTerm, 1);
00700 qt->param_list = param_list;
00701 qt->pdata = pred_data;
00702 qs = qof_query_create ();
00703 query_init (qs, qt);
00704
00705 if (qof_query_has_terms (q))
00706 qr = qof_query_merge (q, qs, op);
00707 else
00708 qr = qof_query_merge (q, qs, QOF_QUERY_OR);
00709
00710 swap_terms (q, qr);
00711 qof_query_destroy (qs);
00712 qof_query_destroy (qr);
00713 }
00714
00715 void
00716 qof_query_purge_terms (QofQuery * q, GSList * param_list)
00717 {
00718 QofQueryTerm *qt;
00719 GList *or, *and;
00720
00721 if (!q || !param_list)
00722 return;
00723
00724 for (or = q->terms; or; or = or->next)
00725 {
00726 for (and = or->data; and; and = and->next)
00727 {
00728 qt = and->data;
00729 if (!param_list_cmp (qt->param_list, param_list))
00730 {
00731 if (g_list_length (or->data) == 1)
00732 {
00733 q->terms = g_list_remove_link (q->terms, or);
00734 g_list_free_1 (or);
00735 or = q->terms;
00736 break;
00737 }
00738 else
00739 {
00740 or->data = g_list_remove_link (or->data, and);
00741 g_list_free_1 (and);
00742 and = or->data;
00743 if (!and)
00744 break;
00745 }
00746 q->changed = 1;
00747 free_query_term (qt);
00748 }
00749 }
00750 if (!or)
00751 break;
00752 }
00753 }
00754
00755 GList *
00756 qof_query_run (QofQuery * q)
00757 {
00758 GList *matching_objects = NULL;
00759 GList *node;
00760 gint object_count = 0;
00761
00762 if (!q)
00763 return NULL;
00764 g_return_val_if_fail (q->search_for, NULL);
00765 g_return_val_if_fail (q->books, NULL);
00766 ENTER (" q=%p", q);
00767
00768
00769
00770
00771 if (q->changed)
00772 {
00773 query_clear_compiles (q);
00774 compile_terms (q);
00775 }
00776
00777
00778 if (qof_log_check (log_module, QOF_LOG_DETAIL))
00779 qof_query_print (q);
00780
00781
00782 {
00783 QofQueryCB qcb;
00784
00785 memset (&qcb, 0, sizeof (qcb));
00786 qcb.query = q;
00787
00788
00789 for (node = q->books; node; node = node->next)
00790 {
00791 QofBook *book = node->data;
00792 QofBackend *be = book->backend;
00793
00794
00795 if (be)
00796 {
00797 gpointer compiled_query =
00798 g_hash_table_lookup (q->be_compiled, book);
00799
00800 if (compiled_query && be->run_query)
00801 {
00802 (be->run_query) (be, compiled_query);
00803 }
00804 }
00805
00806
00807 qof_object_foreach (q->search_for, book,
00808 (QofEntityForeachCB) check_item_cb, &qcb);
00809 }
00810
00811 matching_objects = qcb.list;
00812 object_count = qcb.count;
00813 }
00814 PINFO ("matching objects=%p count=%d", matching_objects, object_count);
00815
00816
00817
00818
00819
00820
00821
00822 matching_objects = g_list_reverse (matching_objects);
00823
00824
00825
00826
00827
00828 if (q->primary_sort.comp_fcn || q->primary_sort.obj_cmp ||
00829 (q->primary_sort.use_default && q->defaultSort))
00830 {
00831 sortQuery = q;
00832 matching_objects = g_list_sort (matching_objects, sort_func);
00833 sortQuery = NULL;
00834 }
00835
00836
00837 if ((object_count > q->max_results) && (q->max_results > -1))
00838 {
00839 if (q->max_results > 0)
00840 {
00841 GList *mptr;
00842
00843
00844 mptr =
00845 g_list_nth (matching_objects,
00846 object_count - q->max_results);
00847
00848 if (mptr != NULL)
00849 {
00850 if (mptr->prev != NULL)
00851 mptr->prev->next = NULL;
00852 mptr->prev = NULL;
00853 }
00854 g_list_free (matching_objects);
00855 matching_objects = mptr;
00856 }
00857 else
00858 {
00859
00860 g_list_free (matching_objects);
00861 matching_objects = NULL;
00862 }
00863 object_count = q->max_results;
00864 }
00865
00866 q->changed = 0;
00867
00868 g_list_free (q->results);
00869 q->results = matching_objects;
00870
00871 LEAVE (" q=%p", q);
00872 return matching_objects;
00873 }
00874
00875 GList *
00876 qof_query_last_run (QofQuery * query)
00877 {
00878 if (!query)
00879 return NULL;
00880
00881 return query->results;
00882 }
00883
00884 void
00885 qof_query_clear (QofQuery * query)
00886 {
00887 QofQuery *q2 = qof_query_create ();
00888 swap_terms (query, q2);
00889 qof_query_destroy (q2);
00890
00891 g_list_free (query->books);
00892 query->books = NULL;
00893 g_list_free (query->results);
00894 query->results = NULL;
00895 query->changed = 1;
00896 }
00897
00898 QofQuery *
00899 qof_query_create (void)
00900 {
00901 QofQuery *qp = g_new0 (QofQuery, 1);
00902 qp->be_compiled = g_hash_table_new (g_direct_hash, g_direct_equal);
00903 query_init (qp, NULL);
00904 return qp;
00905 }
00906
00907 void
00908 qof_query_search_for (QofQuery * q, QofIdTypeConst obj_type)
00909 {
00910 if (!q || !obj_type)
00911 return;
00912
00913 if (safe_strcmp (q->search_for, obj_type))
00914 {
00915 q->search_for = (QofIdType) obj_type;
00916 q->changed = 1;
00917 }
00918 }
00919
00920 QofQuery *
00921 qof_query_create_for (QofIdTypeConst obj_type)
00922 {
00923 QofQuery *q;
00924 if (!obj_type)
00925 return NULL;
00926 q = qof_query_create ();
00927 qof_query_search_for (q, obj_type);
00928 return q;
00929 }
00930
00931 gint
00932 qof_query_has_terms (QofQuery * q)
00933 {
00934 if (!q)
00935 return 0;
00936 return g_list_length (q->terms);
00937 }
00938
00939 gint
00940 qof_query_num_terms (QofQuery * q)
00941 {
00942 GList *o;
00943 gint n = 0;
00944 if (!q)
00945 return 0;
00946 for (o = q->terms; o; o = o->next)
00947 n += g_list_length (o->data);
00948 return n;
00949 }
00950
00951 gboolean
00952 qof_query_has_term_type (QofQuery * q, GSList * term_param)
00953 {
00954 GList *or;
00955 GList *and;
00956
00957 if (!q || !term_param)
00958 return FALSE;
00959
00960 for (or = q->terms; or; or = or->next)
00961 {
00962 for (and = or->data; and; and = and->next)
00963 {
00964 QofQueryTerm *qt = and->data;
00965 if (!param_list_cmp (term_param, qt->param_list))
00966 return TRUE;
00967 }
00968 }
00969
00970 return FALSE;
00971 }
00972
00973 GSList *
00974 qof_query_get_term_type (QofQuery * q, GSList * term_param)
00975 {
00976 GList *or;
00977 GList *and;
00978 GSList *results = NULL;
00979
00980 if (!q || !term_param)
00981 return FALSE;
00982
00983 for (or = q->terms; or; or = or->next)
00984 {
00985 for (and = or->data; and; and = and->next)
00986 {
00987 QofQueryTerm *qt = and->data;
00988 if (!param_list_cmp (term_param, qt->param_list))
00989 results = g_slist_append (results, qt->pdata);
00990 }
00991 }
00992
00993 return results;
00994 }
00995
00996 void
00997 qof_query_destroy (QofQuery * q)
00998 {
00999 if (!q)
01000 return;
01001 free_members (q);
01002 query_clear_compiles (q);
01003 g_hash_table_destroy (q->be_compiled);
01004 g_free (q);
01005 }
01006
01007 QofQuery *
01008 qof_query_copy (QofQuery * q)
01009 {
01010 QofQuery *copy;
01011 GHashTable *ht;
01012
01013 if (!q)
01014 return NULL;
01015 copy = qof_query_create ();
01016 ht = copy->be_compiled;
01017 free_members (copy);
01018
01019 memcpy (copy, q, sizeof (QofQuery));
01020
01021 copy->be_compiled = ht;
01022 copy->terms = copy_or_terms (q->terms);
01023 copy->books = g_list_copy (q->books);
01024 copy->results = g_list_copy (q->results);
01025
01026 copy_sort (&(copy->primary_sort), &(q->primary_sort));
01027 copy_sort (&(copy->secondary_sort), &(q->secondary_sort));
01028 copy_sort (&(copy->tertiary_sort), &(q->tertiary_sort));
01029
01030 copy->changed = 1;
01031
01032 return copy;
01033 }
01034
01035
01036
01037
01038
01039
01040
01041 QofQuery *
01042 qof_query_invert (QofQuery * q)
01043 {
01044 QofQuery *retval;
01045 QofQuery *right, *left, *iright, *ileft;
01046 QofQueryTerm *qt;
01047 GList *aterms;
01048 GList *cur;
01049 GList *new_oterm;
01050 gint num_or_terms;
01051
01052 if (!q)
01053 return NULL;
01054
01055 num_or_terms = g_list_length (q->terms);
01056
01057 switch (num_or_terms)
01058 {
01059 case 0:
01060 retval = qof_query_create ();
01061 retval->max_results = q->max_results;
01062 break;
01063
01064
01065
01066 case 1:
01067 retval = qof_query_create ();
01068 retval->max_results = q->max_results;
01069 retval->books = g_list_copy (q->books);
01070 retval->search_for = q->search_for;
01071 retval->changed = 1;
01072
01073 aterms = g_list_nth_data (q->terms, 0);
01074 new_oterm = NULL;
01075 for (cur = aterms; cur; cur = cur->next)
01076 {
01077 qt = copy_query_term (cur->data);
01078 qt->invert = !(qt->invert);
01079 new_oterm = g_list_append (NULL, qt);
01080
01081
01082
01083
01084 retval->terms = g_list_reverse (retval->terms);
01085 retval->terms = g_list_prepend (retval->terms, new_oterm);
01086 retval->terms = g_list_reverse (retval->terms);
01087 }
01088 break;
01089
01090
01091
01092
01093 default:
01094 right = qof_query_create ();
01095 right->terms = copy_or_terms (g_list_nth (q->terms, 1));
01096
01097 left = qof_query_create ();
01098 left->terms = g_list_append (NULL,
01099 copy_and_terms (g_list_nth_data (q->terms, 0)));
01100
01101 iright = qof_query_invert (right);
01102 ileft = qof_query_invert (left);
01103
01104 retval = qof_query_merge (iright, ileft, QOF_QUERY_AND);
01105 retval->books = g_list_copy (q->books);
01106 retval->max_results = q->max_results;
01107 retval->search_for = q->search_for;
01108 retval->changed = 1;
01109
01110 qof_query_destroy (iright);
01111 qof_query_destroy (ileft);
01112 qof_query_destroy (right);
01113 qof_query_destroy (left);
01114 break;
01115 }
01116
01117 return retval;
01118 }
01119
01120
01121
01122
01123
01124
01125 QofQuery *
01126 qof_query_merge (QofQuery * q1, QofQuery * q2, QofQueryOp op)
01127 {
01128
01129 QofQuery *retval = NULL;
01130 QofQuery *i1, *i2;
01131 QofQuery *t1, *t2;
01132 GList *i, *j;
01133 QofIdType search_for;
01134
01135 if (!q1)
01136 return q2;
01137 if (!q2)
01138 return q1;
01139
01140 if (q1->search_for && q2->search_for)
01141 g_return_val_if_fail (safe_strcmp (q1->search_for,
01142 q2->search_for) == 0, NULL);
01143
01144 search_for = (q1->search_for ? q1->search_for : q2->search_for);
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155 if ((QOF_QUERY_AND == op) && (0 == qof_query_has_terms (q1)))
01156 {
01157 op = QOF_QUERY_OR;
01158 }
01159
01160 switch (op)
01161 {
01162 case QOF_QUERY_OR:
01163 retval = qof_query_create ();
01164 retval->terms =
01165 g_list_concat (copy_or_terms (q1->terms),
01166 copy_or_terms (q2->terms));
01167 retval->books = merge_books (q1->books, q2->books);
01168 retval->max_results = q1->max_results;
01169 retval->changed = 1;
01170 break;
01171
01172 case QOF_QUERY_AND:
01173 retval = qof_query_create ();
01174 retval->books = merge_books (q1->books, q2->books);
01175 retval->max_results = q1->max_results;
01176 retval->changed = 1;
01177
01178
01179
01180
01181
01182 for (i = q1->terms; i; i = i->next)
01183 {
01184 for (j = q2->terms; j; j = j->next)
01185 {
01186 retval->terms =
01187 g_list_prepend (retval->terms,
01188 g_list_concat
01189 (copy_and_terms (i->data), copy_and_terms (j->data)));
01190 }
01191 }
01192 retval->terms = g_list_reverse (retval->terms);
01193 break;
01194
01195 case QOF_QUERY_NAND:
01196
01197 i1 = qof_query_invert (q1);
01198 i2 = qof_query_invert (q2);
01199 retval = qof_query_merge (i1, i2, QOF_QUERY_OR);
01200 qof_query_destroy (i1);
01201 qof_query_destroy (i2);
01202 break;
01203
01204 case QOF_QUERY_NOR:
01205
01206 i1 = qof_query_invert (q1);
01207 i2 = qof_query_invert (q2);
01208 retval = qof_query_merge (i1, i2, QOF_QUERY_AND);
01209 qof_query_destroy (i1);
01210 qof_query_destroy (i2);
01211 break;
01212
01213 case QOF_QUERY_XOR:
01214
01215 i1 = qof_query_invert (q1);
01216 i2 = qof_query_invert (q2);
01217 t1 = qof_query_merge (q1, i2, QOF_QUERY_AND);
01218 t2 = qof_query_merge (i1, q2, QOF_QUERY_AND);
01219 retval = qof_query_merge (t1, t2, QOF_QUERY_OR);
01220
01221 qof_query_destroy (i1);
01222 qof_query_destroy (i2);
01223 qof_query_destroy (t1);
01224 qof_query_destroy (t2);
01225 break;
01226 }
01227
01228 retval->search_for = search_for;
01229 return retval;
01230 }
01231
01232 void
01233 qof_query_merge_in_place (QofQuery * q1, QofQuery * q2, QofQueryOp op)
01234 {
01235 QofQuery *tmp_q;
01236
01237 if (!q1 || !q2)
01238 return;
01239
01240 tmp_q = qof_query_merge (q1, q2, op);
01241 swap_terms (q1, tmp_q);
01242 qof_query_destroy (tmp_q);
01243 }
01244
01245 void
01246 qof_query_set_sort_order (QofQuery * q,
01247 GSList * params1, GSList * params2, GSList * params3)
01248 {
01249 if (!q)
01250 return;
01251 if (q->primary_sort.param_list)
01252 g_slist_free (q->primary_sort.param_list);
01253 q->primary_sort.param_list = params1;
01254 q->primary_sort.options = 0;
01255
01256 if (q->secondary_sort.param_list)
01257 g_slist_free (q->secondary_sort.param_list);
01258 q->secondary_sort.param_list = params2;
01259 q->secondary_sort.options = 0;
01260
01261 if (q->tertiary_sort.param_list)
01262 g_slist_free (q->tertiary_sort.param_list);
01263 q->tertiary_sort.param_list = params3;
01264 q->tertiary_sort.options = 0;
01265
01266 q->changed = 1;
01267 }
01268
01269 void
01270 qof_query_set_sort_options (QofQuery * q, gint prim_op, gint sec_op,
01271 gint tert_op)
01272 {
01273 if (!q)
01274 return;
01275 q->primary_sort.options = prim_op;
01276 q->secondary_sort.options = sec_op;
01277 q->tertiary_sort.options = tert_op;
01278 }
01279
01280 void
01281 qof_query_set_sort_increasing (QofQuery * q, gboolean prim_inc,
01282 gboolean sec_inc, gboolean tert_inc)
01283 {
01284 if (!q)
01285 return;
01286 q->primary_sort.increasing = prim_inc;
01287 q->secondary_sort.increasing = sec_inc;
01288 q->tertiary_sort.increasing = tert_inc;
01289 }
01290
01291 void
01292 qof_query_set_max_results (QofQuery * q, gint n)
01293 {
01294 if (!q)
01295 return;
01296 q->max_results = n;
01297 }
01298
01299 void
01300 qof_query_add_guid_list_match (QofQuery * q, GSList * param_list,
01301 GList * guid_list, QofGuidMatch options, QofQueryOp op)
01302 {
01303 QofQueryPredData *pdata;
01304
01305 if (!q || !param_list)
01306 return;
01307
01308 if (!guid_list)
01309 g_return_if_fail (options == QOF_GUID_MATCH_NULL);
01310
01311 pdata = qof_query_guid_predicate (options, guid_list);
01312 qof_query_add_term (q, param_list, pdata, op);
01313 }
01314
01315 void
01316 qof_query_add_guid_match (QofQuery * q, GSList * param_list,
01317 const GUID * guid, QofQueryOp op)
01318 {
01319 GList *g = NULL;
01320
01321 if (!q || !param_list)
01322 return;
01323
01324 if (guid)
01325 g = g_list_prepend (g, (gpointer) guid);
01326
01327 qof_query_add_guid_list_match (q, param_list, g,
01328 g ? QOF_GUID_MATCH_ANY : QOF_GUID_MATCH_NULL, op);
01329
01330 g_list_free (g);
01331 }
01332
01333 void
01334 qof_query_set_book (QofQuery * q, QofBook * book)
01335 {
01336 GSList *slist = NULL;
01337 if (!q || !book)
01338 return;
01339
01340
01341 if (g_list_index (q->books, book) == -1)
01342 q->books = g_list_prepend (q->books, book);
01343
01344 slist = g_slist_prepend (slist, QOF_PARAM_GUID);
01345 slist = g_slist_prepend (slist, QOF_PARAM_BOOK);
01346 qof_query_add_guid_match (q, slist,
01347 qof_entity_get_guid ((QofEntity*)book), QOF_QUERY_AND);
01348 }
01349
01350 GList *
01351 qof_query_get_books (QofQuery * q)
01352 {
01353 if (!q)
01354 return NULL;
01355 return q->books;
01356 }
01357
01358 void
01359 qof_query_add_boolean_match (QofQuery * q, GSList * param_list,
01360 gboolean value, QofQueryOp op)
01361 {
01362 QofQueryPredData *pdata;
01363 if (!q || !param_list)
01364 return;
01365
01366 pdata = qof_query_boolean_predicate (QOF_COMPARE_EQUAL, value);
01367 qof_query_add_term (q, param_list, pdata, op);
01368 }
01369
01370
01371
01372
01373 void
01374 qof_query_init (void)
01375 {
01376 ENTER (" ");
01377 qof_query_core_init ();
01378 qof_class_init ();
01379 LEAVE ("Completed initialization of QofQuery");
01380 }
01381
01382 void
01383 qof_query_shutdown (void)
01384 {
01385 qof_class_shutdown ();
01386 qof_query_core_shutdown ();
01387 }
01388
01389 gint
01390 qof_query_get_max_results (QofQuery * q)
01391 {
01392 if (!q)
01393 return 0;
01394 return q->max_results;
01395 }
01396
01397 QofIdType
01398 qof_query_get_search_for (QofQuery * q)
01399 {
01400 if (!q)
01401 return NULL;
01402 return q->search_for;
01403 }
01404
01405 GList *
01406 qof_query_get_terms (QofQuery * q)
01407 {
01408 if (!q)
01409 return NULL;
01410 return q->terms;
01411 }
01412
01413 GSList *
01414 qof_query_term_get_param_path (QofQueryTerm * qt)
01415 {
01416 if (!qt)
01417 return NULL;
01418 return qt->param_list;
01419 }
01420
01421 QofQueryPredData *
01422 qof_query_term_get_pred_data (QofQueryTerm * qt)
01423 {
01424 if (!qt)
01425 return NULL;
01426 return qt->pdata;
01427 }
01428
01429 gboolean
01430 qof_query_term_is_inverted (QofQueryTerm * qt)
01431 {
01432 if (!qt)
01433 return FALSE;
01434 return qt->invert;
01435 }
01436
01437 void
01438 qof_query_get_sorts (QofQuery * q, QofQuerySort ** primary,
01439 QofQuerySort ** secondary, QofQuerySort ** tertiary)
01440 {
01441 if (!q)
01442 return;
01443 if (primary)
01444 *primary = &(q->primary_sort);
01445 if (secondary)
01446 *secondary = &(q->secondary_sort);
01447 if (tertiary)
01448 *tertiary = &(q->tertiary_sort);
01449 }
01450
01451 GSList *
01452 qof_query_sort_get_param_path (QofQuerySort * qs)
01453 {
01454 if (!qs)
01455 return NULL;
01456 return qs->param_list;
01457 }
01458
01459 gint
01460 qof_query_sort_get_sort_options (QofQuerySort * qs)
01461 {
01462 if (!qs)
01463 return 0;
01464 return qs->options;
01465 }
01466
01467 gboolean
01468 qof_query_sort_get_increasing (QofQuerySort * qs)
01469 {
01470 if (!qs)
01471 return FALSE;
01472 return qs->increasing;
01473 }
01474
01475 static gboolean
01476 qof_query_term_equal (QofQueryTerm * qt1, QofQueryTerm * qt2)
01477 {
01478 if (qt1 == qt2)
01479 return TRUE;
01480 if (!qt1 || !qt2)
01481 return FALSE;
01482
01483 if (qt1->invert != qt2->invert)
01484 return FALSE;
01485 if (param_list_cmp (qt1->param_list, qt2->param_list))
01486 return FALSE;
01487 return qof_query_core_predicate_equal (qt1->pdata, qt2->pdata);
01488 }
01489
01490 static gboolean
01491 qof_query_sort_equal (QofQuerySort * qs1, QofQuerySort * qs2)
01492 {
01493 if (qs1 == qs2)
01494 return TRUE;
01495 if (!qs1 || !qs2)
01496 return FALSE;
01497
01498
01499 if (!qs1->param_list && !qs2->param_list)
01500 return TRUE;
01501
01502 if (qs1->options != qs2->options)
01503 return FALSE;
01504 if (qs1->increasing != qs2->increasing)
01505 return FALSE;
01506 return (param_list_cmp (qs1->param_list, qs2->param_list) == 0);
01507 }
01508
01509 gboolean
01510 qof_query_equal (QofQuery * q1, QofQuery * q2)
01511 {
01512 GList *or1, *or2;
01513
01514 if (q1 == q2)
01515 return TRUE;
01516 if (!q1 || !q2)
01517 return FALSE;
01518
01519 if (g_list_length (q1->terms) != g_list_length (q2->terms))
01520 return FALSE;
01521 if (q1->max_results != q2->max_results)
01522 return FALSE;
01523
01524 for (or1 = q1->terms, or2 = q2->terms; or1;
01525 or1 = or1->next, or2 = or2->next)
01526 {
01527 GList *and1, *and2;
01528
01529 and1 = or1->data;
01530 and2 = or2->data;
01531
01532 if (g_list_length (and1) != g_list_length (and2))
01533 return FALSE;
01534
01535 for (; and1; and1 = and1->next, and2 = and2->next)
01536 if (!qof_query_term_equal (and1->data, and2->data))
01537 return FALSE;
01538 }
01539
01540 if (!qof_query_sort_equal (&(q1->primary_sort), &(q2->primary_sort)))
01541 return FALSE;
01542 if (!qof_query_sort_equal (&(q1->secondary_sort),
01543 &(q2->secondary_sort)))
01544 return FALSE;
01545 if (!qof_query_sort_equal (&(q1->tertiary_sort), &(q2->tertiary_sort)))
01546 return FALSE;
01547
01548 return TRUE;
01549 }
01550
01551
01552
01553
01554
01555
01556 static GList *qof_query_printSearchFor (QofQuery * query, GList * output);
01557 static GList *qof_query_printTerms (QofQuery * query, GList * output);
01558 static GList *qof_query_printSorts (QofQuerySort * s[],
01559 const gint numSorts, GList * output);
01560 static GList *qof_query_printAndTerms (GList * terms, GList * output);
01561 static gchar *qof_query_printStringForHow (QofQueryCompare how);
01562 static gchar *qof_query_printStringMatch (QofStringMatch s);
01563 static gchar *qof_query_printDateMatch (QofDateMatch d);
01564 static gchar *qof_query_printNumericMatch (QofNumericMatch n);
01565 static gchar *qof_query_printGuidMatch (QofGuidMatch g);
01566 static gchar *qof_query_printCharMatch (QofCharMatch c);
01567 static GList *qof_query_printPredData (QofQueryPredData * pd, GList * lst);
01568 static GString *qof_query_printParamPath (GSList * parmList);
01569 static void qof_query_printValueForParam (QofQueryPredData * pd,
01570 GString * gs);
01571 static void qof_query_printOutput (GList * output);
01572
01574 void
01575 qof_query_print (QofQuery * query)
01576 {
01577 GList *output;
01578 GString *str;
01579 QofQuerySort *s[3];
01580 gint maxResults = 0, numSorts = 3;
01581
01582 ENTER (" ");
01583
01584 if (!query)
01585 {
01586 LEAVE ("query is (null)");
01587 return;
01588 }
01589
01590 output = NULL;
01591 str = NULL;
01592 maxResults = qof_query_get_max_results (query);
01593
01594 output = qof_query_printSearchFor (query, output);
01595 output = qof_query_printTerms (query, output);
01596
01597 qof_query_get_sorts (query, &s[0], &s[1], &s[2]);
01598
01599 if (s[0])
01600 {
01601 output = qof_query_printSorts (s, numSorts, output);
01602 }
01603
01604 str = g_string_new (" ");
01605 g_string_printf (str, "Maximum number of results: %d", maxResults);
01606 output = g_list_append (output, str);
01607
01608 qof_query_printOutput (output);
01609 LEAVE (" ");
01610 }
01611
01612 static void
01613 qof_query_printOutput (GList * output)
01614 {
01615 GList *lst;
01616
01617 for (lst = output; lst; lst = lst->next)
01618 {
01619 GString *line = (GString *) lst->data;
01620
01621 DEBUG (" %s", line->str);
01622 g_string_free (line, TRUE);
01623 line = NULL;
01624 }
01625 }
01626
01627
01628
01629
01630
01631 static GList *
01632 qof_query_printSearchFor (QofQuery * query, GList * output)
01633 {
01634 QofIdType searchFor;
01635 GString *gs;
01636
01637 searchFor = qof_query_get_search_for (query);
01638 gs = g_string_new ("Query Object Type: ");
01639 g_string_append (gs, (NULL == searchFor) ? "(null)" : searchFor);
01640 output = g_list_append (output, gs);
01641
01642 return output;
01643 }
01644
01645
01646
01647
01648
01649
01650 static GList *
01651 qof_query_printTerms (QofQuery * query, GList * output)
01652 {
01653
01654 GList *terms, *lst;
01655
01656 terms = qof_query_get_terms (query);
01657
01658 for (lst = terms; lst; lst = lst->next)
01659 {
01660 output =
01661 g_list_append (output, g_string_new ("OR Terms:"));
01662
01663 if (lst->data)
01664 {
01665 output = qof_query_printAndTerms (lst->data, output);
01666 }
01667 else
01668 {
01669 output =
01670 g_list_append (output,
01671 g_string_new (" No data for AND terms"));
01672 }
01673 }
01674
01675 return output;
01676 }
01677
01678
01679
01680
01681
01682
01683 static GList *
01684 qof_query_printSorts (QofQuerySort * s[], const gint numSorts,
01685 GList * output)
01686 {
01687 GSList *gsl, *n = NULL;
01688 gint curSort;
01689 GString *gs = g_string_new ("Sort Parameters: ");
01690
01691 for (curSort = 0; curSort < numSorts; curSort++)
01692 {
01693 gboolean increasing;
01694 if (!s[curSort])
01695 {
01696 break;
01697 }
01698 increasing = qof_query_sort_get_increasing (s[curSort]);
01699
01700 gsl = qof_query_sort_get_param_path (s[curSort]);
01701 if (gsl)
01702 g_string_append_printf (gs, " Param: ");
01703 for (n = gsl; n; n = n->next)
01704 {
01705 QofIdType param_name = n->data;
01706 if (gsl != n)
01707 g_string_append_printf (gs, " ");
01708 g_string_append_printf (gs, "%s", param_name);
01709 }
01710 if (gsl)
01711 {
01712 g_string_append_printf (gs, " %s ",
01713 increasing ? "DESC" : "ASC");
01714 g_string_append_printf (gs, " Options: 0x%x ",
01715 s[curSort]->options);
01716 }
01717 }
01718
01719 output = g_list_append (output, gs);
01720 return output;
01721
01722 }
01723
01724
01725
01726
01727
01728 static GList *
01729 qof_query_printAndTerms (GList * terms, GList * output)
01730 {
01731 const gchar *prefix = "AND Terms:";
01732 QofQueryTerm *qt;
01733 QofQueryPredData *pd;
01734 GSList *path;
01735 GList *lst;
01736 gboolean invert;
01737
01738 output = g_list_append (output, g_string_new (prefix));
01739 for (lst = terms; lst; lst = lst->next)
01740 {
01741 qt = (QofQueryTerm *) lst->data;
01742 pd = qof_query_term_get_pred_data (qt);
01743 path = qof_query_term_get_param_path (qt);
01744 invert = qof_query_term_is_inverted (qt);
01745
01746 if (invert)
01747 output =
01748 g_list_append (output, g_string_new (" INVERT SENSE "));
01749 output = g_list_append (output, qof_query_printParamPath (path));
01750 output = qof_query_printPredData (pd, output);
01751
01752 }
01753
01754 return output;
01755 }
01756
01757
01758
01759
01760 static GString *
01761 qof_query_printParamPath (GSList * parmList)
01762 {
01763 GSList *list = NULL;
01764 GString *gs = g_string_new ("Param List: ");
01765 g_string_append (gs, " ");
01766 for (list = parmList; list; list = list->next)
01767 {
01768 g_string_append (gs, (gchar *) list->data);
01769 if (list->next)
01770 g_string_append (gs, ", ");
01771 }
01772
01773 return gs;
01774 }
01775
01776
01777
01778
01779 static GList *
01780 qof_query_printPredData (QofQueryPredData * pd, GList * lst)
01781 {
01782 GString *gs;
01783
01784 gs = g_string_new ("Pred Data: ");
01785 g_string_append (gs, (gchar *) pd->type_name);
01786
01787
01788 if (safe_strcmp (pd->type_name, QOF_TYPE_CHAR) &&
01789 safe_strcmp (pd->type_name, QOF_TYPE_GUID))
01790 {
01791 g_string_append_printf (gs, " how: %s",
01792 qof_query_printStringForHow (pd->how));
01793 }
01794 lst = g_list_append (lst, gs);
01795 gs = g_string_new ("");
01796 qof_query_printValueForParam (pd, gs);
01797 lst = g_list_append (lst, gs);
01798 return lst;
01799 }
01800
01801
01802
01803
01804
01805 static gchar *
01806 qof_query_printStringForHow (QofQueryCompare how)
01807 {
01808
01809 switch (how)
01810 {
01811 AS_STRING_CASE(QOF_COMPARE_LT,)
01812 AS_STRING_CASE(QOF_COMPARE_LTE,)
01813 AS_STRING_CASE(QOF_COMPARE_EQUAL,)
01814 AS_STRING_CASE(QOF_COMPARE_GT,)
01815 AS_STRING_CASE(QOF_COMPARE_GTE,)
01816 AS_STRING_CASE(QOF_COMPARE_NEQ,)
01817 }
01818 return "INVALID HOW";
01819 }
01820
01821
01822 static void
01823 qof_query_printValueForParam (QofQueryPredData * pd, GString * gs)
01824 {
01825
01826 if (!safe_strcmp (pd->type_name, QOF_TYPE_GUID))
01827 {
01828 GList *node;
01829 query_guid_t pdata = (query_guid_t) pd;
01830 g_string_append_printf (gs, "Match type %s ",
01831 qof_query_printGuidMatch (pdata->options));
01832 for (node = pdata->guids; node; node = node->next)
01833 {
01834
01835 g_string_append_printf (gs, ", guids: %s",
01836 guid_to_string ((GUID *) node->data));
01837 }
01838 return;
01839 }
01840 if (!safe_strcmp (pd->type_name, QOF_TYPE_STRING))
01841 {
01842 query_string_t pdata = (query_string_t) pd;
01843 g_string_append_printf (gs, "Match type %s ",
01844 qof_query_printStringMatch (pdata->options));
01845 g_string_append_printf (gs, " %s string: %s",
01846 pdata->is_regex ? "Regex" : "Not regex", pdata->matchstring);
01847 return;
01848 }
01849 if (!safe_strcmp (pd->type_name, QOF_TYPE_NUMERIC))
01850 {
01851 query_numeric_t pdata = (query_numeric_t) pd;
01852 g_string_append_printf (gs, "Match type %s ",
01853 qof_query_printNumericMatch (pdata->options));
01854 g_string_append_printf (gs, " gnc_numeric: %s",
01855 gnc_num_dbg_to_string (pdata->amount));
01856 return;
01857 }
01858 if (!safe_strcmp (pd->type_name, QOF_TYPE_KVP))
01859 {
01860 GSList *node;
01861 query_kvp_t pdata = (query_kvp_t) pd;
01862 g_string_append_printf (gs, " kvp path: ");
01863 for (node = pdata->path; node; node = node->next)
01864 {
01865 g_string_append_printf (gs, "/%s", (gchar *) node->data);
01866 }
01867 g_string_append_printf (gs, " kvp value: %s ",
01868 kvp_value_to_string (pdata->value));
01869 return;
01870 }
01871 if (!safe_strcmp (pd->type_name, QOF_TYPE_INT64))
01872 {
01873 query_int64_t pdata = (query_int64_t) pd;
01874 g_string_append_printf (gs, " int64: %" G_GINT64_FORMAT,
01875 pdata->val);
01876 return;
01877 }
01878 if (!safe_strcmp (pd->type_name, QOF_TYPE_INT32))
01879 {
01880 query_int32_t pdata = (query_int32_t) pd;
01881 g_string_append_printf (gs, " int32: %d", pdata->val);
01882 return;
01883 }
01884 if (!safe_strcmp (pd->type_name, QOF_TYPE_DOUBLE))
01885 {
01886 query_double_t pdata = (query_double_t) pd;
01887 g_string_append_printf (gs, " double: %.18g", pdata->val);
01888 return;
01889 }
01890 if (!safe_strcmp (pd->type_name, QOF_TYPE_TIME))
01891 {
01892 query_time_t pdata;
01893 QofDate *qd;
01894
01895 pdata = (query_time_t) pd;
01896 qd = qof_date_from_qtime (pdata->qt);
01897 g_string_append_printf (gs, "Match type %s " ,
01898 qof_query_printDateMatch (pdata->options));
01899 g_string_append_printf (gs, "query date: %s",
01900 qof_date_print (qd, QOF_DATE_FORMAT_UTC));
01901 qof_date_free (qd);
01902 }
01903 #ifndef QOF_DISABLE_DEPRECATED
01904 if (!safe_strcmp (pd->type_name, QOF_TYPE_DATE))
01905 {
01906 query_date_t pdata;
01907
01908 pdata = (query_date_t) pd;
01909 g_string_append_printf (gs, "Match type %s ",
01910 qof_query_printDateMatch (pdata->options));
01911 g_string_append_printf (gs, " query_date: %s",
01912 gnc_print_date (pdata->date));
01913 return;
01914 }
01915 #endif
01916 if (!safe_strcmp (pd->type_name, QOF_TYPE_CHAR))
01917 {
01918 query_char_t pdata = (query_char_t) pd;
01919 g_string_append_printf (gs, "Match type %s ",
01920 qof_query_printCharMatch (pdata->options));
01921 g_string_append_printf (gs, " char list: %s",
01922 pdata->char_list);
01923 return;
01924 }
01925 if (!safe_strcmp (pd->type_name, QOF_TYPE_BOOLEAN))
01926 {
01927 query_boolean_t pdata = (query_boolean_t) pd;
01928 g_string_append_printf (gs, " boolean: %s",
01929 pdata->val ? "TRUE" : "FALSE");
01930 return;
01931 }
01933 return;
01934 }
01935
01936
01937
01938
01939
01940 static gchar *
01941 qof_query_printStringMatch (QofStringMatch s)
01942 {
01943 switch (s)
01944 {
01945 AS_STRING_CASE(QOF_STRING_MATCH_NORMAL,)
01946 AS_STRING_CASE(QOF_STRING_MATCH_CASEINSENSITIVE,)
01947 }
01948 return "UNKNOWN MATCH TYPE";
01949 }
01950
01951
01952
01953
01954
01955 static gchar *
01956 qof_query_printDateMatch (QofDateMatch d)
01957 {
01958 switch (d)
01959 {
01960 AS_STRING_CASE(QOF_DATE_MATCH_NORMAL,)
01961 AS_STRING_CASE(QOF_DATE_MATCH_DAY,)
01962 }
01963 return "UNKNOWN MATCH TYPE";
01964 }
01965
01966
01967
01968
01969
01970 static gchar *
01971 qof_query_printNumericMatch (QofNumericMatch n)
01972 {
01973 switch (n)
01974 {
01975 AS_STRING_CASE(QOF_NUMERIC_MATCH_DEBIT,)
01976 AS_STRING_CASE(QOF_NUMERIC_MATCH_CREDIT,)
01977 AS_STRING_CASE(QOF_NUMERIC_MATCH_ANY,)
01978 }
01979 return "UNKNOWN MATCH TYPE";
01980 }
01981
01982
01983
01984
01985
01986 static gchar *
01987 qof_query_printGuidMatch (QofGuidMatch g)
01988 {
01989 switch (g)
01990 {
01991 AS_STRING_CASE(QOF_GUID_MATCH_ANY,)
01992 AS_STRING_CASE(QOF_GUID_MATCH_ALL,)
01993 AS_STRING_CASE(QOF_GUID_MATCH_NONE,)
01994 AS_STRING_CASE(QOF_GUID_MATCH_NULL,)
01995 AS_STRING_CASE(QOF_GUID_MATCH_LIST_ANY,)
01996 }
01997
01998 return "UNKNOWN MATCH TYPE";
01999 }
02000
02001
02002
02003
02004
02005 static gchar *
02006 qof_query_printCharMatch (QofCharMatch c)
02007 {
02008 switch (c)
02009 {
02010 AS_STRING_CASE(QOF_CHAR_MATCH_ANY,)
02011 AS_STRING_CASE(QOF_CHAR_MATCH_NONE,)
02012 }
02013 return "UNKNOWN MATCH TYPE";
02014 }
02015
02016