X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ffrontend%2Fgrammar.y;h=187f3599c08e2514596bd5046d653c8f03c26842;hb=d25f3c59b5cf5387acd4e6d1467ce9efffa40f9a;hp=b400f9acc51736fc43ebed4cb7a02ea6b03036af;hpb=44a02f37e6bfa9e24ddd35162249779e530b7da4;p=sysdb.git diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index b400f9a..187f359 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -63,6 +63,8 @@ sdb_fe_yyget_extra(sdb_fe_yyscan_t scanner); void sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); +void +sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...); /* quick access to the current parse tree */ #define pt sdb_fe_yyget_extra(scanner)->parsetree @@ -70,6 +72,9 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); /* quick access to the parser mode */ #define parser_mode sdb_fe_yyget_extra(scanner)->mode +/* quick access to the parser's error buffer */ +#define errbuf sdb_fe_yyget_extra(scanner)->errbuf + #define MODE_TO_STRING(m) \ (((m) == SDB_PARSE_DEFAULT) ? "statement" \ : ((m) == SDB_PARSE_COND) ? "condition" \ @@ -156,9 +161,9 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %type matcher compare_matcher -%type expression +%type expression object_expression -%type object_type_plural +%type object_type object_type_plural %type iterable %type field @@ -166,6 +171,7 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %type data interval interval_elem + array array_elem_list %type datetime start_clause end_clause @@ -181,11 +187,9 @@ statements: { /* only accepted in default parse mode */ if (parser_mode != SDB_PARSE_DEFAULT) { - char errmsg[1024]; - snprintf(errmsg, sizeof(errmsg), + sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, unexpected statement, " "expecting %s"), MODE_TO_STRING(parser_mode)); - sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($3)); YYABORT; } @@ -200,11 +204,9 @@ statements: { /* only accepted in default parse mode */ if (parser_mode != SDB_PARSE_DEFAULT) { - char errmsg[1024]; - snprintf(errmsg, sizeof(errmsg), + sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, unexpected statement, " "expecting %s"), MODE_TO_STRING(parser_mode)); - sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($1)); YYABORT; } @@ -219,11 +221,9 @@ statements: { /* only accepted in condition parse mode */ if (! (parser_mode & SDB_PARSE_COND)) { - char errmsg[1024]; - snprintf(errmsg, sizeof(errmsg), + sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, unexpected condition, " "expecting %s"), MODE_TO_STRING(parser_mode)); - sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($1)); YYABORT; } @@ -238,11 +238,9 @@ statements: { /* only accepted in expression parse mode */ if (! (parser_mode & SDB_PARSE_EXPR)) { - char errmsg[1024]; - snprintf(errmsg, sizeof(errmsg), + sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, unexpected expression, " "expecting %s"), MODE_TO_STRING(parser_mode)); - sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($1)); YYABORT; } @@ -251,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)); @@ -281,17 +279,26 @@ statement: * Retrieve detailed information about a single host. */ fetch_statement: - FETCH HOST_T STRING filter_clause + FETCH object_type STRING filter_clause { - /* TODO: support other types as well */ - $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, conn_fetch_t, conn_fetch_destroy)); - CONN_FETCH($$)->type = SDB_HOST; + CONN_FETCH($$)->type = $2; 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 + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_fetch_t, conn_fetch_destroy)); + CONN_FETCH($$)->type = $2; + CONN_FETCH($$)->host = $3; + CONN_FETCH($$)->name = $5; + CONN_FETCH($$)->filter = CONN_MATCHER($6); + $$->cmd = SDB_CONNECTION_FETCH; } ; @@ -307,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; } ; @@ -317,16 +324,14 @@ list_statement: * Returns detailed information about matching condition. */ lookup_statement: - LOOKUP HOSTS_T matching_clause filter_clause + LOOKUP object_type_plural matching_clause filter_clause { - /* TODO: support other types as well */ - $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, conn_lookup_t, conn_lookup_destroy)); - CONN_LOOKUP($$)->type = SDB_HOST; + CONN_LOOKUP($$)->type = $2; CONN_LOOKUP($$)->matcher = CONN_MATCHER($3); CONN_LOOKUP($$)->filter = CONN_MATCHER($4); - $$->cmd = CONNECTION_LOOKUP; + $$->cmd = SDB_CONNECTION_LOOKUP; } ; @@ -354,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; } ; @@ -384,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; } ; @@ -511,11 +516,23 @@ expression: sdb_object_deref(SDB_OBJ($3)); $3 = NULL; } | - HOST_T + object_expression + { + $$ = $1; + } + | + data + { + $$ = sdb_store_expr_constvalue(&$1); + sdb_data_free_datum(&$1); + } + ; + +object_expression: + object_type '.' object_expression { - /* TODO: this only works as long as queries - * are limited to hosts */ - $$ = sdb_store_expr_fieldvalue(SDB_FIELD_NAME); + $$ = sdb_store_expr_typed($1, $3); + sdb_object_deref(SDB_OBJ($3)); } | field @@ -528,12 +545,14 @@ expression: $$ = sdb_store_expr_attrvalue($3); free($3); $3 = NULL; } + ; + +object_type: + HOST_T { $$ = SDB_HOST; } | - data - { - $$ = sdb_store_expr_constvalue(&$1); - sdb_data_free_datum(&$1); - } + SERVICE_T { $$ = SDB_SERVICE; } + | + METRIC_T { $$ = SDB_METRIC; } ; object_type_plural: @@ -550,6 +569,8 @@ iterable: METRIC_T { $$ = SDB_METRIC; } | ATTRIBUTE_T { $$ = SDB_ATTRIBUTE; } + | + BACKEND_T { $$ = SDB_FIELD_BACKEND; } ; field: @@ -592,6 +613,8 @@ data: datetime { $$.type = SDB_TYPE_DATETIME; $$.data.datetime = $1; } | interval { $$ = $1; } + | + array { $$ = $1; } ; datetime: @@ -618,10 +641,8 @@ interval_elem: unit = sdb_strpunit($2); if (! unit) { - char errmsg[strlen($2) + 32]; - snprintf(errmsg, sizeof(errmsg), - YY_("invalid time unit %s"), $2); - sdb_fe_yyerror(&yylloc, scanner, errmsg); + sdb_fe_yyerrorf(&yylloc, scanner, + YY_("syntax error, invalid time unit %s"), $2); free($2); $2 = NULL; YYABORT; } @@ -638,14 +659,89 @@ interval_elem: } ; +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 sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg) { sdb_log(SDB_LOG_ERR, "frontend: parse error: %s", msg); + sdb_strbuf_sprintf(errbuf, "%s", msg); } /* sdb_fe_yyerror */ +void +sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...) +{ + va_list ap, aq; + va_start(ap, fmt); + va_copy(aq, ap); + sdb_vlog(SDB_LOG_ERR, fmt, ap); + sdb_strbuf_vsprintf(errbuf, "%s", aq); + va_end(ap); +} /* sdb_fe_yyerrorf */ + static sdb_store_matcher_t * name_iter_matcher(int m_type, int type, const char *cmp, sdb_store_expr_t *expr) @@ -655,13 +751,15 @@ name_iter_matcher(int m_type, int type, const char *cmp, sdb_store_matcher_t *m, *tmp = NULL; assert(cb); - /* TODO: this only works as long as queries - * are limited to hosts */ + /* hosts are never iterable */ if (type == SDB_HOST) { return NULL; } - e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME); + 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);