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 QofNumeric (*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 QofNumeric obj_val;
00411 gint 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 (qof_numeric_positive_p (obj_val))
00422 return 0;
00423 break;
00424 case QOF_NUMERIC_MATCH_DEBIT:
00425 if (qof_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 QofNumeric cmp_val = qof_numeric_create (1, 10000);
00437 compare =
00438 (qof_numeric_compare (qof_numeric_abs
00439 (qof_numeric_sub (qof_numeric_abs (obj_val),
00440 qof_numeric_abs (pdata->
00441 amount),
00442 100000, QOF_HOW_RND_ROUND)), cmp_val) < 0);
00443 }
00444 else
00445 compare =
00446 qof_numeric_compare (qof_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,
00470 gint options __attribute__ ((unused)), QofParam * getter)
00471 {
00472 QofNumeric 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 qof_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 qof_numeric_equal (pd1->amount, pd2->amount);
00509 }
00510
00511 QofQueryPredData *
00512 qof_query_numeric_predicate (QofQueryCompare how,
00513 QofNumericMatch options, QofNumeric 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 QofNumeric num;
00528 num = ((query_numeric_getter) getter->param_getfcn) (object, getter);
00529
00530 return qof_numeric_to_string (num);
00531 }
00532
00533 static char *
00534 debcred_to_string (gpointer object, QofParam * getter)
00535 {
00536 QofNumeric num;
00537 num = ((query_numeric_getter) getter->param_getfcn) (object, getter);
00538
00539 return qof_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,
00759 gint options __attribute__ ((unused)),
00760 QofParam * getter)
00761 {
00762 gint32 v1, v2;
00763 g_return_val_if_fail (a && b && getter
00764 && getter->param_getfcn, COMPARE_ERROR);
00765
00766 v1 = ((query_int32_getter) getter->param_getfcn) (a, getter);
00767 v2 = ((query_int32_getter) getter->param_getfcn) (b, getter);
00768
00769 if (v1 < v2)
00770 return -1;
00771 if (v1 > v2)
00772 return 1;
00773 return 0;
00774 }
00775
00776 static void
00777 int32_free_pdata (QofQueryPredData * pd)
00778 {
00779 query_int32_t pdata = (query_int32_t) pd;
00780 VERIFY_PDATA (query_int32_type);
00781 g_free (pdata);
00782 }
00783
00784 static QofQueryPredData *
00785 int32_copy_predicate (QofQueryPredData * pd)
00786 {
00787 query_int32_t pdata = (query_int32_t) pd;
00788 VERIFY_PDATA_R (query_int32_type);
00789 return qof_query_int32_predicate (pd->how, pdata->val);
00790 }
00791
00792 static gboolean
00793 int32_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00794 {
00795 query_int32_t pd1 = (query_int32_t) p1;
00796 query_int32_t pd2 = (query_int32_t) p2;
00797
00798 return (pd1->val == pd2->val);
00799 }
00800
00801 QofQueryPredData *
00802 qof_query_int32_predicate (QofQueryCompare how, gint32 val)
00803 {
00804 query_int32_t pdata = g_new0 (query_int32_def, 1);
00805 pdata->pd.type_name = query_int32_type;
00806 pdata->pd.how = how;
00807 pdata->val = val;
00808 return ((QofQueryPredData *) pdata);
00809 }
00810
00811 static char *
00812 int32_to_string (gpointer object, QofParam * getter)
00813 {
00814 gint32 num =
00815 ((query_int32_getter) getter->param_getfcn) (object, getter);
00816
00817 return g_strdup_printf ("%d", num);
00818 }
00819
00820
00821
00822
00823 static int
00824 int64_match_predicate (gpointer object, QofParam * getter,
00825 QofQueryPredData * pd)
00826 {
00827 gint64 val;
00828 query_int64_t pdata = (query_int64_t) pd;
00829
00830 VERIFY_PREDICATE (query_int64_type);
00831
00832 val = ((query_int64_getter) getter->param_getfcn) (object, getter);
00833
00834 switch (pd->how)
00835 {
00836 case QOF_COMPARE_LT:
00837 return (val < pdata->val);
00838 case QOF_COMPARE_LTE:
00839 return (val <= pdata->val);
00840 case QOF_COMPARE_EQUAL:
00841 return (val == pdata->val);
00842 case QOF_COMPARE_GT:
00843 return (val > pdata->val);
00844 case QOF_COMPARE_GTE:
00845 return (val >= pdata->val);
00846 case QOF_COMPARE_NEQ:
00847 return (val != pdata->val);
00848 default:
00849 PWARN ("bad match type: %d", pd->how);
00850 return 0;
00851 }
00852 }
00853
00854 static int
00855 int64_compare_func (gpointer a, gpointer b,
00856 gint options __attribute__ ((unused)), QofParam * getter)
00857 {
00858 gint64 v1, v2;
00859 g_return_val_if_fail (a && b && getter
00860 && getter->param_getfcn, COMPARE_ERROR);
00861
00862 v1 = ((query_int64_getter) getter->param_getfcn) (a, getter);
00863 v2 = ((query_int64_getter) getter->param_getfcn) (b, getter);
00864
00865 if (v1 < v2)
00866 return -1;
00867 if (v1 > v2)
00868 return 1;
00869 return 0;
00870 }
00871
00872 static void
00873 int64_free_pdata (QofQueryPredData * pd)
00874 {
00875 query_int64_t pdata = (query_int64_t) pd;
00876 VERIFY_PDATA (query_int64_type);
00877 g_free (pdata);
00878 }
00879
00880 static QofQueryPredData *
00881 int64_copy_predicate (QofQueryPredData * pd)
00882 {
00883 query_int64_t pdata = (query_int64_t) pd;
00884 VERIFY_PDATA_R (query_int64_type);
00885 return qof_query_int64_predicate (pd->how, pdata->val);
00886 }
00887
00888 static gboolean
00889 int64_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00890 {
00891 query_int64_t pd1 = (query_int64_t) p1;
00892 query_int64_t pd2 = (query_int64_t) p2;
00893
00894 return (pd1->val == pd2->val);
00895 }
00896
00897 QofQueryPredData *
00898 qof_query_int64_predicate (QofQueryCompare how, gint64 val)
00899 {
00900 query_int64_t pdata = g_new0 (query_int64_def, 1);
00901 pdata->pd.type_name = query_int64_type;
00902 pdata->pd.how = how;
00903 pdata->val = val;
00904 return ((QofQueryPredData *) pdata);
00905 }
00906
00907 static char *
00908 int64_to_string (gpointer object, QofParam * getter)
00909 {
00910 gint64 num =
00911 ((query_int64_getter) getter->param_getfcn) (object, getter);
00912
00913 return g_strdup_printf ("%" G_GINT64_FORMAT, num);
00914 }
00915
00916
00917
00918
00919 static int
00920 double_match_predicate (gpointer object, QofParam * getter,
00921 QofQueryPredData * pd)
00922 {
00923 double val;
00924 query_double_t pdata = (query_double_t) pd;
00925
00926 VERIFY_PREDICATE (query_double_type);
00927
00928 val = ((query_double_getter) getter->param_getfcn) (object, getter);
00929
00930 switch (pd->how)
00931 {
00932 case QOF_COMPARE_LT:
00933 return (val < pdata->val);
00934 case QOF_COMPARE_LTE:
00935 return (val <= pdata->val);
00936 case QOF_COMPARE_EQUAL:
00937 return (val == pdata->val);
00938 case QOF_COMPARE_GT:
00939 return (val > pdata->val);
00940 case QOF_COMPARE_GTE:
00941 return (val >= pdata->val);
00942 case QOF_COMPARE_NEQ:
00943 return (val != pdata->val);
00944 default:
00945 PWARN ("bad match type: %d", pd->how);
00946 return 0;
00947 }
00948 }
00949
00950 static int
00951 double_compare_func (gpointer a, gpointer b,
00952 gint options __attribute__ ((unused)), QofParam * getter)
00953 {
00954 double v1, v2;
00955 g_return_val_if_fail (a && b && getter
00956 && getter->param_getfcn, COMPARE_ERROR);
00957
00958 v1 = ((query_double_getter) getter->param_getfcn) (a, getter);
00959 v2 = ((query_double_getter) getter->param_getfcn) (b, getter);
00960
00961 if (v1 < v2)
00962 return -1;
00963 if (v1 > v2)
00964 return 1;
00965 return 0;
00966 }
00967
00968 static void
00969 double_free_pdata (QofQueryPredData * pd)
00970 {
00971 query_double_t pdata = (query_double_t) pd;
00972 VERIFY_PDATA (query_double_type);
00973 g_free (pdata);
00974 }
00975
00976 static QofQueryPredData *
00977 double_copy_predicate (QofQueryPredData * pd)
00978 {
00979 query_double_t pdata = (query_double_t) pd;
00980 VERIFY_PDATA_R (query_double_type);
00981 return qof_query_double_predicate (pd->how, pdata->val);
00982 }
00983
00984 static gboolean
00985 double_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
00986 {
00987 query_double_t pd1 = (query_double_t) p1;
00988 query_double_t pd2 = (query_double_t) p2;
00989
00990 return (pd1->val == pd2->val);
00991 }
00992
00993 QofQueryPredData *
00994 qof_query_double_predicate (QofQueryCompare how, double val)
00995 {
00996 query_double_t pdata = g_new0 (query_double_def, 1);
00997 pdata->pd.type_name = query_double_type;
00998 pdata->pd.how = how;
00999 pdata->val = val;
01000 return ((QofQueryPredData *) pdata);
01001 }
01002
01003 static char *
01004 double_to_string (gpointer object, QofParam * getter)
01005 {
01006 double num =
01007 ((query_double_getter) getter->param_getfcn) (object, getter);
01008
01009 return g_strdup_printf ("%f", num);
01010 }
01011
01012
01013
01014 static int
01015 boolean_match_predicate (gpointer object, QofParam * getter,
01016 QofQueryPredData * pd)
01017 {
01018 gboolean val;
01019 query_boolean_t pdata = (query_boolean_t) pd;
01020
01021 VERIFY_PREDICATE (query_boolean_type);
01022
01023 val = ((query_boolean_getter) getter->param_getfcn) (object, getter);
01024
01025 switch (pd->how)
01026 {
01027 case QOF_COMPARE_EQUAL:
01028 return (val == pdata->val);
01029 case QOF_COMPARE_NEQ:
01030 return (val != pdata->val);
01031 default:
01032 PWARN ("bad match type: %d", pd->how);
01033 return 0;
01034 }
01035 }
01036
01037 static int
01038 boolean_compare_func (gpointer a, gpointer b,
01039 gint options __attribute__ ((unused)), QofParam * getter)
01040 {
01041 gboolean va, vb;
01042 g_return_val_if_fail (a && b && getter
01043 && getter->param_getfcn, COMPARE_ERROR);
01044 va = ((query_boolean_getter) getter->param_getfcn) (a, getter);
01045 vb = ((query_boolean_getter) getter->param_getfcn) (b, getter);
01046 if (!va && vb)
01047 return -1;
01048 if (va && !vb)
01049 return 1;
01050 return 0;
01051 }
01052
01053 static void
01054 boolean_free_pdata (QofQueryPredData * pd)
01055 {
01056 query_boolean_t pdata = (query_boolean_t) pd;
01057 VERIFY_PDATA (query_boolean_type);
01058 g_free (pdata);
01059 }
01060
01061 static QofQueryPredData *
01062 boolean_copy_predicate (QofQueryPredData * pd)
01063 {
01064 query_boolean_t pdata = (query_boolean_t) pd;
01065 VERIFY_PDATA_R (query_boolean_type);
01066 return qof_query_boolean_predicate (pd->how, pdata->val);
01067 }
01068
01069 static gboolean
01070 boolean_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01071 {
01072 query_boolean_t pd1 = (query_boolean_t) p1;
01073 query_boolean_t pd2 = (query_boolean_t) p2;
01074
01075 return (pd1->val == pd2->val);
01076 }
01077
01078 QofQueryPredData *
01079 qof_query_boolean_predicate (QofQueryCompare how, gboolean val)
01080 {
01081 query_boolean_t pdata;
01082 g_return_val_if_fail (how == QOF_COMPARE_EQUAL
01083 || how == QOF_COMPARE_NEQ, NULL);
01084
01085 pdata = g_new0 (query_boolean_def, 1);
01086 pdata->pd.type_name = query_boolean_type;
01087 pdata->pd.how = how;
01088 pdata->val = val;
01089 return ((QofQueryPredData *) pdata);
01090 }
01091
01092 static char *
01093 boolean_to_string (gpointer object, QofParam * getter)
01094 {
01095 gboolean num =
01096 ((query_boolean_getter) getter->param_getfcn) (object, getter);
01097
01098 return g_strdup_printf ("%s", (num ? "X" : ""));
01099 }
01100
01101
01102
01103 static int
01104 char_match_predicate (gpointer object, QofParam * getter,
01105 QofQueryPredData * pd)
01106 {
01107 char c;
01108 query_char_t pdata = (query_char_t) pd;
01109
01110 VERIFY_PREDICATE (query_char_type);
01111
01112 c = ((query_char_getter) getter->param_getfcn) (object, getter);
01113
01114 switch (pdata->options)
01115 {
01116 case QOF_CHAR_MATCH_ANY:
01117 if (strchr (pdata->char_list, c))
01118 return 1;
01119 return 0;
01120 case QOF_CHAR_MATCH_NONE:
01121 if (!strchr (pdata->char_list, c))
01122 return 1;
01123 return 0;
01124 default:
01125 PWARN ("bad match type");
01126 return 0;
01127 }
01128 }
01129
01130 static int
01131 char_compare_func (gpointer a, gpointer b,
01132 gint options __attribute__ ((unused)), QofParam * getter)
01133 {
01134 char va, vb;
01135 g_return_val_if_fail (a && b && getter
01136 && getter->param_getfcn, COMPARE_ERROR);
01137 va = ((query_char_getter) getter->param_getfcn) (a, getter);
01138 vb = ((query_char_getter) getter->param_getfcn) (b, getter);
01139 return (va - vb);
01140 }
01141
01142 static void
01143 char_free_pdata (QofQueryPredData * pd)
01144 {
01145 query_char_t pdata = (query_char_t) pd;
01146 VERIFY_PDATA (query_char_type);
01147 g_free (pdata->char_list);
01148 g_free (pdata);
01149 }
01150
01151 static QofQueryPredData *
01152 char_copy_predicate (QofQueryPredData * pd)
01153 {
01154 query_char_t pdata = (query_char_t) pd;
01155 VERIFY_PDATA_R (query_char_type);
01156 return qof_query_char_predicate (pdata->options, pdata->char_list);
01157 }
01158
01159 static gboolean
01160 char_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01161 {
01162 query_char_t pd1 = (query_char_t) p1;
01163 query_char_t pd2 = (query_char_t) p2;
01164
01165 if (pd1->options != pd2->options)
01166 return FALSE;
01167 return (safe_strcmp (pd1->char_list, pd2->char_list) == 0);
01168 }
01169
01170 QofQueryPredData *
01171 qof_query_char_predicate (QofCharMatch options, const char *chars)
01172 {
01173 query_char_t pdata;
01174 g_return_val_if_fail (chars, NULL);
01175 pdata = g_new0 (query_char_def, 1);
01176 pdata->pd.type_name = query_char_type;
01177 pdata->pd.how = QOF_COMPARE_EQUAL;
01178 pdata->options = options;
01179 pdata->char_list = g_strdup (chars);
01180 return ((QofQueryPredData *) pdata);
01181 }
01182
01183 static char *
01184 char_to_string (gpointer object, QofParam * getter)
01185 {
01186 char num = ((query_char_getter) getter->param_getfcn) (object, getter);
01187
01188 return g_strdup_printf ("%c", num);
01189 }
01190
01191
01192
01193 static int
01194 kvp_match_predicate (gpointer object, QofParam * getter,
01195 QofQueryPredData * pd)
01196 {
01197 int compare;
01198 KvpFrame *kvp;
01199 KvpValue *value;
01200 query_kvp_t pdata = (query_kvp_t) pd;
01201
01202 VERIFY_PREDICATE (query_kvp_type);
01203
01204 kvp = ((query_kvp_getter) getter->param_getfcn) (object, getter);
01205 if (!kvp)
01206 return 0;
01207
01208 value = kvp_frame_get_slot_path_gslist (kvp, pdata->path);
01209 if (!value)
01210 return 0;
01211
01212 if (kvp_value_get_type (value) != kvp_value_get_type (pdata->value))
01213 return 0;
01214
01215 compare = kvp_value_compare (value, pdata->value);
01216
01217 switch (pd->how)
01218 {
01219 case QOF_COMPARE_LT:
01220 return (compare < 0);
01221 case QOF_COMPARE_LTE:
01222 return (compare <= 0);
01223 case QOF_COMPARE_EQUAL:
01224 return (compare == 0);
01225 case QOF_COMPARE_GTE:
01226 return (compare >= 0);
01227 case QOF_COMPARE_GT:
01228 return (compare > 0);
01229 case QOF_COMPARE_NEQ:
01230 return (compare != 0);
01231 default:
01232 PWARN ("bad match type: %d", pd->how);
01233 return 0;
01234 }
01235 }
01236
01237 static void
01238 kvp_free_pdata (QofQueryPredData * pd)
01239 {
01240 query_kvp_t pdata = (query_kvp_t) pd;
01241 GSList *node;
01242
01243 VERIFY_PDATA (query_kvp_type);
01244 kvp_value_delete (pdata->value);
01245 for (node = pdata->path; node; node = node->next)
01246 {
01247 g_free (node->data);
01248 node->data = NULL;
01249 }
01250 g_slist_free (pdata->path);
01251 g_free (pdata);
01252 }
01253
01254 static QofQueryPredData *
01255 kvp_copy_predicate (QofQueryPredData * pd)
01256 {
01257 query_kvp_t pdata = (query_kvp_t) pd;
01258 VERIFY_PDATA_R (query_kvp_type);
01259 return qof_query_kvp_predicate (pd->how, pdata->path, pdata->value);
01260 }
01261
01262 static gboolean
01263 kvp_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01264 {
01265 query_kvp_t pd1 = (query_kvp_t) p1;
01266 query_kvp_t pd2 = (query_kvp_t) p2;
01267 GSList *n1, *n2;
01268
01269 n1 = pd1->path;
01270 n2 = pd2->path;
01271
01272 for (; n1 && n2; n1 = n1->next, n2 = n2->next)
01273 {
01274 if (safe_strcmp (n1->data, n2->data) != 0)
01275 return FALSE;
01276 }
01277
01278 if (n1 || n2)
01279 return FALSE;
01280
01281 return (kvp_value_compare (pd1->value, pd2->value) == 0);
01282 }
01283
01284 QofQueryPredData *
01285 qof_query_kvp_predicate (QofQueryCompare how,
01286 GSList * path, const KvpValue * value)
01287 {
01288 query_kvp_t pdata;
01289 GSList *node;
01290
01291 g_return_val_if_fail (path && value, NULL);
01292
01293 pdata = g_new0 (query_kvp_def, 1);
01294 pdata->pd.type_name = query_kvp_type;
01295 pdata->pd.how = how;
01296 pdata->value = kvp_value_copy (value);
01297 pdata->path = g_slist_copy (path);
01298 for (node = pdata->path; node; node = node->next)
01299 node->data = g_strdup (node->data);
01300
01301 return ((QofQueryPredData *) pdata);
01302 }
01303
01304 QofQueryPredData *
01305 qof_query_kvp_predicate_path (QofQueryCompare how,
01306 const char *path, const KvpValue * value)
01307 {
01308 QofQueryPredData *pd;
01309 GSList *spath = NULL;
01310 char *str, *p;
01311
01312 if (!path)
01313 return NULL;
01314
01315 str = g_strdup (path);
01316 p = str;
01317 if (0 == *p)
01318 return NULL;
01319 if ('/' == *p)
01320 p++;
01321
01322 while (p)
01323 {
01324 spath = g_slist_append (spath, p);
01325 p = strchr (p, '/');
01326 if (p)
01327 {
01328 *p = 0;
01329 p++;
01330 }
01331 }
01332
01333 pd = qof_query_kvp_predicate (how, spath, value);
01334 g_free (str);
01335 return pd;
01336 }
01337
01338
01339
01340
01341 static int
01342 collect_match_predicate (gpointer object, QofParam * getter,
01343 QofQueryPredData * pd)
01344 {
01345 query_coll_t pdata;
01346 QofCollection *coll;
01347 GList *node, *node2, *o_list;
01348 const GUID *guid;
01349
01350 pdata = (query_coll_t) pd;
01351 VERIFY_PREDICATE (query_collect_type);
01352 coll = ((query_collect_getter) getter->param_getfcn) (object, getter);
01353 guid = NULL;
01354 switch (pdata->options)
01355 {
01356 case QOF_GUID_MATCH_ALL:
01357 {
01358 for (node = pdata->guids; node; node = node->next)
01359 {
01360 for (o_list = object; o_list; o_list = o_list->next)
01361 {
01362 guid = ((query_guid_getter) getter->param_getfcn)
01363 (o_list->data, getter);
01364 if (guid_equal (node->data, guid))
01365 {
01366 break;
01367 }
01368 }
01369 if (o_list == NULL)
01370 {
01371 break;
01372 }
01373 }
01374 break;
01375 }
01376 case QOF_GUID_MATCH_LIST_ANY:
01377 {
01378 o_list =
01379 ((query_glist_getter) getter->param_getfcn) (object,
01380 getter);
01381 for (node = o_list; node; node = node->next)
01382 {
01383 for (node2 = pdata->guids; node2; node2 = node2->next)
01384 {
01385 if (guid_equal (node->data, node2->data))
01386 {
01387 break;
01388 }
01389 }
01390 if (node2 != NULL)
01391 {
01392 break;
01393 }
01394 }
01395 g_list_free (o_list);
01396 break;
01397 }
01398 default:
01399 {
01400 guid =
01401 ((query_guid_getter) getter->param_getfcn) (object,
01402 getter);
01403 for (node = pdata->guids; node; node = node->next)
01404 {
01405 if (guid_equal (node->data, guid))
01406 {
01407 break;
01408 }
01409 }
01410 }
01411 switch (pdata->options)
01412 {
01413 case QOF_GUID_MATCH_ANY:
01414 case QOF_GUID_MATCH_LIST_ANY:
01415 {
01416 return (node != NULL);
01417 break;
01418 }
01419 case QOF_GUID_MATCH_NONE:
01420 case QOF_GUID_MATCH_ALL:
01421 {
01422 return (node == NULL);
01423 break;
01424 }
01425 case QOF_GUID_MATCH_NULL:
01426 {
01427 return (guid == NULL);
01428 break;
01429 }
01430 default:
01431 {
01432 PWARN ("bad match type");
01433 return 0;
01434 }
01435 }
01436 }
01437 return 0;
01438 }
01439
01440 static int
01441 collect_compare_func (gpointer a, gpointer b,
01442 gint options __attribute__ ((unused)),
01443 QofParam * getter)
01444 {
01445 gint result;
01446 QofCollection *c1, *c2;
01447
01448 c1 = ((query_collect_getter) getter->param_getfcn) (a, getter);
01449 c2 = ((query_collect_getter) getter->param_getfcn) (b, getter);
01450 result = qof_collection_compare (c1, c2);
01451 return result;
01452 }
01453
01454 static void
01455 collect_free_pdata (QofQueryPredData * pd)
01456 {
01457 query_coll_t pdata;
01458 GList *node;
01459
01460 node = NULL;
01461 pdata = (query_coll_t) pd;
01462 VERIFY_PDATA (query_collect_type);
01463 for (node = pdata->guids; node; node = node->next)
01464 {
01465 guid_free (node->data);
01466 }
01467 qof_collection_destroy (pdata->coll);
01468 g_list_free (pdata->guids);
01469 g_free (pdata);
01470 }
01471
01472 static QofQueryPredData *
01473 collect_copy_predicate (QofQueryPredData * pd)
01474 {
01475 query_coll_t pdata = (query_coll_t) pd;
01476
01477 VERIFY_PDATA_R (query_collect_type);
01478 return qof_query_collect_predicate (pdata->options, pdata->coll);
01479 }
01480
01481 static gboolean
01482 collect_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01483 {
01484 query_coll_t pd1;
01485 query_coll_t pd2;
01486 gint result;
01487
01488 pd1 = (query_coll_t) p1;
01489 pd2 = (query_coll_t) p2;
01490 result = qof_collection_compare (pd1->coll, pd2->coll);
01491 if (result == 0)
01492 {
01493 return TRUE;
01494 }
01495 return FALSE;
01496 }
01497
01498 static void
01499 query_collect_cb (QofEntity * ent, gpointer user_data)
01500 {
01501 query_coll_t pdata;
01502 GUID *guid;
01503
01504 guid = guid_malloc ();
01505 guid = (GUID *) qof_entity_get_guid (ent);
01506 pdata = (query_coll_t) user_data;
01507 pdata->guids = g_list_append (pdata->guids, guid);
01508 }
01509
01510 QofQueryPredData *
01511 qof_query_collect_predicate (QofGuidMatch options, QofCollection * coll)
01512 {
01513 query_coll_t pdata;
01514
01515 g_return_val_if_fail (coll, NULL);
01516 pdata = g_new0 (query_coll_def, 1);
01517 pdata->pd.type_name = query_collect_type;
01518 pdata->options = options;
01519 qof_collection_foreach (coll, query_collect_cb, pdata);
01520 if (NULL == pdata->guids)
01521 {
01522 return NULL;
01523 }
01524 return ((QofQueryPredData *) pdata);
01525 }
01526
01527
01528
01529 static int
01530 choice_match_predicate (gpointer object, QofParam * getter,
01531 QofQueryPredData * pd)
01532 {
01533 query_choice_t pdata = (query_choice_t) pd;
01534 GList *node, *o_list;
01535 const GUID *guid = NULL;
01536
01537 VERIFY_PREDICATE (query_choice_type);
01538
01539 switch (pdata->options)
01540 {
01541
01542 case QOF_GUID_MATCH_ALL:
01543
01544
01545
01546
01547
01548 for (node = pdata->guids; node; node = node->next)
01549 {
01550
01551 for (o_list = object; o_list; o_list = o_list->next)
01552 {
01553 guid =
01554 ((query_choice_getter) getter->param_getfcn) (o_list->
01555 data, getter);
01556 if (guid_equal (node->data, guid))
01557 break;
01558 }
01559
01560
01561
01562
01563
01564 if (o_list == NULL)
01565 break;
01566 }
01567
01568
01569
01570
01571
01572
01573
01574 break;
01575
01576 case QOF_GUID_MATCH_LIST_ANY:
01577
01578 o_list =
01579 ((query_glist_getter) getter->param_getfcn) (object, getter);
01580
01581 for (node = o_list; node; node = node->next)
01582 {
01583 GList *node2;
01584
01585 for (node2 = pdata->guids; node2; node2 = node2->next)
01586 {
01587 if (guid_equal (node->data, node2->data))
01588 break;
01589 }
01590
01591 if (node2 != NULL)
01592 break;
01593 }
01594
01595 g_list_free (o_list);
01596
01597 break;
01598
01599 default:
01600
01601
01602
01603
01604
01605 guid =
01606 ((query_choice_getter) getter->param_getfcn) (object, getter);
01607 for (node = pdata->guids; node; node = node->next)
01608 {
01609 if (guid_equal (node->data, guid))
01610 break;
01611 }
01612 }
01613
01614 switch (pdata->options)
01615 {
01616 case QOF_GUID_MATCH_ANY:
01617 case QOF_GUID_MATCH_LIST_ANY:
01618 return (node != NULL);
01619 break;
01620 case QOF_GUID_MATCH_NONE:
01621 case QOF_GUID_MATCH_ALL:
01622 return (node == NULL);
01623 break;
01624 case QOF_GUID_MATCH_NULL:
01625 return (guid == NULL);
01626 break;
01627 default:
01628 PWARN ("bad match type");
01629 return 0;
01630 }
01631 }
01632
01633 static void
01634 choice_free_pdata (QofQueryPredData * pd)
01635 {
01636 query_choice_t pdata = (query_choice_t) pd;
01637 GList *node;
01638 VERIFY_PDATA (query_choice_type);
01639 for (node = pdata->guids; node; node = node->next)
01640 {
01641 guid_free (node->data);
01642 }
01643 g_list_free (pdata->guids);
01644 g_free (pdata);
01645 }
01646
01647 static QofQueryPredData *
01648 choice_copy_predicate (QofQueryPredData * pd)
01649 {
01650 query_choice_t pdata = (query_choice_t) pd;
01651 VERIFY_PDATA_R (query_choice_type);
01652 return qof_query_choice_predicate (pdata->options, pdata->guids);
01653 }
01654
01655 static gboolean
01656 choice_predicate_equal (QofQueryPredData * p1, QofQueryPredData * p2)
01657 {
01658 query_choice_t pd1 = (query_choice_t) p1;
01659 query_choice_t pd2 = (query_choice_t) p2;
01660 GList *l1 = pd1->guids, *l2 = pd2->guids;
01661
01662 if (pd1->options != pd2->options)
01663 return FALSE;
01664 if (g_list_length (l1) != g_list_length (l2))
01665 return FALSE;
01666 for (; l1; l1 = l1->next, l2 = l2->next)
01667 {
01668 if (!guid_equal (l1->data, l2->data))
01669 return FALSE;
01670 }
01671 return TRUE;
01672 }
01673
01674 QofQueryPredData *
01675 qof_query_choice_predicate (QofGuidMatch options, GList * guid_list)
01676 {
01677 query_choice_t pdata;
01678 GList *node;
01679
01680 if (NULL == guid_list)
01681 return NULL;
01682
01683 pdata = g_new0 (query_choice_def, 1);
01684 pdata->pd.how = QOF_COMPARE_EQUAL;
01685 pdata->pd.type_name = query_choice_type;
01686 pdata->options = options;
01687
01688 pdata->guids = g_list_copy (guid_list);
01689 for (node = pdata->guids; node; node = node->next)
01690 {
01691 GUID *guid = guid_malloc ();
01692 *guid = *((GUID *) node->data);
01693 node->data = guid;
01694 }
01695 return ((QofQueryPredData *) pdata);
01696 }
01697
01698
01699
01711 static void
01712 qof_query_register_core_object (QofType core_name,
01713 QofQueryPredicateFunc pred,
01714 QofCompareFunc comp,
01715 QueryPredicateCopyFunc copy,
01716 QueryPredDataFree pd_free,
01717 QueryToString toString, QueryPredicateEqual pred_equal)
01718 {
01719 g_return_if_fail (core_name);
01720 g_return_if_fail (*core_name != '\0');
01721
01722 if (pred)
01723 g_hash_table_insert (predTable, (char *) core_name, pred);
01724
01725 if (comp)
01726 g_hash_table_insert (cmpTable, (char *) core_name, comp);
01727
01728 if (copy)
01729 g_hash_table_insert (copyTable, (char *) core_name, copy);
01730
01731 if (pd_free)
01732 g_hash_table_insert (freeTable, (char *) core_name, pd_free);
01733
01734 if (toString)
01735 g_hash_table_insert (toStringTable, (char *) core_name, toString);
01736
01737 if (pred_equal)
01738 g_hash_table_insert (predEqualTable, (char *) core_name,
01739 pred_equal);
01740 }
01741
01742
01743 #ifndef QOF_DISABLE_DEPRECATED
01744
01745 typedef Timespec (*query_date_getter) (gpointer, QofParam *);
01746 static const gchar *query_date_type = QOF_TYPE_DATE;
01747
01748 static gint
01749 date_compare (Timespec ta, Timespec tb, QofDateMatch options)
01750 {
01751
01752 if (options == QOF_DATE_MATCH_DAY)
01753 {
01754 ta = timespecCanonicalDayTime (ta);
01755 tb = timespecCanonicalDayTime (tb);
01756 }
01757
01758 if (ta.tv_sec < tb.tv_sec)
01759 return -1;
01760 if (ta.tv_sec > tb.tv_sec)
01761 return 1;
01762
01763 if (ta.tv_nsec < tb.tv_nsec)
01764 return -1;
01765 if (ta.tv_nsec > tb.tv_nsec)
01766 return 1;
01767
01768 return 0;
01769 }
01770
01771 static int
01772 date_match_predicate (gpointer object, QofParam *getter,
01773 QofQueryPredData *pd)
01774 {
01775 query_date_t pdata = (query_date_t)pd;
01776 Timespec objtime;
01777 int compare;
01778
01779 VERIFY_PREDICATE (query_date_type);
01780
01781 objtime = ((query_date_getter)getter->param_getfcn) (object, getter);
01782 compare = date_compare (objtime, pdata->date, pdata->options);
01783
01784 switch (pd->how) {
01785 case QOF_COMPARE_LT:
01786 return (compare < 0);
01787 case QOF_COMPARE_LTE:
01788 return (compare <= 0);
01789 case QOF_COMPARE_EQUAL:
01790 return (compare == 0);
01791 case QOF_COMPARE_GT:
01792 return (compare > 0);
01793 case QOF_COMPARE_GTE:
01794 return (compare >= 0);
01795 case QOF_COMPARE_NEQ:
01796 return (compare != 0);
01797 default:
01798 PWARN ("bad match type: %d", pd->how);
01799 return 0;
01800 }
01801 }
01802
01803 static gint
01804 date_compare_func (gpointer a, gpointer b, gint options, QofParam * getter)
01805 {
01806 Timespec ta, tb;
01807
01808 g_return_val_if_fail (a && b && getter
01809 && getter->param_getfcn, COMPARE_ERROR);
01810
01811 ta = ((query_date_getter) getter->param_getfcn) (a, getter);
01812 tb = ((query_date_getter) getter->param_getfcn) (b, getter);
01813
01814 return date_compare (ta, tb, options);
01815 }
01816
01817 static void
01818 date_free_pdata (QofQueryPredData * pd)
01819 {
01820 query_date_t pdata = (query_date_t) pd;
01821
01822 VERIFY_PDATA (query_date_type);
01823
01824 g_free (pdata);
01825 }
01826
01827 static QofQueryPredData *
01828 date_copy_predicate (QofQueryPredData *pd)
01829 {
01830 query_date_t pdata = (query_date_t)pd;
01831
01832 VERIFY_PDATA_R (query_date_type);
01833
01834 return qof_query_date_predicate (pd->how, pdata->options, pdata->date);
01835 }
01836
01837 static gboolean
01838 date_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
01839 {
01840 query_date_t pd1 = (query_date_t) p1;
01841 query_date_t pd2 = (query_date_t) p2;
01842
01843 if (pd1->options != pd2->options) return FALSE;
01844 return timespec_equal (&(pd1->date), &(pd2->date));
01845 }
01846
01847 QofQueryPredData *
01848 qof_query_date_predicate (QofQueryCompare how,
01849 QofDateMatch options, Timespec date)
01850 {
01851 query_date_t pdata;
01852
01853 pdata = g_new0 (query_date_def, 1);
01854 pdata->pd.type_name = query_date_type;
01855 pdata->pd.how = how;
01856 pdata->options = options;
01857 pdata->date = date;
01858 return ((QofQueryPredData*)pdata);
01859 }
01860
01861 gboolean
01862 qof_query_date_predicate_get_date (QofQueryPredData *pd, Timespec *date)
01863 {
01864 query_date_t pdata = (query_date_t)pd;
01865
01866 if (pdata->pd.type_name != query_date_type)
01867 return FALSE;
01868 *date = pdata->date;
01869 return TRUE;
01870 }
01871
01872 static gchar *
01873 date_to_string (gpointer object, QofParam * getter)
01874 {
01875 Timespec ts =
01876 ((query_date_getter) getter->param_getfcn) (object, getter);
01877
01878 if (ts.tv_sec || ts.tv_nsec)
01879 return g_strdup (gnc_print_date (ts));
01880
01881 return NULL;
01882 }
01883
01884 #endif // QOF_DISABLE_DEPRECATED QOF_TYPE_DATE
01885
01886 static void
01887 init_tables (void)
01888 {
01889 guint i;
01890 struct
01891 {
01892 QofType name;
01893 QofQueryPredicateFunc pred;
01894 QofCompareFunc comp;
01895 QueryPredicateCopyFunc copy;
01896 QueryPredDataFree pd_free;
01897 QueryToString toString;
01898 QueryPredicateEqual pred_equal;
01899 } knownTypes[] =
01900 {
01901 {
01902 QOF_TYPE_STRING, string_match_predicate, string_compare_func,
01903 string_copy_predicate, string_free_pdata,
01904 string_to_string, string_predicate_equal},
01905 #ifndef QOF_DISABLE_DEPRECATED
01906 {
01907 QOF_TYPE_DATE, date_match_predicate, date_compare_func,
01908 date_copy_predicate, date_free_pdata, date_to_string,
01909 date_predicate_equal},
01910 #endif
01911 {
01912 QOF_TYPE_TIME, time_match_predicate, time_compare_func,
01913 time_copy_predicate, time_free_pdata, time_to_string,
01914 time_predicate_equal},
01915 {
01916 QOF_TYPE_DEBCRED, numeric_match_predicate,
01917 numeric_compare_func, numeric_copy_predicate,
01918 numeric_free_pdata, debcred_to_string,
01919 numeric_predicate_equal},
01920 {
01921 QOF_TYPE_NUMERIC, numeric_match_predicate,
01922 numeric_compare_func, numeric_copy_predicate,
01923 numeric_free_pdata, numeric_to_string,
01924 numeric_predicate_equal},
01925 {
01926 QOF_TYPE_GUID, guid_match_predicate, NULL,
01927 guid_copy_predicate, guid_free_pdata, NULL,
01928 guid_predicate_equal},
01929 {
01930 QOF_TYPE_INT32, int32_match_predicate, int32_compare_func,
01931 int32_copy_predicate, int32_free_pdata,
01932 int32_to_string, int32_predicate_equal},
01933 {
01934 QOF_TYPE_INT64, int64_match_predicate, int64_compare_func,
01935 int64_copy_predicate, int64_free_pdata,
01936 int64_to_string, int64_predicate_equal},
01937 {
01938 QOF_TYPE_DOUBLE, double_match_predicate, double_compare_func,
01939 double_copy_predicate, double_free_pdata,
01940 double_to_string, double_predicate_equal},
01941 {
01942 QOF_TYPE_BOOLEAN, boolean_match_predicate,
01943 boolean_compare_func, boolean_copy_predicate,
01944 boolean_free_pdata, boolean_to_string,
01945 boolean_predicate_equal},
01946 {
01947 QOF_TYPE_CHAR, char_match_predicate, char_compare_func,
01948 char_copy_predicate, char_free_pdata, char_to_string,
01949 char_predicate_equal},
01950 {
01951 QOF_TYPE_KVP, kvp_match_predicate, NULL, kvp_copy_predicate,
01952 kvp_free_pdata, NULL, kvp_predicate_equal},
01953 {
01954 QOF_TYPE_COLLECT, collect_match_predicate,
01955 collect_compare_func, collect_copy_predicate,
01956 collect_free_pdata, NULL, collect_predicate_equal},
01957 {
01958 QOF_TYPE_CHOICE, choice_match_predicate, NULL,
01959 choice_copy_predicate, choice_free_pdata, NULL,
01960 choice_predicate_equal},};
01961
01962
01963 for (i = 0; i < (sizeof (knownTypes) / sizeof (*knownTypes)); i++)
01964 {
01965 qof_query_register_core_object (knownTypes[i].name,
01966 knownTypes[i].pred,
01967 knownTypes[i].comp,
01968 knownTypes[i].copy,
01969 knownTypes[i].pd_free,
01970 knownTypes[i].toString, knownTypes[i].pred_equal);
01971 }
01972 }
01973
01974 static QueryPredicateCopyFunc
01975 qof_query_copy_predicate (QofType type)
01976 {
01977 QueryPredicateCopyFunc rc;
01978 g_return_val_if_fail (type, NULL);
01979 rc = g_hash_table_lookup (copyTable, type);
01980 return rc;
01981 }
01982
01983 static QueryPredDataFree
01984 qof_query_predicate_free (QofType type)
01985 {
01986 g_return_val_if_fail (type, NULL);
01987 return g_hash_table_lookup (freeTable, type);
01988 }
01989
01990
01991
01992
01993 void
01994 qof_query_core_init (void)
01995 {
01996
01997 if (initialized)
01998 return;
01999 initialized = TRUE;
02000
02001
02002 predTable = g_hash_table_new (g_str_hash, g_str_equal);
02003 cmpTable = g_hash_table_new (g_str_hash, g_str_equal);
02004 copyTable = g_hash_table_new (g_str_hash, g_str_equal);
02005 freeTable = g_hash_table_new (g_str_hash, g_str_equal);
02006 toStringTable = g_hash_table_new (g_str_hash, g_str_equal);
02007 predEqualTable = g_hash_table_new (g_str_hash, g_str_equal);
02008
02009 init_tables ();
02010 }
02011
02012 void
02013 qof_query_core_shutdown (void)
02014 {
02015 if (!initialized)
02016 return;
02017 initialized = FALSE;
02018
02019 g_hash_table_destroy (predTable);
02020 g_hash_table_destroy (cmpTable);
02021 g_hash_table_destroy (copyTable);
02022 g_hash_table_destroy (freeTable);
02023 g_hash_table_destroy (toStringTable);
02024 g_hash_table_destroy (predEqualTable);
02025 }
02026
02027 QofQueryPredicateFunc
02028 qof_query_core_get_predicate (QofType type)
02029 {
02030 g_return_val_if_fail (type, NULL);
02031 return g_hash_table_lookup (predTable, type);
02032 }
02033
02034 QofCompareFunc
02035 qof_query_core_get_compare (QofType type)
02036 {
02037 g_return_val_if_fail (type, NULL);
02038 return g_hash_table_lookup (cmpTable, type);
02039 }
02040
02041 void
02042 qof_query_core_predicate_free (QofQueryPredData * pdata)
02043 {
02044 QueryPredDataFree free_fcn;
02045
02046 g_return_if_fail (pdata);
02047 g_return_if_fail (pdata->type_name);
02048
02049 free_fcn = qof_query_predicate_free (pdata->type_name);
02050 free_fcn (pdata);
02051 }
02052
02053 QofQueryPredData *
02054 qof_query_core_predicate_copy (QofQueryPredData * pdata)
02055 {
02056 QueryPredicateCopyFunc copy;
02057
02058 g_return_val_if_fail (pdata, NULL);
02059 g_return_val_if_fail (pdata->type_name, NULL);
02060
02061 copy = qof_query_copy_predicate (pdata->type_name);
02062 return (copy (pdata));
02063 }
02064
02065 gchar *
02066 qof_query_core_to_string (QofType type, gpointer object,
02067 QofParam * getter)
02068 {
02069 QueryToString toString;
02070
02071 g_return_val_if_fail (type, NULL);
02072 g_return_val_if_fail (object, NULL);
02073 g_return_val_if_fail (getter, NULL);
02074
02075 toString = g_hash_table_lookup (toStringTable, type);
02076 g_return_val_if_fail (toString, NULL);
02077
02078 return toString (object, getter);
02079 }
02080
02081 gboolean
02082 qof_query_core_predicate_equal (QofQueryPredData * p1,
02083 QofQueryPredData * p2)
02084 {
02085 QueryPredicateEqual pred_equal;
02086
02087 if (p1 == p2)
02088 return TRUE;
02089 if (!p1 || !p2)
02090 return FALSE;
02091
02092 if (p1->how != p2->how)
02093 return FALSE;
02094 if (safe_strcmp (p1->type_name, p2->type_name))
02095 return FALSE;
02096
02097 pred_equal = g_hash_table_lookup (predEqualTable, p1->type_name);
02098 g_return_val_if_fail (pred_equal, FALSE);
02099
02100 return pred_equal (p1, p2);
02101 }