Code

query language: Add support for attribute.value access.
authorSebastian Harl <sh@tokkee.org>
Sun, 15 Mar 2015 14:54:21 +0000 (10:54 -0400)
committerSebastian Harl <sh@tokkee.org>
Sun, 15 Mar 2015 14:54:21 +0000 (10:54 -0400)
src/frontend/analyzer.c
src/frontend/grammar.y
src/frontend/scanner.l
t/unit/core/store_lookup_test.c
t/unit/frontend/parser_test.c

index cf077de41174df7e913ae46b835fd429218b535c..4bd370222e8e11d4a41e9a3b297a1e35412155be 100644 (file)
@@ -100,14 +100,24 @@ analyze_expr(int context, sdb_store_expr_t *e, sdb_strbuf_t *errbuf)
                        sdb_strbuf_sprintf(errbuf, "Invalid expression %s.%s "
                                        "in %s context",
                                        SDB_STORE_TYPE_TO_NAME(e->data.data.integer),
-                                       EXPR_TO_STRING(e->left), SDB_STORE_TYPE_TO_NAME(context));
+                                       EXPR_TO_STRING(e->left),
+                                       context == -1 ? "generic" : SDB_STORE_TYPE_TO_NAME(context));
                        return -1;
 
                case ATTR_VALUE:
-               case FIELD_VALUE:
                case 0:
                        break;
 
+               case FIELD_VALUE:
+                       if ((e->data.data.integer == SDB_FIELD_VALUE)
+                                       && (context != SDB_ATTRIBUTE)) {
+                               sdb_strbuf_sprintf(errbuf, "Invalid expression %s.value "
+                                               "(only attributes have a value)",
+                                               SDB_STORE_TYPE_TO_NAME(context));
+                               return -1;
+                       }
+                       break;
+
                default:
                        if (analyze_expr(context, e->left, errbuf))
                                return -1;
@@ -161,7 +171,7 @@ analyze_matcher(int context, int parent_type,
 
                        if ((ITER_M(m)->iter->type == TYPED_EXPR)
                                        || (ITER_M(m)->iter->type == FIELD_VALUE))
-                               type = ITER_M(m)->iter->data.data.integer;
+                               type = (int)ITER_M(m)->iter->data.data.integer;
 
                        if (context == -1) { /* inside a filter */
                                /* attributes are always iterable */
index a573b2b1dac5e425d3febba39cbc10657f399ed6..70e6c3c2dc2fe0caf07e3ce9725667fddec4f48f 100644 (file)
@@ -119,7 +119,7 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...);
 
 %token HOST_T HOSTS_T SERVICE_T SERVICES_T METRIC_T METRICS_T
 %token ATTRIBUTE_T ATTRIBUTES_T
-%token NAME_T LAST_UPDATE_T AGE_T INTERVAL_T BACKEND_T
+%token NAME_T LAST_UPDATE_T AGE_T INTERVAL_T BACKEND_T VALUE_T
 
 %token LAST UPDATE
 
@@ -700,6 +700,8 @@ field:
        INTERVAL_T { $$ = SDB_FIELD_INTERVAL; }
        |
        BACKEND_T { $$ = SDB_FIELD_BACKEND; }
+       |
+       VALUE_T { $$ = SDB_FIELD_VALUE; }
        ;
 
 cmp:
index 3985bf87433553545a8ee7022cfb926370ab3b5b..ab8b80daf560459822714f473ebc7a5adc76f21f 100644 (file)
@@ -86,6 +86,7 @@ static struct {
        { "age",         AGE_T },
        { "interval",    INTERVAL_T },
        { "backend",     BACKEND_T },
+       { "value",       VALUE_T },
 };
 
 void
index 923ce066e498b90ab41e7754020e04d3d4dd55ff..3555495d79e4dfd681cf5ad5dc6220ade578a5ea 100644 (file)
@@ -569,6 +569,9 @@ struct {
        { "ANY attribute.name = 'x'", NULL,    0 },
        { "ANY attribute.name =~ 'x'", NULL,   0 },
        { "ALL attribute.name = 'k1'", NULL,   2 },
+       { "ANY attribute.value = 'v1'", NULL,  1 },
+       { "ANY attribute.value =~ 'v'", NULL,  2 },
+       { "ANY attribute.value = 123", NULL,   1 },
        { "host.name = 'a'", NULL,             1 },
        { "host.attribute['k1'] =~ 'v1'",
                NULL,                              1 },
index b67b133c367c045506576be9de50ce96aeb0919b..65ec6cad5b8797052b16d7c5a45bc1455018de67 100644 (file)
@@ -64,18 +64,61 @@ struct {
          "'host'.'metric'",     -1,  1, SDB_CONNECTION_FETCH  },
 
        /* LIST commands */
-       { "LIST hosts",          -1,  1, SDB_CONNECTION_LIST   },
-       { "LIST hosts -- foo",   -1,  1, SDB_CONNECTION_LIST   },
-       { "LIST hosts;",         -1,  1, SDB_CONNECTION_LIST   },
-       { "LIST hosts; INVALID", 11,  1, SDB_CONNECTION_LIST   },
+       { "LIST hosts",            -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST hosts -- foo",     -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST hosts;",           -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST hosts; INVALID",   11,  1, SDB_CONNECTION_LIST   },
        { "LIST hosts FILTER "
-         "age > 60s",           -1,  1, SDB_CONNECTION_LIST   },
-       { "LIST services",       -1,  1, SDB_CONNECTION_LIST   },
+         "age > 60s",             -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST services",         -1,  1, SDB_CONNECTION_LIST   },
        { "LIST services FILTER "
-         "age > 60s",           -1,  1, SDB_CONNECTION_LIST   },
-       { "LIST metrics",        -1,  1, SDB_CONNECTION_LIST   },
+         "age > 60s",             -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST metrics",          -1,  1, SDB_CONNECTION_LIST   },
        { "LIST metrics FILTER "
-         "age > 60s",           -1,  1, SDB_CONNECTION_LIST   },
+         "age > 60s",             -1,  1, SDB_CONNECTION_LIST   },
+       /* field access */
+       { "LIST hosts FILTER "
+         "name = 'a'",            -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST hosts FILTER "
+         "last_update > 1s",      -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST hosts FILTER "
+         "age > 120s",            -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST hosts FILTER "
+         "interval > 10s",        -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST hosts FILTER "
+         "backend = ['b']",       -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST hosts FILTER "
+         "value = 'a'",           -1, -1, 0 },
+       { "LIST hosts FILTER ANY "
+         "attribute.value = 'a'", -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST services FILTER "
+         "name = 'a'",            -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST services FILTER "
+         "last_update > 1s",      -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST services FILTER "
+         "age > 120s",            -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST services FILTER "
+         "interval > 10s",        -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST services FILTER "
+         "backend = ['b']",       -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST services FILTER "
+         "value = 'a'",           -1, -1, 0 },
+       { "LIST services FILTER ANY "
+         "attribute.value = 'a'", -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST metrics FILTER "
+         "name = 'a'",            -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST metrics FILTER "
+         "last_update > 1s",      -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST metrics FILTER "
+         "age > 120s",            -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST metrics FILTER "
+         "interval > 10s",        -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST metrics FILTER "
+         "backend = ['b']",       -1,  1, SDB_CONNECTION_LIST   },
+       { "LIST metrics FILTER "
+         "value = 'a'",           -1, -1, 0 },
+       { "LIST metrics FILTER ANY "
+         "attribute.value = 'a'", -1,  1, SDB_CONNECTION_LIST   },
 
        /* LOOKUP commands */
        { "LOOKUP hosts",        -1,  1, SDB_CONNECTION_LOOKUP },