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 const GncGUID * (*query_choice_getter) (gpointer, QofParam *);
86 static const char * query_choice_type = QOF_TYPE_CHOICE;
89 static gboolean initialized = FALSE;
90 static GHashTable *predTable =
nullptr;
91 static GHashTable *cmpTable =
nullptr;
92 static GHashTable *copyTable =
nullptr;
93 static GHashTable *freeTable =
nullptr;
94 static GHashTable *toStringTable =
nullptr;
95 static GHashTable *predEqualTable =
nullptr;
97 #define COMPARE_ERROR -3 98 #define PREDICATE_ERROR -2 100 #define VERIFY_PDATA(str) { \ 101 g_return_if_fail (pd != nullptr); \ 102 g_return_if_fail (pd->type_name == str || \ 103 !g_strcmp0 (str, pd->type_name)); \ 105 #define VERIFY_PDATA_R(str) { \ 106 g_return_val_if_fail (pd != nullptr, nullptr); \ 107 g_return_val_if_fail (pd->type_name == str || \ 108 !g_strcmp0 (str, pd->type_name), \ 111 #define VERIFY_PREDICATE(str) { \ 112 g_return_val_if_fail (getter != nullptr, PREDICATE_ERROR); \ 113 g_return_val_if_fail (getter->param_getfcn != nullptr, PREDICATE_ERROR); \ 114 g_return_val_if_fail (pd != nullptr, PREDICATE_ERROR); \ 115 g_return_val_if_fail (pd->type_name == str || \ 116 !g_strcmp0 (str, pd->type_name), \ 126 string_match_predicate (gpointer
object,
128 QofQueryPredData *pd)
134 VERIFY_PREDICATE (query_string_type);
136 s = ((query_string_getter)getter->param_getfcn) (object, getter);
143 if (!regexec (&pdata->compiled, s, 1, &match, 0))
148 if (pdata->options == QOF_STRING_MATCH_CASEINSENSITIVE)
150 if (pd->how == QOF_COMPARE_CONTAINS || pd->how == QOF_COMPARE_NCONTAINS)
163 if (pd->how == QOF_COMPARE_CONTAINS || pd->how == QOF_COMPARE_NCONTAINS)
165 if (strstr (s, pdata->matchstring))
170 if (g_strcmp0 (s, pdata->matchstring) == 0)
178 case QOF_COMPARE_CONTAINS:
180 case QOF_COMPARE_NCONTAINS:
182 case QOF_COMPARE_EQUAL:
184 case QOF_COMPARE_NEQ:
187 PWARN (
"bad match type: %d", pd->how);
193 string_compare_func (gpointer a, gpointer b, gint options,
197 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
199 s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
200 s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
202 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
205 return g_strcmp0 (s1, s2);
215 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
217 s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
218 s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
221 if (s1 == s2)
return 0;
222 if (!s1 && s2)
return -1;
223 if (s1 && !s2)
return 1;
226 i1 = strtol(s1, &sr1, 10);
227 i2 = strtol(s2, &sr2, 10);
228 if (i1 < i2)
return -1;
229 if (i1 > i2)
return 1;
232 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
235 return g_strcmp0 (sr1, sr2);
239 string_free_pdata (QofQueryPredData *pd)
243 VERIFY_PDATA (query_string_type);
246 regfree (&pdata->compiled);
248 g_free (pdata->matchstring);
252 static QofQueryPredData *
253 string_copy_predicate (
const QofQueryPredData *pd)
257 VERIFY_PDATA_R (query_string_type);
259 return qof_query_string_predicate (pd->how, pdata->matchstring,
265 string_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
270 if (pd1->options != pd2->options)
return FALSE;
271 if (pd1->is_regex != pd2->is_regex)
return FALSE;
272 return (g_strcmp0 (pd1->matchstring, pd2->matchstring) == 0);
282 g_return_val_if_fail (str,
nullptr);
284 g_return_val_if_fail (how == QOF_COMPARE_CONTAINS || how == QOF_COMPARE_NCONTAINS ||
285 how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ,
nullptr);
288 pdata->pd.type_name = query_string_type;
290 pdata->options = options;
291 pdata->matchstring = g_strdup (str);
296 int flags = REG_EXTENDED;
297 if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
300 rc = regcomp(&pdata->compiled, str, flags);
303 g_free(pdata->matchstring);
307 pdata->is_regex = TRUE;
310 return ((QofQueryPredData*)pdata);
314 string_to_string (gpointer
object, QofParam *getter)
317 res = ((query_string_getter)getter->param_getfcn)(object, getter);
319 return g_strdup (res);
329 if (options == QOF_DATE_MATCH_DAY)
344 date_match_predicate (gpointer
object, QofParam *getter,
345 QofQueryPredData *pd)
351 VERIFY_PREDICATE (query_date_type);
353 objtime = ((query_date_getter)getter->param_getfcn) (object, getter);
354 compare = date_compare (objtime, pdata->date, pdata->options);
359 return (compare < 0);
360 case QOF_COMPARE_LTE:
361 return (compare <= 0);
362 case QOF_COMPARE_EQUAL:
363 return (compare == 0);
365 return (compare > 0);
366 case QOF_COMPARE_GTE:
367 return (compare >= 0);
368 case QOF_COMPARE_NEQ:
369 return (compare != 0);
371 PWARN (
"bad match type: %d", pd->how);
377 date_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
381 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
383 ta = ((query_date_getter)getter->param_getfcn) (a, getter);
384 tb = ((query_date_getter)getter->param_getfcn) (b, getter);
386 return date_compare (ta, tb, static_cast<QofDateMatch>(options));
390 date_free_pdata (QofQueryPredData *pd)
394 VERIFY_PDATA (query_date_type);
399 static QofQueryPredData *
400 date_copy_predicate (
const QofQueryPredData *pd)
404 VERIFY_PDATA_R (query_date_type);
406 return qof_query_date_predicate (pd->how, pdata->options, pdata->date);
410 date_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
415 if (pd1->options != pd2->options)
return FALSE;
416 return (pd1->date == pd2->date);
426 pdata->pd.type_name = query_date_type;
428 pdata->options = options;
430 return ((QofQueryPredData*)pdata);
438 if (pdata->pd.type_name != query_date_type)
445 date_to_string (gpointer
object, QofParam *getter)
447 time64 tt = ((query_date_getter)getter->param_getfcn)(object, getter);
458 numeric_match_predicate (gpointer
object, QofParam *getter,
459 QofQueryPredData* pd)
465 VERIFY_PREDICATE (query_numeric_type);
467 obj_val = ((query_numeric_getter)getter->param_getfcn) (object, getter);
469 switch (pdata->options)
471 case QOF_NUMERIC_MATCH_CREDIT:
474 case QOF_NUMERIC_MATCH_DEBIT:
483 if (pd->how == QOF_COMPARE_EQUAL || pd->how == QOF_COMPARE_NEQ)
485 gnc_numeric cmp_val = gnc_numeric_create (1, 10000);
499 return (compare < 0);
500 case QOF_COMPARE_LTE:
501 return (compare <= 0);
502 case QOF_COMPARE_EQUAL:
505 return (compare > 0);
506 case QOF_COMPARE_GTE:
507 return (compare >= 0);
508 case QOF_COMPARE_NEQ:
511 PWARN (
"bad match type: %d", pd->how);
517 numeric_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
521 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
523 va = ((query_numeric_getter)getter->param_getfcn) (a, getter);
524 vb = ((query_numeric_getter)getter->param_getfcn) (b, getter);
530 numeric_free_pdata (QofQueryPredData* pd)
533 VERIFY_PDATA (query_numeric_type);
537 static QofQueryPredData *
538 numeric_copy_predicate (
const QofQueryPredData *pd)
541 VERIFY_PDATA_R (query_numeric_type);
542 return qof_query_numeric_predicate (pd->how, pdata->options, pdata->amount);
546 numeric_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
551 if (pd1->options != pd2->options)
return FALSE;
562 pdata->pd.type_name = query_numeric_type;
564 pdata->options = options;
565 pdata->amount = value;
566 return ((QofQueryPredData*)pdata);
570 numeric_to_string (gpointer
object, QofParam *getter)
573 num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
579 debcred_to_string (gpointer
object, QofParam *getter)
582 num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
590 guid_match_predicate (gpointer
object, QofParam *getter,
591 QofQueryPredData *pd)
594 GList *node, *o_list;
597 VERIFY_PREDICATE (query_guid_type);
599 switch (pdata->options)
608 for (node = pdata->guids; node; node = node->next)
611 for (o_list = static_cast<GList*>(
object); o_list;
612 o_list =
static_cast<GList*
>(o_list->next))
614 guid = ((query_guid_getter)getter->param_getfcn) (o_list->data, getter);
615 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
623 if (o_list ==
nullptr)
642 o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
644 for (node = o_list; node; node = node->next)
649 for (node2 = pdata->guids; node2; node2 = node2->next)
651 if (
guid_equal (static_cast<GncGUID*>(node->data),
652 static_cast<GncGUID*
>(node2->data)))
657 if (node2 !=
nullptr)
675 guid = ((query_guid_getter)getter->param_getfcn) (object, getter);
676 for (node = pdata->guids; node; node = node->next)
678 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
683 switch (pdata->options)
687 return (node !=
nullptr);
689 case QOF_GUID_MATCH_NONE:
691 return (node ==
nullptr);
693 case QOF_GUID_MATCH_NULL:
697 PWARN (
"bad match type");
703 guid_free_pdata (QofQueryPredData *pd)
707 VERIFY_PDATA (query_guid_type);
708 for (node = pdata->guids; node; node = node->next)
710 guid_free (static_cast<GncGUID*>(node->data));
712 g_list_free (pdata->guids);
716 static QofQueryPredData *
717 guid_copy_predicate (
const QofQueryPredData *pd)
720 VERIFY_PDATA_R (query_guid_type);
721 return qof_query_guid_predicate (pdata->options, pdata->guids);
725 guid_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
729 GList *l1 = pd1->guids, *l2 = pd2->guids;
731 if (pd1->options != pd2->options)
return FALSE;
732 for (; l1 || l2; l1 = l1->next, l2 = l2->next)
736 if (!
guid_equal (static_cast<GncGUID*>(l1->data),
737 static_cast<GncGUID*
>(l2->data)))
744 qof_query_guid_predicate (
QofGuidMatch options, GList *guid_list)
751 g_return_val_if_fail (options == QOF_GUID_MATCH_NULL,
nullptr);
754 pdata->pd.how = QOF_COMPARE_EQUAL;
755 pdata->pd.type_name = query_guid_type;
756 pdata->options = options;
758 pdata->guids = g_list_copy (guid_list);
759 for (node = pdata->guids; node; node = node->next)
762 *guid = *((
GncGUID *)node->data);
765 return ((QofQueryPredData*)pdata);
772 int32_match_predicate (gpointer
object, QofParam *getter,
773 QofQueryPredData *pd)
778 VERIFY_PREDICATE (query_int32_type);
780 val = ((query_int32_getter)getter->param_getfcn) (object, getter);
785 return (val < pdata->val);
786 case QOF_COMPARE_LTE:
787 return (val <= pdata->val);
788 case QOF_COMPARE_EQUAL:
789 return (val == pdata->val);
791 return (val > pdata->val);
792 case QOF_COMPARE_GTE:
793 return (val >= pdata->val);
794 case QOF_COMPARE_NEQ:
795 return (val != pdata->val);
797 PWARN (
"bad match type: %d", pd->how);
803 int32_compare_func (gpointer a, gpointer b, gint options,
807 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
809 v1 = ((query_int32_getter)getter->param_getfcn)(a, getter);
810 v2 = ((query_int32_getter)getter->param_getfcn)(b, getter);
812 if (v1 < v2)
return -1;
813 if (v1 > v2)
return 1;
818 int32_free_pdata (QofQueryPredData *pd)
821 VERIFY_PDATA (query_int32_type);
825 static QofQueryPredData *
826 int32_copy_predicate (
const QofQueryPredData *pd)
829 VERIFY_PDATA_R (query_int32_type);
830 return qof_query_int32_predicate (pd->how, pdata->val);
834 int32_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
839 return (pd1->val == pd2->val);
846 pdata->pd.type_name = query_int32_type;
849 return ((QofQueryPredData*)pdata);
853 int32_to_string (gpointer
object, QofParam *getter)
855 gint32 num = ((query_int32_getter)getter->param_getfcn)(object, getter);
857 return g_strdup_printf (
"%d", num);
864 int64_match_predicate (gpointer
object, QofParam *getter,
865 QofQueryPredData *pd)
870 VERIFY_PREDICATE (query_int64_type);
872 val = ((query_int64_getter)getter->param_getfcn) (object, getter);
877 return (val < pdata->val);
878 case QOF_COMPARE_LTE:
879 return (val <= pdata->val);
880 case QOF_COMPARE_EQUAL:
881 return (val == pdata->val);
883 return (val > pdata->val);
884 case QOF_COMPARE_GTE:
885 return (val >= pdata->val);
886 case QOF_COMPARE_NEQ:
887 return (val != pdata->val);
889 PWARN (
"bad match type: %d", pd->how);
895 int64_compare_func (gpointer a, gpointer b, gint options,
899 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
901 v1 = ((query_int64_getter)getter->param_getfcn)(a, getter);
902 v2 = ((query_int64_getter)getter->param_getfcn)(b, getter);
904 if (v1 < v2)
return -1;
905 if (v1 > v2)
return 1;
910 int64_free_pdata (QofQueryPredData *pd)
913 VERIFY_PDATA (query_int64_type);
917 static QofQueryPredData *
918 int64_copy_predicate (
const QofQueryPredData *pd)
921 VERIFY_PDATA_R (query_int64_type);
922 return qof_query_int64_predicate (pd->how, pdata->val);
926 int64_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
931 return (pd1->val == pd2->val);
938 pdata->pd.type_name = query_int64_type;
941 return ((QofQueryPredData*)pdata);
945 int64_to_string (gpointer
object, QofParam *getter)
947 gint64 num = ((query_int64_getter)getter->param_getfcn)(object, getter);
949 return g_strdup_printf (
"%" G_GINT64_FORMAT, num);
956 double_match_predicate (gpointer
object, QofParam *getter,
957 QofQueryPredData *pd)
962 VERIFY_PREDICATE (query_double_type);
964 val = ((query_double_getter)getter->param_getfcn) (object, getter);
969 return (val < pdata->val);
970 case QOF_COMPARE_LTE:
971 return (val <= pdata->val);
972 case QOF_COMPARE_EQUAL:
973 return (val == pdata->val);
975 return (val > pdata->val);
976 case QOF_COMPARE_GTE:
977 return (val >= pdata->val);
978 case QOF_COMPARE_NEQ:
979 return (val != pdata->val);
981 PWARN (
"bad match type: %d", pd->how);
987 double_compare_func (gpointer a, gpointer b, gint options,
991 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
993 v1 = ((query_double_getter)getter->param_getfcn) (a, getter);
994 v2 = ((query_double_getter)getter->param_getfcn) (b, getter);
996 if (v1 < v2)
return -1;
997 if (v1 > v2)
return 1;
1002 double_free_pdata (QofQueryPredData *pd)
1005 VERIFY_PDATA (query_double_type);
1009 static QofQueryPredData *
1010 double_copy_predicate (
const QofQueryPredData *pd)
1013 VERIFY_PDATA_R (query_double_type);
1014 return qof_query_double_predicate (pd->how, pdata->val);
1018 double_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1023 return (pd1->val == pd2->val);
1030 pdata->pd.type_name = query_double_type;
1031 pdata->pd.how = how;
1033 return ((QofQueryPredData*)pdata);
1037 double_to_string (gpointer
object, QofParam *getter)
1039 double num = ((query_double_getter)getter->param_getfcn)(object, getter);
1041 return g_strdup_printf (
"%f", num);
1047 boolean_match_predicate (gpointer
object, QofParam *getter,
1048 QofQueryPredData *pd)
1053 VERIFY_PREDICATE (query_boolean_type);
1055 val = ((query_boolean_getter)getter->param_getfcn) (object, getter);
1059 case QOF_COMPARE_EQUAL:
1060 return (val == pdata->val);
1061 case QOF_COMPARE_NEQ:
1062 return (val != pdata->val);
1064 PWARN (
"bad match type: %d", pd->how);
1070 boolean_compare_func (gpointer a, gpointer b, gint options,
1074 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
1075 va = ((query_boolean_getter)getter->param_getfcn) (a, getter);
1076 vb = ((query_boolean_getter)getter->param_getfcn) (b, getter);
1077 if (!va && vb)
return -1;
1078 if (va && !vb)
return 1;
1083 boolean_free_pdata (QofQueryPredData *pd)
1086 VERIFY_PDATA (query_boolean_type);
1090 static QofQueryPredData *
1091 boolean_copy_predicate (
const QofQueryPredData *pd)
1094 VERIFY_PDATA_R (query_boolean_type);
1095 return qof_query_boolean_predicate (pd->how, pdata->val);
1099 boolean_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1104 return (pd1->val == pd2->val);
1111 g_return_val_if_fail (how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ,
nullptr);
1114 pdata->pd.type_name = query_boolean_type;
1115 pdata->pd.how = how;
1117 return ((QofQueryPredData*)pdata);
1121 boolean_to_string (gpointer
object, QofParam *getter)
1123 gboolean num = ((query_boolean_getter)getter->param_getfcn)(object, getter);
1125 return g_strdup_printf (
"%s", (num ?
"X" :
""));
1131 char_match_predicate (gpointer
object, QofParam *getter,
1132 QofQueryPredData *pd)
1137 VERIFY_PREDICATE (query_char_type);
1139 c = ((query_char_getter)getter->param_getfcn) (object, getter);
1141 switch (pdata->options)
1143 case QOF_CHAR_MATCH_ANY:
1144 if (strchr (pdata->char_list, c))
return 1;
1146 case QOF_CHAR_MATCH_NONE:
1147 if (!strchr (pdata->char_list, c))
return 1;
1150 PWARN (
"bad match type");
1156 char_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
1159 g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
1160 va = ((query_char_getter)getter->param_getfcn)(a, getter);
1161 vb = ((query_char_getter)getter->param_getfcn)(b, getter);
1166 char_free_pdata (QofQueryPredData *pd)
1169 VERIFY_PDATA (query_char_type);
1170 g_free (pdata->char_list);
1174 static QofQueryPredData *
1175 char_copy_predicate (
const QofQueryPredData *pd)
1178 VERIFY_PDATA_R (query_char_type);
1179 return qof_query_char_predicate (pdata->options, pdata->char_list);
1183 char_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1188 if (pd1->options != pd2->options)
return FALSE;
1189 return (g_strcmp0 (pd1->char_list, pd2->char_list) == 0);
1193 qof_query_char_predicate (
QofCharMatch options,
const char *chars)
1196 g_return_val_if_fail (chars,
nullptr);
1198 pdata->pd.type_name = query_char_type;
1199 pdata->pd.how = QOF_COMPARE_EQUAL;
1200 pdata->options = options;
1201 pdata->char_list = g_strdup (chars);
1202 return ((QofQueryPredData*)pdata);
1206 qof_query_char_predicate_get_char (
const QofQueryPredData *pd,
char **chars)
1210 if (pdata->pd.type_name != query_char_type)
1213 *chars = g_strdup (pdata->char_list);
1218 char_to_string (gpointer
object, QofParam *getter)
1220 char num = ((query_char_getter)getter->param_getfcn)(object, getter);
1222 return g_strdup_printf (
"%c", num);
1229 choice_match_predicate (gpointer
object, QofParam *getter,
1230 QofQueryPredData *pd)
1233 GList *node, *o_list;
1234 const GncGUID *guid =
nullptr;
1236 VERIFY_PREDICATE (query_choice_type);
1238 switch (pdata->options)
1247 for (node = pdata->guids; node; node = node->next)
1250 for (o_list = static_cast<GList*>(
object); o_list;
1251 o_list =
static_cast<GList*
>(o_list->next))
1253 guid = ((query_choice_getter)getter->param_getfcn) (o_list->data, getter);
1254 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
1262 if (o_list ==
nullptr)
1276 o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
1278 for (node = o_list; node; node = node->next)
1282 for (node2 = pdata->guids; node2; node2 = node2->next)
1284 if (
guid_equal (static_cast<GncGUID*>(node->data),
1285 static_cast<GncGUID*
>(node2->data)))
1289 if (node2 !=
nullptr)
1293 g_list_free(o_list);
1303 guid = ((query_choice_getter)getter->param_getfcn) (object, getter);
1304 for (node = pdata->guids; node; node = node->next)
1306 if (
guid_equal (static_cast<GncGUID*>(node->data), guid))
1311 switch (pdata->options)
1315 return (node !=
nullptr);
1317 case QOF_GUID_MATCH_NONE:
1319 return (node ==
nullptr);
1321 case QOF_GUID_MATCH_NULL:
1325 PWARN (
"bad match type");
1331 choice_free_pdata (QofQueryPredData *pd)
1335 VERIFY_PDATA (query_choice_type);
1336 for (node = pdata->guids; node; node = node->next)
1338 guid_free (static_cast<GncGUID*>(node->data));
1340 g_list_free (pdata->guids);
1344 static QofQueryPredData *
1345 choice_copy_predicate (
const QofQueryPredData *pd)
1348 VERIFY_PDATA_R (query_choice_type);
1349 return qof_query_choice_predicate (pdata->options, pdata->guids);
1353 choice_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1357 GList *l1 = pd1->guids, *l2 = pd2->guids;
1359 if (pd1->options != pd2->options)
return FALSE;
1360 for (; l1 || l2; l1 = l1->next, l2 = l2->next)
1364 if (!
guid_equal (static_cast<GncGUID*>(l1->data),
1365 static_cast<GncGUID*
>(l2->data)))
1372 qof_query_choice_predicate (
QofGuidMatch options, GList *guid_list)
1377 if (
nullptr == guid_list)
return nullptr;
1380 pdata->pd.how = QOF_COMPARE_EQUAL;
1381 pdata->pd.type_name = query_choice_type;
1382 pdata->options = options;
1384 pdata->guids = g_list_copy (guid_list);
1385 for (node = pdata->guids; node; node = node->next)
1388 *guid = *((
GncGUID *)node->data);
1391 return ((QofQueryPredData*)pdata);
1408 qof_query_register_core_object (
QofType core_name,
1409 QofQueryPredicateFunc pred,
1410 QofCompareFunc comp,
1411 QueryPredicateCopyFunc copy,
1412 QueryPredDataFree pd_free,
1413 QueryToString toString,
1414 QueryPredicateEqual pred_equal)
1416 g_return_if_fail (core_name);
1417 g_return_if_fail (*core_name !=
'\0');
1420 g_hash_table_insert (predTable, (
char *)core_name,
1421 reinterpret_cast<void*>(pred));
1424 g_hash_table_insert (cmpTable, (
char *)core_name,
1425 reinterpret_cast<void*>(comp));
1428 g_hash_table_insert (copyTable, (
char *)core_name,
1429 reinterpret_cast<void*>(copy));
1432 g_hash_table_insert (freeTable, (
char *)core_name,
1433 reinterpret_cast<void*>(pd_free));
1436 g_hash_table_insert (toStringTable, (
char *)core_name,
1437 reinterpret_cast<void*>(toString));
1440 g_hash_table_insert (predEqualTable, (
char *)core_name,
1441 reinterpret_cast<void*>(pred_equal));
1444 static void init_tables (
void)
1450 QofQueryPredicateFunc pred;
1451 QofCompareFunc comp;
1452 QueryPredicateCopyFunc copy;
1453 QueryPredDataFree pd_free;
1454 QueryToString toString;
1455 QueryPredicateEqual pred_equal;
1459 QOF_TYPE_STRING, string_match_predicate, string_compare_func,
1460 string_copy_predicate, string_free_pdata, string_to_string,
1461 string_predicate_equal
1464 QOF_TYPE_DATE, date_match_predicate, date_compare_func,
1465 date_copy_predicate, date_free_pdata, date_to_string,
1466 date_predicate_equal
1469 QOF_TYPE_DEBCRED, numeric_match_predicate, numeric_compare_func,
1470 numeric_copy_predicate, numeric_free_pdata, debcred_to_string,
1471 numeric_predicate_equal
1474 QOF_TYPE_NUMERIC, numeric_match_predicate, numeric_compare_func,
1475 numeric_copy_predicate, numeric_free_pdata, numeric_to_string,
1476 numeric_predicate_equal
1479 QOF_TYPE_GUID, guid_match_predicate,
nullptr,
1480 guid_copy_predicate, guid_free_pdata,
nullptr,
1481 guid_predicate_equal
1484 QOF_TYPE_INT32, int32_match_predicate, int32_compare_func,
1485 int32_copy_predicate, int32_free_pdata, int32_to_string,
1486 int32_predicate_equal
1489 QOF_TYPE_INT64, int64_match_predicate, int64_compare_func,
1490 int64_copy_predicate, int64_free_pdata, int64_to_string,
1491 int64_predicate_equal
1494 QOF_TYPE_DOUBLE, double_match_predicate, double_compare_func,
1495 double_copy_predicate, double_free_pdata, double_to_string,
1496 double_predicate_equal
1499 QOF_TYPE_BOOLEAN, boolean_match_predicate, boolean_compare_func,
1500 boolean_copy_predicate, boolean_free_pdata, boolean_to_string,
1501 boolean_predicate_equal
1504 QOF_TYPE_CHAR, char_match_predicate, char_compare_func,
1505 char_copy_predicate, char_free_pdata, char_to_string,
1506 char_predicate_equal
1509 QOF_TYPE_CHOICE, choice_match_predicate,
nullptr,
1510 choice_copy_predicate, choice_free_pdata,
nullptr, choice_predicate_equal
1515 for (i = 0; i < (
sizeof(knownTypes) /
sizeof(*knownTypes)); i++)
1517 qof_query_register_core_object (knownTypes[i].name,
1521 knownTypes[i].pd_free,
1522 knownTypes[i].toString,
1523 knownTypes[i].pred_equal);
1527 static QueryPredicateCopyFunc
1528 qof_query_copy_predicate (
QofType type)
1530 QueryPredicateCopyFunc rc;
1531 g_return_val_if_fail (type,
nullptr);
1532 rc =
reinterpret_cast<QueryPredicateCopyFunc
>(g_hash_table_lookup (copyTable, type));
1536 static QueryPredDataFree
1537 qof_query_predicate_free (
QofType type)
1539 g_return_val_if_fail (type,
nullptr);
1540 return reinterpret_cast<QueryPredDataFree
>(g_hash_table_lookup (freeTable, type));
1546 void qof_query_core_init (
void)
1549 if (initialized)
return;
1553 predTable = g_hash_table_new (g_str_hash, g_str_equal);
1554 cmpTable = g_hash_table_new (g_str_hash, g_str_equal);
1555 copyTable = g_hash_table_new (g_str_hash, g_str_equal);
1556 freeTable = g_hash_table_new (g_str_hash, g_str_equal);
1557 toStringTable = g_hash_table_new (g_str_hash, g_str_equal);
1558 predEqualTable = g_hash_table_new (g_str_hash, g_str_equal);
1563 void qof_query_core_shutdown (
void)
1565 if (!initialized)
return;
1566 initialized = FALSE;
1568 g_hash_table_destroy (predTable);
1569 g_hash_table_destroy (cmpTable);
1570 g_hash_table_destroy (copyTable);
1571 g_hash_table_destroy (freeTable);
1572 g_hash_table_destroy (toStringTable);
1573 g_hash_table_destroy (predEqualTable);
1576 QofQueryPredicateFunc
1577 qof_query_core_get_predicate (
QofType type)
1579 g_return_val_if_fail (type,
nullptr);
1580 return reinterpret_cast<QofQueryPredicateFunc
>(g_hash_table_lookup (predTable, type));
1584 qof_query_core_get_compare (
QofType type)
1586 g_return_val_if_fail (type,
nullptr);
1587 return reinterpret_cast<QofCompareFunc
>(g_hash_table_lookup (cmpTable, type));
1593 QueryPredDataFree free_fcn;
1595 g_return_if_fail (pdata);
1596 g_return_if_fail (pdata->type_name);
1598 free_fcn = qof_query_predicate_free (pdata->type_name);
1605 QueryPredicateCopyFunc copy;
1607 g_return_val_if_fail (pdata,
nullptr);
1608 g_return_val_if_fail (pdata->type_name,
nullptr);
1610 copy = qof_query_copy_predicate (pdata->type_name);
1611 return (copy (pdata));
1618 QueryToString toString;
1620 g_return_val_if_fail (type,
nullptr);
1621 g_return_val_if_fail (
object,
nullptr);
1622 g_return_val_if_fail (getter,
nullptr);
1624 toString =
reinterpret_cast<QueryToString
>(g_hash_table_lookup (toStringTable, type));
1625 g_return_val_if_fail (toString,
nullptr);
1627 return toString (
object, getter);
1631 qof_query_core_predicate_equal (
const QofQueryPredData *p1,
const QofQueryPredData *p2)
1633 QueryPredicateEqual pred_equal;
1635 if (p1 == p2)
return TRUE;
1636 if (!p1 || !p2)
return FALSE;
1638 if (p1->how != p2->how)
return FALSE;
1639 if (g_strcmp0 (p1->type_name, p2->type_name))
return FALSE;
1641 pred_equal =
reinterpret_cast<QueryPredicateEqual
>(g_hash_table_lookup (predEqualTable, p1->type_name));
1642 g_return_val_if_fail (pred_equal, FALSE);
1644 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.
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.