X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fcore%2Fstore_lookup.c;h=21e0ba4ef4dd13d30d1fcfe7d9bf6c9a0465fafa;hb=10a65c7e584820b403567bc849581bb0c3176ff5;hp=9968aba468eab75c8dfc8b4da86c915504c1c3e9;hpb=f257d14eeca9e263e561f2f597b31bd9b0f4e931;p=sysdb.git diff --git a/src/core/store_lookup.c b/src/core/store_lookup.c index 9968aba..21e0ba4 100644 --- a/src/core/store_lookup.c +++ b/src/core/store_lookup.c @@ -435,6 +435,16 @@ match_cmp_eq(sdb_store_matcher_t *m, sdb_store_obj_t *obj, return (status != INT_MAX) && (! status); } /* match_cmp_eq */ +static int +match_cmp_ne(sdb_store_matcher_t *m, sdb_store_obj_t *obj, + sdb_store_matcher_t *filter) +{ + int status; + assert(m->type == MATCHER_CMP_NE); + status = cmp_expr(CMP_M(m)->left, CMP_M(m)->right, obj, filter); + return (status != INT_MAX) && status; +} /* match_cmp_ne */ + static int match_cmp_ge(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) @@ -455,14 +465,86 @@ match_cmp_gt(sdb_store_matcher_t *m, sdb_store_obj_t *obj, return (status != INT_MAX) && (status > 0); } /* match_cmp_gt */ +static int +match_regex(sdb_store_matcher_t *m, sdb_store_obj_t *obj, + sdb_store_matcher_t *filter) +{ + sdb_data_t v = SDB_DATA_INIT; + int status = 0; + + regex_t regex; + _Bool free_regex = 0; + + assert((m->type == MATCHER_REGEX) + || (m->type == MATCHER_NREGEX)); + + if (! CMP_M(m)->right->type) { + assert(CMP_M(m)->right->data.type == SDB_TYPE_REGEX); + regex = CMP_M(m)->right->data.data.re.regex; + } + else { + sdb_data_t tmp = SDB_DATA_INIT; + char *raw; + + if (sdb_store_expr_eval(CMP_M(m)->right, obj, &tmp, filter)) + return 0; + + if (tmp.type != SDB_TYPE_STRING) { + sdb_data_free_datum(&tmp); + return 0; + } + + raw = tmp.data.string; + if (sdb_data_parse(raw, SDB_TYPE_REGEX, &tmp)) { + free(raw); + return 0; + } + + regex = tmp.data.re.regex; + free_regex = 1; + free(tmp.data.re.raw); + free(raw); + } + + if (sdb_store_expr_eval(CMP_M(m)->left, obj, &v, filter)) + status = 0; + else { + char value[sdb_data_strlen(&v) + 1]; + if (sdb_data_format(&v, value, sizeof(value), SDB_UNQUOTED) < 0) + status = 0; + else if (! regexec(®ex, value, 0, NULL, 0)) + status = 1; + } + + if (free_regex) + regfree(®ex); + sdb_data_free_datum(&v); + if (m->type == MATCHER_NREGEX) + return !status; + return status; +} /* match_regex */ + static int match_isnull(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { - assert(m->type == MATCHER_ISNULL); - if (obj->type != SDB_HOST) - return 0; - return attr_get(HOST(obj), ISNULL_M(m)->attr_name, filter) == NULL; + sdb_data_t v = SDB_DATA_INIT; + int status; + + assert((m->type == MATCHER_ISNULL) || (m->type == MATCHER_ISNNULL)); + + /* TODO: this might hide real errors; + * improve error reporting and propagation */ + if (sdb_store_expr_eval(ISNULL_M(m)->expr, obj, &v, filter) + || sdb_data_isnull(&v)) + status = 1; + else + status = 0; + + sdb_data_free_datum(&v); + if (m->type == MATCHER_ISNNULL) + return !status; + return status; } /* match_isnull */ typedef int (*matcher_cb)(sdb_store_matcher_t *, sdb_store_obj_t *, @@ -488,8 +570,12 @@ matchers[] = { match_cmp_lt, match_cmp_le, match_cmp_eq, + match_cmp_ne, match_cmp_ge, match_cmp_gt, + match_regex, + match_regex, + match_isnull, match_isnull, }; @@ -878,33 +964,30 @@ uop_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen) static int isnull_matcher_init(sdb_object_t *obj, va_list ap) { - const char *name; - M(obj)->type = va_arg(ap, int); - if (M(obj)->type != MATCHER_ISNULL) + if ((M(obj)->type != MATCHER_ISNULL) && (M(obj)->type != MATCHER_ISNNULL)) return -1; - name = va_arg(ap, const char *); - if (! name) - return -1; - ISNULL_M(obj)->attr_name = strdup(name); - if (! ISNULL_M(obj)->attr_name) - return -1; + ISNULL_M(obj)->expr = va_arg(ap, sdb_store_expr_t *); + sdb_object_ref(SDB_OBJ(ISNULL_M(obj)->expr)); return 0; } /* isnull_matcher_init */ static void isnull_matcher_destroy(sdb_object_t *obj) { - if (ISNULL_M(obj)->attr_name) - free(ISNULL_M(obj)->attr_name); - ISNULL_M(obj)->attr_name = NULL; + sdb_object_deref(SDB_OBJ(ISNULL_M(obj)->expr)); + ISNULL_M(obj)->expr = NULL; } /* isnull_matcher_destroy */ static char * isnull_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen) { - snprintf(buf, buflen, "(IS NULL, ATTR[%s])", ISNULL_M(m)->attr_name); + /* XXX */ + if (m->type == MATCHER_ISNULL) + strncpy(buf, "(IS NULL)", buflen); + else + strncpy(buf, "(IS NOT NULL)", buflen); return buf; } /* isnull_tostring */ @@ -980,6 +1063,10 @@ matchers_tostring[] = { cmp_tostring, cmp_tostring, cmp_tostring, + cmp_tostring, + cmp_tostring, + cmp_tostring, + isnull_tostring, isnull_tostring, }; @@ -1110,6 +1197,13 @@ sdb_store_cmp_eq(sdb_store_expr_t *left, sdb_store_expr_t *right) MATCHER_CMP_EQ, left, right)); } /* sdb_store_cmp_eq */ +sdb_store_matcher_t * +sdb_store_cmp_ne(sdb_store_expr_t *left, sdb_store_expr_t *right) +{ + return M(sdb_object_create("ne-matcher", cmp_type, + MATCHER_CMP_NE, left, right)); +} /* sdb_store_cmp_ne */ + sdb_store_matcher_t * sdb_store_cmp_ge(sdb_store_expr_t *left, sdb_store_expr_t *right) { @@ -1125,12 +1219,70 @@ sdb_store_cmp_gt(sdb_store_expr_t *left, sdb_store_expr_t *right) } /* sdb_store_cmp_gt */ sdb_store_matcher_t * -sdb_store_isnull_matcher(const char *attr_name) +sdb_store_regex_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) +{ + if (! right->type) { + if ((right->data.type != SDB_TYPE_STRING) + && (right->data.type != SDB_TYPE_REGEX)) + return NULL; + + if (right->data.type == SDB_TYPE_STRING) { + char *raw = right->data.data.string; + if (sdb_data_parse(raw, SDB_TYPE_REGEX, &right->data)) + return NULL; + free(raw); + } + } + return M(sdb_object_create("regex-matcher", cmp_type, + MATCHER_REGEX, left, right)); +} /* sdb_store_regex_matcher */ + +sdb_store_matcher_t * +sdb_store_nregex_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) +{ + sdb_store_matcher_t *m = sdb_store_regex_matcher(left, right); + if (! m) + return NULL; + m->type = MATCHER_NREGEX; + return m; +} /* sdb_store_nregex_matcher */ + +sdb_store_matcher_t * +sdb_store_isnull_matcher(sdb_store_expr_t *expr) { return M(sdb_object_create("isnull-matcher", isnull_type, - MATCHER_ISNULL, attr_name)); + MATCHER_ISNULL, expr)); } /* sdb_store_isnull_matcher */ +sdb_store_matcher_t * +sdb_store_isnnull_matcher(sdb_store_expr_t *expr) +{ + return M(sdb_object_create("isnull-matcher", isnull_type, + MATCHER_ISNNULL, expr)); +} /* sdb_store_isnnull_matcher */ + +sdb_store_matcher_op_cb +sdb_store_parse_matcher_op(const char *op) +{ + if (! strcasecmp(op, "<")) + return sdb_store_cmp_lt; + else if (! strcasecmp(op, "<=")) + return sdb_store_cmp_le; + else if (! strcasecmp(op, "=")) + return sdb_store_cmp_eq; + else if (! strcasecmp(op, "!=")) + return sdb_store_cmp_ne; + else if (! strcasecmp(op, ">=")) + return sdb_store_cmp_ge; + else if (! strcasecmp(op, ">")) + return sdb_store_cmp_gt; + else if (! strcasecmp(op, "=~")) + return sdb_store_regex_matcher; + else if (! strcasecmp(op, "!~")) + return sdb_store_nregex_matcher; + return NULL; +} /* sdb_store_parse_matcher_op */ + int sdb_store_parse_object_type_plural(const char *name) { @@ -1208,13 +1360,7 @@ parse_attr_cmp(const char *attr, const char *op, sdb_store_expr_t *expr) if (! attr) return NULL; - if (! strcasecmp(op, "IS")) { - if (! expr) - return sdb_store_isnull_matcher(attr); - else - return NULL; - } - else if (! expr) + if (! expr) return NULL; else if (parse_cond_op(op, &matcher, &inv)) return NULL;