Code

store: Let array iterators support regex matches as well.
authorSebastian Harl <sh@tokkee.org>
Sun, 9 Nov 2014 13:49:20 +0000 (14:49 +0100)
committerSebastian Harl <sh@tokkee.org>
Sun, 9 Nov 2014 13:49:20 +0000 (14:49 +0100)
That is, all operators are supported now.

src/core/store-private.h
src/core/store_lookup.c
src/frontend/analyzer.c

index 953a8826c741abbb21e0b8b3e9871922da3e00d8..d2ea3f9a08c9f443584a4d021df97e02d1638111 100644 (file)
@@ -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 */
index eab37b4787bb2ba7e752ab6c06eb4b8bc019a7ea..e5dad19a960b2c18bebd8172452a58ac41bcb8fd 100644 (file)
@@ -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, &regex, 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(&regex, value, 0, NULL, 0))
-                       status = 1;
-       }
+       status = match_regex_value(m->type, &v, &regex);
 
-       if (free_regex)
-               regfree(&regex);
        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(&regex);
        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,
 };
 
 /*
index 20864cae4d348ca2e3072e1e48945fd157cb6c66..c1b9d01ef19494188dddd2d3dd916601715e924a 100644 (file)
@@ -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,