Code

Let the first operand of ANY/ALL iterators be an expression.
authorSebastian Harl <sh@tokkee.org>
Sun, 8 Mar 2015 10:56:33 +0000 (11:56 +0100)
committerSebastian Harl <sh@tokkee.org>
Sun, 8 Mar 2015 10:56:33 +0000 (11:56 +0100)
For now, the same restrictions apply as before (iterate child objects or the
backends field). This is in preparation for more generic iterators.

src/core/store-private.h
src/core/store_lookup.c
src/frontend/analyzer.c
src/frontend/grammar.y
src/include/core/store.h
t/unit/core/store_lookup_test.c
t/unit/frontend/parser_test.c

index 4ef11f917ac22eb875a912c7839868c99c9d54dd..cde2216327582968966d6f053adc62174ee0de99 100644 (file)
@@ -214,7 +214,7 @@ typedef struct {
 /* iter matcher */
 typedef struct {
        sdb_store_matcher_t super;
-       int type;
+       sdb_store_expr_t *iter;
        sdb_store_matcher_t *m;
 } iter_matcher_t;
 #define ITER_M(m) ((iter_matcher_t *)(m))
index 2e73780fbf8da67f51c7e040470d051668b20621..94f95cc5188f4c03d146bd1b7157adab3f62f76f 100644 (file)
@@ -38,6 +38,7 @@
 #include "sysdb.h"
 #include "core/store-private.h"
 #include "core/object.h"
+#include "utils/error.h"
 
 #include <assert.h>
 
@@ -252,26 +253,32 @@ match_iter(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
                sdb_store_matcher_t *filter)
 {
        sdb_avltree_iter_t *iter = NULL;
-       int status;
+       int type, status;
        int all = (int)(m->type == MATCHER_ALL);
 
        assert((m->type == MATCHER_ANY) || (m->type == MATCHER_ALL));
 
-       if (ITER_M(m)->type == SDB_FIELD_BACKEND)
+       if (ITER_M(m)->iter->type == FIELD_VALUE) {
+               if (ITER_M(m)->iter->data.data.integer != SDB_FIELD_BACKEND)
+                       return 0;
                return match_iter_array(m, obj, filter);
+       }
 
+       assert(ITER_M(m)->iter->type == TYPED_EXPR);
+
+       type = (int)ITER_M(m)->iter->data.data.integer;
        if (obj->type == SDB_HOST) {
-               if (ITER_M(m)->type == SDB_SERVICE)
+               if (type == SDB_SERVICE)
                        iter = sdb_avltree_get_iter(HOST(obj)->services);
-               else if (ITER_M(m)->type == SDB_METRIC)
+               else if (type == SDB_METRIC)
                        iter = sdb_avltree_get_iter(HOST(obj)->metrics);
-               else if (ITER_M(m)->type == SDB_ATTRIBUTE)
+               else if (type == SDB_ATTRIBUTE)
                        iter = sdb_avltree_get_iter(HOST(obj)->attributes);
        } else if (obj->type == SDB_SERVICE) {
-               if (ITER_M(m)->type == SDB_ATTRIBUTE)
+               if (type == SDB_ATTRIBUTE)
                        iter = sdb_avltree_get_iter(SVC(obj)->attributes);
        } else if (obj->type == SDB_METRIC) {
-               if (ITER_M(m)->type == SDB_ATTRIBUTE)
+               if (type == SDB_ATTRIBUTE)
                        iter = sdb_avltree_get_iter(METRIC(obj)->attributes);
        }
 
@@ -459,19 +466,21 @@ static int
 iter_matcher_init(sdb_object_t *obj, va_list ap)
 {
        M(obj)->type = va_arg(ap, int);
-       ITER_M(obj)->type = va_arg(ap, int);
+       ITER_M(obj)->iter = va_arg(ap, sdb_store_expr_t *);
        ITER_M(obj)->m = va_arg(ap, sdb_store_matcher_t *);
 
-       if (! ITER_M(obj)->m)
-               return -1;
-
+       sdb_object_ref(SDB_OBJ(ITER_M(obj)->iter));
        sdb_object_ref(SDB_OBJ(ITER_M(obj)->m));
+
+       if ((! ITER_M(obj)->iter) || (! ITER_M(obj)->m))
+               return -1;
        return 0;
 } /* iter_matcher_init */
 
 static void
 iter_matcher_destroy(sdb_object_t *obj)
 {
+       sdb_object_deref(SDB_OBJ(ITER_M(obj)->iter));
        sdb_object_deref(SDB_OBJ(ITER_M(obj)->m));
 } /* iter_matcher_destroy */
 
@@ -573,23 +582,27 @@ static sdb_type_t isnull_type = {
  */
 
 sdb_store_matcher_t *
-sdb_store_any_matcher(int type, sdb_store_matcher_t *m)
+sdb_store_any_matcher(sdb_store_expr_t *iter, sdb_store_matcher_t *m)
 {
-       if ((type != SDB_SERVICE) && (type != SDB_METRIC)
-                       && (type != SDB_ATTRIBUTE) && (type != SDB_FIELD_BACKEND))
+       if ((m->type < MATCHER_LT) || (MATCHER_NREGEX < m->type)) {
+               sdb_log(SDB_LOG_ERR, "store: Invalid ANY -> %s matcher "
+                               "(invalid operator)", MATCHER_SYM(m->type));
                return NULL;
+       }
        return M(sdb_object_create("any-matcher", iter_type,
-                               MATCHER_ANY, type, m));
+                               MATCHER_ANY, iter, m));
 } /* sdb_store_any_matcher */
 
 sdb_store_matcher_t *
-sdb_store_all_matcher(int type, sdb_store_matcher_t *m)
+sdb_store_all_matcher(sdb_store_expr_t *iter, sdb_store_matcher_t *m)
 {
-       if ((type != SDB_SERVICE) && (type != SDB_METRIC)
-                       && (type != SDB_ATTRIBUTE) && (type != SDB_FIELD_BACKEND))
+       if ((m->type < MATCHER_LT) || (MATCHER_NREGEX < m->type)) {
+               sdb_log(SDB_LOG_ERR, "store: Invalid ALL -> %s matcher "
+                               "(invalid operator)", MATCHER_SYM(m->type));
                return NULL;
+       }
        return M(sdb_object_create("all-matcher", iter_type,
-                               MATCHER_ALL, type, m));
+                               MATCHER_ALL, iter, m));
 } /* sdb_store_all_matcher */
 
 sdb_store_matcher_t *
index 62bae1c134904af8a84ede0d7906912fe3704f3e..b5d0e0825ce785dd09468d2474676bd7888749b8 100644 (file)
@@ -151,32 +151,40 @@ analyze_matcher(int context, int parent_type,
 
                case MATCHER_ANY:
                case MATCHER_ALL:
+               {
+                       int type;
                        assert(ITER_M(m)->m);
+                       if ((ITER_M(m)->iter->type == TYPED_EXPR)
+                                       || (ITER_M(m)->iter->type == FIELD_VALUE)) {
+                               type = (int)ITER_M(m)->iter->data.data.integer;
+                       }
+                       else {
+                               iter_error(errbuf, m->type, -1, context);
+                               return -1;
+                       }
                        if ((context != SDB_HOST)
                                        && (context != SDB_SERVICE)
                                        && (context != SDB_METRIC)) {
-                               iter_error(errbuf, m->type, ITER_M(m)->type, context);
+                               iter_error(errbuf, m->type, type, context);
                                return -1;
                        }
-                       if (ITER_M(m)->type == context) {
-                               iter_error(errbuf, m->type, ITER_M(m)->type, context);
+                       if (type == context) {
+                               iter_error(errbuf, m->type, type, context);
                                return -1;
                        }
-                       if ((ITER_M(m)->type != SDB_SERVICE)
-                                       && (ITER_M(m)->type != SDB_METRIC)
-                                       && (ITER_M(m)->type != SDB_ATTRIBUTE)
-                                       && (ITER_M(m)->type != SDB_FIELD_BACKEND)) {
-                               iter_error(errbuf, m->type, ITER_M(m)->type, context);
+                       if ((type != SDB_SERVICE)
+                                       && (type != SDB_METRIC)
+                                       && (type != SDB_ATTRIBUTE)
+                                       && (type != SDB_FIELD_BACKEND)) {
+                               iter_error(errbuf, m->type, type, context);
                                return -1;
                        }
-                       if ((context == SDB_SERVICE)
-                                       && (ITER_M(m)->type == SDB_METRIC)) {
-                               iter_error(errbuf, m->type, ITER_M(m)->type, context);
+                       if ((context == SDB_SERVICE) && (type == SDB_METRIC)) {
+                               iter_error(errbuf, m->type, type, context);
                                return -1;
                        }
-                       else if ((context == SDB_METRIC)
-                                       && (ITER_M(m)->type == SDB_SERVICE)) {
-                               iter_error(errbuf, m->type, ITER_M(m)->type, context);
+                       else if ((context == SDB_METRIC) && (type == SDB_SERVICE)) {
+                               iter_error(errbuf, m->type, type, context);
                                return -1;
                        }
                        /* any ary operator will do but these are the once
@@ -195,7 +203,7 @@ analyze_matcher(int context, int parent_type,
                                                CMP_M(ITER_M(m)->m)->right->data_type);
                                return -1;
                        }
-                       if (ITER_M(m)->type == SDB_FIELD_BACKEND) {
+                       if (type == SDB_FIELD_BACKEND) {
                                if (CMP_M(ITER_M(m)->m)->right->data_type < 0)
                                        return 0; /* skip further type checks */
                                if (CMP_M(ITER_M(m)->m)->right->data_type & SDB_TYPE_ARRAY) {
@@ -214,10 +222,10 @@ analyze_matcher(int context, int parent_type,
                                        return -1;
                                }
                        }
-                       else if (analyze_matcher(ITER_M(m)->type, m->type,
-                                               ITER_M(m)->m, errbuf))
+                       else if (analyze_matcher(type, m->type, ITER_M(m)->m, errbuf))
                                return -1;
                        break;
+               }
 
                case MATCHER_LT:
                case MATCHER_LE:
index 4021031d4e8f3dd29e39e03634decfe98e1b22cc..ac899e3708212fe78b928fe6977fb86c6d5cfb2b 100644 (file)
@@ -48,7 +48,7 @@
  */
 
 static sdb_store_matcher_t *
-name_iter_matcher(int m_type, int type, const char *cmp,
+name_iter_matcher(int m_type, sdb_store_expr_t *iter, const char *cmp,
                sdb_store_expr_t *expr);
 
 /*
@@ -169,7 +169,6 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...);
 %type <expr> expression arithmetic_expression object_expression
 
 %type <integer> object_type object_type_plural
-%type <integer> iterable
 %type <integer> field
 
 %type <sstr> cmp
@@ -535,15 +534,17 @@ compare_matcher:
                        sdb_object_deref(SDB_OBJ($3));
                }
        |
-       ANY iterable cmp expression
+       ANY expression cmp expression
                {
                        $$ = name_iter_matcher(MATCHER_ANY, $2, $3, $4);
+                       sdb_object_deref(SDB_OBJ($2));
                        sdb_object_deref(SDB_OBJ($4));
                }
        |
-       ALL iterable cmp expression
+       ALL expression cmp expression
                {
                        $$ = name_iter_matcher(MATCHER_ALL, $2, $3, $4);
+                       sdb_object_deref(SDB_OBJ($2));
                        sdb_object_deref(SDB_OBJ($4));
                }
        |
@@ -655,6 +656,12 @@ object_expression:
                        sdb_object_deref(SDB_OBJ($3));
                }
        |
+       ATTRIBUTE_T '.' object_expression
+               {
+                       $$ = sdb_store_expr_typed(SDB_ATTRIBUTE, $3);
+                       sdb_object_deref(SDB_OBJ($3));
+               }
+       |
        field
                {
                        $$ = sdb_store_expr_fieldvalue($1);
@@ -683,16 +690,6 @@ object_type_plural:
        METRICS_T { $$ = SDB_METRIC; }
        ;
 
-iterable:
-       SERVICE_T '.' NAME_T { $$ = SDB_SERVICE; }
-       |
-       METRIC_T '.' NAME_T { $$ = SDB_METRIC; }
-       |
-       ATTRIBUTE_T '.' NAME_T { $$ = SDB_ATTRIBUTE; }
-       |
-       BACKEND_T { $$ = SDB_FIELD_BACKEND; }
-       ;
-
 field:
        NAME_T { $$ = SDB_FIELD_NAME; }
        |
@@ -863,30 +860,19 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...)
 } /* sdb_fe_yyerrorf */
 
 static sdb_store_matcher_t *
-name_iter_matcher(int m_type, int type, const char *cmp,
+name_iter_matcher(int type, sdb_store_expr_t *iter, const char *cmp,
                sdb_store_expr_t *expr)
 {
        sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op(cmp);
-       sdb_store_expr_t *e;
        sdb_store_matcher_t *m, *tmp = NULL;
        assert(cb);
 
-       /* hosts are never iterable */
-       if (type == SDB_HOST) {
-               return NULL;
-       }
-
-       if (type == SDB_FIELD_BACKEND)
-               e = sdb_store_expr_fieldvalue(type);
-       else
-               e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME);
-       m = cb(e, expr);
-       if (m_type == MATCHER_ANY)
-               tmp = sdb_store_any_matcher(type, m);
-       else if (m_type == MATCHER_ALL)
-               tmp = sdb_store_all_matcher(type, m);
+       m = cb(iter, expr);
+       if (type == MATCHER_ANY)
+               tmp = sdb_store_any_matcher(iter, m);
+       else if (type == MATCHER_ALL)
+               tmp = sdb_store_all_matcher(iter, m);
        sdb_object_deref(SDB_OBJ(m));
-       sdb_object_deref(SDB_OBJ(e));
        return tmp;
 } /* name_iter_matcher */
 
index e83ff8486ebcf2a8d21a49a9c8da87ddeceba9ec..3722a7262d6aa773d4f3210e12217e7505d449f1 100644 (file)
@@ -483,19 +483,21 @@ sdb_store_inv_matcher(sdb_store_matcher_t *m);
 
 /*
  * sdb_store_any_matcher:
- * Creates a matcher iterating over objects of the specified type. It matches
- * if *any* of those objects match 'm'.
+ * Creates a matcher iterating over values of the first expression (which has
+ * to be iterable). It matches if *any* of those elements match 'm'. 'm' has
+ * to be an ary operation with the left operand unset.
  */
 sdb_store_matcher_t *
-sdb_store_any_matcher(int type, sdb_store_matcher_t *m);
+sdb_store_any_matcher(sdb_store_expr_t *iter, sdb_store_matcher_t *m);
 
 /*
  * sdb_store_all_matcher:
- * Creates a matcher iterating over objects of the specified type. It matches
- * if *all* of those objects match 'm'.
+ * Creates a matcher iterating over values of the first expression (which has
+ * to be iterable). It matches if *all* of those elements match 'm'. 'm' has
+ * to be an ary operation with the left operand unset.
  */
 sdb_store_matcher_t *
-sdb_store_all_matcher(int type, sdb_store_matcher_t *m);
+sdb_store_all_matcher(sdb_store_expr_t *iter, sdb_store_matcher_t *m);
 
 /*
  * sdb_store_in_matcher:
index f202c6ba463ffd291f8da2b6a95071b6ca2a6c07..642af72d92bffed59364085e6556d673cddcdf6c 100644 (file)
@@ -177,8 +177,11 @@ START_TEST(test_cmp_name)
        else
                m = sdb_store_eq_matcher(obj, value);
        if (cmp_name_data[_i].type != SDB_HOST) {
+               sdb_store_expr_t *iter;
                sdb_store_matcher_t *tmp;
-               tmp = sdb_store_any_matcher(cmp_name_data[_i].type, m);
+               iter = sdb_store_expr_typed(cmp_name_data[_i].type, obj);
+               tmp = sdb_store_any_matcher(iter, m);
+               sdb_object_deref(SDB_OBJ(iter));
                sdb_object_deref(SDB_OBJ(m));
                m = tmp;
        }
index e64da004450359056136f61d79ae8351f2da3200..b67b133c367c045506576be9de50ce96aeb0919b 100644 (file)
@@ -453,6 +453,8 @@ struct {
          "name + 1 IS NULL",    -1, -1, 0 },
        { "LOOKUP hosts FILTER "
          "name + 1 IS NULL",    -1, -1, 0 },
+       { "LOOKUP hosts MATCHING "
+         "ANY 'patt' =~ 'p'",  -1,  -1, 0 },
 
        /* comments */
        { "/* some comment */",  -1,  0, 0 },