summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 6d0d1e3)
raw | patch | inline | side by side (parent: 6d0d1e3)
author | Sebastian Harl <sh@tokkee.org> | |
Sat, 25 Oct 2014 12:31:06 +0000 (14:31 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sat, 25 Oct 2014 12:31:06 +0000 (14:31 +0200) |
… for services, metrics, and attributes. That is, let this involve less magic
but make it clear that this looks at multiple objects and matches if any of
them match.
but make it clear that this looks at multiple objects and matches if any of
them match.
diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y
index cfffdac5f35d6fac421a082e8d58c55c9dfc3091..8057710c76851d4819a11e9d24ad91cc18562f88 100644 (file)
--- a/src/frontend/grammar.y
+++ b/src/frontend/grammar.y
#include <stdio.h>
#include <string.h>
+/*
+ * private helper functions
+ */
+
+static sdb_store_matcher_t *
+name_matcher(char *type_name, 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);
+
+/*
+ * public API
+ */
+
int
sdb_fe_yylex(YYSTYPE *yylval, YYLTYPE *yylloc, sdb_fe_yyscan_t yyscanner);
%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 IN
+%token CMP_LT CMP_LE CMP_GE CMP_GT ANY IN
%token CONCAT
%token START END
|
IDENTIFIER cmp expression
{
- int type = sdb_store_parse_object_type($1);
- sdb_store_expr_t *e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME);
- sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op($2);
- sdb_store_matcher_t *m;
- assert(cb);
-
- m = cb(e, $3);
- /* TODO: this only works as long as queries
- * are limited to hosts */
- if (type == SDB_HOST) {
- $$ = m;
- }
- else {
- $$ = sdb_store_any_matcher(type, m);
- sdb_object_deref(SDB_OBJ(m));
- }
-
+ $$ = name_matcher($1, $2, $3);
free($1); $1 = NULL;
sdb_object_deref(SDB_OBJ($3));
- sdb_object_deref(SDB_OBJ(e));
+ }
+ |
+ ANY IDENTIFIER cmp expression
+ {
+ $$ = name_iter_matcher($2, $3, $4);
+ free($2); $2 = NULL;
+ sdb_object_deref(SDB_OBJ($4));
}
|
expression IS NULL_T
sdb_log(SDB_LOG_ERR, "frontend: parse error: %s", msg);
} /* sdb_fe_yyerror */
+static sdb_store_matcher_t *
+name_matcher(char *type_name, 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;
+ assert(cb);
+
+ /* TODO: this only works as long as queries
+ * are limited to hosts */
+ if (type != SDB_HOST)
+ return NULL;
+
+ e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME);
+ m = cb(e, expr);
+ sdb_object_deref(SDB_OBJ(e));
+ return m;
+} /* name_matcher */
+
+static sdb_store_matcher_t *
+name_iter_matcher(char *type_name, 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;
+ assert(cb);
+
+ /* TODO: this only works as long as queries
+ * are limited to hosts */
+ if (type == SDB_HOST) {
+ return NULL;
+ }
+
+ e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME);
+ m = cb(e, expr);
+ tmp = sdb_store_any_matcher(type, m);
+ sdb_object_deref(SDB_OBJ(m));
+ sdb_object_deref(SDB_OBJ(e));
+ return tmp;
+} /* name_iter_matcher */
+
/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l
index 33b762cce6dfa416a6b5e9869b40013a74df2b34..4f09c3730be73cb4e01a4af554f147fd31eaf9e3 100644 (file)
--- a/src/frontend/scanner.l
+++ b/src/frontend/scanner.l
int id;
} reserved_words[] = {
{ "AND", AND },
+ { "ANY", ANY },
{ "END", END },
{ "FETCH", FETCH },
{ "FILTER", FILTER },
index fa21dd364833f07d5c11586dedb477ea2666103e..9c9fb0cf17de6c5b08d60010abac317bd04b12e0 100755 (executable)
--- a/t/integration/filter.sh
+++ b/t/integration/filter.sh
sleep 3
output="$( run_sysdb -H "$SOCKET_FILE" \
- -c "LOOKUP hosts MATCHING attribute != 'architecture'
+ -c "LOOKUP hosts MATCHING ANY attribute != 'architecture'
FILTER .age >= 0s" )"
echo "$output" \
| grep -F '"some.host.name"' \
echo "$output" | grep -F 'host2.example.com' && exit 1
output="$( run_sysdb -H "$SOCKET_FILE" \
- -c "LOOKUP hosts MATCHING attribute != 'architecture'
+ -c "LOOKUP hosts MATCHING ANY attribute != 'architecture'
FILTER .last_update < 2Y" )"
echo $output | grep -E '^\[\]$'
index 67b97210058a5e44247f67a873794c5e364ffe42..751b22ba9c00f58325bc2956bd5180278fb2eb13 100755 (executable)
sleep 3
output="$( run_sysdb -H "$SOCKET_FILE" \
- -c "LOOKUP hosts MATCHING metric = 'foo/bar/qux'" )"
+ -c "LOOKUP hosts MATCHING ANY metric = 'foo/bar/qux'" )"
echo "$output" \
| grep -F '"some.host.name"' \
| grep -F '"other.host.name"'
echo "$output" | grep -F 'host2.example.com' && exit 1
output="$( run_sysdb -H "$SOCKET_FILE" \
- -c "LOOKUP hosts MATCHING service = 'mock service'" )"
+ -c "LOOKUP hosts MATCHING ANY service = 'mock service'" )"
echo "$output" \
| grep -F '"some.host.name"' \
| grep -F '"host1.example.com"' \
echo "$output" | grep -F 'some.host.name' && exit 1
output="$( run_sysdb -H "$SOCKET_FILE" \
- -c "LOOKUP hosts MATCHING attribute != 'architecture'" )"
+ -c "LOOKUP hosts MATCHING ANY attribute != 'architecture'" )"
echo "$output" \
| grep -F '"some.host.name"' \
| grep -F '"localhost"'
echo "$output" | grep -F 'host2.example.com' && exit 1
output="$( run_sysdb -H "$SOCKET_FILE" \
- -c "LOOKUP hosts MATCHING service = 'sysdbd'" )"
+ -c "LOOKUP hosts MATCHING ANY service = 'sysdbd'" )"
echo "$output" | grep -F '"localhost"'
echo "$output" | grep -F 'some.host.name' && exit 1
echo "$output" | grep -F 'other.host.name' && exit 1
index dbf313acaa6709119b84d2d6636b61b5b57b233c..3c99bb15553d64f0407489b21a3db56334977935 100644 (file)
{ "host =~ 'a|b'", NULL, 2 },
{ "host =~ 'host'", NULL, 0 },
{ "host =~ '.'", NULL, 3 },
- { "metric = 'm1'", NULL, 2 },
- { "metric= 'm1'", "host = 'x'", 0 }, /* filter never matches */
- { "metric = 'm1'",
+ { "ANY metric = 'm1'", NULL, 2 },
+ { "ANY metric= 'm1'", "host = 'x'", 0 }, /* filter never matches */
+ { "ANY metric = 'm1'",
"NOT attribute['x'] = ''", 2 }, /* filter always matches */
- { "metric =~ 'm'", NULL, 2 },
- { "metric !~ 'm'", NULL, 1 },
- { "metric =~ 'x'", NULL, 0 },
- { "service = 's1'", NULL, 2 },
- { "service = 's1'", "host = 'x'", 0 }, /* filter never matches */
- { "service = 's1'",
+ { "ANY metric =~ 'm'", NULL, 2 },
+ { "ANY metric !~ 'm'", NULL, 1 },
+ { "ANY metric =~ 'x'", NULL, 0 },
+ { "ANY service = 's1'", NULL, 2 },
+ { "ANY service = 's1'", "host = 'x'", 0 }, /* filter never matches */
+ { "ANY service = 's1'",
"NOT attribute['x'] = ''", 2 }, /* filter always matches */
- { "service =~ 's'", NULL, 2 },
- { "service !~ 's'", NULL, 1 },
- { "attribute = 'k1'", NULL, 2 },
- { "attribute = 'k1'", "host = 'x'", 0 }, /* filter never matches */
- { "attribute = 'k1'",
+ { "ANY service =~ 's'", NULL, 2 },
+ { "ANY service !~ 's'", NULL, 1 },
+ { "ANY attribute = 'k1'", NULL, 2 },
+ { "ANY attribute = 'k1'", "host = 'x'",0 }, /* filter never matches */
+ { "ANY attribute = 'k1'",
"NOT attribute['x'] = ''", 2 }, /* filter always matches */
- { "attribute =~ 'k'", NULL, 2 },
- { "attribute =~ '1'", NULL, 2 },
- { "attribute =~ '2'", NULL, 1 },
- { "attribute = 'x'", NULL, 0 },
- { "attribute =~ 'x'", NULL, 0 },
+ { "ANY attribute =~ 'k'", NULL, 2 },
+ { "ANY attribute =~ '1'", NULL, 2 },
+ { "ANY attribute =~ '2'", NULL, 1 },
+ { "ANY attribute = 'x'", NULL, 0 },
+ { "ANY attribute =~ 'x'", NULL, 0 },
{ "attribute['k1'] = 'v1'", NULL, 1 },
{ "attribute['k1'] =~ 'v1'", NULL, 1 },
{ "attribute['k1'] =~ '^v1$'", NULL, 1 },
{ "attribute['k2'] != 123", NULL, 0 },
{ "attribute['k1'] != 'v1'", NULL, 1 },
{ "attribute['k1'] != 'v2'", NULL, 1 },
- { "attribute != 'x' "
+ { "ANY attribute != 'x' "
"AND attribute['y'] !~ 'x'", NULL, 3 },
};
index 1ca9f2ddfd37a95d2a4a1864bdb6f1699eebc91c..fd9e32fa3ee19ee7e99edf7b1e0dc3fc49be1538 100644 (file)
"host = 'host'", -1, 1, CONNECTION_LIST },
{ "LIST services", -1, 1, CONNECTION_LIST },
{ "LIST services FILTER "
- "service = 'svc'", -1, 1, CONNECTION_LIST },
+ "ANY service = 'svc'", -1, 1, CONNECTION_LIST },
{ "LIST metrics", -1, 1, CONNECTION_LIST },
{ "LIST metrics FILTER "
- "metric = 'metric'", -1, 1, CONNECTION_LIST },
+ "ANY metric = 'm'", -1, 1, CONNECTION_LIST },
{ "LOOKUP hosts", -1, 1, CONNECTION_LOOKUP },
{ "LOOKUP hosts MATCHING "
"host = 'host'", -1, 1, CONNECTION_LOOKUP },
{ "LOOKUP hosts MATCHING "
"host =~ 'p' AND "
- "service =~ 'p'", -1, 1, CONNECTION_LOOKUP },
+ "ANY service =~ 'p'", -1, 1, CONNECTION_LOOKUP },
{ "LOOKUP hosts MATCHING NOT "
"host =~ 'p' AND "
- "service =~ 'p'", -1, 1, CONNECTION_LOOKUP },
+ "ANY service =~ 'p'", -1, 1, CONNECTION_LOOKUP },
{ "LOOKUP hosts MATCHING "
"host =~ 'p' AND "
- "service =~ 'p' OR "
- "service =~ 'r'", -1, 1, CONNECTION_LOOKUP },
+ "ANY service =~ 'p' OR "
+ "ANY service =~ 'r'", -1, 1, CONNECTION_LOOKUP },
{ "LOOKUP hosts MATCHING NOT "
"host =~ 'p' AND "
- "service =~ 'p' OR "
- "service =~ 'r'", -1, 1, CONNECTION_LOOKUP },
+ "ANY service =~ 'p' OR "
+ "ANY service =~ 'r'", -1, 1, CONNECTION_LOOKUP },
{ "LOOKUP hosts MATCHING "
"host =~ 'p' "
"FILTER .age > 1D", -1, 1, CONNECTION_LOOKUP },
{ "LOOKUP hosts MATCHING "
"host IS NULL", -1, -1, 0 },
{ "LOOKUP hosts MATCHING "
- "service IS NULL", -1, -1, 0 },
+ "ANY service IS NULL", -1, -1, 0 },
/* invalid numeric constants */
{ "LOOKUP hosts MATCHING "
{ "host = 'host' <garbage>", 13, MATCHER_EQ },
{ "host &^ 'localhost'", -1, -1 },
/* match hosts by service */
- { "service < 'name'", -1, MATCHER_ANY },
- { "service <= 'name'", -1, MATCHER_ANY },
- { "service = 'name'", -1, MATCHER_ANY },
- { "service != 'name'", -1, MATCHER_ANY },
- { "service >= 'name'", -1, MATCHER_ANY },
- { "service > 'name'", -1, MATCHER_ANY },
- { "service =~ 'pattern'", -1, MATCHER_ANY },
- { "service !~ 'pattern'", -1, MATCHER_ANY },
- { "service &^ 'name'", -1, -1 },
+ { "ANY service < 'name'", -1, MATCHER_ANY },
+ { "ANY service <= 'name'", -1, MATCHER_ANY },
+ { "ANY service = 'name'", -1, MATCHER_ANY },
+ { "ANY service != 'name'", -1, MATCHER_ANY },
+ { "ANY service >= 'name'", -1, MATCHER_ANY },
+ { "ANY service > 'name'", -1, MATCHER_ANY },
+ { "ANY service =~ 'pattern'", -1, MATCHER_ANY },
+ { "ANY service !~ 'pattern'", -1, MATCHER_ANY },
+ { "ANY service &^ 'name'", -1, -1 },
/* match hosts by metric */
- { "metric < 'name'", -1, MATCHER_ANY },
- { "metric <= 'name'", -1, MATCHER_ANY },
- { "metric = 'name'", -1, MATCHER_ANY },
- { "metric != 'name'", -1, MATCHER_ANY },
- { "metric >= 'name'", -1, MATCHER_ANY },
- { "metric > 'name'", -1, MATCHER_ANY },
- { "metric =~ 'pattern'", -1, MATCHER_ANY },
- { "metric !~ 'pattern'", -1, MATCHER_ANY },
+ { "ANY metric < 'name'", -1, MATCHER_ANY },
+ { "ANY metric <= 'name'", -1, MATCHER_ANY },
+ { "ANY metric = 'name'", -1, MATCHER_ANY },
+ { "ANY metric != 'name'", -1, MATCHER_ANY },
+ { "ANY metric >= 'name'", -1, MATCHER_ANY },
+ { "ANY metric > 'name'", -1, MATCHER_ANY },
+ { "ANY metric =~ 'pattern'", -1, MATCHER_ANY },
+ { "ANY metric !~ 'pattern'", -1, MATCHER_ANY },
/* match hosts by attribute */
- { "attribute < 'name'", -1, MATCHER_ANY },
- { "attribute <= 'name'", -1, MATCHER_ANY },
- { "attribute = 'name'", -1, MATCHER_ANY },
- { "attribute != 'name'", -1, MATCHER_ANY },
- { "attribute >= 'name'", -1, MATCHER_ANY },
- { "attribute > 'name'", -1, MATCHER_ANY },
- { "attribute =~ 'pattern'", -1, MATCHER_ANY },
- { "attribute !~ 'pattern'", -1, MATCHER_ANY },
- { "attribute &^ 'pattern'", -1, -1 },
+ { "ANY attribute < 'name'", -1, MATCHER_ANY },
+ { "ANY attribute <= 'name'", -1, MATCHER_ANY },
+ { "ANY attribute = 'name'", -1, MATCHER_ANY },
+ { "ANY attribute != 'name'", -1, MATCHER_ANY },
+ { "ANY attribute >= 'name'", -1, MATCHER_ANY },
+ { "ANY attribute > 'name'", -1, MATCHER_ANY },
+ { "ANY attribute =~ 'pattern'", -1, MATCHER_ANY },
+ { "ANY attribute !~ 'pattern'", -1, MATCHER_ANY },
+ { "ANY attribute &^ 'pattern'", -1, -1 },
/* composite expressions */
{ "host =~ 'pattern' AND "
- "service =~ 'pattern'", -1, MATCHER_AND },
+ "ANY service =~ 'pattern'", -1, MATCHER_AND },
{ "host =~ 'pattern' OR "
- "service =~ 'pattern'", -1, MATCHER_OR },
+ "ANY service =~ 'pattern'", -1, MATCHER_OR },
{ "NOT host = 'host'", -1, MATCHER_NOT },
/* numeric expressions */
{ "attribute['foo'] < 123", -1, MATCHER_LT },
/* check operator precedence */
{ "host = 'name' OR "
- "service = 'name' AND "
- "attribute = 'name' OR "
+ "ANY service = 'name' AND "
+ "ANY attribute = 'name' OR "
"attribute['foo'] = 'bar'", -1, MATCHER_OR },
{ "host = 'name' AND "
- "service = 'name' AND "
- "attribute = 'name' OR "
+ "ANY service = 'name' AND "
+ "ANY attribute = 'name' OR "
"attribute['foo'] = 'bar'", -1, MATCHER_OR },
{ "host = 'name' AND "
- "service = 'name' OR "
- "attribute = 'name' AND "
+ "ANY service = 'name' OR "
+ "ANY attribute = 'name' AND "
"attribute['foo'] = 'bar'", -1, MATCHER_OR },
{ "(host = 'name' OR "
- "service = 'name') AND "
- "(attribute = 'name' OR "
+ "ANY service = 'name') AND "
+ "(ANY attribute = 'name' OR "
"attribute['foo'] = 'bar')", -1, MATCHER_AND },
{ "NOT host = 'name' OR "
- "service = 'name'", -1, MATCHER_OR },
+ "ANY service = 'name'", -1, MATCHER_OR },
{ "NOT host = 'name' OR "
- "NOT service = 'name'", -1, MATCHER_OR },
+ "NOT ANY service = 'name'", -1, MATCHER_OR },
{ "NOT (host = 'name' OR "
- "NOT service = 'name')", -1, MATCHER_NOT },
+ "NOT ANY service = 'name')", -1, MATCHER_NOT },
/* syntax errors */
{ "LIST", -1, -1 },