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