31 #include "qofquerycore-p.h" 33 static QofLogModule log_module = QOF_MOD_QUERY;
36 typedef void (*QueryPredDataFree) (QofQueryPredData *pdata);
39 typedef QofQueryPredData *(*QueryPredicateCopyFunc) (
const QofQueryPredData *pdata);
47 typedef char * (*QueryToString) (gpointer object, QofParam *getter);
50 typedef gboolean (*QueryPredicateEqual) (
const QofQueryPredData *p1,
51 const QofQueryPredData *p2);
53 static QueryPredicateCopyFunc qof_query_copy_predicate (
QofType type);
54 static QueryPredDataFree qof_query_predicate_free (
QofType type);
57 typedef const char * (*query_string_getter) (gpointer, QofParam *);
58 static const char * query_string_type = QOF_TYPE_STRING;
60 typedef time64 (*query_date_getter) (gpointer, QofParam *);
61 static const char * query_date_type = QOF_TYPE_DATE;
63 typedef gnc_numeric (*query_numeric_getter) (gpointer, QofParam *);
64 static const char * query_numeric_type = QOF_TYPE_NUMERIC;
66 typedef GList * (*query_glist_getter) (gpointer, QofParam *);
67 typedef const GncGUID * (*query_guid_getter) (gpointer, QofParam *);
68 static const char * query_guid_type = QOF_TYPE_GUID;
70 typedef gint32 (*query_int32_getter) (gpointer, QofParam *);
71 static const char * query_int32_type = QOF_TYPE_INT32;
73 typedef gint64 (*query_int64_getter) (gpointer, QofParam *);
74 static const char * query_int64_type = QOF_TYPE_INT64;
76 typedef double (*query_double_getter) (gpointer, QofParam *);
77 static const char * query_double_type = QOF_TYPE_DOUBLE;
79 typedef gboolean (*query_boolean_getter) (gpointer, QofParam *);
80 static const char * query_boolean_type = QOF_TYPE_BOOLEAN;
82 typedef char (*query_char_getter) (gpointer, QofParam *);
83 static const char * query_char_type = QOF_TYPE_CHAR;
85 typedef QofCollection * (*query_collect_getter) (gpointer, QofParam*);
88 typedef const GncGUID * (*query_choice_getter) (gpointer, QofParam *);
89 static const char * query_choice_type = QOF_TYPE_CHOICE;
92 static gboolean initialized = FALSE;
93 static GHashTable *predTable =
nullptr;
94 static GHashTable *cmpTable =
nullptr;
95 static GHashTable *copyTable =
nullptr;
96 static GHashTable *freeTable =
nullptr;
97 static GHashTable *toStringTable =
nullptr;
98 static GHashTable *predEqualTable =
nullptr;
100 #define COMPARE_ERROR -3 101 #define PREDICATE_ERROR -2 103 #define VERIFY_PDATA(str) { \ 104 g_return_if_fail (pd != nullptr); \ 105 g_return_if_fail (pd->type_name == str || \ 106 !g_strcmp0 (str, pd->type_name)); \ 108 #define VERIFY_PDATA_R(str) { \ 109 g_return_val_if_fail (pd != nullptr, nullptr); \ 110 g_return_val_if_fail (pd->type_name == str || \ 111 !g_strcmp0 (str, pd->type_name), \ 114 #define VERIFY_PREDICATE(str) { \ 115 g_return_val_if_fail (getter != nullptr, PREDICATE_ERROR); \ 116 g_return_val_if_fail (getter->param_getfcn != nullptr, PREDICATE_ERROR); \ 117 g_return_val_if_fail (pd != nullptr, PREDICATE_ERROR); \ 118 g_return_val_if_fail (pd->type_name == str || \ 119 !g_strcmp0 (str, pd->type_name), \ 129 string_match_predicate (gpointer
object,
131 QofQueryPredData *pd)
137 VERIFY_PREDICATE (query_string_type);
139 s = ((query_string_getter)getter->param_getfcn) (object, getter);
146 if (!regexec (&pdata->compiled, s, 1, &match, 0))
151 if (pdata->options == QOF_STRING_MATCH_CASEINSENSITIVE)
153 if (pd->how == QOF_COMPARE_CONTAINS || pd->how == QOF_COMPARE_NCONTAINS)
166 if (pd->how == QOF_COMPARE_CONTAINS || pd->how == QOF_COMPARE_NCONTAINS)
168 if (strstr (s, pdata->matchstring))
173 if (g_strcmp0 (s, pdata->matchstring) == 0)
181 case QOF_COMPARE_CONTAINS:
183 case QOF_COMPARE_NCONTAINS:
185 case QOF_COMPARE_EQUAL:
187 case QOF_COMPARE_NEQ:
190 PWARN (
"bad match type: %d", pd->how);
196 string_compare_func (gpointer a, gpointer b, gint options,
200 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
202 s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
203 s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
205 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
208 return g_strcmp0 (s1, s2);
218 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
220 s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
221 s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
224 if (s1 == s2)
return 0;
225 if (!s1 && s2)
return -1;
226 if (s1 && !s2)
return 1;
229 i1 = strtol(s1, &sr1, 10);
230 i2 = strtol(s2, &sr2, 10);
231 if (i1 < i2)
return -1;
232 if (i1 > i2)
return 1;
235 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
238 return g_strcmp0 (sr1, sr2);
242 string_free_pdata (QofQueryPredData *pd)
246 VERIFY_PDATA (query_string_type);
249 regfree (&pdata->compiled);
251 g_free (pdata->matchstring);
255 static QofQueryPredData *
256 string_copy_predicate (
const QofQueryPredData *pd)
260 VERIFY_PDATA_R (query_string_type);
262 return qof_query_string_predicate (pd->how, pdata->matchstring,
268 string_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
273 if (pd1->options != pd2->options)
return FALSE;
274 if (pd1->is_regex != pd2->is_regex)
return FALSE;
275 return (g_strcmp0 (pd1->matchstring, pd2->matchstring) == 0);
285 g_return_val_if_fail (str,
nullptr);
287 g_return_val_if_fail (how == QOF_COMPARE_CONTAINS || how == QOF_COMPARE_NCONTAINS ||
288 how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ,
nullptr);
291 pdata->pd.type_name = query_string_type;
293 pdata->options = options;
294 pdata->matchstring = g_strdup (str);
299 int flags = REG_EXTENDED;
300 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
303 rc = regcomp(&pdata->compiled, str, flags);
306 g_free(pdata->matchstring);
310 pdata->is_regex = TRUE;
313 return ((QofQueryPredData*)pdata);
317 string_to_string (gpointer
object, QofParam *getter)
320 res = ((query_string_getter)getter->param_getfcn)(object, getter);
322 return g_strdup (res);
332 if (options == QOF_DATE_MATCH_DAY)
347 date_match_predicate (gpointer
object, QofParam *getter,
348 QofQueryPredData *pd)
354 VERIFY_PREDICATE (query_date_type);
356 objtime = ((query_date_getter)getter->param_getfcn) (object, getter);
357 compare = date_compare (objtime, pdata->date, pdata->options);
362 return (compare < 0);
363 case QOF_COMPARE_LTE:
364 return (compare <= 0);
365 case QOF_COMPARE_EQUAL:
366 return (compare == 0);
368 return (compare > 0);
369 case QOF_COMPARE_GTE:
370 return (compare >= 0);
371 case QOF_COMPARE_NEQ:
372 return (compare != 0);
374 PWARN (
"bad match type: %d", pd->how);
380 date_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
384 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
386 ta = ((query_date_getter)getter->param_getfcn) (a, getter);
387 tb = ((query_date_getter)getter->param_getfcn) (b, getter);
389 return date_compare (ta, tb, static_cast<QofDateMatch>(options));
393 date_free_pdata (QofQueryPredData *pd)
397 VERIFY_PDATA (query_date_type);
402 static QofQueryPredData *
403 date_copy_predicate (
const QofQueryPredData *pd)
407 VERIFY_PDATA_R (query_date_type);
409 return qof_query_date_predicate (pd->how, pdata->options, pdata->date);
413 date_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
418 if (pd1->options != pd2->options)
return FALSE;
419 return (pd1->date == pd2->date);
429 pdata->pd.type_name = query_date_type;
431 pdata->options = options;
433 return ((QofQueryPredData*)pdata);
441 if (pdata->pd.type_name != query_date_type)
448 date_to_string (gpointer
object, QofParam *getter)
450 time64 tt = ((query_date_getter)getter->param_getfcn)(object, getter);
461 numeric_match_predicate (gpointer
object, QofParam *getter,
462 QofQueryPredData* pd)
468 VERIFY_PREDICATE (query_numeric_type);
470 obj_val = ((query_numeric_getter)getter->param_getfcn) (object, getter);
472 switch (pdata->options)
474 case QOF_NUMERIC_MATCH_CREDIT:
477 case QOF_NUMERIC_MATCH_DEBIT:
486 if (pd->how == QOF_COMPARE_EQUAL || pd->how == QOF_COMPARE_NEQ)
488 gnc_numeric cmp_val = gnc_numeric_create (1, 10000);
502 return (compare < 0);
503 case QOF_COMPARE_LTE:
504 return (compare <= 0);
505 case QOF_COMPARE_EQUAL:
508 return (compare > 0);
509 case QOF_COMPARE_GTE:
510 return (compare >= 0);
511 case QOF_COMPARE_NEQ:
514 PWARN (
"bad match type: %d", pd->how);
520 numeric_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
524 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
526 va = ((query_numeric_getter)getter->param_getfcn) (a, getter);
527 vb = ((query_numeric_getter)getter->param_getfcn) (b, getter);
533 numeric_free_pdata (QofQueryPredData* pd)
536 VERIFY_PDATA (query_numeric_type);
540 static QofQueryPredData *
541 numeric_copy_predicate (
const QofQueryPredData *pd)
544 VERIFY_PDATA_R (query_numeric_type);
545 return qof_query_numeric_predicate (pd->how, pdata->options, pdata->amount);
549 numeric_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
554 if (pd1->options != pd2->options)
return FALSE;
565 pdata->pd.type_name = query_numeric_type;
567 pdata->options = options;
568 pdata->amount = value;
569 return ((QofQueryPredData*)pdata);
573 numeric_to_string (gpointer
object, QofParam *getter)
576 num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
582 debcred_to_string (gpointer
object, QofParam *getter)
585 num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
593 guid_match_predicate (gpointer
object, QofParam *getter,
594 QofQueryPredData *pd)
597 GList *node, *o_list;
600 VERIFY_PREDICATE (query_guid_type);
602 switch (pdata->options)
611 for (node = pdata->guids; node; node = node->next)
614 for (o_list = static_cast<GList*>(
object); o_list;
615 o_list =
static_cast<GList*
>(o_list->next))
617 guid = ((query_guid_getter)getter->param_getfcn) (o_list->data, getter);
618 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
626 if (o_list ==
nullptr)
645 o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
647 for (node = o_list; node; node = node->next)
652 for (node2 = pdata->guids; node2; node2 = node2->next)
654 if (
guid_equal (static_cast<GncGUID*>(node->data),
655 static_cast<GncGUID*
>(node2->data)))
660 if (node2 !=
nullptr)
678 guid = ((query_guid_getter)getter->param_getfcn) (object, getter);
679 for (node = pdata->guids; node; node = node->next)
681 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
686 switch (pdata->options)
690 return (node !=
nullptr);
692 case QOF_GUID_MATCH_NONE:
694 return (node ==
nullptr);
696 case QOF_GUID_MATCH_NULL:
700 PWARN (
"bad match type");
706 guid_free_pdata (QofQueryPredData *pd)
710 VERIFY_PDATA (query_guid_type);
711 for (node = pdata->guids; node; node = node->next)
713 guid_free (static_cast<GncGUID*>(node->data));
715 g_list_free (pdata->guids);
719 static QofQueryPredData *
720 guid_copy_predicate (
const QofQueryPredData *pd)
723 VERIFY_PDATA_R (query_guid_type);
724 return qof_query_guid_predicate (pdata->options, pdata->guids);
728 guid_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
732 GList *l1 = pd1->guids, *l2 = pd2->guids;
734 if (pd1->options != pd2->options)
return FALSE;
735 for (; l1 || l2; l1 = l1->next, l2 = l2->next)
739 if (!
guid_equal (static_cast<GncGUID*>(l1->data),
740 static_cast<GncGUID*
>(l2->data)))
747 qof_query_guid_predicate (
QofGuidMatch options, GList *guid_list)
754 g_return_val_if_fail (options == QOF_GUID_MATCH_NULL,
nullptr);
757 pdata->pd.how = QOF_COMPARE_EQUAL;
758 pdata->pd.type_name = query_guid_type;
759 pdata->options = options;
761 pdata->guids = g_list_copy (guid_list);
762 for (node = pdata->guids; node; node = node->next)
765 *guid = *((
GncGUID *)node->data);
768 return ((QofQueryPredData*)pdata);
775 int32_match_predicate (gpointer
object, QofParam *getter,
776 QofQueryPredData *pd)
781 VERIFY_PREDICATE (query_int32_type);
783 val = ((query_int32_getter)getter->param_getfcn) (object, getter);
788 return (val < pdata->val);
789 case QOF_COMPARE_LTE:
790 return (val <= pdata->val);
791 case QOF_COMPARE_EQUAL:
792 return (val == pdata->val);
794 return (val > pdata->val);
795 case QOF_COMPARE_GTE:
796 return (val >= pdata->val);
797 case QOF_COMPARE_NEQ:
798 return (val != pdata->val);
800 PWARN (
"bad match type: %d", pd->how);
806 int32_compare_func (gpointer a, gpointer b, gint options,
810 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
812 v1 = ((query_int32_getter)getter->param_getfcn)(a, getter);
813 v2 = ((query_int32_getter)getter->param_getfcn)(b, getter);
815 if (v1 < v2)
return -1;
816 if (v1 > v2)
return 1;
821 int32_free_pdata (QofQueryPredData *pd)
824 VERIFY_PDATA (query_int32_type);
828 static QofQueryPredData *
829 int32_copy_predicate (
const QofQueryPredData *pd)
832 VERIFY_PDATA_R (query_int32_type);
833 return qof_query_int32_predicate (pd->how, pdata->val);
837 int32_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
842 return (pd1->val == pd2->val);
849 pdata->pd.type_name = query_int32_type;
852 return ((QofQueryPredData*)pdata);
856 int32_to_string (gpointer
object, QofParam *getter)
858 gint32 num = ((query_int32_getter)getter->param_getfcn)(object, getter);
860 return g_strdup_printf (
"%d", num);
867 int64_match_predicate (gpointer
object, QofParam *getter,
868 QofQueryPredData *pd)
873 VERIFY_PREDICATE (query_int64_type);
875 val = ((query_int64_getter)getter->param_getfcn) (object, getter);
880 return (val < pdata->val);
881 case QOF_COMPARE_LTE:
882 return (val <= pdata->val);
883 case QOF_COMPARE_EQUAL:
884 return (val == pdata->val);
886 return (val > pdata->val);
887 case QOF_COMPARE_GTE:
888 return (val >= pdata->val);
889 case QOF_COMPARE_NEQ:
890 return (val != pdata->val);
892 PWARN (
"bad match type: %d", pd->how);
898 int64_compare_func (gpointer a, gpointer b, gint options,
902 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
904 v1 = ((query_int64_getter)getter->param_getfcn)(a, getter);
905 v2 = ((query_int64_getter)getter->param_getfcn)(b, getter);
907 if (v1 < v2)
return -1;
908 if (v1 > v2)
return 1;
913 int64_free_pdata (QofQueryPredData *pd)
916 VERIFY_PDATA (query_int64_type);
920 static QofQueryPredData *
921 int64_copy_predicate (
const QofQueryPredData *pd)
924 VERIFY_PDATA_R (query_int64_type);
925 return qof_query_int64_predicate (pd->how, pdata->val);
929 int64_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
934 return (pd1->val == pd2->val);
941 pdata->pd.type_name = query_int64_type;
944 return ((QofQueryPredData*)pdata);
948 int64_to_string (gpointer
object, QofParam *getter)
950 gint64 num = ((query_int64_getter)getter->param_getfcn)(object, getter);
952 return g_strdup_printf (
"%" G_GINT64_FORMAT, num);
959 double_match_predicate (gpointer
object, QofParam *getter,
960 QofQueryPredData *pd)
965 VERIFY_PREDICATE (query_double_type);
967 val = ((query_double_getter)getter->param_getfcn) (object, getter);
972 return (val < pdata->val);
973 case QOF_COMPARE_LTE:
974 return (val <= pdata->val);
975 case QOF_COMPARE_EQUAL:
976 return (val == pdata->val);
978 return (val > pdata->val);
979 case QOF_COMPARE_GTE:
980 return (val >= pdata->val);
981 case QOF_COMPARE_NEQ:
982 return (val != pdata->val);
984 PWARN (
"bad match type: %d", pd->how);
990 double_compare_func (gpointer a, gpointer b, gint options,
994 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
996 v1 = ((query_double_getter)getter->param_getfcn) (a, getter);
997 v2 = ((query_double_getter)getter->param_getfcn) (b, getter);
999 if (v1 < v2)
return -1;
1000 if (v1 > v2)
return 1;
1005 double_free_pdata (QofQueryPredData *pd)
1008 VERIFY_PDATA (query_double_type);
1012 static QofQueryPredData *
1013 double_copy_predicate (
const QofQueryPredData *pd)
1016 VERIFY_PDATA_R (query_double_type);
1017 return qof_query_double_predicate (pd->how, pdata->val);
1021 double_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1026 return (pd1->val == pd2->val);
1033 pdata->pd.type_name = query_double_type;
1034 pdata->pd.how = how;
1036 return ((QofQueryPredData*)pdata);
1040 double_to_string (gpointer
object, QofParam *getter)
1042 double num = ((query_double_getter)getter->param_getfcn)(object, getter);
1044 return g_strdup_printf (
"%f", num);
1050 boolean_match_predicate (gpointer
object, QofParam *getter,
1051 QofQueryPredData *pd)
1056 VERIFY_PREDICATE (query_boolean_type);
1058 val = ((query_boolean_getter)getter->param_getfcn) (object, getter);
1062 case QOF_COMPARE_EQUAL:
1063 return (val == pdata->val);
1064 case QOF_COMPARE_NEQ:
1065 return (val != pdata->val);
1067 PWARN (
"bad match type: %d", pd->how);
1073 boolean_compare_func (gpointer a, gpointer b, gint options,
1077 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
1078 va = ((query_boolean_getter)getter->param_getfcn) (a, getter);
1079 vb = ((query_boolean_getter)getter->param_getfcn) (b, getter);
1080 if (!va && vb)
return -1;
1081 if (va && !vb)
return 1;
1086 boolean_free_pdata (QofQueryPredData *pd)
1089 VERIFY_PDATA (query_boolean_type);
1093 static QofQueryPredData *
1094 boolean_copy_predicate (
const QofQueryPredData *pd)
1097 VERIFY_PDATA_R (query_boolean_type);
1098 return qof_query_boolean_predicate (pd->how, pdata->val);
1102 boolean_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1107 return (pd1->val == pd2->val);
1114 g_return_val_if_fail (how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ,
nullptr);
1117 pdata->pd.type_name = query_boolean_type;
1118 pdata->pd.how = how;
1120 return ((QofQueryPredData*)pdata);
1124 boolean_to_string (gpointer
object, QofParam *getter)
1126 gboolean num = ((query_boolean_getter)getter->param_getfcn)(object, getter);
1128 return g_strdup_printf (
"%s", (num ?
"X" :
""));
1134 char_match_predicate (gpointer
object, QofParam *getter,
1135 QofQueryPredData *pd)
1140 VERIFY_PREDICATE (query_char_type);
1142 c = ((query_char_getter)getter->param_getfcn) (object, getter);
1144 switch (pdata->options)
1146 case QOF_CHAR_MATCH_ANY:
1147 if (strchr (pdata->char_list, c))
return 1;
1149 case QOF_CHAR_MATCH_NONE:
1150 if (!strchr (pdata->char_list, c))
return 1;
1153 PWARN (
"bad match type");
1159 char_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
1162 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
1163 va = ((query_char_getter)getter->param_getfcn)(a, getter);
1164 vb = ((query_char_getter)getter->param_getfcn)(b, getter);
1169 char_free_pdata (QofQueryPredData *pd)
1172 VERIFY_PDATA (query_char_type);
1173 g_free (pdata->char_list);
1177 static QofQueryPredData *
1178 char_copy_predicate (
const QofQueryPredData *pd)
1181 VERIFY_PDATA_R (query_char_type);
1182 return qof_query_char_predicate (pdata->options, pdata->char_list);
1186 char_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1191 if (pd1->options != pd2->options)
return FALSE;
1192 return (g_strcmp0 (pd1->char_list, pd2->char_list) == 0);
1196 qof_query_char_predicate (
QofCharMatch options,
const char *chars)
1199 g_return_val_if_fail (chars,
nullptr);
1201 pdata->pd.type_name = query_char_type;
1202 pdata->pd.how = QOF_COMPARE_EQUAL;
1203 pdata->options = options;
1204 pdata->char_list = g_strdup (chars);
1205 return ((QofQueryPredData*)pdata);
1209 qof_query_char_predicate_get_char (
const QofQueryPredData *pd,
char **chars)
1213 if (pdata->pd.type_name != query_char_type)
1216 *chars = g_strdup (pdata->char_list);
1221 char_to_string (gpointer
object, QofParam *getter)
1223 char num = ((query_char_getter)getter->param_getfcn)(object, getter);
1225 return g_strdup_printf (
"%c", num);
1231 collect_match_predicate (gpointer
object, QofParam *getter,
1232 QofQueryPredData *pd)
1235 GList *node, *node2, *o_list;
1239 VERIFY_PREDICATE (query_collect_type);
1241 switch (pdata->options)
1245 for (node = pdata->guids; node; node = node->next)
1247 for (o_list = static_cast<GList*>(
object); o_list;
1248 o_list =
static_cast<GList*
>(o_list->next))
1250 guid = ((query_guid_getter)getter->param_getfcn)
1251 (o_list->data, getter);
1252 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
1257 if (o_list ==
nullptr)
1266 o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
1267 for (node = o_list; node; node = node->next)
1269 for (node2 = pdata->guids; node2; node2 = node2->next)
1271 if (
guid_equal (static_cast<GncGUID*>(node->data),
1272 static_cast<GncGUID*
>(node2->data)))
1277 if (node2 !=
nullptr)
1282 g_list_free(o_list);
1287 guid = ((query_guid_getter)getter->param_getfcn) (object, getter);
1288 for (node = pdata->guids; node; node = node->next)
1290 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
1296 switch (pdata->options)
1301 return (node !=
nullptr);
1304 case QOF_GUID_MATCH_NONE :
1307 return (node ==
nullptr);
1310 case QOF_GUID_MATCH_NULL :
1317 PWARN (
"bad match type");
1326 collect_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
1329 QofCollection *c1, *c2;
1331 c1 = ((query_collect_getter)getter->param_getfcn) (a, getter);
1332 c2 = ((query_collect_getter)getter->param_getfcn) (b, getter);
1338 collect_free_pdata (QofQueryPredData *pd)
1345 VERIFY_PDATA (query_collect_type);
1346 for (node = pdata->guids; node; node = node->next)
1348 guid_free (static_cast<GncGUID*>(node->data));
1351 g_list_free (pdata->guids);
1355 static QofQueryPredData *
1356 collect_copy_predicate (
const QofQueryPredData *pd)
1360 VERIFY_PDATA_R (query_collect_type);
1361 return qof_query_collect_predicate (pdata->options, pdata->coll);
1365 collect_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1380 query_collect_cb(
QofInstance* ent, gpointer user_data)
1387 pdata->guids = g_list_append(pdata->guids, guid);
1391 qof_query_collect_predicate (
QofGuidMatch options, QofCollection *coll)
1395 g_return_val_if_fail (coll,
nullptr);
1397 pdata->pd.type_name = query_collect_type;
1398 pdata->options = options;
1399 qof_collection_foreach(coll, query_collect_cb, pdata);
1400 if (
nullptr == pdata->guids)
1404 return ((QofQueryPredData*)pdata);
1410 choice_match_predicate (gpointer
object, QofParam *getter,
1411 QofQueryPredData *pd)
1414 GList *node, *o_list;
1415 const GncGUID *guid =
nullptr;
1417 VERIFY_PREDICATE (query_choice_type);
1419 switch (pdata->options)
1428 for (node = pdata->guids; node; node = node->next)
1431 for (o_list = static_cast<GList*>(
object); o_list;
1432 o_list =
static_cast<GList*
>(o_list->next))
1434 guid = ((query_choice_getter)getter->param_getfcn) (o_list->data, getter);
1435 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
1443 if (o_list ==
nullptr)
1457 o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
1459 for (node = o_list; node; node = node->next)
1463 for (node2 = pdata->guids; node2; node2 = node2->next)
1465 if (
guid_equal (static_cast<GncGUID*>(node->data),
1466 static_cast<GncGUID*
>(node2->data)))
1470 if (node2 !=
nullptr)
1474 g_list_free(o_list);
1484 guid = ((query_choice_getter)getter->param_getfcn) (object, getter);
1485 for (node = pdata->guids; node; node = node->next)
1487 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
1492 switch (pdata->options)
1496 return (node !=
nullptr);
1498 case QOF_GUID_MATCH_NONE:
1500 return (node ==
nullptr);
1502 case QOF_GUID_MATCH_NULL:
1506 PWARN (
"bad match type");
1512 choice_free_pdata (QofQueryPredData *pd)
1516 VERIFY_PDATA (query_choice_type);
1517 for (node = pdata->guids; node; node = node->next)
1519 guid_free (static_cast<GncGUID*>(node->data));
1521 g_list_free (pdata->guids);
1525 static QofQueryPredData *
1526 choice_copy_predicate (
const QofQueryPredData *pd)
1529 VERIFY_PDATA_R (query_choice_type);
1530 return qof_query_choice_predicate (pdata->options, pdata->guids);
1534 choice_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1538 GList *l1 = pd1->guids, *l2 = pd2->guids;
1540 if (pd1->options != pd2->options)
return FALSE;
1541 for (; l1 || l2; l1 = l1->next, l2 = l2->next)
1545 if (!
guid_equal (static_cast<GncGUID*>(l1->data),
1546 static_cast<GncGUID*
>(l2->data)))
1553 qof_query_choice_predicate (
QofGuidMatch options, GList *guid_list)
1558 if (
nullptr == guid_list)
return nullptr;
1561 pdata->pd.how = QOF_COMPARE_EQUAL;
1562 pdata->pd.type_name = query_choice_type;
1563 pdata->options = options;
1565 pdata->guids = g_list_copy (guid_list);
1566 for (node = pdata->guids; node; node = node->next)
1569 *guid = *((
GncGUID *)node->data);
1572 return ((QofQueryPredData*)pdata);
1589 qof_query_register_core_object (
QofType core_name,
1590 QofQueryPredicateFunc pred,
1591 QofCompareFunc comp,
1592 QueryPredicateCopyFunc copy,
1593 QueryPredDataFree pd_free,
1594 QueryToString toString,
1595 QueryPredicateEqual pred_equal)
1597 g_return_if_fail (core_name);
1598 g_return_if_fail (*core_name !=
'\0');
1601 g_hash_table_insert (predTable, (
char *)core_name,
1602 reinterpret_cast<void*>(pred));
1605 g_hash_table_insert (cmpTable, (
char *)core_name,
1606 reinterpret_cast<void*>(comp));
1609 g_hash_table_insert (copyTable, (
char *)core_name,
1610 reinterpret_cast<void*>(copy));
1613 g_hash_table_insert (freeTable, (
char *)core_name,
1614 reinterpret_cast<void*>(pd_free));
1617 g_hash_table_insert (toStringTable, (
char *)core_name,
1618 reinterpret_cast<void*>(toString));
1621 g_hash_table_insert (predEqualTable, (
char *)core_name,
1622 reinterpret_cast<void*>(pred_equal));
1625 static void init_tables (
void)
1631 QofQueryPredicateFunc pred;
1632 QofCompareFunc comp;
1633 QueryPredicateCopyFunc copy;
1634 QueryPredDataFree pd_free;
1635 QueryToString toString;
1636 QueryPredicateEqual pred_equal;
1640 QOF_TYPE_STRING, string_match_predicate, string_compare_func,
1641 string_copy_predicate, string_free_pdata, string_to_string,
1642 string_predicate_equal
1645 QOF_TYPE_DATE, date_match_predicate, date_compare_func,
1646 date_copy_predicate, date_free_pdata, date_to_string,
1647 date_predicate_equal
1650 QOF_TYPE_DEBCRED, numeric_match_predicate, numeric_compare_func,
1651 numeric_copy_predicate, numeric_free_pdata, debcred_to_string,
1652 numeric_predicate_equal
1655 QOF_TYPE_NUMERIC, numeric_match_predicate, numeric_compare_func,
1656 numeric_copy_predicate, numeric_free_pdata, numeric_to_string,
1657 numeric_predicate_equal
1660 QOF_TYPE_GUID, guid_match_predicate,
nullptr,
1661 guid_copy_predicate, guid_free_pdata,
nullptr,
1662 guid_predicate_equal
1665 QOF_TYPE_INT32, int32_match_predicate, int32_compare_func,
1666 int32_copy_predicate, int32_free_pdata, int32_to_string,
1667 int32_predicate_equal
1670 QOF_TYPE_INT64, int64_match_predicate, int64_compare_func,
1671 int64_copy_predicate, int64_free_pdata, int64_to_string,
1672 int64_predicate_equal
1675 QOF_TYPE_DOUBLE, double_match_predicate, double_compare_func,
1676 double_copy_predicate, double_free_pdata, double_to_string,
1677 double_predicate_equal
1680 QOF_TYPE_BOOLEAN, boolean_match_predicate, boolean_compare_func,
1681 boolean_copy_predicate, boolean_free_pdata, boolean_to_string,
1682 boolean_predicate_equal
1685 QOF_TYPE_CHAR, char_match_predicate, char_compare_func,
1686 char_copy_predicate, char_free_pdata, char_to_string,
1687 char_predicate_equal
1691 collect_copy_predicate, collect_free_pdata,
nullptr,
1692 collect_predicate_equal
1695 QOF_TYPE_CHOICE, choice_match_predicate,
nullptr,
1696 choice_copy_predicate, choice_free_pdata,
nullptr, choice_predicate_equal
1701 for (i = 0; i < (
sizeof(knownTypes) /
sizeof(*knownTypes)); i++)
1703 qof_query_register_core_object (knownTypes[i].name,
1707 knownTypes[i].pd_free,
1708 knownTypes[i].toString,
1709 knownTypes[i].pred_equal);
1713 static QueryPredicateCopyFunc
1714 qof_query_copy_predicate (
QofType type)
1716 QueryPredicateCopyFunc rc;
1717 g_return_val_if_fail (type,
nullptr);
1718 rc =
reinterpret_cast<QueryPredicateCopyFunc
>(g_hash_table_lookup (copyTable, type));
1722 static QueryPredDataFree
1723 qof_query_predicate_free (
QofType type)
1725 g_return_val_if_fail (type,
nullptr);
1726 return reinterpret_cast<QueryPredDataFree
>(g_hash_table_lookup (freeTable, type));
1732 void qof_query_core_init (
void)
1735 if (initialized)
return;
1739 predTable = g_hash_table_new (g_str_hash, g_str_equal);
1740 cmpTable = g_hash_table_new (g_str_hash, g_str_equal);
1741 copyTable = g_hash_table_new (g_str_hash, g_str_equal);
1742 freeTable = g_hash_table_new (g_str_hash, g_str_equal);
1743 toStringTable = g_hash_table_new (g_str_hash, g_str_equal);
1744 predEqualTable = g_hash_table_new (g_str_hash, g_str_equal);
1749 void qof_query_core_shutdown (
void)
1751 if (!initialized)
return;
1752 initialized = FALSE;
1754 g_hash_table_destroy (predTable);
1755 g_hash_table_destroy (cmpTable);
1756 g_hash_table_destroy (copyTable);
1757 g_hash_table_destroy (freeTable);
1758 g_hash_table_destroy (toStringTable);
1759 g_hash_table_destroy (predEqualTable);
1762 QofQueryPredicateFunc
1763 qof_query_core_get_predicate (
QofType type)
1765 g_return_val_if_fail (type,
nullptr);
1766 return reinterpret_cast<QofQueryPredicateFunc
>(g_hash_table_lookup (predTable, type));
1770 qof_query_core_get_compare (
QofType type)
1772 g_return_val_if_fail (type,
nullptr);
1773 return reinterpret_cast<QofCompareFunc
>(g_hash_table_lookup (cmpTable, type));
1779 QueryPredDataFree free_fcn;
1781 g_return_if_fail (pdata);
1782 g_return_if_fail (pdata->type_name);
1784 free_fcn = qof_query_predicate_free (pdata->type_name);
1791 QueryPredicateCopyFunc copy;
1793 g_return_val_if_fail (pdata,
nullptr);
1794 g_return_val_if_fail (pdata->type_name,
nullptr);
1796 copy = qof_query_copy_predicate (pdata->type_name);
1797 return (copy (pdata));
1804 QueryToString toString;
1806 g_return_val_if_fail (type,
nullptr);
1807 g_return_val_if_fail (
object,
nullptr);
1808 g_return_val_if_fail (getter,
nullptr);
1810 toString =
reinterpret_cast<QueryToString
>(g_hash_table_lookup (toStringTable, type));
1811 g_return_val_if_fail (toString,
nullptr);
1813 return toString (
object, getter);
1817 qof_query_core_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1819 QueryPredicateEqual pred_equal;
1821 if (p1 == p2)
return TRUE;
1822 if (!p1 || !p2)
return FALSE;
1824 if (p1->how != p2->how)
return FALSE;
1825 if (g_strcmp0 (p1->type_name, p2->type_name))
return FALSE;
1827 pred_equal =
reinterpret_cast<QueryPredicateEqual
>(g_hash_table_lookup (predEqualTable, p1->type_name));
1828 g_return_val_if_fail (pred_equal, FALSE);
1830 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.
#define QOF_TYPE_COLLECT
secondary collections are used for one-to-many references between entities and are implemented using ...
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...
int 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.
gint qof_collection_compare(QofCollection *target, QofCollection *merge)
Compare two secondary collections.
#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.
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...
const GncGUID * qof_entity_get_guid(gconstpointer ent)
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.
void qof_collection_destroy(QofCollection *col)
destroy the collection
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.