X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Ffrontend%2Fgrammar.y;h=31b71a0eba7665b94de03bd47c50a0cd989ff24e;hp=80fb249684e0120be85cd421905fec666d277bc4;hb=5ced2b9eb4d4def7d3ad5b1172004293e7a68e0e;hpb=2ebe67e1b7d71c3e7e9b7ab06944637b143daba9 diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 80fb249..31b71a0 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -48,7 +48,7 @@ */ static sdb_store_matcher_t * -name_iter_matcher(int m_type, int type, const char *cmp, +name_iter_matcher(int m_type, sdb_store_expr_t *iter, const char *cmp, sdb_store_expr_t *expr); /* @@ -78,7 +78,7 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...); #define MODE_TO_STRING(m) \ (((m) == SDB_PARSE_DEFAULT) ? "statement" \ : ((m) == SDB_PARSE_COND) ? "condition" \ - : ((m) == SDB_PARSE_EXPR) ? "expression" \ + : ((m) == SDB_PARSE_ARITH) ? "arithmetic expression" \ : "UNKNOWN") %} @@ -104,6 +104,8 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...); sdb_store_matcher_t *m; sdb_store_expr_t *expr; + + sdb_metric_store_t metric_store; } %start statements @@ -117,14 +119,16 @@ 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 %token START END /* NULL token */ %token NULL_T -%token FETCH LIST LOOKUP TIMESERIES +%token FETCH LIST LOOKUP STORE TIMESERIES %token IDENTIFIER STRING @@ -153,6 +157,7 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...); fetch_statement list_statement lookup_statement + store_statement timeseries_statement matching_clause filter_clause @@ -161,19 +166,22 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...); %type matcher compare_matcher -%type expression +%type expression arithmetic_expression object_expression %type object_type object_type_plural -%type iterable %type field %type cmp %type data interval interval_elem + array array_elem_list %type datetime start_clause end_clause + last_update_clause + +%type metric_store_clause %destructor { free($$); } %destructor { sdb_object_deref(SDB_OBJ($$)); } @@ -236,7 +244,7 @@ statements: expression { /* only accepted in expression parse mode */ - if (! (parser_mode & SDB_PARSE_EXPR)) { + if (! (parser_mode & SDB_PARSE_ARITH)) { sdb_fe_yyerrorf(&yylloc, scanner, YY_("syntax error, unexpected expression, " "expecting %s"), MODE_TO_STRING(parser_mode)); @@ -248,7 +256,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)); @@ -264,6 +272,8 @@ statement: | lookup_statement | + store_statement + | timeseries_statement | /* empty */ @@ -286,7 +296,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 @@ -297,7 +307,7 @@ fetch_statement: CONN_FETCH($$)->host = $3; CONN_FETCH($$)->name = $5; CONN_FETCH($$)->filter = CONN_MATCHER($6); - $$->cmd = CONNECTION_FETCH; + $$->cmd = SDB_CONNECTION_FETCH; } ; @@ -313,7 +323,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; } ; @@ -330,7 +340,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; } ; @@ -344,6 +354,95 @@ filter_clause: | /* empty */ { $$ = NULL; } +/* + * STORE |. [LAST UPDATE ]; + * STORE METRIC . STORE [LAST UPDATE ]; + * STORE ATTRIBUTE . [LAST UPDATE ]; + * + * Store or update an object in the database. + */ +store_statement: + STORE HOST_T STRING last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_host_t, conn_store_host_destroy)); + CONN_STORE_HOST($$)->name = $3; + CONN_STORE_HOST($$)->last_update = $4; + $$->cmd = SDB_CONNECTION_STORE_HOST; + } + | + STORE SERVICE_T STRING '.' STRING last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_svc_t, conn_store_svc_destroy)); + CONN_STORE_SVC($$)->hostname = $3; + CONN_STORE_SVC($$)->name = $5; + CONN_STORE_SVC($$)->last_update = $6; + $$->cmd = SDB_CONNECTION_STORE_SERVICE; + } + | + STORE METRIC_T STRING '.' STRING metric_store_clause last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_metric_t, conn_store_metric_destroy)); + CONN_STORE_METRIC($$)->hostname = $3; + CONN_STORE_METRIC($$)->name = $5; + CONN_STORE_METRIC($$)->store_type = $6.type; + CONN_STORE_METRIC($$)->store_id = $6.id; + CONN_STORE_METRIC($$)->last_update = $7; + $$->cmd = SDB_CONNECTION_STORE_METRIC; + } + | + STORE HOST_T ATTRIBUTE_T STRING '.' STRING data last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_attr_t, conn_store_attr_destroy)); + CONN_STORE_ATTR($$)->parent_type = SDB_HOST; + CONN_STORE_ATTR($$)->hostname = NULL; + CONN_STORE_ATTR($$)->parent = $4; + CONN_STORE_ATTR($$)->key = $6; + CONN_STORE_ATTR($$)->value = $7; + CONN_STORE_ATTR($$)->last_update = $8; + $$->cmd = SDB_CONNECTION_STORE_ATTRIBUTE; + } + | + STORE SERVICE_T ATTRIBUTE_T STRING '.' STRING '.' STRING data last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_attr_t, conn_store_attr_destroy)); + CONN_STORE_ATTR($$)->parent_type = SDB_SERVICE; + CONN_STORE_ATTR($$)->hostname = $4; + CONN_STORE_ATTR($$)->parent = $6; + CONN_STORE_ATTR($$)->key = $8; + CONN_STORE_ATTR($$)->value = $9; + CONN_STORE_ATTR($$)->last_update = $10; + $$->cmd = SDB_CONNECTION_STORE_ATTRIBUTE; + } + | + STORE METRIC_T ATTRIBUTE_T STRING '.' STRING '.' STRING data last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_attr_t, conn_store_attr_destroy)); + CONN_STORE_ATTR($$)->parent_type = SDB_METRIC; + CONN_STORE_ATTR($$)->hostname = $4; + CONN_STORE_ATTR($$)->parent = $6; + CONN_STORE_ATTR($$)->key = $8; + CONN_STORE_ATTR($$)->value = $9; + CONN_STORE_ATTR($$)->last_update = $10; + $$->cmd = SDB_CONNECTION_STORE_ATTRIBUTE; + } + ; + +last_update_clause: + LAST UPDATE datetime { $$ = $3; } + | + /* empty */ { $$ = sdb_gettime(); } + +metric_store_clause: + STORE STRING STRING { $$.type = $2; $$.id = $3; } + | + /* empty */ { $$.type = $$.id = NULL; } + /* * TIMESERIES . [START ] [END ]; * @@ -358,7 +457,7 @@ timeseries_statement: CONN_TS($$)->metric = $4; CONN_TS($$)->opts.start = $5; CONN_TS($$)->opts.end = $6; - $$->cmd = CONNECTION_TIMESERIES; + $$->cmd = SDB_CONNECTION_TIMESERIES; } ; @@ -388,7 +487,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; } ; @@ -435,15 +534,17 @@ compare_matcher: sdb_object_deref(SDB_OBJ($3)); } | - ANY iterable cmp expression + ANY expression cmp expression { $$ = name_iter_matcher(MATCHER_ANY, $2, $3, $4); + sdb_object_deref(SDB_OBJ($2)); sdb_object_deref(SDB_OBJ($4)); } | - ALL iterable cmp expression + ALL expression cmp expression { $$ = name_iter_matcher(MATCHER_ALL, $2, $3, $4); + sdb_object_deref(SDB_OBJ($2)); sdb_object_deref(SDB_OBJ($4)); } | @@ -465,9 +566,41 @@ compare_matcher: sdb_object_deref(SDB_OBJ($1)); sdb_object_deref(SDB_OBJ($3)); } + | + expression NOT IN expression + { + $$ = sdb_store_nin_matcher($1, $4); + sdb_object_deref(SDB_OBJ($1)); + sdb_object_deref(SDB_OBJ($4)); + } ; expression: + arithmetic_expression + { + if (! $1) { + /* we should have better error messages here + * TODO: maybe let the analyzer handle this instead */ + sdb_fe_yyerror(&yylloc, scanner, + YY_("syntax error, invalid arithmetic expression")); + YYABORT; + } + $$ = $1; + } + | + object_expression + { + $$ = $1; + } + | + data + { + $$ = sdb_store_expr_constvalue(&$1); + sdb_data_free_datum(&$1); + } + ; + +arithmetic_expression: '(' expression ')' { $$ = $2; @@ -514,6 +647,20 @@ expression: sdb_object_deref(SDB_OBJ($1)); $1 = NULL; sdb_object_deref(SDB_OBJ($3)); $3 = NULL; } + ; + +object_expression: + object_type '.' object_expression + { + $$ = sdb_store_expr_typed($1, $3); + sdb_object_deref(SDB_OBJ($3)); + } + | + ATTRIBUTE_T '.' object_expression + { + $$ = sdb_store_expr_typed(SDB_ATTRIBUTE, $3); + sdb_object_deref(SDB_OBJ($3)); + } | field { @@ -525,12 +672,6 @@ expression: $$ = sdb_store_expr_attrvalue($3); free($3); $3 = NULL; } - | - data - { - $$ = sdb_store_expr_constvalue(&$1); - sdb_data_free_datum(&$1); - } ; object_type: @@ -549,16 +690,6 @@ object_type_plural: METRICS_T { $$ = SDB_METRIC; } ; -iterable: - SERVICE_T { $$ = SDB_SERVICE; } - | - METRIC_T { $$ = SDB_METRIC; } - | - ATTRIBUTE_T { $$ = SDB_ATTRIBUTE; } - | - BACKEND_T { $$ = SDB_FIELD_BACKEND; } - ; - field: NAME_T { $$ = SDB_FIELD_NAME; } | @@ -569,6 +700,8 @@ field: INTERVAL_T { $$ = SDB_FIELD_INTERVAL; } | BACKEND_T { $$ = SDB_FIELD_BACKEND; } + | + VALUE_T { $$ = SDB_FIELD_VALUE; } ; cmp: @@ -599,6 +732,8 @@ data: datetime { $$.type = SDB_TYPE_DATETIME; $$.data.datetime = $1; } | interval { $$ = $1; } + | + array { $$ = $1; } ; datetime: @@ -626,7 +761,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; } @@ -643,6 +778,69 @@ 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 @@ -659,35 +857,24 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...) va_start(ap, fmt); va_copy(aq, ap); sdb_vlog(SDB_LOG_ERR, fmt, ap); - sdb_strbuf_vsprintf(errbuf, "%s", aq); + sdb_strbuf_vsprintf(errbuf, fmt, aq); va_end(ap); } /* sdb_fe_yyerrorf */ static sdb_store_matcher_t * -name_iter_matcher(int m_type, int type, const char *cmp, +name_iter_matcher(int type, sdb_store_expr_t *iter, const char *cmp, sdb_store_expr_t *expr) { sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op(cmp); - sdb_store_expr_t *e; sdb_store_matcher_t *m, *tmp = NULL; assert(cb); - /* hosts are never iterable */ - if (type == SDB_HOST) { - return NULL; - } - - 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); - else if (m_type == MATCHER_ALL) - tmp = sdb_store_all_matcher(type, m); + m = cb(NULL, expr); + if (type == MATCHER_ANY) + tmp = sdb_store_any_matcher(iter, m); + else if (type == MATCHER_ALL) + tmp = sdb_store_all_matcher(iter, m); sdb_object_deref(SDB_OBJ(m)); - sdb_object_deref(SDB_OBJ(e)); return tmp; } /* name_iter_matcher */