From b072d9b2786422fcb8f068dd5076bd108a6228e9 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sun, 8 Mar 2015 11:56:33 +0100 Subject: [PATCH] Let the first operand of ANY/ALL iterators be an expression. 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 | 2 +- src/core/store_lookup.c | 51 +++++++++++++++++++++------------ src/frontend/analyzer.c | 42 ++++++++++++++++----------- src/frontend/grammar.y | 48 +++++++++++-------------------- src/include/core/store.h | 14 +++++---- t/unit/core/store_lookup_test.c | 5 +++- t/unit/frontend/parser_test.c | 2 ++ 7 files changed, 89 insertions(+), 75 deletions(-) diff --git a/src/core/store-private.h b/src/core/store-private.h index 4ef11f9..cde2216 100644 --- a/src/core/store-private.h +++ b/src/core/store-private.h @@ -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)) diff --git a/src/core/store_lookup.c b/src/core/store_lookup.c index 2e73780..94f95cc 100644 --- a/src/core/store_lookup.c +++ b/src/core/store_lookup.c @@ -38,6 +38,7 @@ #include "sysdb.h" #include "core/store-private.h" #include "core/object.h" +#include "utils/error.h" #include @@ -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 * diff --git a/src/frontend/analyzer.c b/src/frontend/analyzer.c index 62bae1c..b5d0e08 100644 --- a/src/frontend/analyzer.c +++ b/src/frontend/analyzer.c @@ -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: diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 4021031..ac899e3 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -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 expression arithmetic_expression object_expression %type object_type object_type_plural -%type iterable %type field %type 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 */ diff --git a/src/include/core/store.h b/src/include/core/store.h index e83ff84..3722a72 100644 --- a/src/include/core/store.h +++ b/src/include/core/store.h @@ -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: diff --git a/t/unit/core/store_lookup_test.c b/t/unit/core/store_lookup_test.c index f202c6b..642af72 100644 --- a/t/unit/core/store_lookup_test.c +++ b/t/unit/core/store_lookup_test.c @@ -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; } diff --git a/t/unit/frontend/parser_test.c b/t/unit/frontend/parser_test.c index e64da00..b67b133 100644 --- a/t/unit/frontend/parser_test.c +++ b/t/unit/frontend/parser_test.c @@ -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 }, -- 2.30.2