32 #include "qofquerycore-p.h" 34 static QofLogModule log_module = QOF_MOD_QUERY;
37 typedef void (*QueryPredDataFree) (QofQueryPredData *pdata);
40 typedef QofQueryPredData *(*QueryPredicateCopyFunc) (
const QofQueryPredData *pdata);
48 typedef char * (*QueryToString) (gpointer object, QofParam *getter);
51 typedef gboolean (*QueryPredicateEqual) (
const QofQueryPredData *p1,
52 const QofQueryPredData *p2);
54 static QueryPredicateCopyFunc qof_query_copy_predicate (
QofType type);
55 static QueryPredDataFree qof_query_predicate_free (
QofType type);
58 typedef const char * (*query_string_getter) (gpointer, QofParam *);
59 static const char * query_string_type = QOF_TYPE_STRING;
61 typedef time64 (*query_date_getter) (gpointer, QofParam *);
62 static const char * query_date_type = QOF_TYPE_DATE;
64 typedef gnc_numeric (*query_numeric_getter) (gpointer, QofParam *);
65 static const char * query_numeric_type = QOF_TYPE_NUMERIC;
67 typedef GList * (*query_glist_getter) (gpointer, QofParam *);
68 typedef const GncGUID * (*query_guid_getter) (gpointer, QofParam *);
69 static const char * query_guid_type = QOF_TYPE_GUID;
71 typedef gint32 (*query_int32_getter) (gpointer, QofParam *);
72 static const char * query_int32_type = QOF_TYPE_INT32;
74 typedef gint64 (*query_int64_getter) (gpointer, QofParam *);
75 static const char * query_int64_type = QOF_TYPE_INT64;
77 typedef double (*query_double_getter) (gpointer, QofParam *);
78 static const char * query_double_type = QOF_TYPE_DOUBLE;
80 typedef gboolean (*query_boolean_getter) (gpointer, QofParam *);
81 static const char * query_boolean_type = QOF_TYPE_BOOLEAN;
83 typedef char (*query_char_getter) (gpointer, QofParam *);
84 static const char * query_char_type = QOF_TYPE_CHAR;
86 typedef const GncGUID * (*query_choice_getter) (gpointer, QofParam *);
87 static const char * query_choice_type = QOF_TYPE_CHOICE;
90 static gboolean initialized = FALSE;
91 static GHashTable *predTable =
nullptr;
92 static GHashTable *cmpTable =
nullptr;
93 static GHashTable *copyTable =
nullptr;
94 static GHashTable *freeTable =
nullptr;
95 static GHashTable *toStringTable =
nullptr;
96 static GHashTable *predEqualTable =
nullptr;
98 #define COMPARE_ERROR -3 99 #define PREDICATE_ERROR -2 101 #define VERIFY_PDATA(str) { \ 102 g_return_if_fail (pd != nullptr); \ 103 g_return_if_fail (pd->type_name == str || \ 104 !g_strcmp0 (str, pd->type_name)); \ 106 #define VERIFY_PDATA_R(str) { \ 107 g_return_val_if_fail (pd != nullptr, nullptr); \ 108 g_return_val_if_fail (pd->type_name == str || \ 109 !g_strcmp0 (str, pd->type_name), \ 112 #define VERIFY_PREDICATE(str) { \ 113 g_return_val_if_fail (getter != nullptr, PREDICATE_ERROR); \ 114 g_return_val_if_fail (getter->param_getfcn != nullptr, PREDICATE_ERROR); \ 115 g_return_val_if_fail (pd != nullptr, PREDICATE_ERROR); \ 116 g_return_val_if_fail (pd->type_name == str || \ 117 !g_strcmp0 (str, pd->type_name), \ 127 string_match_predicate (gpointer
object,
129 QofQueryPredData *pd)
135 VERIFY_PREDICATE (query_string_type);
137 s = ((query_string_getter)getter->param_getfcn) (object, getter);
144 if (!regexec (&pdata->compiled, s, 1, &match, 0))
149 if (pdata->options == QOF_STRING_MATCH_CASEINSENSITIVE)
151 if (pd->how == QOF_COMPARE_CONTAINS || pd->how == QOF_COMPARE_NCONTAINS)
164 if (pd->how == QOF_COMPARE_CONTAINS || pd->how == QOF_COMPARE_NCONTAINS)
166 if (strstr (s, pdata->matchstring))
171 if (g_strcmp0 (s, pdata->matchstring) == 0)
179 case QOF_COMPARE_CONTAINS:
181 case QOF_COMPARE_NCONTAINS:
183 case QOF_COMPARE_EQUAL:
185 case QOF_COMPARE_NEQ:
188 PWARN (
"bad match type: %d", pd->how);
194 string_compare_func (gpointer a, gpointer b, gint options,
198 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
200 s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
201 s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
203 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
206 return g_strcmp0 (s1, s2);
210 natural_compare_func (gpointer a, gpointer b, gint options,
214 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
216 s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
217 s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
219 if (options == QOF_STRING_MATCH_CASEINSENSITIVE) {
241 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
243 s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
244 s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
247 if (s1 == s2)
return 0;
248 if (!s1 && s2)
return -1;
249 if (s1 && !s2)
return 1;
252 i1 = strtol(s1, &sr1, 10);
253 i2 = strtol(s2, &sr2, 10);
254 if (i1 < i2)
return -1;
255 if (i1 > i2)
return 1;
258 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
261 return g_strcmp0 (sr1, sr2);
265 string_free_pdata (QofQueryPredData *pd)
269 VERIFY_PDATA (query_string_type);
272 regfree (&pdata->compiled);
274 g_free (pdata->matchstring);
278 static QofQueryPredData *
279 string_copy_predicate (
const QofQueryPredData *pd)
283 VERIFY_PDATA_R (query_string_type);
285 return qof_query_string_predicate (pd->how, pdata->matchstring,
291 string_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
296 if (pd1->options != pd2->options)
return FALSE;
297 if (pd1->is_regex != pd2->is_regex)
return FALSE;
298 return (g_strcmp0 (pd1->matchstring, pd2->matchstring) == 0);
308 g_return_val_if_fail (str,
nullptr);
310 g_return_val_if_fail (how == QOF_COMPARE_CONTAINS || how == QOF_COMPARE_NCONTAINS ||
311 how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ,
nullptr);
314 pdata->pd.type_name = query_string_type;
316 pdata->options = options;
317 pdata->matchstring = g_strdup (str);
322 int flags = REG_EXTENDED;
323 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
326 rc = regcomp(&pdata->compiled, str, flags);
329 g_free(pdata->matchstring);
333 pdata->is_regex = TRUE;
336 return ((QofQueryPredData*)pdata);
340 string_to_string (gpointer
object, QofParam *getter)
343 res = ((query_string_getter)getter->param_getfcn)(object, getter);
345 return g_strdup (res);
355 if (options == QOF_DATE_MATCH_DAY)
370 date_match_predicate (gpointer
object, QofParam *getter,
371 QofQueryPredData *pd)
377 VERIFY_PREDICATE (query_date_type);
379 objtime = ((query_date_getter)getter->param_getfcn) (object, getter);
380 compare = date_compare (objtime, pdata->date, pdata->options);
385 return (compare < 0);
386 case QOF_COMPARE_LTE:
387 return (compare <= 0);
388 case QOF_COMPARE_EQUAL:
389 return (compare == 0);
391 return (compare > 0);
392 case QOF_COMPARE_GTE:
393 return (compare >= 0);
394 case QOF_COMPARE_NEQ:
395 return (compare != 0);
397 PWARN (
"bad match type: %d", pd->how);
403 date_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
407 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
409 ta = ((query_date_getter)getter->param_getfcn) (a, getter);
410 tb = ((query_date_getter)getter->param_getfcn) (b, getter);
412 return date_compare (ta, tb, static_cast<QofDateMatch>(options));
416 date_free_pdata (QofQueryPredData *pd)
420 VERIFY_PDATA (query_date_type);
425 static QofQueryPredData *
426 date_copy_predicate (
const QofQueryPredData *pd)
430 VERIFY_PDATA_R (query_date_type);
432 return qof_query_date_predicate (pd->how, pdata->options, pdata->date);
436 date_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
441 if (pd1->options != pd2->options)
return FALSE;
442 return (pd1->date == pd2->date);
452 pdata->pd.type_name = query_date_type;
454 pdata->options = options;
456 return ((QofQueryPredData*)pdata);
464 if (pdata->pd.type_name != query_date_type)
471 date_to_string (gpointer
object, QofParam *getter)
473 time64 tt = ((query_date_getter)getter->param_getfcn)(object, getter);
484 numeric_match_predicate (gpointer
object, QofParam *getter,
485 QofQueryPredData* pd)
491 VERIFY_PREDICATE (query_numeric_type);
493 obj_val = ((query_numeric_getter)getter->param_getfcn) (object, getter);
495 switch (pdata->options)
497 case QOF_NUMERIC_MATCH_CREDIT:
500 case QOF_NUMERIC_MATCH_DEBIT:
509 if (pd->how == QOF_COMPARE_EQUAL || pd->how == QOF_COMPARE_NEQ)
511 gnc_numeric cmp_val = gnc_numeric_create (1, 10000);
525 return (compare < 0);
526 case QOF_COMPARE_LTE:
527 return (compare <= 0);
528 case QOF_COMPARE_EQUAL:
531 return (compare > 0);
532 case QOF_COMPARE_GTE:
533 return (compare >= 0);
534 case QOF_COMPARE_NEQ:
537 PWARN (
"bad match type: %d", pd->how);
543 numeric_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
547 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
549 va = ((query_numeric_getter)getter->param_getfcn) (a, getter);
550 vb = ((query_numeric_getter)getter->param_getfcn) (b, getter);
556 numeric_free_pdata (QofQueryPredData* pd)
559 VERIFY_PDATA (query_numeric_type);
563 static QofQueryPredData *
564 numeric_copy_predicate (
const QofQueryPredData *pd)
567 VERIFY_PDATA_R (query_numeric_type);
568 return qof_query_numeric_predicate (pd->how, pdata->options, pdata->amount);
572 numeric_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
577 if (pd1->options != pd2->options)
return FALSE;
588 pdata->pd.type_name = query_numeric_type;
590 pdata->options = options;
591 pdata->amount = value;
592 return ((QofQueryPredData*)pdata);
596 numeric_to_string (gpointer
object, QofParam *getter)
599 num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
605 debcred_to_string (gpointer
object, QofParam *getter)
608 num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
616 guid_match_predicate (gpointer
object, QofParam *getter,
617 QofQueryPredData *pd)
620 GList *node, *o_list;
623 VERIFY_PREDICATE (query_guid_type);
625 switch (pdata->options)
634 for (node = pdata->guids; node; node = node->next)
637 for (o_list = static_cast<GList*>(
object); o_list;
638 o_list =
static_cast<GList*
>(o_list->next))
640 guid = ((query_guid_getter)getter->param_getfcn) (o_list->data, getter);
641 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
649 if (o_list ==
nullptr)
668 o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
670 for (node = o_list; node; node = node->next)
675 for (node2 = pdata->guids; node2; node2 = node2->next)
677 if (
guid_equal (static_cast<GncGUID*>(node->data),
678 static_cast<GncGUID*
>(node2->data)))
683 if (node2 !=
nullptr)
701 guid = ((query_guid_getter)getter->param_getfcn) (object, getter);
702 for (node = pdata->guids; node; node = node->next)
704 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
709 switch (pdata->options)
713 return (node !=
nullptr);
715 case QOF_GUID_MATCH_NONE:
717 return (node ==
nullptr);
719 case QOF_GUID_MATCH_NULL:
723 PWARN (
"bad match type");
729 guid_free_pdata (QofQueryPredData *pd)
733 VERIFY_PDATA (query_guid_type);
734 for (node = pdata->guids; node; node = node->next)
736 guid_free (static_cast<GncGUID*>(node->data));
738 g_list_free (pdata->guids);
742 static QofQueryPredData *
743 guid_copy_predicate (
const QofQueryPredData *pd)
746 VERIFY_PDATA_R (query_guid_type);
747 return qof_query_guid_predicate (pdata->options, pdata->guids);
751 guid_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
755 GList *l1 = pd1->guids, *l2 = pd2->guids;
757 if (pd1->options != pd2->options)
return FALSE;
758 for (; l1 || l2; l1 = l1->next, l2 = l2->next)
762 if (!
guid_equal (static_cast<GncGUID*>(l1->data),
763 static_cast<GncGUID*
>(l2->data)))
770 qof_query_guid_predicate (
QofGuidMatch options, GList *guid_list)
777 g_return_val_if_fail (options == QOF_GUID_MATCH_NULL,
nullptr);
780 pdata->pd.how = QOF_COMPARE_EQUAL;
781 pdata->pd.type_name = query_guid_type;
782 pdata->options = options;
784 pdata->guids = g_list_copy (guid_list);
785 for (node = pdata->guids; node; node = node->next)
788 *guid = *((
GncGUID *)node->data);
791 return ((QofQueryPredData*)pdata);
798 int32_match_predicate (gpointer
object, QofParam *getter,
799 QofQueryPredData *pd)
804 VERIFY_PREDICATE (query_int32_type);
806 val = ((query_int32_getter)getter->param_getfcn) (object, getter);
811 return (val < pdata->val);
812 case QOF_COMPARE_LTE:
813 return (val <= pdata->val);
814 case QOF_COMPARE_EQUAL:
815 return (val == pdata->val);
817 return (val > pdata->val);
818 case QOF_COMPARE_GTE:
819 return (val >= pdata->val);
820 case QOF_COMPARE_NEQ:
821 return (val != pdata->val);
823 PWARN (
"bad match type: %d", pd->how);
829 int32_compare_func (gpointer a, gpointer b, gint options,
833 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
835 v1 = ((query_int32_getter)getter->param_getfcn)(a, getter);
836 v2 = ((query_int32_getter)getter->param_getfcn)(b, getter);
838 if (v1 < v2)
return -1;
839 if (v1 > v2)
return 1;
844 int32_free_pdata (QofQueryPredData *pd)
847 VERIFY_PDATA (query_int32_type);
851 static QofQueryPredData *
852 int32_copy_predicate (
const QofQueryPredData *pd)
855 VERIFY_PDATA_R (query_int32_type);
856 return qof_query_int32_predicate (pd->how, pdata->val);
860 int32_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
865 return (pd1->val == pd2->val);
872 pdata->pd.type_name = query_int32_type;
875 return ((QofQueryPredData*)pdata);
879 int32_to_string (gpointer
object, QofParam *getter)
881 gint32 num = ((query_int32_getter)getter->param_getfcn)(object, getter);
883 return g_strdup_printf (
"%d", num);
890 int64_match_predicate (gpointer
object, QofParam *getter,
891 QofQueryPredData *pd)
896 VERIFY_PREDICATE (query_int64_type);
898 val = ((query_int64_getter)getter->param_getfcn) (object, getter);
903 return (val < pdata->val);
904 case QOF_COMPARE_LTE:
905 return (val <= pdata->val);
906 case QOF_COMPARE_EQUAL:
907 return (val == pdata->val);
909 return (val > pdata->val);
910 case QOF_COMPARE_GTE:
911 return (val >= pdata->val);
912 case QOF_COMPARE_NEQ:
913 return (val != pdata->val);
915 PWARN (
"bad match type: %d", pd->how);
921 int64_compare_func (gpointer a, gpointer b, gint options,
925 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
927 v1 = ((query_int64_getter)getter->param_getfcn)(a, getter);
928 v2 = ((query_int64_getter)getter->param_getfcn)(b, getter);
930 if (v1 < v2)
return -1;
931 if (v1 > v2)
return 1;
936 int64_free_pdata (QofQueryPredData *pd)
939 VERIFY_PDATA (query_int64_type);
943 static QofQueryPredData *
944 int64_copy_predicate (
const QofQueryPredData *pd)
947 VERIFY_PDATA_R (query_int64_type);
948 return qof_query_int64_predicate (pd->how, pdata->val);
952 int64_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
957 return (pd1->val == pd2->val);
964 pdata->pd.type_name = query_int64_type;
967 return ((QofQueryPredData*)pdata);
971 int64_to_string (gpointer
object, QofParam *getter)
973 gint64 num = ((query_int64_getter)getter->param_getfcn)(object, getter);
975 return g_strdup_printf (
"%" G_GINT64_FORMAT, num);
982 double_match_predicate (gpointer
object, QofParam *getter,
983 QofQueryPredData *pd)
988 VERIFY_PREDICATE (query_double_type);
990 val = ((query_double_getter)getter->param_getfcn) (object, getter);
995 return (val < pdata->val);
996 case QOF_COMPARE_LTE:
997 return (val <= pdata->val);
998 case QOF_COMPARE_EQUAL:
999 return (val == pdata->val);
1000 case QOF_COMPARE_GT:
1001 return (val > pdata->val);
1002 case QOF_COMPARE_GTE:
1003 return (val >= pdata->val);
1004 case QOF_COMPARE_NEQ:
1005 return (val != pdata->val);
1007 PWARN (
"bad match type: %d", pd->how);
1013 double_compare_func (gpointer a, gpointer b, gint options,
1017 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
1019 v1 = ((query_double_getter)getter->param_getfcn) (a, getter);
1020 v2 = ((query_double_getter)getter->param_getfcn) (b, getter);
1022 if (v1 < v2)
return -1;
1023 if (v1 > v2)
return 1;
1028 double_free_pdata (QofQueryPredData *pd)
1031 VERIFY_PDATA (query_double_type);
1035 static QofQueryPredData *
1036 double_copy_predicate (
const QofQueryPredData *pd)
1039 VERIFY_PDATA_R (query_double_type);
1040 return qof_query_double_predicate (pd->how, pdata->val);
1044 double_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1049 return (pd1->val == pd2->val);
1056 pdata->pd.type_name = query_double_type;
1057 pdata->pd.how = how;
1059 return ((QofQueryPredData*)pdata);
1063 double_to_string (gpointer
object, QofParam *getter)
1065 double num = ((query_double_getter)getter->param_getfcn)(object, getter);
1067 return g_strdup_printf (
"%f", num);
1073 boolean_match_predicate (gpointer
object, QofParam *getter,
1074 QofQueryPredData *pd)
1079 VERIFY_PREDICATE (query_boolean_type);
1081 val = ((query_boolean_getter)getter->param_getfcn) (object, getter);
1085 case QOF_COMPARE_EQUAL:
1086 return (val == pdata->val);
1087 case QOF_COMPARE_NEQ:
1088 return (val != pdata->val);
1090 PWARN (
"bad match type: %d", pd->how);
1096 boolean_compare_func (gpointer a, gpointer b, gint options,
1100 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
1101 va = ((query_boolean_getter)getter->param_getfcn) (a, getter);
1102 vb = ((query_boolean_getter)getter->param_getfcn) (b, getter);
1103 if (!va && vb)
return -1;
1104 if (va && !vb)
return 1;
1109 boolean_free_pdata (QofQueryPredData *pd)
1112 VERIFY_PDATA (query_boolean_type);
1116 static QofQueryPredData *
1117 boolean_copy_predicate (
const QofQueryPredData *pd)
1120 VERIFY_PDATA_R (query_boolean_type);
1121 return qof_query_boolean_predicate (pd->how, pdata->val);
1125 boolean_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1130 return (pd1->val == pd2->val);
1137 g_return_val_if_fail (how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ,
nullptr);
1140 pdata->pd.type_name = query_boolean_type;
1141 pdata->pd.how = how;
1143 return ((QofQueryPredData*)pdata);
1147 boolean_to_string (gpointer
object, QofParam *getter)
1149 gboolean num = ((query_boolean_getter)getter->param_getfcn)(object, getter);
1151 return g_strdup_printf (
"%s", (num ?
"X" :
""));
1157 char_match_predicate (gpointer
object, QofParam *getter,
1158 QofQueryPredData *pd)
1163 VERIFY_PREDICATE (query_char_type);
1165 c = ((query_char_getter)getter->param_getfcn) (object, getter);
1167 switch (pdata->options)
1169 case QOF_CHAR_MATCH_ANY:
1170 if (strchr (pdata->char_list, c))
return 1;
1172 case QOF_CHAR_MATCH_NONE:
1173 if (!strchr (pdata->char_list, c))
return 1;
1176 PWARN (
"bad match type");
1182 char_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
1185 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
1186 va = ((query_char_getter)getter->param_getfcn)(a, getter);
1187 vb = ((query_char_getter)getter->param_getfcn)(b, getter);
1192 char_free_pdata (QofQueryPredData *pd)
1195 VERIFY_PDATA (query_char_type);
1196 g_free (pdata->char_list);
1200 static QofQueryPredData *
1201 char_copy_predicate (
const QofQueryPredData *pd)
1204 VERIFY_PDATA_R (query_char_type);
1205 return qof_query_char_predicate (pdata->options, pdata->char_list);
1209 char_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1214 if (pd1->options != pd2->options)
return FALSE;
1215 return (g_strcmp0 (pd1->char_list, pd2->char_list) == 0);
1219 qof_query_char_predicate (
QofCharMatch options,
const char *chars)
1222 g_return_val_if_fail (chars,
nullptr);
1224 pdata->pd.type_name = query_char_type;
1225 pdata->pd.how = QOF_COMPARE_EQUAL;
1226 pdata->options = options;
1227 pdata->char_list = g_strdup (chars);
1228 return ((QofQueryPredData*)pdata);
1232 qof_query_char_predicate_get_char (
const QofQueryPredData *pd,
char **chars)
1236 if (pdata->pd.type_name != query_char_type)
1239 *chars = g_strdup (pdata->char_list);
1244 char_to_string (gpointer
object, QofParam *getter)
1246 char num = ((query_char_getter)getter->param_getfcn)(object, getter);
1248 return g_strdup_printf (
"%c", num);
1255 choice_match_predicate (gpointer
object, QofParam *getter,
1256 QofQueryPredData *pd)
1259 GList *node, *o_list;
1260 const GncGUID *guid =
nullptr;
1262 VERIFY_PREDICATE (query_choice_type);
1264 switch (pdata->options)
1273 for (node = pdata->guids; node; node = node->next)
1276 for (o_list = static_cast<GList*>(
object); o_list;
1277 o_list =
static_cast<GList*
>(o_list->next))
1279 guid = ((query_choice_getter)getter->param_getfcn) (o_list->data, getter);
1280 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
1288 if (o_list ==
nullptr)
1302 o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
1304 for (node = o_list; node; node = node->next)
1308 for (node2 = pdata->guids; node2; node2 = node2->next)
1310 if (
guid_equal (static_cast<GncGUID*>(node->data),
1311 static_cast<GncGUID*
>(node2->data)))
1315 if (node2 !=
nullptr)
1319 g_list_free(o_list);
1329 guid = ((query_choice_getter)getter->param_getfcn) (object, getter);
1330 for (node = pdata->guids; node; node = node->next)
1332 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
1337 switch (pdata->options)
1341 return (node !=
nullptr);
1343 case QOF_GUID_MATCH_NONE:
1345 return (node ==
nullptr);
1347 case QOF_GUID_MATCH_NULL:
1351 PWARN (
"bad match type");
1357 choice_free_pdata (QofQueryPredData *pd)
1361 VERIFY_PDATA (query_choice_type);
1362 for (node = pdata->guids; node; node = node->next)
1364 guid_free (static_cast<GncGUID*>(node->data));
1366 g_list_free (pdata->guids);
1370 static QofQueryPredData *
1371 choice_copy_predicate (
const QofQueryPredData *pd)
1374 VERIFY_PDATA_R (query_choice_type);
1375 return qof_query_choice_predicate (pdata->options, pdata->guids);
1379 choice_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1383 GList *l1 = pd1->guids, *l2 = pd2->guids;
1385 if (pd1->options != pd2->options)
return FALSE;
1386 for (; l1 || l2; l1 = l1->next, l2 = l2->next)
1390 if (!
guid_equal (static_cast<GncGUID*>(l1->data),
1391 static_cast<GncGUID*
>(l2->data)))
1398 qof_query_choice_predicate (
QofGuidMatch options, GList *guid_list)
1403 if (
nullptr == guid_list)
return nullptr;
1406 pdata->pd.how = QOF_COMPARE_EQUAL;
1407 pdata->pd.type_name = query_choice_type;
1408 pdata->options = options;
1410 pdata->guids = g_list_copy (guid_list);
1411 for (node = pdata->guids; node; node = node->next)
1414 *guid = *((
GncGUID *)node->data);
1417 return ((QofQueryPredData*)pdata);
1434 qof_query_register_core_object (
QofType core_name,
1435 QofQueryPredicateFunc pred,
1436 QofCompareFunc comp,
1437 QueryPredicateCopyFunc copy,
1438 QueryPredDataFree pd_free,
1439 QueryToString toString,
1440 QueryPredicateEqual pred_equal)
1442 g_return_if_fail (core_name);
1443 g_return_if_fail (*core_name !=
'\0');
1446 g_hash_table_insert (predTable, (
char *)core_name,
1447 reinterpret_cast<void*>(pred));
1450 g_hash_table_insert (cmpTable, (
char *)core_name,
1451 reinterpret_cast<void*>(comp));
1454 g_hash_table_insert (copyTable, (
char *)core_name,
1455 reinterpret_cast<void*>(copy));
1458 g_hash_table_insert (freeTable, (
char *)core_name,
1459 reinterpret_cast<void*>(pd_free));
1462 g_hash_table_insert (toStringTable, (
char *)core_name,
1463 reinterpret_cast<void*>(toString));
1466 g_hash_table_insert (predEqualTable, (
char *)core_name,
1467 reinterpret_cast<void*>(pred_equal));
1470 static void init_tables (
void)
1476 QofQueryPredicateFunc pred;
1477 QofCompareFunc comp;
1478 QueryPredicateCopyFunc copy;
1479 QueryPredDataFree pd_free;
1480 QueryToString toString;
1481 QueryPredicateEqual pred_equal;
1485 QOF_TYPE_STRING, string_match_predicate, string_compare_func,
1486 string_copy_predicate, string_free_pdata, string_to_string,
1487 string_predicate_equal
1490 QOF_TYPE_NATURAL, string_match_predicate, natural_compare_func,
1491 string_copy_predicate, string_free_pdata, string_to_string,
1492 string_predicate_equal
1495 QOF_TYPE_DATE, date_match_predicate, date_compare_func,
1496 date_copy_predicate, date_free_pdata, date_to_string,
1497 date_predicate_equal
1500 QOF_TYPE_DEBCRED, numeric_match_predicate, numeric_compare_func,
1501 numeric_copy_predicate, numeric_free_pdata, debcred_to_string,
1502 numeric_predicate_equal
1505 QOF_TYPE_NUMERIC, numeric_match_predicate, numeric_compare_func,
1506 numeric_copy_predicate, numeric_free_pdata, numeric_to_string,
1507 numeric_predicate_equal
1510 QOF_TYPE_GUID, guid_match_predicate,
nullptr,
1511 guid_copy_predicate, guid_free_pdata,
nullptr,
1512 guid_predicate_equal
1515 QOF_TYPE_INT32, int32_match_predicate, int32_compare_func,
1516 int32_copy_predicate, int32_free_pdata, int32_to_string,
1517 int32_predicate_equal
1520 QOF_TYPE_INT64, int64_match_predicate, int64_compare_func,
1521 int64_copy_predicate, int64_free_pdata, int64_to_string,
1522 int64_predicate_equal
1525 QOF_TYPE_DOUBLE, double_match_predicate, double_compare_func,
1526 double_copy_predicate, double_free_pdata, double_to_string,
1527 double_predicate_equal
1530 QOF_TYPE_BOOLEAN, boolean_match_predicate, boolean_compare_func,
1531 boolean_copy_predicate, boolean_free_pdata, boolean_to_string,
1532 boolean_predicate_equal
1535 QOF_TYPE_CHAR, char_match_predicate, char_compare_func,
1536 char_copy_predicate, char_free_pdata, char_to_string,
1537 char_predicate_equal
1540 QOF_TYPE_CHOICE, choice_match_predicate,
nullptr,
1541 choice_copy_predicate, choice_free_pdata,
nullptr, choice_predicate_equal
1546 for (i = 0; i < (
sizeof(knownTypes) /
sizeof(*knownTypes)); i++)
1548 qof_query_register_core_object (knownTypes[i].name,
1552 knownTypes[i].pd_free,
1553 knownTypes[i].toString,
1554 knownTypes[i].pred_equal);
1558 static QueryPredicateCopyFunc
1559 qof_query_copy_predicate (
QofType type)
1561 QueryPredicateCopyFunc rc;
1562 g_return_val_if_fail (type,
nullptr);
1563 rc =
reinterpret_cast<QueryPredicateCopyFunc
>(g_hash_table_lookup (copyTable, type));
1567 static QueryPredDataFree
1568 qof_query_predicate_free (
QofType type)
1570 g_return_val_if_fail (type,
nullptr);
1571 return reinterpret_cast<QueryPredDataFree
>(g_hash_table_lookup (freeTable, type));
1577 void qof_query_core_init (
void)
1580 if (initialized)
return;
1584 predTable = g_hash_table_new (g_str_hash, g_str_equal);
1585 cmpTable = g_hash_table_new (g_str_hash, g_str_equal);
1586 copyTable = g_hash_table_new (g_str_hash, g_str_equal);
1587 freeTable = g_hash_table_new (g_str_hash, g_str_equal);
1588 toStringTable = g_hash_table_new (g_str_hash, g_str_equal);
1589 predEqualTable = g_hash_table_new (g_str_hash, g_str_equal);
1594 void qof_query_core_shutdown (
void)
1596 if (!initialized)
return;
1597 initialized = FALSE;
1599 g_hash_table_destroy (predTable);
1600 g_hash_table_destroy (cmpTable);
1601 g_hash_table_destroy (copyTable);
1602 g_hash_table_destroy (freeTable);
1603 g_hash_table_destroy (toStringTable);
1604 g_hash_table_destroy (predEqualTable);
1607 QofQueryPredicateFunc
1608 qof_query_core_get_predicate (
QofType type)
1610 g_return_val_if_fail (type,
nullptr);
1611 return reinterpret_cast<QofQueryPredicateFunc
>(g_hash_table_lookup (predTable, type));
1615 qof_query_core_get_compare (
QofType type)
1617 g_return_val_if_fail (type,
nullptr);
1618 return reinterpret_cast<QofCompareFunc
>(g_hash_table_lookup (cmpTable, type));
1624 QueryPredDataFree free_fcn;
1626 g_return_if_fail (pdata);
1627 g_return_if_fail (pdata->type_name);
1629 free_fcn = qof_query_predicate_free (pdata->type_name);
1636 QueryPredicateCopyFunc copy;
1638 g_return_val_if_fail (pdata,
nullptr);
1639 g_return_val_if_fail (pdata->type_name,
nullptr);
1641 copy = qof_query_copy_predicate (pdata->type_name);
1642 return (copy (pdata));
1649 QueryToString toString;
1651 g_return_val_if_fail (type,
nullptr);
1652 g_return_val_if_fail (
object,
nullptr);
1653 g_return_val_if_fail (getter,
nullptr);
1655 toString =
reinterpret_cast<QueryToString
>(g_hash_table_lookup (toStringTable, type));
1656 g_return_val_if_fail (toString,
nullptr);
1658 return toString (
object, getter);
1662 qof_query_core_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1664 QueryPredicateEqual pred_equal;
1666 if (p1 == p2)
return TRUE;
1667 if (!p1 || !p2)
return FALSE;
1669 if (p1->how != p2->how)
return FALSE;
1670 if (g_strcmp0 (p1->type_name, p2->type_name))
return FALSE;
1672 pred_equal =
reinterpret_cast<QueryPredicateEqual
>(g_hash_table_lookup (predEqualTable, p1->type_name));
1673 g_return_val_if_fail (pred_equal, FALSE);
1675 return pred_equal (p1, p2);
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
void qof_query_core_predicate_free(QofQueryPredData *pdata)
Destroy a predicate.
const char * QofType
Type of Parameters (String, Date, Numeric, GncGUID, etc.)
gint safe_strcasecmp(const gchar *da, const gchar *db)
case sensitive comparison of strings da and db - either may be NULL.
QofStringMatch
List of known core query data-types...
gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b.
gchar * gnc_numeric_to_string(gnc_numeric n)
Convert to string.
These expect a single object and expect the QofAccessFunc returns GncGUID*.
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
gboolean qof_query_date_predicate_get_date(const QofQueryPredData *pd, time64 *date)
Retrieve a predicate.
#define PWARN(format, args...)
Log a warning.
char * qof_print_date(time64 secs)
Convenience; calls through to qof_print_date_dmy_buff().
GncGUID * guid_malloc(void)
Allocate memory for a GUID.
char * qof_query_core_to_string(QofType type, gpointer object, QofParam *getter)
Return a printable string for a core data object.
int safe_utf8_collate_natural(const char *da, const char *db)
Collate two UTF-8 strings naturally.
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
Given two GUIDs, return TRUE if they are non-NULL and equal.
QofQueryCompare
Standard Query comparators, for how to compare objects in a predicate.
QofCharMatch
A CHAR type is for a RECNCell, Comparisons for QOF_TYPE_CHAR 'ANY' will match any character in the st...
gnc_numeric gnc_numeric_abs(gnc_numeric a)
Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value...
These expect a single object and expect the QofAccessFunc function to return a GList* of GncGUID* (th...
These expect a GList* of objects and calls the QofAccessFunc routine on each item in the list to obta...
gboolean gnc_numeric_positive_p(gnc_numeric a)
Returns 1 if a > 0, otherwise returns 0.
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a-b.
int qof_string_number_compare_func(gpointer a, gpointer b, gint options, QofParam *getter)
Compare two parameter(strings) as if they are numbers! the two objects, a and b, are the objects bein...
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
gboolean qof_utf8_substr_nocase(const gchar *haystack, const gchar *needle)
Search for an occurrence of the substring needle in the string haystack, ignoring case...
QofDateMatch
Comparisons for QOF_TYPE_DATE The QOF_DATE_MATCH_DAY comparison rounds the two time values to mid-day...
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
time64 time64CanonicalDayTime(time64 t)
convert a time64 on a certain day (localtime) to the time64 representing midday on that day...
QofQueryPredData * qof_query_core_predicate_copy(const QofQueryPredData *pdata)
Copy a predicate.
The type used to store guids in C.
QofNumericMatch
Comparisons for QOF_TYPE_NUMERIC, QOF_TYPE_DEBCRED.