From 369fdff9e2ddaa96acb1bf3498d027011796f2e8 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sun, 9 Nov 2014 14:49:20 +0100 Subject: [PATCH] store: Let array iterators support regex matches as well. That is, all operators are supported now. --- src/core/store-private.h | 16 ++++-- src/core/store_lookup.c | 121 +++++++++++++++++++++------------------ src/frontend/analyzer.c | 4 +- 3 files changed, 79 insertions(+), 62 deletions(-) diff --git a/src/core/store-private.h b/src/core/store-private.h index 953a882..d2ea3f9 100644 --- a/src/core/store-private.h +++ b/src/core/store-private.h @@ -138,17 +138,21 @@ enum { MATCHER_NOT, MATCHER_ANY, MATCHER_ALL, + MATCHER_IN, + + /* unary operators */ + MATCHER_ISNULL, + MATCHER_ISNNULL, + + /* ary operators */ MATCHER_LT, MATCHER_LE, MATCHER_EQ, MATCHER_NE, MATCHER_GE, MATCHER_GT, - MATCHER_IN, MATCHER_REGEX, MATCHER_NREGEX, - MATCHER_ISNULL, - MATCHER_ISNNULL, }; #define MATCHER_SYM(t) \ @@ -157,17 +161,17 @@ enum { : ((t) == MATCHER_NOT) ? "NOT" \ : ((t) == MATCHER_ANY) ? "ANY" \ : ((t) == MATCHER_ALL) ? "ALL" \ + : ((t) == MATCHER_IN) ? "IN" \ + : ((t) == MATCHER_ISNULL) ? "IS NULL" \ + : ((t) == MATCHER_ISNNULL) ? "IS NOT NULL" \ : ((t) == MATCHER_LT) ? "<" \ : ((t) == MATCHER_LE) ? "<=" \ : ((t) == MATCHER_EQ) ? "=" \ : ((t) == MATCHER_NE) ? "!=" \ : ((t) == MATCHER_GE) ? ">=" \ : ((t) == MATCHER_GT) ? ">" \ - : ((t) == MATCHER_IN) ? "IN" \ : ((t) == MATCHER_REGEX) ? "=~" \ : ((t) == MATCHER_NREGEX) ? "!~" \ - : ((t) == MATCHER_ISNULL) ? "IS NULL" \ - : ((t) == MATCHER_ISNNULL) ? "IS NOT NULL" \ : "UNKNOWN") /* matcher base type */ diff --git a/src/core/store_lookup.c b/src/core/store_lookup.c index eab37b4..e5dad19 100644 --- a/src/core/store_lookup.c +++ b/src/core/store_lookup.c @@ -59,7 +59,7 @@ * is enabled, compare the string values in case of a type mismatch. */ static int -cmp_value(int op, sdb_data_t *v1, sdb_data_t *v2, _Bool strcmp_fallback) +match_cmp_value(int op, sdb_data_t *v1, sdb_data_t *v2, _Bool strcmp_fallback) { int status; @@ -87,7 +87,49 @@ cmp_value(int op, sdb_data_t *v1, sdb_data_t *v2, _Bool strcmp_fallback) else if (op == MATCHER_GT) return status > 0; return 0; -} /* cmp_value */ +} /* match_cmp_value */ + +static int +match_regex_value(int op, sdb_data_t *v, sdb_data_t *re) +{ + char value[sdb_data_strlen(v) + 1]; + int status = 0; + + assert((op == MATCHER_REGEX) + || (op == MATCHER_NREGEX)); + + if (sdb_data_isnull(v) || sdb_data_isnull(re)) + return 0; + + if (re->type == SDB_TYPE_STRING) { + sdb_data_t tmp = SDB_DATA_INIT; + + if (sdb_data_parse(re->data.string, SDB_TYPE_REGEX, &tmp)) + return 0; + + sdb_data_free_datum(re); + *re = tmp; + } + else if (re->type != SDB_TYPE_REGEX) + return 0; + + if (sdb_data_format(v, value, sizeof(value), SDB_UNQUOTED) < 0) + status = 0; + else if (! regexec(&re->data.re.regex, value, 0, NULL, 0)) + status = 1; + + if (op == MATCHER_NREGEX) + return !status; + return status; +} /* match_regex_value */ + +static int +match_value(int op, sdb_data_t *v1, sdb_data_t *v2, _Bool strcmp_fallback) +{ + if ((op == MATCHER_REGEX) || (op == MATCHER_NREGEX)) + return match_regex_value(op, v1, v2); + return match_cmp_value(op, v1, v2, strcmp_fallback); +} /* match_value */ static int match_logical(sdb_store_matcher_t *m, sdb_store_obj_t *obj, @@ -130,8 +172,8 @@ match_iter_array(sdb_store_matcher_t *m, sdb_store_obj_t *obj, int status; - /* TODO: fully support arbitrary operators (?) */ - if ((ITER_M(m)->m->type < MATCHER_LT) || (MATCHER_GT < ITER_M(m)->m->type)) + if ((ITER_M(m)->m->type < MATCHER_LT) + || (MATCHER_NREGEX < ITER_M(m)->m->type)) return 0; e1 = CMP_M(ITER_M(m)->m)->left; @@ -160,7 +202,7 @@ match_iter_array(sdb_store_matcher_t *m, sdb_store_obj_t *obj, break; } - if (cmp_value(ITER_M(m)->m->type, &v, &v2, + if (match_value(ITER_M(m)->m->type, &v, &v2, (e1->data_type) < 0 || (e2->data_type < 0))) { if (! all) { status = 1; @@ -250,7 +292,7 @@ match_cmp(sdb_store_matcher_t *m, sdb_store_obj_t *obj, return 0; } - status = cmp_value(m->type, &v1, &v2, + status = match_cmp_value(m->type, &v1, &v2, (e1->data_type) < 0 || (e2->data_type < 0)); sdb_data_free_datum(&v1); @@ -283,61 +325,26 @@ 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; + sdb_data_t regex = SDB_DATA_INIT, 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)) + return 0; + else if (! CMP_M(m)->right->type) + regex = CMP_M(m)->right->data; + else if (sdb_store_expr_eval(CMP_M(m)->right, obj, ®ex, filter)) { + sdb_data_free_datum(&v); + return 0; } - if ((sdb_store_expr_eval(CMP_M(m)->left, obj, &v, filter)) - || (sdb_data_isnull(&v))) - status = INT_MAX; - 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; - } + status = match_regex_value(m->type, &v, ®ex); - if (free_regex) - regfree(®ex); sdb_data_free_datum(&v); - if (status == INT_MAX) - return 0; - if (m->type == MATCHER_NREGEX) - return !status; + if (CMP_M(m)->right->type) + sdb_data_free_datum(®ex); return status; } /* match_regex */ @@ -376,17 +383,21 @@ matchers[] = { match_unary, match_iter, match_iter, + match_in, + + /* unary operators */ + match_isnull, + match_isnull, + + /* ary operators */ match_cmp, match_cmp, match_cmp, match_cmp, match_cmp, match_cmp, - match_in, match_regex, match_regex, - match_isnull, - match_isnull, }; /* diff --git a/src/frontend/analyzer.c b/src/frontend/analyzer.c index 20864ca..c1b9d01 100644 --- a/src/frontend/analyzer.c +++ b/src/frontend/analyzer.c @@ -127,7 +127,9 @@ analyze_matcher(int context, sdb_store_matcher_t *m, sdb_strbuf_t *errbuf) && (ITER_M(m)->m->type != MATCHER_EQ) && (ITER_M(m)->m->type != MATCHER_NE) && (ITER_M(m)->m->type != MATCHER_GE) - && (ITER_M(m)->m->type != MATCHER_GT)) { + && (ITER_M(m)->m->type != MATCHER_GT) + && (ITER_M(m)->m->type != MATCHER_REGEX) + && (ITER_M(m)->m->type != MATCHER_NREGEX)) { iter_array_error(errbuf, m->type, CMP_M(ITER_M(m)->m)->left->data_type, ITER_M(m)->m->type, -- 2.30.2