From 8075debb62385a01df5b8d344ad590cf0575c2eb Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sat, 25 Oct 2014 22:22:45 +0200 Subject: [PATCH] frontend/grammar: Added support for 'ALL '. This matches, if all of the specified objects match the specified expression. ALL also matches on empty object lists. --- src/frontend/grammar.y | 28 ++++++++++++++++++++-------- src/frontend/scanner.l | 1 + t/integration/matching.sh | 17 +++++++++++++---- t/unit/core/store_lookup_test.c | 5 +++++ 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 8057710..92b55eb 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -48,10 +48,11 @@ */ static sdb_store_matcher_t * -name_matcher(char *type_name, char *cmp, sdb_store_expr_t *expr); +name_matcher(const char *type_name, const char *cmp, sdb_store_expr_t *expr); static sdb_store_matcher_t * -name_iter_matcher(char *type_name, char *cmp, sdb_store_expr_t *expr); +name_iter_matcher(int m_type, const char *type_name, const char *cmp, + sdb_store_expr_t *expr); /* * public API @@ -108,7 +109,7 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %token AND OR IS NOT MATCHING FILTER %token CMP_EQUAL CMP_NEQUAL CMP_REGEX CMP_NREGEX -%token CMP_LT CMP_LE CMP_GE CMP_GT ANY IN +%token CMP_LT CMP_LE CMP_GE CMP_GT ALL ANY IN %token CONCAT %token START END @@ -466,7 +467,14 @@ compare_matcher: | ANY IDENTIFIER cmp expression { - $$ = name_iter_matcher($2, $3, $4); + $$ = name_iter_matcher(MATCHER_ANY, $2, $3, $4); + free($2); $2 = NULL; + sdb_object_deref(SDB_OBJ($4)); + } + | + ALL IDENTIFIER cmp expression + { + $$ = name_iter_matcher(MATCHER_ALL, $2, $3, $4); free($2); $2 = NULL; sdb_object_deref(SDB_OBJ($4)); } @@ -652,7 +660,7 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg) } /* sdb_fe_yyerror */ static sdb_store_matcher_t * -name_matcher(char *type_name, char *cmp, sdb_store_expr_t *expr) +name_matcher(const char *type_name, const char *cmp, sdb_store_expr_t *expr) { int type = sdb_store_parse_object_type(type_name); sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op(cmp); @@ -672,12 +680,13 @@ name_matcher(char *type_name, char *cmp, sdb_store_expr_t *expr) } /* name_matcher */ static sdb_store_matcher_t * -name_iter_matcher(char *type_name, char *cmp, sdb_store_expr_t *expr) +name_iter_matcher(int m_type, const char *type_name, const char *cmp, + sdb_store_expr_t *expr) { int type = sdb_store_parse_object_type(type_name); sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op(cmp); sdb_store_expr_t *e; - sdb_store_matcher_t *m, *tmp; + sdb_store_matcher_t *m, *tmp = NULL; assert(cb); /* TODO: this only works as long as queries @@ -688,7 +697,10 @@ name_iter_matcher(char *type_name, char *cmp, sdb_store_expr_t *expr) e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME); m = cb(e, expr); - tmp = sdb_store_any_matcher(type, m); + 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); sdb_object_deref(SDB_OBJ(m)); sdb_object_deref(SDB_OBJ(e)); return tmp; diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l index 4f09c37..b581e3d 100644 --- a/src/frontend/scanner.l +++ b/src/frontend/scanner.l @@ -51,6 +51,7 @@ static struct { const char *name; int id; } reserved_words[] = { + { "ALL", ALL }, { "AND", AND }, { "ANY", ANY }, { "END", END }, diff --git a/t/integration/matching.sh b/t/integration/matching.sh index 21a730f..c96f7ab 100755 --- a/t/integration/matching.sh +++ b/t/integration/matching.sh @@ -78,11 +78,20 @@ echo "$output" | grep -F 'some.host.name' && exit 1 output="$( run_sysdb -H "$SOCKET_FILE" \ -c "LOOKUP hosts MATCHING ANY attribute != 'architecture'" )" echo "$output" \ - | grep -F '"localhost"' + | grep -F '"localhost"' \ + | grep -F '"other.host.name"' \ + | grep -F '"host1.example.com"' \ + | grep -F '"host2.example.com"' echo "$output" | grep -F 'some.host.name' && exit 1 -#echo "$output" | grep -F 'other.host.name' && exit 1 -#echo "$output" | grep -F 'host1.example.com' && exit 1 -#echo "$output" | grep -F 'host2.example.com' && exit 1 + +output="$( run_sysdb -H "$SOCKET_FILE" \ + -c "LOOKUP hosts MATCHING ALL attribute != 'architecture'" )" +echo "$output" \ + | grep -F '"some.host.name"' \ + | grep -F '"localhost"' +echo "$output" | grep -F 'other.host.name' && exit 1 +echo "$output" | grep -F 'host1.example.com' && exit 1 +echo "$output" | grep -F 'host2.example.com' && exit 1 output="$( run_sysdb -H "$SOCKET_FILE" \ -c "LOOKUP hosts MATCHING ANY service = 'sysdbd'" )" diff --git a/t/unit/core/store_lookup_test.c b/t/unit/core/store_lookup_test.c index d532757..8d15086 100644 --- a/t/unit/core/store_lookup_test.c +++ b/t/unit/core/store_lookup_test.c @@ -534,7 +534,11 @@ START_TEST(test_scan) { "ANY metric = 'm1'", "NOT attribute['x'] = ''", 2 }, /* filter always matches */ { "ANY metric =~ 'm'", NULL, 2 }, + { "ALL metric =~ 'm'", NULL, 3 }, + { "ALL metric =~ '1'", NULL, 2 }, + { "ALL metric =~ '2'", NULL, 1 }, { "ANY metric !~ 'm'", NULL, 0 }, + { "ALL metric !~ 'm'", NULL, 1 }, { "ANY metric =~ 'x'", NULL, 0 }, { "ANY service = 's1'", NULL, 2 }, { "ANY service = 's1'", "host = 'x'", 0 }, /* filter never matches */ @@ -551,6 +555,7 @@ START_TEST(test_scan) { "ANY attribute =~ '2'", NULL, 1 }, { "ANY attribute = 'x'", NULL, 0 }, { "ANY attribute =~ 'x'", NULL, 0 }, + { "ALL attribute = 'k1'", NULL, 2 }, { "attribute['k1'] = 'v1'", NULL, 1 }, { "attribute['k1'] =~ 'v1'", NULL, 1 }, { "attribute['k1'] =~ '^v1$'", NULL, 1 }, -- 2.30.2