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 <glib.h>
00028
00029 #include "qof.h"
00030 #include "qofquerycore-p.h"
00031
00032 static QofLogModule log_module = QOF_MOD_QUERY;
00033
00034
00035 typedef void (*QueryPredDataFree) (QofQueryPredData * pdata);
00036
00037
00038 typedef QofQueryPredData *(*QueryPredicateCopyFunc) (QofQueryPredData *
00039 pdata);
00040
00041
00042
00043
00044
00045
00046
00047 typedef gchar *(*QueryToString) (gpointer object, QofParam * getter);
00048
00049
00050 typedef gboolean (*QueryPredicateEqual) (QofQueryPredData * p1,
00051 QofQueryPredData * p2);
00052
00053 static QueryPredicateCopyFunc qof_query_copy_predicate (QofType type);
00054 static QueryPredDataFree qof_query_predicate_free (QofType type);
00055
00056
00057 typedef const gchar *(*query_string_getter) (gpointer, QofParam *);
00058 static const gchar *query_string_type = QOF_TYPE_STRING;
00059
00060 typedef QofTime *(*query_time_getter) (gpointer, QofParam *);
00061 static const gchar *query_time_type = QOF_TYPE_TIME;
00062
00063 typedef gnc_numeric (*query_numeric_getter) (gpointer, QofParam *);
00064 static const gchar *query_numeric_type = QOF_TYPE_NUMERIC;
00065
00066 typedef GList *(*query_glist_getter) (gpointer, QofParam *);
00067 typedef const GUID *(*query_guid_getter) (gpointer, QofParam *);
00068 static const gchar *query_guid_type = QOF_TYPE_GUID;
00069
00070 typedef gint32 (*query_int32_getter) (gpointer, QofParam *);
00071 static const gchar *query_int32_type = QOF_TYPE_INT32;
00072
00073 typedef gint64 (*query_int64_getter) (gpointer, QofParam *);
00074 static const char *query_int64_type = QOF_TYPE_INT64;
00075
00076 typedef double (*query_double_getter) (gpointer, QofParam *);
00077 static const gchar *query_double_type = QOF_TYPE_DOUBLE;
00078
00079 typedef gboolean (*query_boolean_getter) (gpointer, QofParam *);
00080 static const gchar *query_boolean_type = QOF_TYPE_BOOLEAN;
00081
00082 typedef char (*query_char_getter) (gpointer, QofParam *);
00083 static const char *query_char_type = QOF_TYPE_CHAR;
00084
00085 typedef KvpFrame *(*query_kvp_getter) (gpointer, QofParam *);
00086 static const gchar *query_kvp_type = QOF_TYPE_KVP;
00087
00088 typedef QofCollection *(*query_collect_getter) (gpointer, QofParam *);
00089 static const gchar *query_collect_type = QOF_TYPE_COLLECT;
00090
00091 typedef const GUID *(*query_choice_getter) (gpointer, QofParam *);
00092 static const gchar *query_choice_type = QOF_TYPE_CHOICE;
00093
00094
00095 static gboolean initialized = FALSE;
00096 static GHashTable *predTable = NULL;
00097 static GHashTable *cmpTable = NULL;
00098 static GHashTable *copyTable = NULL;
00099 static GHashTable *freeTable = NULL;
00100 static GHashTable *toStringTable = NULL;
00101 static GHashTable *predEqualTable = NULL;
00102
00103 #define COMPARE_ERROR -3
00104 #define PREDICATE_ERROR -2
00105
00106 #define VERIFY_PDATA(str) { \
00107 g_return_if_fail (pd != NULL); \
00108 g_return_if_fail (pd->type_name == str || \
00109 !safe_strcmp (str, pd->type_name)); \
00110 }
00111 #define VERIFY_PDATA_R(str) { \
00112 g_return_val_if_fail (pd != NULL, NULL); \
00113 g_return_val_if_fail (pd->type_name == str || \
00114 !safe_strcmp (str, pd->type_name), \
00115 NULL); \
00116 }
00117 #define VERIFY_PREDICATE(str) { \
00118 g_return_val_if_fail (getter != NULL, PREDICATE_ERROR); \
00119 g_return_val_if_fail (getter->param_getfcn != NULL, PREDICATE_ERROR); \
00120 g_return_val_if_fail (pd != NULL, PREDICATE_ERROR); \
00121 g_return_val_if_fail (pd->type_name == str || \
00122 !safe_strcmp (str, pd->type_name), \
00123 PREDICATE_ERROR); \
00124 }
00125
00126
00127
00128
00129
00130
00131 static gint
00132 string_match_predicate (gpointer object,
00133 QofParam * getter, QofQueryPredData * pd)
00134 {
00135 query_string_t pdata = (query_string_t) pd;
00136 const gchar *s;
00137 gint ret = 0;
00138
00139 VERIFY_PREDICATE (query_string_type);
00140
00141 s = ((query_string_getter) getter->param_getfcn) (object, getter);
00142
00143 if (!s)
00144 s = "";
00145
00146 if (pdata->is_regex)
00147 {
00148 regmatch_t match;
00149 if (!regexec (&pdata->compiled, s, 1, &match, 0))
00150 ret = 1;
00151
00152 }
00153 else if (pdata->options == QOF_STRING_MATCH_CASEINSENSITIVE)
00154 {
00155 if (strcasestr (s, pdata->matchstring))
00156 ret = 1;
00157
00158 }
00159 else
00160 {
00161 if (strstr (s, pdata->matchstring))
00162 ret = 1;
00163 }
00164
00165 switch (pd->how)
00166 {
00167 case QOF_COMPARE_EQUAL:
00168 return ret;
00169 case QOF_COMPARE_NEQ:
00170 return !ret;
00171 default:
00172 PWARN ("bad match type: %d", pd->how);
00173 return 0;
00174 }
00175 }
00176
00177 static gint
00178 string_compare_func (gpointer a, gpointer b, gint options,
00179 QofParam * getter)
00180 {
00181 const gchar *s1, *s2;
00182 g_return_val_if_fail (a && b && getter
00183 && getter->param_getfcn, COMPARE_ERROR);
00184
00185 s1 = ((query_string_getter) getter->param_getfcn) (a, getter);
00186 s2 = ((query_string_getter) getter->param_getfcn) (b, getter);
00187
00188 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
00189 return safe_strcasecmp (s1, s2);
00190
00191 return safe_strcmp (s1, s2);
00192 }
00193
00194 static void
00195 string_free_pdata (QofQueryPredData * pd)
00196 {
00197 query_string_t pdata = (query_string_t) pd;
00198
00199 VERIFY_PDATA (query_string_type);
00200
00201 if (pdata->is_regex)
00202 regfree (&pdata->compiled);
00203 else
00204 g_free (pdata->matchstring);
00205
00206 g_free (pdata);
00207 }
00208
00209 static QofQueryPredData *
00210 string_copy_predicate (QofQueryPredData * pd)
00211 {
00212 query_string_t pdata = (query_string_t) pd;
00213
00214 VERIFY_PDATA_R (query_string_type);
00215
00216 return qof_query_string_predicate (pd->how, pdata->matchstring,
00217 pdata->options, pdata->is_regex);
00218 }
00219
00220 static gboolean
00221 string_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00222 {
00223 query_string_t pd1 = (query_string_t) p1;
00224 query_string_t pd2 = (query_string_t) p2;
00225
00226 if (pd1->options != pd2->options)
00227 return FALSE;
00228 if (pd1->is_regex != pd2->is_regex)
00229 return FALSE;
00230 return (safe_strcmp (pd1->matchstring, pd2->matchstring) == 0);
00231 }
00232
00233 QofQueryPredData *
00234 qof_query_string_predicate (QofQueryCompare how,
00235 const gchar *str, QofStringMatch options, gboolean is_regex)
00236 {
00237 query_string_t pdata;
00238
00239 g_return_val_if_fail (str, NULL);
00240 g_return_val_if_fail (*str != '\0', NULL);
00241 g_return_val_if_fail (how == QOF_COMPARE_EQUAL
00242 || how == QOF_COMPARE_NEQ, NULL);
00243
00244 pdata = g_new0 (query_string_def, 1);
00245 pdata->pd.type_name = query_string_type;
00246 pdata->pd.how = how;
00247 pdata->options = options;
00248 pdata->matchstring = g_strdup (str);
00249
00250 if (is_regex)
00251 {
00252 int flags = REG_EXTENDED;
00253 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
00254 flags |= REG_ICASE;
00255
00256 regcomp (&pdata->compiled, str, flags);
00257 pdata->is_regex = TRUE;
00258 }
00259
00260 return ((QofQueryPredData *) pdata);
00261 }
00262
00263 static gchar *
00264 string_to_string (gpointer object, QofParam * getter)
00265 {
00266 const char *res;
00267 res = ((query_string_getter) getter->param_getfcn) (object, getter);
00268 if (res)
00269 return g_strdup (res);
00270 return NULL;
00271 }
00272
00273
00274
00275 static gint
00276 time_compare (QofTime *ta, QofTime *tb, QofDateMatch options)
00277 {
00278 if (options == QOF_DATE_MATCH_DAY)
00279 {
00280 qof_time_set_day_start (ta);
00281 qof_time_set_day_start (tb);
00282 }
00283 return qof_time_cmp (ta, tb);
00284 }
00285
00286 static int
00287 time_match_predicate (gpointer object, QofParam * getter,
00288 QofQueryPredData * pd)
00289 {
00290 query_time_t pdata = (query_time_t) pd;
00291 QofTime *objtime;
00292 gint compare;
00293
00294 VERIFY_PREDICATE (query_time_type);
00295
00296 objtime = ((query_time_getter) getter->param_getfcn) (object, getter);
00297 compare = time_compare (objtime, pdata->qt, pdata->options);
00298
00299 switch (pd->how)
00300 {
00301 case QOF_COMPARE_LT:
00302 return (compare < 0);
00303 case QOF_COMPARE_LTE:
00304 return (compare <= 0);
00305 case QOF_COMPARE_EQUAL:
00306 return (compare == 0);
00307 case QOF_COMPARE_GT:
00308 return (compare > 0);
00309 case QOF_COMPARE_GTE:
00310 return (compare >= 0);
00311 case QOF_COMPARE_NEQ:
00312 return (compare != 0);
00313 default:
00314 PWARN ("bad match type: %d", pd->how);
00315 return 0;
00316 }
00317 }
00318
00319 static gint
00320 time_compare_func (gpointer a, gpointer b, gint options,
00321 QofParam * getter)
00322 {
00323 QofTime *ta, *tb;
00324
00325 g_return_val_if_fail (a && b && getter
00326 && getter->param_getfcn, COMPARE_ERROR);
00327
00328 ta = ((query_time_getter) getter->param_getfcn) (a, getter);
00329 tb = ((query_time_getter) getter->param_getfcn) (b, getter);
00330
00331 return time_compare (ta, tb, options);
00332 }
00333
00334 static void
00335 time_free_pdata (QofQueryPredData * pd)
00336 {
00337 query_time_t pdata = (query_time_t) pd;
00338
00339 VERIFY_PDATA (query_time_type);
00340
00341 g_free (pdata);
00342 }
00343
00344 static QofQueryPredData *
00345 time_copy_predicate (QofQueryPredData * pd)
00346 {
00347 query_time_t pdata = (query_time_t) pd;
00348
00349 VERIFY_PDATA_R (query_time_type);
00350
00351 return qof_query_time_predicate (pd->how, pdata->options,
00352 pdata->qt);
00353 }
00354
00355 static gboolean
00356 time_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00357 {
00358 query_time_t pd1 = (query_time_t) p1;
00359 query_time_t pd2 = (query_time_t) p2;
00360
00361 if (pd1->options != pd2->options)
00362 return FALSE;
00363 return qof_time_equal (pd1->qt, pd2->qt);
00364 }
00365
00366 QofQueryPredData *
00367 qof_query_time_predicate (QofQueryCompare how,
00368 QofDateMatch options, QofTime *qt)
00369 {
00370 query_time_t pdata;
00371
00372 pdata = g_new0 (query_time_def, 1);
00373 pdata->pd.type_name = query_time_type;
00374 pdata->pd.how = how;
00375 pdata->options = options;
00376 pdata->qt = qt;
00377 return ((QofQueryPredData *) pdata);
00378 }
00379
00380 gboolean
00381 qof_query_time_predicate_get_time (QofQueryPredData * pd,
00382 QofTime *qt)
00383 {
00384 query_time_t pdata = (query_time_t) pd;
00385
00386 if (pdata->pd.type_name != query_time_type)
00387 return FALSE;
00388 qt = pdata->qt;
00389 return TRUE;
00390 }
00391
00392 static gchar *
00393 time_to_string (gpointer object, QofParam * getter)
00394 {
00395 QofDate *qd;
00396 QofTime *qt =
00397 ((query_time_getter) getter->param_getfcn) (object, getter);
00398
00399 qd = qof_date_from_qtime (qt);
00400 return qof_date_print (qd, QOF_DATE_FORMAT_UTC);
00401 }
00402
00403
00404
00405 static int
00406 numeric_match_predicate (gpointer object, QofParam * getter,
00407 QofQueryPredData * pd)
00408 {
00409 query_numeric_t pdata = (query_numeric_t) pd;
00410 gnc_numeric obj_val;
00411 int compare;
00412
00413 VERIFY_PREDICATE (query_numeric_type);
00414
00415 obj_val =
00416 ((query_numeric_getter) getter->param_getfcn) (object, getter);
00417
00418 switch (pdata->options)
00419 {
00420 case QOF_NUMERIC_MATCH_CREDIT:
00421 if (gnc_numeric_positive_p (obj_val))
00422 return 0;
00423 break;
00424 case QOF_NUMERIC_MATCH_DEBIT:
00425 if (gnc_numeric_negative_p (obj_val))
00426 return 0;
00427 break;
00428 default:
00429 break;
00430 }
00431
00432
00433
00434 if (pd->how == QOF_COMPARE_EQUAL || pd->how == QOF_COMPARE_NEQ)
00435 {
00436 gnc_numeric cmp_val = gnc_numeric_create (1, 10000);
00437 compare =
00438 (gnc_numeric_compare (gnc_numeric_abs
00439 (gnc_numeric_sub (gnc_numeric_abs (obj_val),
00440 gnc_numeric_abs (pdata->
00441 amount),
00442 100000, GNC_HOW_RND_ROUND)), cmp_val) < 0);
00443 }
00444 else
00445 compare =
00446 gnc_numeric_compare (gnc_numeric_abs (obj_val), pdata->amount);
00447
00448 switch (pd->how)
00449 {
00450 case QOF_COMPARE_LT:
00451 return (compare < 0);
00452 case QOF_COMPARE_LTE:
00453 return (compare <= 0);
00454 case QOF_COMPARE_EQUAL:
00455 return compare;
00456 case QOF_COMPARE_GT:
00457 return (compare > 0);
00458 case QOF_COMPARE_GTE:
00459 return (compare >= 0);
00460 case QOF_COMPARE_NEQ:
00461 return !compare;
00462 default:
00463 PWARN ("bad match type: %d", pd->how);
00464 return 0;
00465 }
00466 }
00467
00468 static int
00469 numeric_compare_func (gpointer a, gpointer b, gint options,
00470 QofParam * getter)
00471 {
00472 gnc_numeric va, vb;
00473
00474 g_return_val_if_fail (a && b && getter
00475 && getter->param_getfcn, COMPARE_ERROR);
00476
00477 va = ((query_numeric_getter) getter->param_getfcn) (a, getter);
00478 vb = ((query_numeric_getter) getter->param_getfcn) (b, getter);
00479
00480 return gnc_numeric_compare (va, vb);
00481 }
00482
00483 static void
00484 numeric_free_pdata (QofQueryPredData * pd)
00485 {
00486 query_numeric_t pdata = (query_numeric_t) pd;
00487 VERIFY_PDATA (query_numeric_type);
00488 g_free (pdata);
00489 }
00490
00491 static QofQueryPredData *
00492 numeric_copy_predicate (QofQueryPredData * pd)
00493 {
00494 query_numeric_t pdata = (query_numeric_t) pd;
00495 VERIFY_PDATA_R (query_numeric_type);
00496 return qof_query_numeric_predicate (pd->how, pdata->options,
00497 pdata->amount);
00498 }
00499
00500 static gboolean
00501 numeric_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00502 {
00503 query_numeric_t pd1 = (query_numeric_t) p1;
00504 query_numeric_t pd2 = (query_numeric_t) p2;
00505
00506 if (pd1->options != pd2->options)
00507 return FALSE;
00508 return gnc_numeric_equal (pd1->amount, pd2->amount);
00509 }
00510
00511 QofQueryPredData *
00512 qof_query_numeric_predicate (QofQueryCompare how,
00513 QofNumericMatch options, gnc_numeric value)
00514 {
00515 query_numeric_t pdata;
00516 pdata = g_new0 (query_numeric_def, 1);
00517 pdata->pd.type_name = query_numeric_type;
00518 pdata->pd.how = how;
00519 pdata->options = options;
00520 pdata->amount = value;
00521 return ((QofQueryPredData *) pdata);
00522 }
00523
00524 static char *
00525 numeric_to_string (gpointer object, QofParam * getter)
00526 {
00527 gnc_numeric num;
00528 num = ((query_numeric_getter) getter->param_getfcn) (object, getter);
00529
00530 return gnc_numeric_to_string (num);
00531 }
00532
00533 static char *
00534 debcred_to_string (gpointer object, QofParam * getter)
00535 {
00536 gnc_numeric num;
00537 num = ((query_numeric_getter) getter->param_getfcn) (object, getter);
00538
00539 return gnc_numeric_to_string (num);
00540 }
00541
00542
00543
00544 static int
00545 guid_match_predicate (gpointer object, QofParam * getter,
00546 QofQueryPredData * pd)
00547 {
00548 query_guid_t pdata = (query_guid_t) pd;
00549 GList *node, *o_list;
00550 const GUID *guid = NULL;
00551
00552 VERIFY_PREDICATE (query_guid_type);
00553
00554 switch (pdata->options)
00555 {
00556
00557 case QOF_GUID_MATCH_ALL:
00558
00559
00560
00561
00562
00563 for (node = pdata->guids; node; node = node->next)
00564 {
00565
00566 for (o_list = object; o_list; o_list = o_list->next)
00567 {
00568 guid =
00569 ((query_guid_getter) getter->param_getfcn) (o_list->
00570 data, getter);
00571 if (guid_equal (node->data, guid))
00572 break;
00573 }
00574
00575
00576
00577
00578
00579 if (o_list == NULL)
00580 break;
00581 }
00582
00583
00584
00585
00586
00587
00588
00589 break;
00590
00591 case QOF_GUID_MATCH_LIST_ANY:
00592
00593
00594
00595
00596
00597
00598 o_list =
00599 ((query_glist_getter) getter->param_getfcn) (object, getter);
00600
00601 for (node = o_list; node; node = node->next)
00602 {
00603 GList *node2;
00604
00605
00606 for (node2 = pdata->guids; node2; node2 = node2->next)
00607 {
00608 if (guid_equal (node->data, node2->data))
00609 break;
00610 }
00611
00612
00613 if (node2 != NULL)
00614 break;
00615 }
00616
00617 g_list_free (o_list);
00618
00619
00620
00621
00622
00623 break;
00624
00625 default:
00626
00627
00628
00629
00630
00631 guid = ((query_guid_getter) getter->param_getfcn) (object, getter);
00632 for (node = pdata->guids; node; node = node->next)
00633 {
00634 if (guid_equal (node->data, guid))
00635 break;
00636 }
00637 }
00638
00639 switch (pdata->options)
00640 {
00641 case QOF_GUID_MATCH_ANY:
00642 case QOF_GUID_MATCH_LIST_ANY:
00643 return (node != NULL);
00644 break;
00645 case QOF_GUID_MATCH_NONE:
00646 case QOF_GUID_MATCH_ALL:
00647 return (node == NULL);
00648 break;
00649 case QOF_GUID_MATCH_NULL:
00650 return (guid == NULL);
00651 break;
00652 default:
00653 PWARN ("bad match type");
00654 return 0;
00655 }
00656 }
00657
00658 static void
00659 guid_free_pdata (QofQueryPredData * pd)
00660 {
00661 query_guid_t pdata = (query_guid_t) pd;
00662 GList *node;
00663 VERIFY_PDATA (query_guid_type);
00664 for (node = pdata->guids; node; node = node->next)
00665 {
00666 guid_free (node->data);
00667 }
00668 g_list_free (pdata->guids);
00669 g_free (pdata);
00670 }
00671
00672 static QofQueryPredData *
00673 guid_copy_predicate (QofQueryPredData * pd)
00674 {
00675 query_guid_t pdata = (query_guid_t) pd;
00676 VERIFY_PDATA_R (query_guid_type);
00677 return qof_query_guid_predicate (pdata->options, pdata->guids);
00678 }
00679
00680 static gboolean
00681 guid_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00682 {
00683 query_guid_t pd1 = (query_guid_t) p1;
00684 query_guid_t pd2 = (query_guid_t) p2;
00685 GList *l1 = pd1->guids, *l2 = pd2->guids;
00686
00687 if (pd1->options != pd2->options)
00688 return FALSE;
00689 if (g_list_length (l1) != g_list_length (l2))
00690 return FALSE;
00691 for (; l1; l1 = l1->next, l2 = l2->next)
00692 {
00693 if (!guid_equal (l1->data, l2->data))
00694 return FALSE;
00695 }
00696 return TRUE;
00697 }
00698
00699 QofQueryPredData *
00700 qof_query_guid_predicate (QofGuidMatch options, GList * guid_list)
00701 {
00702 query_guid_t pdata;
00703 GList *node;
00704
00705 if (NULL == guid_list)
00706 return NULL;
00707
00708 pdata = g_new0 (query_guid_def, 1);
00709 pdata->pd.how = QOF_COMPARE_EQUAL;
00710 pdata->pd.type_name = query_guid_type;
00711 pdata->options = options;
00712
00713 pdata->guids = g_list_copy (guid_list);
00714 for (node = pdata->guids; node; node = node->next)
00715 {
00716 GUID *guid = guid_malloc ();
00717 *guid = *((GUID *) node->data);
00718 node->data = guid;
00719 }
00720 return ((QofQueryPredData *) pdata);
00721 }
00722
00723
00724
00725
00726 static int
00727 int32_match_predicate (gpointer object, QofParam * getter,
00728 QofQueryPredData * pd)
00729 {
00730 gint32 val;
00731 query_int32_t pdata = (query_int32_t) pd;
00732
00733 VERIFY_PREDICATE (query_int32_type);
00734
00735 val = ((query_int32_getter) getter->param_getfcn) (object, getter);
00736
00737 switch (pd->how)
00738 {
00739 case QOF_COMPARE_LT:
00740 return (val < pdata->val);
00741 case QOF_COMPARE_LTE:
00742 return (val <= pdata->val);
00743 case QOF_COMPARE_EQUAL:
00744 return (val == pdata->val);
00745 case QOF_COMPARE_GT:
00746 return (val > pdata->val);
00747 case QOF_COMPARE_GTE:
00748 return (val >= pdata->val);
00749 case QOF_COMPARE_NEQ:
00750 return (val != pdata->val);
00751 default:
00752 PWARN ("bad match type: %d", pd->how);
00753 return 0;
00754 }
00755 }
00756
00757 static int
00758 int32_compare_func (gpointer a, gpointer b, gint options,
00759 QofParam * getter)
00760 {
00761 gint32 v1, v2;
00762 g_return_val_if_fail (a && b && getter
00763 && getter->param_getfcn, COMPARE_ERROR);
00764
00765 v1 = ((query_int32_getter) getter->param_getfcn) (a, getter);
00766 v2 = ((query_int32_getter) getter->param_getfcn) (b, getter);
00767
00768 if (v1 < v2)
00769 return -1;
00770 if (v1 > v2)
00771 return 1;
00772 return 0;
00773 }
00774
00775 static void
00776 int32_free_pdata (QofQueryPredData * pd)
00777 {
00778 query_int32_t pdata = (query_int32_t) pd;
00779 VERIFY_PDATA (query_int32_type);
00780 g_free (pdata);
00781 }
00782
00783 static QofQueryPredData *
00784 int32_copy_predicate (QofQueryPredData * pd)
00785 {
00786 query_int32_t pdata = (query_int32_t) pd;
00787 VERIFY_PDATA_R (query_int32_type);
00788 return qof_query_int32_predicate (pd->how, pdata->val);
00789 }
00790
00791 static gboolean
00792 int32_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00793 {
00794 query_int32_t pd1 = (query_int32_t) p1;
00795 query_int32_t pd2 = (query_int32_t) p2;
00796
00797 return (pd1->val == pd2->val);
00798 }
00799
00800 QofQueryPredData *
00801 qof_query_int32_predicate (QofQueryCompare how, gint32 val)
00802 {
00803 query_int32_t pdata = g_new0 (query_int32_def, 1);
00804 pdata->pd.type_name = query_int32_type;
00805 pdata->pd.how = how;
00806 pdata->val = val;
00807 return ((QofQueryPredData *) pdata);
00808 }
00809
00810 static char *
00811 int32_to_string (gpointer object, QofParam * getter)
00812 {
00813 gint32 num =
00814 ((query_int32_getter) getter->param_getfcn) (object, getter);
00815
00816 return g_strdup_printf ("%d", num);
00817 }
00818
00819
00820
00821
00822 static int
00823 int64_match_predicate (gpointer object, QofParam * getter,
00824 QofQueryPredData * pd)
00825 {
00826 gint64 val;
00827 query_int64_t pdata = (query_int64_t) pd;
00828
00829 VERIFY_PREDICATE (query_int64_type);
00830
00831 val = ((query_int64_getter) getter->param_getfcn) (object, getter);
00832
00833 switch (pd->how)
00834 {
00835 case QOF_COMPARE_LT:
00836 return (val < pdata->val);
00837 case QOF_COMPARE_LTE:
00838 return (val <= pdata->val);
00839 case QOF_COMPARE_EQUAL:
00840 return (val == pdata->val);
00841 case QOF_COMPARE_GT:
00842 return (val > pdata->val);
00843 case QOF_COMPARE_GTE:
00844 return (val >= pdata->val);
00845 case QOF_COMPARE_NEQ:
00846 return (val != pdata->val);
00847 default:
00848 PWARN ("bad match type: %d", pd->how);
00849 return 0;
00850 }
00851 }
00852
00853 static int
00854 int64_compare_func (gpointer a, gpointer b, gint options,
00855 QofParam * getter)
00856 {
00857 gint64 v1, v2;
00858 g_return_val_if_fail (a && b && getter
00859 && getter->param_getfcn, COMPARE_ERROR);
00860
00861 v1 = ((query_int64_getter) getter->param_getfcn) (a, getter);
00862 v2 = ((query_int64_getter) getter->param_getfcn) (b, getter);
00863
00864 if (v1 < v2)
00865 return -1;
00866 if (v1 > v2)
00867 return 1;
00868 return 0;
00869 }
00870
00871 static void
00872 int64_free_pdata (QofQueryPredData * pd)
00873 {
00874 query_int64_t pdata = (query_int64_t) pd;
00875 VERIFY_PDATA (query_int64_type);
00876 g_free (pdata);
00877 }
00878
00879 static QofQueryPredData *
00880 int64_copy_predicate (QofQueryPredData * pd)
00881 {
00882 query_int64_t pdata = (query_int64_t) pd;
00883 VERIFY_PDATA_R (query_int64_type);
00884 return qof_query_int64_predicate (pd->how, pdata->val);
00885 }
00886
00887 static gboolean
00888 int64_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00889 {
00890 query_int64_t pd1 = (query_int64_t) p1;
00891 query_int64_t pd2 = (query_int64_t) p2;
00892
00893 return (pd1->val == pd2->val);
00894 }
00895
00896 QofQueryPredData *
00897 qof_query_int64_predicate (QofQueryCompare how, gint64 val)
00898 {
00899 query_int64_t pdata = g_new0 (query_int64_def, 1);
00900 pdata->pd.type_name = query_int64_type;
00901 pdata->pd.how = how;
00902 pdata->val = val;
00903 return ((QofQueryPredData *) pdata);
00904 }
00905
00906 static char *
00907 int64_to_string (gpointer object, QofParam * getter)
00908 {
00909 gint64 num =
00910 ((query_int64_getter) getter->param_getfcn) (object, getter);
00911
00912 return g_strdup_printf ("%" G_GINT64_FORMAT, num);
00913 }
00914
00915
00916
00917
00918 static int
00919 double_match_predicate (gpointer object, QofParam * getter,
00920 QofQueryPredData * pd)
00921 {
00922 double val;
00923 query_double_t pdata = (query_double_t) pd;
00924
00925 VERIFY_PREDICATE (query_double_type);
00926
00927 val = ((query_double_getter) getter->param_getfcn) (object, getter);
00928
00929 switch (pd->how)
00930 {
00931 case QOF_COMPARE_LT:
00932 return (val < pdata->val);
00933 case QOF_COMPARE_LTE:
00934 return (val <= pdata->val);
00935 case QOF_COMPARE_EQUAL:
00936 return (val == pdata->val);
00937 case QOF_COMPARE_GT:
00938 return (val > pdata->val);
00939 case QOF_COMPARE_GTE:
00940 return (val >= pdata->val);
00941 case QOF_COMPARE_NEQ:
00942 return (val != pdata->val);
00943 default:
00944 PWARN ("bad match type: %d", pd->how);
00945 return 0;
00946 }
00947 }
00948
00949 static int
00950 double_compare_func (gpointer a, gpointer b, gint options,
00951 QofParam * getter)
00952 {
00953 double v1, v2;
00954 g_return_val_if_fail (a && b && getter
00955 && getter->param_getfcn, COMPARE_ERROR);
00956
00957 v1 = ((query_double_getter) getter->param_getfcn) (a, getter);
00958 v2 = ((query_double_getter) getter->param_getfcn) (b, getter);
00959
00960 if (v1 < v2)
00961 return -1;
00962 if (v1 > v2)
00963 return 1;
00964 return 0;
00965 }
00966
00967 static void
00968 double_free_pdata (QofQueryPredData * pd)
00969 {
00970 query_double_t pdata = (query_double_t) pd;
00971 VERIFY_PDATA (query_double_type);
00972 g_free (pdata);
00973 }
00974
00975 static QofQueryPredData *
00976 double_copy_predicate (QofQueryPredData * pd)
00977 {
00978 query_double_t pdata = (query_double_t) pd;
00979 VERIFY_PDATA_R (query_double_type);
00980 return qof_query_double_predicate (pd->how, pdata->val);
00981 }
00982
00983 static gboolean
00984 double_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00985 {
00986 query_double_t pd1 = (query_double_t) p1;
00987 query_double_t pd2 = (query_double_t) p2;
00988
00989 return (pd1->val == pd2->val);
00990 }
00991
00992 QofQueryPredData *
00993 qof_query_double_predicate (QofQueryCompare how, double val)
00994 {
00995 query_double_t pdata = g_new0 (query_double_def, 1);
00996 pdata->pd.type_name = query_double_type;
00997 pdata->pd.how = how;
00998 pdata->val = val;
00999 return ((QofQueryPredData *) pdata);
01000 }
01001
01002 static char *
01003 double_to_string (gpointer object, QofParam * getter)
01004 {
01005 double num =
01006 ((query_double_getter) getter->param_getfcn) (object, getter);
01007
01008 return g_strdup_printf ("%f", num);
01009 }
01010
01011
01012
01013 static int
01014 boolean_match_predicate (gpointer object, QofParam * getter,
01015 QofQueryPredData * pd)
01016 {
01017 gboolean val;
01018 query_boolean_t pdata = (query_boolean_t) pd;
01019
01020 VERIFY_PREDICATE (query_boolean_type);
01021
01022 val = ((query_boolean_getter) getter->param_getfcn) (object, getter);
01023
01024 switch (pd->how)
01025 {
01026 case QOF_COMPARE_EQUAL:
01027 return (val == pdata->val);
01028 case QOF_COMPARE_NEQ:
01029 return (val != pdata->val);
01030 default:
01031 PWARN ("bad match type: %d", pd->how);
01032 return 0;
01033 }
01034 }
01035
01036 static int
01037 boolean_compare_func (gpointer a, gpointer b, gint options,
01038 QofParam * getter)
01039 {
01040 gboolean va, vb;
01041 g_return_val_if_fail (a && b && getter
01042 && getter->param_getfcn, COMPARE_ERROR);
01043 va = ((query_boolean_getter) getter->param_getfcn) (a, getter);
01044 vb = ((query_boolean_getter) getter->param_getfcn) (b, getter);
01045 if (!va && vb)
01046 return -1;
01047 if (va && !vb)
01048 return 1;
01049 return 0;
01050 }
01051
01052 static void
01053 boolean_free_pdata (QofQueryPredData * pd)
01054 {
01055 query_boolean_t pdata = (query_boolean_t) pd;
01056 VERIFY_PDATA (query_boolean_type);
01057 g_free (pdata);
01058 }
01059
01060 static QofQueryPredData *
01061 boolean_copy_predicate (QofQueryPredData * pd)
01062 {
01063 query_boolean_t pdata = (query_boolean_t) pd;
01064 VERIFY_PDATA_R (query_boolean_type);
01065 return qof_query_boolean_predicate (pd->how, pdata->val);
01066 }
01067
01068 static gboolean
01069 boolean_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01070 {
01071 query_boolean_t pd1 = (query_boolean_t) p1;
01072 query_boolean_t pd2 = (query_boolean_t) p2;
01073
01074 return (pd1->val == pd2->val);
01075 }
01076
01077 QofQueryPredData *
01078 qof_query_boolean_predicate (QofQueryCompare how, gboolean val)
01079 {
01080 query_boolean_t pdata;
01081 g_return_val_if_fail (how == QOF_COMPARE_EQUAL
01082 || how == QOF_COMPARE_NEQ, NULL);
01083
01084 pdata = g_new0 (query_boolean_def, 1);
01085 pdata->pd.type_name = query_boolean_type;
01086 pdata->pd.how = how;
01087 pdata->val = val;
01088 return ((QofQueryPredData *) pdata);
01089 }
01090
01091 static char *
01092 boolean_to_string (gpointer object, QofParam * getter)
01093 {
01094 gboolean num =
01095 ((query_boolean_getter) getter->param_getfcn) (object, getter);
01096
01097 return g_strdup_printf ("%s", (num ? "X" : ""));
01098 }
01099
01100
01101
01102 static int
01103 char_match_predicate (gpointer object, QofParam * getter,
01104 QofQueryPredData * pd)
01105 {
01106 char c;
01107 query_char_t pdata = (query_char_t) pd;
01108
01109 VERIFY_PREDICATE (query_char_type);
01110
01111 c = ((query_char_getter) getter->param_getfcn) (object, getter);
01112
01113 switch (pdata->options)
01114 {
01115 case QOF_CHAR_MATCH_ANY:
01116 if (strchr (pdata->char_list, c))
01117 return 1;
01118 return 0;
01119 case QOF_CHAR_MATCH_NONE:
01120 if (!strchr (pdata->char_list, c))
01121 return 1;
01122 return 0;
01123 default:
01124 PWARN ("bad match type");
01125 return 0;
01126 }
01127 }
01128
01129 static int
01130 char_compare_func (gpointer a, gpointer b, gint options, QofParam * getter)
01131 {
01132 char va, vb;
01133 g_return_val_if_fail (a && b && getter
01134 && getter->param_getfcn, COMPARE_ERROR);
01135 va = ((query_char_getter) getter->param_getfcn) (a, getter);
01136 vb = ((query_char_getter) getter->param_getfcn) (b, getter);
01137 return (va - vb);
01138 }
01139
01140 static void
01141 char_free_pdata (QofQueryPredData * pd)
01142 {
01143 query_char_t pdata = (query_char_t) pd;
01144 VERIFY_PDATA (query_char_type);
01145 g_free (pdata->char_list);
01146 g_free (pdata);
01147 }
01148
01149 static QofQueryPredData *
01150 char_copy_predicate (QofQueryPredData * pd)
01151 {
01152 query_char_t pdata = (query_char_t) pd;
01153 VERIFY_PDATA_R (query_char_type);
01154 return qof_query_char_predicate (pdata->options, pdata->char_list);
01155 }
01156
01157 static gboolean
01158 char_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01159 {
01160 query_char_t pd1 = (query_char_t) p1;
01161 query_char_t pd2 = (query_char_t) p2;
01162
01163 if (pd1->options != pd2->options)
01164 return FALSE;
01165 return (safe_strcmp (pd1->char_list, pd2->char_list) == 0);
01166 }
01167
01168 QofQueryPredData *
01169 qof_query_char_predicate (QofCharMatch options, const char *chars)
01170 {
01171 query_char_t pdata;
01172 g_return_val_if_fail (chars, NULL);
01173 pdata = g_new0 (query_char_def, 1);
01174 pdata->pd.type_name = query_char_type;
01175 pdata->pd.how = QOF_COMPARE_EQUAL;
01176 pdata->options = options;
01177 pdata->char_list = g_strdup (chars);
01178 return ((QofQueryPredData *) pdata);
01179 }
01180
01181 static char *
01182 char_to_string (gpointer object, QofParam * getter)
01183 {
01184 char num = ((query_char_getter) getter->param_getfcn) (object, getter);
01185
01186 return g_strdup_printf ("%c", num);
01187 }
01188
01189
01190
01191 static int
01192 kvp_match_predicate (gpointer object, QofParam * getter,
01193 QofQueryPredData * pd)
01194 {
01195 int compare;
01196 KvpFrame *kvp;
01197 KvpValue *value;
01198 query_kvp_t pdata = (query_kvp_t) pd;
01199
01200 VERIFY_PREDICATE (query_kvp_type);
01201
01202 kvp = ((query_kvp_getter) getter->param_getfcn) (object, getter);
01203 if (!kvp)
01204 return 0;
01205
01206 value = kvp_frame_get_slot_path_gslist (kvp, pdata->path);
01207 if (!value)
01208 return 0;
01209
01210 if (kvp_value_get_type (value) != kvp_value_get_type (pdata->value))
01211 return 0;
01212
01213 compare = kvp_value_compare (value, pdata->value);
01214
01215 switch (pd->how)
01216 {
01217 case QOF_COMPARE_LT:
01218 return (compare < 0);
01219 case QOF_COMPARE_LTE:
01220 return (compare <= 0);
01221 case QOF_COMPARE_EQUAL:
01222 return (compare == 0);
01223 case QOF_COMPARE_GTE:
01224 return (compare >= 0);
01225 case QOF_COMPARE_GT:
01226 return (compare > 0);
01227 case QOF_COMPARE_NEQ:
01228 return (compare != 0);
01229 default:
01230 PWARN ("bad match type: %d", pd->how);
01231 return 0;
01232 }
01233 }
01234
01235 static void
01236 kvp_free_pdata (QofQueryPredData * pd)
01237 {
01238 query_kvp_t pdata = (query_kvp_t) pd;
01239 GSList *node;
01240
01241 VERIFY_PDATA (query_kvp_type);
01242 kvp_value_delete (pdata->value);
01243 for (node = pdata->path; node; node = node->next)
01244 {
01245 g_free (node->data);
01246 node->data = NULL;
01247 }
01248 g_slist_free (pdata->path);
01249 g_free (pdata);
01250 }
01251
01252 static QofQueryPredData *
01253 kvp_copy_predicate (QofQueryPredData * pd)
01254 {
01255 query_kvp_t pdata = (query_kvp_t) pd;
01256 VERIFY_PDATA_R (query_kvp_type);
01257 return qof_query_kvp_predicate (pd->how, pdata->path, pdata->value);
01258 }
01259
01260 static gboolean
01261 kvp_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01262 {
01263 query_kvp_t pd1 = (query_kvp_t) p1;
01264 query_kvp_t pd2 = (query_kvp_t) p2;
01265 GSList *n1, *n2;
01266
01267 n1 = pd1->path;
01268 n2 = pd2->path;
01269
01270 for (; n1 && n2; n1 = n1->next, n2 = n2->next)
01271 {
01272 if (safe_strcmp (n1->data, n2->data) != 0)
01273 return FALSE;
01274 }
01275
01276 if (n1 || n2)
01277 return FALSE;
01278
01279 return (kvp_value_compare (pd1->value, pd2->value) == 0);
01280 }
01281
01282 QofQueryPredData *
01283 qof_query_kvp_predicate (QofQueryCompare how,
01284 GSList * path, const KvpValue * value)
01285 {
01286 query_kvp_t pdata;
01287 GSList *node;
01288
01289 g_return_val_if_fail (path && value, NULL);
01290
01291 pdata = g_new0 (query_kvp_def, 1);
01292 pdata->pd.type_name = query_kvp_type;
01293 pdata->pd.how = how;
01294 pdata->value = kvp_value_copy (value);
01295 pdata->path = g_slist_copy (path);
01296 for (node = pdata->path; node; node = node->next)
01297 node->data = g_strdup (node->data);
01298
01299 return ((QofQueryPredData *) pdata);
01300 }
01301
01302 QofQueryPredData *
01303 qof_query_kvp_predicate_path (QofQueryCompare how,
01304 const char *path, const KvpValue * value)
01305 {
01306 QofQueryPredData *pd;
01307 GSList *spath = NULL;
01308 char *str, *p;
01309
01310 if (!path)
01311 return NULL;
01312
01313 str = g_strdup (path);
01314 p = str;
01315 if (0 == *p)
01316 return NULL;
01317 if ('/' == *p)
01318 p++;
01319
01320 while (p)
01321 {
01322 spath = g_slist_append (spath, p);
01323 p = strchr (p, '/');
01324 if (p)
01325 {
01326 *p = 0;
01327 p++;
01328 }
01329 }
01330
01331 pd = qof_query_kvp_predicate (how, spath, value);
01332 g_free (str);
01333 return pd;
01334 }
01335
01336
01337
01338
01339 static int
01340 collect_match_predicate (gpointer object, QofParam * getter,
01341 QofQueryPredData * pd)
01342 {
01343 query_coll_t pdata;
01344 QofCollection *coll;
01345 GList *node, *node2, *o_list;
01346 const GUID *guid;
01347
01348 pdata = (query_coll_t) pd;
01349 VERIFY_PREDICATE (query_collect_type);
01350 coll = ((query_collect_getter) getter->param_getfcn) (object, getter);
01351 guid = NULL;
01352 switch (pdata->options)
01353 {
01354 case QOF_GUID_MATCH_ALL:
01355 {
01356 for (node = pdata->guids; node; node = node->next)
01357 {
01358 for (o_list = object; o_list; o_list = o_list->next)
01359 {
01360 guid = ((query_guid_getter) getter->param_getfcn)
01361 (o_list->data, getter);
01362 if (guid_equal (node->data, guid))
01363 {
01364 break;
01365 }
01366 }
01367 if (o_list == NULL)
01368 {
01369 break;
01370 }
01371 }
01372 break;
01373 }
01374 case QOF_GUID_MATCH_LIST_ANY:
01375 {
01376 o_list =
01377 ((query_glist_getter) getter->param_getfcn) (object,
01378 getter);
01379 for (node = o_list; node; node = node->next)
01380 {
01381 for (node2 = pdata->guids; node2; node2 = node2->next)
01382 {
01383 if (guid_equal (node->data, node2->data))
01384 {
01385 break;
01386 }
01387 }
01388 if (node2 != NULL)
01389 {
01390 break;
01391 }
01392 }
01393 g_list_free (o_list);
01394 break;
01395 }
01396 default:
01397 {
01398 guid =
01399 ((query_guid_getter) getter->param_getfcn) (object,
01400 getter);
01401 for (node = pdata->guids; node; node = node->next)
01402 {
01403 if (guid_equal (node->data, guid))
01404 {
01405 break;
01406 }
01407 }
01408 }
01409 switch (pdata->options)
01410 {
01411 case QOF_GUID_MATCH_ANY:
01412 case QOF_GUID_MATCH_LIST_ANY:
01413 {
01414 return (node != NULL);
01415 break;
01416 }
01417 case QOF_GUID_MATCH_NONE:
01418 case QOF_GUID_MATCH_ALL:
01419 {
01420 return (node == NULL);
01421 break;
01422 }
01423 case QOF_GUID_MATCH_NULL:
01424 {
01425 return (guid == NULL);
01426 break;
01427 }
01428 default:
01429 {
01430 PWARN ("bad match type");
01431 return 0;
01432 }
01433 }
01434 }
01435 return 0;
01436 }
01437
01438 static int
01439 collect_compare_func (gpointer a, gpointer b, gint options,
01440 QofParam * getter)
01441 {
01442 gint result;
01443 QofCollection *c1, *c2;
01444
01445 c1 = ((query_collect_getter) getter->param_getfcn) (a, getter);
01446 c2 = ((query_collect_getter) getter->param_getfcn) (b, getter);
01447 result = qof_collection_compare (c1, c2);
01448 return result;
01449 }
01450
01451 static void
01452 collect_free_pdata (QofQueryPredData * pd)
01453 {
01454 query_coll_t pdata;
01455 GList *node;
01456
01457 node = NULL;
01458 pdata = (query_coll_t) pd;
01459 VERIFY_PDATA (query_collect_type);
01460 for (node = pdata->guids; node; node = node->next)
01461 {
01462 guid_free (node->data);
01463 }
01464 qof_collection_destroy (pdata->coll);
01465 g_list_free (pdata->guids);
01466 g_free (pdata);
01467 }
01468
01469 static QofQueryPredData *
01470 collect_copy_predicate (QofQueryPredData * pd)
01471 {
01472 query_coll_t pdata = (query_coll_t) pd;
01473
01474 VERIFY_PDATA_R (query_collect_type);
01475 return qof_query_collect_predicate (pdata->options, pdata->coll);
01476 }
01477
01478 static gboolean
01479 collect_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01480 {
01481 query_coll_t pd1;
01482 query_coll_t pd2;
01483 gint result;
01484
01485 pd1 = (query_coll_t) p1;
01486 pd2 = (query_coll_t) p2;
01487 result = qof_collection_compare (pd1->coll, pd2->coll);
01488 if (result == 0)
01489 {
01490 return TRUE;
01491 }
01492 return FALSE;
01493 }
01494
01495 static void
01496 query_collect_cb (QofEntity * ent, gpointer user_data)
01497 {
01498 query_coll_t pdata;
01499 GUID *guid;
01500
01501 guid = guid_malloc ();
01502 guid = (GUID *) qof_entity_get_guid (ent);
01503 pdata = (query_coll_t) user_data;
01504 pdata->guids = g_list_append (pdata->guids, guid);
01505 }
01506
01507 QofQueryPredData *
01508 qof_query_collect_predicate (QofGuidMatch options, QofCollection * coll)
01509 {
01510 query_coll_t pdata;
01511
01512 g_return_val_if_fail (coll, NULL);
01513 pdata = g_new0 (query_coll_def, 1);
01514 pdata->pd.type_name = query_collect_type;
01515 pdata->options = options;
01516 qof_collection_foreach (coll, query_collect_cb, pdata);
01517 if (NULL == pdata->guids)
01518 {
01519 return NULL;
01520 }
01521 return ((QofQueryPredData *) pdata);
01522 }
01523
01524
01525
01526 static int
01527 choice_match_predicate (gpointer object, QofParam * getter,
01528 QofQueryPredData * pd)
01529 {
01530 query_choice_t pdata = (query_choice_t) pd;
01531 GList *node, *o_list;
01532 const GUID *guid = NULL;
01533
01534 VERIFY_PREDICATE (query_choice_type);
01535
01536 switch (pdata->options)
01537 {
01538
01539 case QOF_GUID_MATCH_ALL:
01540
01541
01542
01543
01544
01545 for (node = pdata->guids; node; node = node->next)
01546 {
01547
01548 for (o_list = object; o_list; o_list = o_list->next)
01549 {
01550 guid =
01551 ((query_choice_getter) getter->param_getfcn) (o_list->
01552 data, getter);
01553 if (guid_equal (node->data, guid))
01554 break;
01555 }
01556
01557
01558
01559
01560
01561 if (o_list == NULL)
01562 break;
01563 }
01564
01565
01566
01567
01568
01569
01570
01571 break;
01572
01573 case QOF_GUID_MATCH_LIST_ANY:
01574
01575 o_list =
01576 ((query_glist_getter) getter->param_getfcn) (object, getter);
01577
01578 for (node = o_list; node; node = node->next)
01579 {
01580 GList *node2;
01581
01582 for (node2 = pdata->guids; node2; node2 = node2->next)
01583 {
01584 if (guid_equal (node->data, node2->data))
01585 break;
01586 }
01587
01588 if (node2 != NULL)
01589 break;
01590 }
01591
01592 g_list_free (o_list);
01593
01594 break;
01595
01596 default:
01597
01598
01599
01600
01601
01602 guid =
01603 ((query_choice_getter) getter->param_getfcn) (object, getter);
01604 for (node = pdata->guids; node; node = node->next)
01605 {
01606 if (guid_equal (node->data, guid))
01607 break;
01608 }
01609 }
01610
01611 switch (pdata->options)
01612 {
01613 case QOF_GUID_MATCH_ANY:
01614 case QOF_GUID_MATCH_LIST_ANY:
01615 return (node != NULL);
01616 break;
01617 case QOF_GUID_MATCH_NONE:
01618 case QOF_GUID_MATCH_ALL:
01619 return (node == NULL);
01620 break;
01621 case QOF_GUID_MATCH_NULL:
01622 return (guid == NULL);
01623 break;
01624 default:
01625 PWARN ("bad match type");
01626 return 0;
01627 }
01628 }
01629
01630 static void
01631 choice_free_pdata (QofQueryPredData * pd)
01632 {
01633 query_choice_t pdata = (query_choice_t) pd;
01634 GList *node;
01635 VERIFY_PDATA (query_choice_type);
01636 for (node = pdata->guids; node; node = node->next)
01637 {
01638 guid_free (node->data);
01639 }
01640 g_list_free (pdata->guids);
01641 g_free (pdata);
01642 }
01643
01644 static QofQueryPredData *
01645 choice_copy_predicate (QofQueryPredData * pd)
01646 {
01647 query_choice_t pdata = (query_choice_t) pd;
01648 VERIFY_PDATA_R (query_choice_type);
01649 return qof_query_choice_predicate (pdata->options, pdata->guids);
01650 }
01651
01652 static gboolean
01653 choice_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01654 {
01655 query_choice_t pd1 = (query_choice_t) p1;
01656 query_choice_t pd2 = (query_choice_t) p2;
01657 GList *l1 = pd1->guids, *l2 = pd2->guids;
01658
01659 if (pd1->options != pd2->options)
01660 return FALSE;
01661 if (g_list_length (l1) != g_list_length (l2))
01662 return FALSE;
01663 for (; l1; l1 = l1->next, l2 = l2->next)
01664 {
01665 if (!guid_equal (l1->data, l2->data))
01666 return FALSE;
01667 }
01668 return TRUE;
01669 }
01670
01671 QofQueryPredData *
01672 qof_query_choice_predicate (QofGuidMatch options, GList * guid_list)
01673 {
01674 query_choice_t pdata;
01675 GList *node;
01676
01677 if (NULL == guid_list)
01678 return NULL;
01679
01680 pdata = g_new0 (query_choice_def, 1);
01681 pdata->pd.how = QOF_COMPARE_EQUAL;
01682 pdata->pd.type_name = query_choice_type;
01683 pdata->options = options;
01684
01685 pdata->guids = g_list_copy (guid_list);
01686 for (node = pdata->guids; node; node = node->next)
01687 {
01688 GUID *guid = guid_malloc ();
01689 *guid = *((GUID *) node->data);
01690 node->data = guid;
01691 }
01692 return ((QofQueryPredData *) pdata);
01693 }
01694
01695
01696
01708 static void
01709 qof_query_register_core_object (QofType core_name,
01710 QofQueryPredicateFunc pred,
01711 QofCompareFunc comp,
01712 QueryPredicateCopyFunc copy,
01713 QueryPredDataFree pd_free,
01714 QueryToString toString, QueryPredicateEqual pred_equal)
01715 {
01716 g_return_if_fail (core_name);
01717 g_return_if_fail (*core_name != '\0');
01718
01719 if (pred)
01720 g_hash_table_insert (predTable, (char *) core_name, pred);
01721
01722 if (comp)
01723 g_hash_table_insert (cmpTable, (char *) core_name, comp);
01724
01725 if (copy)
01726 g_hash_table_insert (copyTable, (char *) core_name, copy);
01727
01728 if (pd_free)
01729 g_hash_table_insert (freeTable, (char *) core_name, pd_free);
01730
01731 if (toString)
01732 g_hash_table_insert (toStringTable, (char *) core_name, toString);
01733
01734 if (pred_equal)
01735 g_hash_table_insert (predEqualTable, (char *) core_name,
01736 pred_equal);
01737 }
01738
01739
01740 #ifndef QOF_DISABLE_DEPRECATED
01741
01742 typedef Timespec (*query_date_getter) (gpointer, QofParam *);
01743 static const gchar *query_date_type = QOF_TYPE_DATE;
01744
01745 static gint
01746 date_compare (Timespec ta, Timespec tb, QofDateMatch options)
01747 {
01748
01749 if (options == QOF_DATE_MATCH_DAY)
01750 {
01751 ta = timespecCanonicalDayTime (ta);
01752 tb = timespecCanonicalDayTime (tb);
01753 }
01754
01755 if (ta.tv_sec < tb.tv_sec)
01756 return -1;
01757 if (ta.tv_sec > tb.tv_sec)
01758 return 1;
01759
01760 if (ta.tv_nsec < tb.tv_nsec)
01761 return -1;
01762 if (ta.tv_nsec > tb.tv_nsec)
01763 return 1;
01764
01765 return 0;
01766 }
01767
01768 static int
01769 date_match_predicate (gpointer object, QofParam *getter,
01770 QofQueryPredData *pd)
01771 {
01772 query_date_t pdata = (query_date_t)pd;
01773 Timespec objtime;
01774 int compare;
01775
01776 VERIFY_PREDICATE (query_date_type);
01777
01778 objtime = ((query_date_getter)getter->param_getfcn) (object, getter);
01779 compare = date_compare (objtime, pdata->date, pdata->options);
01780
01781 switch (pd->how) {
01782 case QOF_COMPARE_LT:
01783 return (compare < 0);
01784 case QOF_COMPARE_LTE:
01785 return (compare <= 0);
01786 case QOF_COMPARE_EQUAL:
01787 return (compare == 0);
01788 case QOF_COMPARE_GT:
01789 return (compare > 0);
01790 case QOF_COMPARE_GTE:
01791 return (compare >= 0);
01792 case QOF_COMPARE_NEQ:
01793 return (compare != 0);
01794 default:
01795 PWARN ("bad match type: %d", pd->how);
01796 return 0;
01797 }
01798 }
01799
01800 static gint
01801 date_compare_func (gpointer a, gpointer b, gint options, QofParam * getter)
01802 {
01803 Timespec ta, tb;
01804
01805 g_return_val_if_fail (a && b && getter
01806 && getter->param_getfcn, COMPARE_ERROR);
01807
01808 ta = ((query_date_getter) getter->param_getfcn) (a, getter);
01809 tb = ((query_date_getter) getter->param_getfcn) (b, getter);
01810
01811 return date_compare (ta, tb, options);
01812 }
01813
01814 static void
01815 date_free_pdata (QofQueryPredData * pd)
01816 {
01817 query_date_t pdata = (query_date_t) pd;
01818
01819 VERIFY_PDATA (query_date_type);
01820
01821 g_free (pdata);
01822 }
01823
01824 static QofQueryPredData *
01825 date_copy_predicate (QofQueryPredData *pd)
01826 {
01827 query_date_t pdata = (query_date_t)pd;
01828
01829 VERIFY_PDATA_R (query_date_type);
01830
01831 return qof_query_date_predicate (pd->how, pdata->options, pdata->date);
01832 }
01833
01834 static gboolean
01835 date_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
01836 {
01837 query_date_t pd1 = (query_date_t) p1;
01838 query_date_t pd2 = (query_date_t) p2;
01839
01840 if (pd1->options != pd2->options) return FALSE;
01841 return timespec_equal (&(pd1->date), &(pd2->date));
01842 }
01843
01844 QofQueryPredData *
01845 qof_query_date_predicate (QofQueryCompare how,
01846 QofDateMatch options, Timespec date)
01847 {
01848 query_date_t pdata;
01849
01850 pdata = g_new0 (query_date_def, 1);
01851 pdata->pd.type_name = query_date_type;
01852 pdata->pd.how = how;
01853 pdata->options = options;
01854 pdata->date = date;
01855 return ((QofQueryPredData*)pdata);
01856 }
01857
01858 gboolean
01859 qof_query_date_predicate_get_date (QofQueryPredData *pd, Timespec *date)
01860 {
01861 query_date_t pdata = (query_date_t)pd;
01862
01863 if (pdata->pd.type_name != query_date_type)
01864 return FALSE;
01865 *date = pdata->date;
01866 return TRUE;
01867 }
01868
01869 static gchar *
01870 date_to_string (gpointer object, QofParam * getter)
01871 {
01872 Timespec ts =
01873 ((query_date_getter) getter->param_getfcn) (object, getter);
01874
01875 if (ts.tv_sec || ts.tv_nsec)
01876 return g_strdup (gnc_print_date (ts));
01877
01878 return NULL;
01879 }
01880
01881 #endif // QOF_DISABLE_DEPRECATED QOF_TYPE_DATE
01882
01883 static void
01884 init_tables (void)
01885 {
01886 guint i;
01887 struct
01888 {
01889 QofType name;
01890 QofQueryPredicateFunc pred;
01891 QofCompareFunc comp;
01892 QueryPredicateCopyFunc copy;
01893 QueryPredDataFree pd_free;
01894 QueryToString toString;
01895 QueryPredicateEqual pred_equal;
01896 } knownTypes[] =
01897 {
01898 {
01899 QOF_TYPE_STRING, string_match_predicate, string_compare_func,
01900 string_copy_predicate, string_free_pdata,
01901 string_to_string, string_predicate_equal},
01902 #ifndef QOF_DISABLE_DEPRECATED
01903 {
01904 QOF_TYPE_DATE, date_match_predicate, date_compare_func,
01905 date_copy_predicate, date_free_pdata, date_to_string,
01906 date_predicate_equal},
01907 #endif
01908 {
01909 QOF_TYPE_TIME, time_match_predicate, time_compare_func,
01910 time_copy_predicate, time_free_pdata, time_to_string,
01911 time_predicate_equal},
01912 {
01913 QOF_TYPE_DEBCRED, numeric_match_predicate,
01914 numeric_compare_func, numeric_copy_predicate,
01915 numeric_free_pdata, debcred_to_string,
01916 numeric_predicate_equal},
01917 {
01918 QOF_TYPE_NUMERIC, numeric_match_predicate,
01919 numeric_compare_func, numeric_copy_predicate,
01920 numeric_free_pdata, numeric_to_string,
01921 numeric_predicate_equal},
01922 {
01923 QOF_TYPE_GUID, guid_match_predicate, NULL,
01924 guid_copy_predicate, guid_free_pdata, NULL,
01925 guid_predicate_equal},
01926 {
01927 QOF_TYPE_INT32, int32_match_predicate, int32_compare_func,
01928 int32_copy_predicate, int32_free_pdata,
01929 int32_to_string, int32_predicate_equal},
01930 {
01931 QOF_TYPE_INT64, int64_match_predicate, int64_compare_func,
01932 int64_copy_predicate, int64_free_pdata,
01933 int64_to_string, int64_predicate_equal},
01934 {
01935 QOF_TYPE_DOUBLE, double_match_predicate, double_compare_func,
01936 double_copy_predicate, double_free_pdata,
01937 double_to_string, double_predicate_equal},
01938 {
01939 QOF_TYPE_BOOLEAN, boolean_match_predicate,
01940 boolean_compare_func, boolean_copy_predicate,
01941 boolean_free_pdata, boolean_to_string,
01942 boolean_predicate_equal},
01943 {
01944 QOF_TYPE_CHAR, char_match_predicate, char_compare_func,
01945 char_copy_predicate, char_free_pdata, char_to_string,
01946 char_predicate_equal},
01947 {
01948 QOF_TYPE_KVP, kvp_match_predicate, NULL, kvp_copy_predicate,
01949 kvp_free_pdata, NULL, kvp_predicate_equal},
01950 {
01951 QOF_TYPE_COLLECT, collect_match_predicate,
01952 collect_compare_func, collect_copy_predicate,
01953 collect_free_pdata, NULL, collect_predicate_equal},
01954 {
01955 QOF_TYPE_CHOICE, choice_match_predicate, NULL,
01956 choice_copy_predicate, choice_free_pdata, NULL,
01957 choice_predicate_equal},};
01958
01959
01960 for (i = 0; i < (sizeof (knownTypes) / sizeof (*knownTypes)); i++)
01961 {
01962 qof_query_register_core_object (knownTypes[i].name,
01963 knownTypes[i].pred,
01964 knownTypes[i].comp,
01965 knownTypes[i].copy,
01966 knownTypes[i].pd_free,
01967 knownTypes[i].toString, knownTypes[i].pred_equal);
01968 }
01969 }
01970
01971 static QueryPredicateCopyFunc
01972 qof_query_copy_predicate (QofType type)
01973 {
01974 QueryPredicateCopyFunc rc;
01975 g_return_val_if_fail (type, NULL);
01976 rc = g_hash_table_lookup (copyTable, type);
01977 return rc;
01978 }
01979
01980 static QueryPredDataFree
01981 qof_query_predicate_free (QofType type)
01982 {
01983 g_return_val_if_fail (type, NULL);
01984 return g_hash_table_lookup (freeTable, type);
01985 }
01986
01987
01988
01989
01990 void
01991 qof_query_core_init (void)
01992 {
01993
01994 if (initialized)
01995 return;
01996 initialized = TRUE;
01997
01998
01999 predTable = g_hash_table_new (g_str_hash, g_str_equal);
02000 cmpTable = g_hash_table_new (g_str_hash, g_str_equal);
02001 copyTable = g_hash_table_new (g_str_hash, g_str_equal);
02002 freeTable = g_hash_table_new (g_str_hash, g_str_equal);
02003 toStringTable = g_hash_table_new (g_str_hash, g_str_equal);
02004 predEqualTable = g_hash_table_new (g_str_hash, g_str_equal);
02005
02006 init_tables ();
02007 }
02008
02009 void
02010 qof_query_core_shutdown (void)
02011 {
02012 if (!initialized)
02013 return;
02014 initialized = FALSE;
02015
02016 g_hash_table_destroy (predTable);
02017 g_hash_table_destroy (cmpTable);
02018 g_hash_table_destroy (copyTable);
02019 g_hash_table_destroy (freeTable);
02020 g_hash_table_destroy (toStringTable);
02021 g_hash_table_destroy (predEqualTable);
02022 }
02023
02024 QofQueryPredicateFunc
02025 qof_query_core_get_predicate (QofType type)
02026 {
02027 g_return_val_if_fail (type, NULL);
02028 return g_hash_table_lookup (predTable, type);
02029 }
02030
02031 QofCompareFunc
02032 qof_query_core_get_compare (QofType type)
02033 {
02034 g_return_val_if_fail (type, NULL);
02035 return g_hash_table_lookup (cmpTable, type);
02036 }
02037
02038 void
02039 qof_query_core_predicate_free (QofQueryPredData * pdata)
02040 {
02041 QueryPredDataFree free_fcn;
02042
02043 g_return_if_fail (pdata);
02044 g_return_if_fail (pdata->type_name);
02045
02046 free_fcn = qof_query_predicate_free (pdata->type_name);
02047 free_fcn (pdata);
02048 }
02049
02050 QofQueryPredData *
02051 qof_query_core_predicate_copy (QofQueryPredData * pdata)
02052 {
02053 QueryPredicateCopyFunc copy;
02054
02055 g_return_val_if_fail (pdata, NULL);
02056 g_return_val_if_fail (pdata->type_name, NULL);
02057
02058 copy = qof_query_copy_predicate (pdata->type_name);
02059 return (copy (pdata));
02060 }
02061
02062 gchar *
02063 qof_query_core_to_string (QofType type, gpointer object,
02064 QofParam * getter)
02065 {
02066 QueryToString toString;
02067
02068 g_return_val_if_fail (type, NULL);
02069 g_return_val_if_fail (object, NULL);
02070 g_return_val_if_fail (getter, NULL);
02071
02072 toString = g_hash_table_lookup (toStringTable, type);
02073 g_return_val_if_fail (toString, NULL);
02074
02075 return toString (object, getter);
02076 }
02077
02078 gboolean
02079 qof_query_core_predicate_equal (QofQueryPredData * p1,
02080 QofQueryPredData * p2)
02081 {
02082 QueryPredicateEqual pred_equal;
02083
02084 if (p1 == p2)
02085 return TRUE;
02086 if (!p1 || !p2)
02087 return FALSE;
02088
02089 if (p1->how != p2->how)
02090 return FALSE;
02091 if (safe_strcmp (p1->type_name, p2->type_name))
02092 return FALSE;
02093
02094 pred_equal = g_hash_table_lookup (predEqualTable, p1->type_name);
02095 g_return_val_if_fail (pred_equal, FALSE);
02096
02097 return pred_equal (p1, p2);
02098 }