Code

Merged branch 'master' of git://git.tokkee.org/sysdb.
authorSebastian Harl <sh@tokkee.org>
Wed, 12 Nov 2014 21:16:35 +0000 (22:16 +0100)
committerSebastian Harl <sh@tokkee.org>
Wed, 12 Nov 2014 21:21:03 +0000 (22:21 +0100)
1  2 
src/frontend/analyzer.c
src/frontend/grammar.y
t/unit/frontend/parser_test.c

diff --combined src/frontend/analyzer.c
index 2de9befa6eeb6605ca405fb07689f6672c86b169,6a50736be23752fe6ea96c2beaccda8815ea9c8d..701130e88d498335c13ccc133719bca5989cda4a
@@@ -165,10 -165,6 +165,10 @@@ analyze_matcher(int context, sdb_store_
                case MATCHER_GE:
                case MATCHER_GT:
                        assert(CMP_M(m)->left && CMP_M(m)->right);
 +                      if ((CMP_M(m)->left->data_type > 0)
 +                                      && (CMP_M(m)->right->data_type > 0)
 +                                      && (CMP_M(m)->left->data_type == CMP_M(m)->right->data_type))
 +                              return 0;
                        if ((CMP_M(m)->left->data_type > 0)
                                        && (CMP_M(m)->left->data_type & SDB_TYPE_ARRAY)) {
                                cmp_error(errbuf, m->type, CMP_M(m)->left->data_type,
@@@ -237,7 -233,7 +237,7 @@@ sdb_fe_analyze(sdb_conn_node_t *node, s
  
        /* For now, this function checks basic matcher attributes only;
         * later, this may be turned into one of multiple AST visitors. */
-       if (node->cmd == CONNECTION_FETCH) {
+       if (node->cmd == SDB_CONNECTION_FETCH) {
                conn_fetch_t *fetch = CONN_FETCH(node);
                if ((fetch->type == SDB_HOST) && fetch->name) {
                        sdb_strbuf_sprintf(errbuf, "Unexpected STRING '%s'", fetch->name);
                        filter = fetch->filter->matcher;
                context = fetch->type;
        }
-       else if (node->cmd == CONNECTION_LIST) {
+       else if (node->cmd == SDB_CONNECTION_LIST) {
                if (CONN_LIST(node)->filter)
                        filter = CONN_LIST(node)->filter->matcher;
                context = CONN_LIST(node)->type;
        }
-       else if (node->cmd == CONNECTION_LOOKUP) {
+       else if (node->cmd == SDB_CONNECTION_LOOKUP) {
                if (CONN_LOOKUP(node)->matcher)
                        m = CONN_LOOKUP(node)->matcher->matcher;
                if (CONN_LOOKUP(node)->filter)
                        filter = CONN_LOOKUP(node)->filter->matcher;
                context = CONN_LOOKUP(node)->type;
        }
-       else if (node->cmd == CONNECTION_TIMESERIES)
+       else if (node->cmd == SDB_CONNECTION_TIMESERIES)
                return 0;
        else
                return -1;
diff --combined src/frontend/grammar.y
index d4e54a9c4c8f3869946bfa151de5d764c1156e88,3180167fe2d98256637078338be98baf1e5368f8..2872bcf447fdeacb561aae754b9c85420a3fddc7
@@@ -171,7 -171,6 +171,7 @@@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_y
  
  %type <data> data
        interval interval_elem
 +      array array_elem_list
  
  %type <datetime> datetime
        start_clause end_clause
@@@ -249,7 -248,7 +249,7 @@@ statements
                                sdb_conn_node_t *n;
                                n = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
                                                        conn_expr_t, conn_expr_destroy));
-                               n->cmd = CONNECTION_EXPR;
+                               n->cmd = SDB_CONNECTION_EXPR;
                                CONN_EXPR(n)->expr = $1;
  
                                sdb_llist_append(pt, SDB_OBJ(n));
@@@ -287,7 -286,7 +287,7 @@@ fetch_statement
                        CONN_FETCH($$)->host = $3;
                        CONN_FETCH($$)->name = NULL;
                        CONN_FETCH($$)->filter = CONN_MATCHER($4);
-                       $$->cmd = CONNECTION_FETCH;
+                       $$->cmd = SDB_CONNECTION_FETCH;
                }
        |
        FETCH object_type STRING '.' STRING filter_clause
                        CONN_FETCH($$)->host = $3;
                        CONN_FETCH($$)->name = $5;
                        CONN_FETCH($$)->filter = CONN_MATCHER($6);
-                       $$->cmd = CONNECTION_FETCH;
+                       $$->cmd = SDB_CONNECTION_FETCH;
                }
        ;
  
@@@ -314,7 -313,7 +314,7 @@@ list_statement
                                                conn_list_t, conn_list_destroy));
                        CONN_LIST($$)->type = $2;
                        CONN_LIST($$)->filter = CONN_MATCHER($3);
-                       $$->cmd = CONNECTION_LIST;
+                       $$->cmd = SDB_CONNECTION_LIST;
                }
        ;
  
@@@ -331,7 -330,7 +331,7 @@@ lookup_statement
                        CONN_LOOKUP($$)->type = $2;
                        CONN_LOOKUP($$)->matcher = CONN_MATCHER($3);
                        CONN_LOOKUP($$)->filter = CONN_MATCHER($4);
-                       $$->cmd = CONNECTION_LOOKUP;
+                       $$->cmd = SDB_CONNECTION_LOOKUP;
                }
        ;
  
@@@ -359,7 -358,7 +359,7 @@@ timeseries_statement
                        CONN_TS($$)->metric = $4;
                        CONN_TS($$)->opts.start = $5;
                        CONN_TS($$)->opts.end = $6;
-                       $$->cmd = CONNECTION_TIMESERIES;
+                       $$->cmd = SDB_CONNECTION_TIMESERIES;
                }
        ;
  
@@@ -389,7 -388,7 +389,7 @@@ condition
  
                        $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
                                                conn_matcher_t, conn_matcher_destroy));
-                       $$->cmd = CONNECTION_MATCHER;
+                       $$->cmd = SDB_CONNECTION_MATCHER;
                        CONN_MATCHER($$)->matcher = $1;
                }
        ;
@@@ -600,8 -599,6 +600,8 @@@ data
        datetime { $$.type = SDB_TYPE_DATETIME; $$.data.datetime = $1; }
        |
        interval { $$ = $1; }
 +      |
 +      array { $$ = $1; }
        ;
  
  datetime:
@@@ -629,7 -626,7 +629,7 @@@ interval_elem
                        unit = sdb_strpunit($2);
                        if (! unit) {
                                sdb_fe_yyerrorf(&yylloc, scanner,
 -                                              YY_("invalid time unit %s"), $2);
 +                                              YY_("syntax error, invalid time unit %s"), $2);
                                free($2); $2 = NULL;
                                YYABORT;
                        }
                }
        ;
  
 +array:
 +      '[' array_elem_list ']'
 +              {
 +                      $$ = $2;
 +              }
 +      ;
 +
 +array_elem_list:
 +      array_elem_list ',' data
 +              {
 +                      size_t elem_size;
 +
 +                      if (($3.type & SDB_TYPE_ARRAY) || (($1.type & 0xff) != $3.type)) {
 +                              sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, "
 +                                              "cannot use element of type %s in array of type %s"),
 +                                              SDB_TYPE_TO_STRING($3.type),
 +                                              SDB_TYPE_TO_STRING($1.type));
 +                              sdb_data_free_datum(&$1);
 +                              sdb_data_free_datum(&$3);
 +                              YYABORT;
 +                      }
 +
 +                      elem_size = sdb_data_sizeof($3.type);
 +                      $1.data.array.values = realloc($1.data.array.values,
 +                                      ($1.data.array.length + 1) * elem_size);
 +                      if (! $1.data.array.values) {
 +                              sdb_fe_yyerror(&yylloc, scanner, YY_("out of memory"));
 +                              YYABORT;
 +                      }
 +
 +                      memcpy((char *)$1.data.array.values
 +                                              + $1.data.array.length * elem_size,
 +                                      &$3.data, elem_size);
 +                      ++$1.data.array.length;
 +
 +                      $$ = $1;
 +              }
 +      |
 +      data
 +              {
 +                      size_t elem_size;
 +
 +                      if ($1.type & SDB_TYPE_ARRAY) {
 +                              sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, "
 +                                              "cannot construct array of type %s"),
 +                                              SDB_TYPE_TO_STRING($1.type));
 +                              sdb_data_free_datum(&$1);
 +                              YYABORT;
 +                      }
 +
 +                      $$ = $1;
 +                      $$.type = $1.type | SDB_TYPE_ARRAY;
 +                      $$.data.array.length = 1;
 +                      elem_size = sdb_data_sizeof($1.type);
 +                      $$.data.array.values = malloc(elem_size);
 +                      if (! $$.data.array.values ) {
 +                              sdb_fe_yyerror(&yylloc, scanner, YY_("out of memory"));
 +                              YYABORT;
 +                      }
 +                      memcpy($$.data.array.values, &$1.data, elem_size);
 +              }
 +      ;
 +
  %%
  
  void
index c377f78fa59a9acd359de8fdeb560fce0013ce52,2368bcc4d3efe821a5342aa25ee07316ff69e7e1..c5b514fde5156fa43fafed5a714e6ffbd2e768cf
@@@ -53,155 -53,149 +53,155 @@@ START_TEST(test_parse
                { ";;",                  -1,  0, 0 },
  
                /* valid commands */
-               { "FETCH host 'host'",   -1,  1, CONNECTION_FETCH  },
+               { "FETCH host 'host'",   -1,  1, SDB_CONNECTION_FETCH  },
                { "FETCH host 'host' FILTER "
-                 "age > 60s",           -1,  1, CONNECTION_FETCH  },
+                 "age > 60s",           -1,  1, SDB_CONNECTION_FETCH  },
                { "FETCH service "
-                 "'host'.'service'",    -1,  1, CONNECTION_FETCH  },
+                 "'host'.'service'",    -1,  1, SDB_CONNECTION_FETCH  },
                { "FETCH metric "
-                 "'host'.'metric'",     -1,  1, CONNECTION_FETCH  },
+                 "'host'.'metric'",     -1,  1, SDB_CONNECTION_FETCH  },
  
-               { "LIST hosts",          -1,  1, CONNECTION_LIST   },
-               { "LIST hosts -- foo",   -1,  1, CONNECTION_LIST   },
-               { "LIST hosts;",         -1,  1, CONNECTION_LIST   },
-               { "LIST hosts; INVALID", 11,  1, 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, CONNECTION_LIST   },
-               { "LIST services",       -1,  1, CONNECTION_LIST   },
+                 "age > 60s",           -1,  1, SDB_CONNECTION_LIST   },
+               { "LIST services",       -1,  1, SDB_CONNECTION_LIST   },
                { "LIST services FILTER "
-                 "age > 60s",           -1,  1, CONNECTION_LIST   },
-               { "LIST metrics",        -1,  1, CONNECTION_LIST   },
+                 "age > 60s",           -1,  1, SDB_CONNECTION_LIST   },
+               { "LIST metrics",        -1,  1, SDB_CONNECTION_LIST   },
                { "LIST metrics FILTER "
-                 "age > 60s",           -1,  1, CONNECTION_LIST   },
+                 "age > 60s",           -1,  1, SDB_CONNECTION_LIST   },
  
-               { "LOOKUP hosts",        -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts",        -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
-                 "name = 'host'",       -1,  1, CONNECTION_LOOKUP },
+                 "name = 'host'",       -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING NOT "
-                 "name = 'host'",       -1,  1, CONNECTION_LOOKUP },
+                 "name = 'host'",       -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "name =~ 'p' AND "
-                 "ANY service =~ 'p'",  -1,  1, CONNECTION_LOOKUP },
+                 "ANY service =~ 'p'",  -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING NOT "
                  "name =~ 'p' AND "
-                 "ANY service =~ 'p'",  -1,  1, CONNECTION_LOOKUP },
+                 "ANY service =~ 'p'",  -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "name =~ 'p' AND "
                  "ANY service =~ 'p' OR "
-                 "ANY service =~ 'r'",  -1,  1, CONNECTION_LOOKUP },
+                 "ANY service =~ 'r'",  -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING NOT "
                  "name =~ 'p' AND "
                  "ANY service =~ 'p' OR "
-                 "ANY service =~ 'r'",  -1,  1, CONNECTION_LOOKUP },
+                 "ANY service =~ 'r'",  -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "name =~ 'p' "
-                 "FILTER age > 1D",    -1,   1, CONNECTION_LOOKUP },
+                 "FILTER age > 1D",    -1,   1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "name =~ 'p' "
                  "FILTER age > 1D AND "
-                 "interval < 240s" ,   -1,   1, CONNECTION_LOOKUP },
+                 "interval < 240s" ,   -1,   1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "name =~ 'p' "
-                 "FILTER NOT age>1D",  -1,   1, CONNECTION_LOOKUP },
+                 "FILTER NOT age>1D",  -1,   1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "name =~ 'p' "
                  "FILTER age>"
-                 "interval",           -1,   1, CONNECTION_LOOKUP },
-               { "LOOKUP services",    -1,   1, CONNECTION_LOOKUP },
+                 "interval",           -1,   1, SDB_CONNECTION_LOOKUP },
+               { "LOOKUP services",    -1,   1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP services MATCHING ANY "
-                 "attribute =~ 'a'",   -1,   1, CONNECTION_LOOKUP },
-               { "LOOKUP metrics",     -1,   1, CONNECTION_LOOKUP },
+                 "attribute =~ 'a'",   -1,   1, SDB_CONNECTION_LOOKUP },
+               { "LOOKUP metrics",     -1,   1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP metrics MATCHING ANY "
-                 "attribute =~ 'a'",   -1,   1, CONNECTION_LOOKUP },
+                 "attribute =~ 'a'",   -1,   1, SDB_CONNECTION_LOOKUP },
  
                { "TIMESERIES 'host'.'metric' "
                  "START 2014-01-01 "
                  "END 2014-12-31 "
-                 "23:59:59",            -1,  1, CONNECTION_TIMESERIES },
+                 "23:59:59",            -1,  1, SDB_CONNECTION_TIMESERIES },
                { "TIMESERIES 'host'.'metric' "
                  "START 2014-02-02 "
-                 "14:02",               -1,  1, CONNECTION_TIMESERIES },
+                 "14:02",               -1,  1, SDB_CONNECTION_TIMESERIES },
                { "TIMESERIES 'host'.'metric' "
-                 "END 2014-02-02",      -1,  1, CONNECTION_TIMESERIES },
+                 "END 2014-02-02",      -1,  1, SDB_CONNECTION_TIMESERIES },
                { "TIMESERIES "
-                 "'host'.'metric'",     -1,  1, CONNECTION_TIMESERIES },
+                 "'host'.'metric'",     -1,  1, SDB_CONNECTION_TIMESERIES },
  
                /* string constants */
                { "LOOKUP hosts MATCHING "
-                 "name = ''''",         -1,  1, CONNECTION_LOOKUP },
+                 "name = ''''",         -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
-                 "name = '''foo'",      -1,  1, CONNECTION_LOOKUP },
+                 "name = '''foo'",      -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
-                 "name = 'f''oo'",      -1,  1, CONNECTION_LOOKUP },
+                 "name = 'f''oo'",      -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
-                 "name = 'foo'''",      -1,  1, CONNECTION_LOOKUP },
+                 "name = 'foo'''",      -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "name = '''",          -1, -1, 0 },
  
                /* numeric constants */
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] = "
-                 "1234",                -1,  1, CONNECTION_LOOKUP },
+                 "1234",                -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] != "
-                 "+234",                -1,  1, CONNECTION_LOOKUP },
+                 "+234",                -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] < "
-                 "-234",                -1,  1, CONNECTION_LOOKUP },
+                 "-234",                -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] > "
-                 "12.4",                -1,  1, CONNECTION_LOOKUP },
+                 "12.4",                -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] <= "
-                 "12. + .3",            -1,  1, CONNECTION_LOOKUP },
+                 "12. + .3",            -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] <= "
-                 "'f' || 'oo'",         -1,  1, CONNECTION_LOOKUP },
+                 "'f' || 'oo'",         -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] >= "
-                 ".4",                  -1,  1, CONNECTION_LOOKUP },
+                 ".4",                  -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] = "
-                 "+12e3",               -1,  1, CONNECTION_LOOKUP },
+                 "+12e3",               -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] = "
-                 "+12e-3",              -1,  1, CONNECTION_LOOKUP },
+                 "+12e-3",              -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] = "
-                 "-12e+3",              -1,  1, CONNECTION_LOOKUP },
+                 "-12e+3",              -1,  1, SDB_CONNECTION_LOOKUP },
  
                /* date, time, interval constants */
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] = "
-                 "1 Y 42D",             -1,  1, CONNECTION_LOOKUP },
+                 "1 Y 42D",             -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] = "
-                 "1s 42D",              -1,  1, CONNECTION_LOOKUP },
+                 "1s 42D",              -1,  1, SDB_CONNECTION_LOOKUP },
                /*
                 * TODO: Something like 1Y42D should work as well but it doesn't since
                 * the scanner will tokenize it into {digit}{identifier} :-/
                 *
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] = "
-                 "1Y42D",               -1,  1, CONNECTION_LOOKUP },
+                 "1Y42D",               -1,  1, SDB_CONNECTION_LOOKUP },
                 */
  
-                 "backend = ['foo']",   -1,  1, CONNECTION_LOOKUP },
 +              /* array constants */
 +              { "LOOKUP hosts MATCHING "
-                 "backend = ['a','b']", -1,  1, CONNECTION_LOOKUP },
++                "backend = ['foo']",   -1,  1, SDB_CONNECTION_LOOKUP },
 +              { "LOOKUP hosts MATCHING "
++                "backend = ['a','b']", -1,  1, SDB_CONNECTION_LOOKUP },
 +
                /* NULL */
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] "
-                 "IS NULL",             -1,  1, CONNECTION_LOOKUP },
+                 "IS NULL",             -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "attribute['foo'] "
-                 "IS NOT NULL",         -1,  1, CONNECTION_LOOKUP },
+                 "IS NOT NULL",         -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "NOT attribute['foo'] "
-                 "IS NULL",             -1,  1, CONNECTION_LOOKUP },
+                 "IS NULL",             -1,  1, SDB_CONNECTION_LOOKUP },
                { "LOOKUP hosts MATCHING "
                  "ANY service IS NULL", -1, -1, 0 },
  
@@@ -458,14 -452,6 +458,14 @@@ START_TEST(test_parse_matcher
                 * IS NULL currently maps to an equality matcher */
                { "attribute['foo'] IS NULL",     -1,  MATCHER_ISNULL },
                { "attribute['foo'] IS NOT NULL", -1,  MATCHER_ISNNULL },
 +              /* array expressions */
 +              { "backend < ['a']",              -1,  MATCHER_LT },
 +              { "backend <= ['a']",             -1,  MATCHER_LE },
 +              { "backend = ['a']",              -1,  MATCHER_EQ },
 +              { "backend != ['a']",             -1,  MATCHER_NE },
 +              { "backend >= ['a']",             -1,  MATCHER_GE },
 +              { "backend > ['a']",              -1,  MATCHER_GT },
 +              { "backend &^ ['a']",             -1,  -1 },
  
                /* object field matchers */
                { "name < 'a'",                   -1,  MATCHER_LT },