X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Fparser%2Fanalyzer.c;h=dea83d7e0c828d8966fbffe9e91a2895c466fdf7;hp=2f79fc394c79dcf2f2fb65087942935db5efd59e;hb=1ef0d00327e4b5f56b438f44053f48fd8b198baa;hpb=f1975b0bdc00eff623288b34961b9de7d83e7ba1 diff --git a/src/parser/analyzer.c b/src/parser/analyzer.c index 2f79fc3..dea83d7 100644 --- a/src/parser/analyzer.c +++ b/src/parser/analyzer.c @@ -155,6 +155,8 @@ analyze_logical(int context, sdb_ast_op_t *op, sdb_strbuf_t *errbuf) break; case SDB_AST_ISNULL: + case SDB_AST_ISTRUE: + case SDB_AST_ISFALSE: if (analyze_node(context, op->right, errbuf)) return -1; break; @@ -215,25 +217,19 @@ analyze_iter(int context, sdb_ast_iter_t *iter, sdb_strbuf_t *errbuf) if (iter->iter->type == SDB_AST_TYPE_TYPED) iter_context = SDB_AST_TYPED(iter->iter)->type; - if (analyze_node(context, iter->iter, errbuf)) + if (analyze_node(iter_context, iter->iter, errbuf)) return -1; - if (iter->iter->data_type > 0) - c.value.type = iter->iter->data_type & 0xff; - else - c.value.type = -1; - /* TODO: support other setups as well */ assert((iter->expr->type == SDB_AST_TYPE_OPERATOR) && (! SDB_AST_OP(iter->expr)->left)); - SDB_AST_OP(iter->expr)->left = SDB_AST_NODE(&c); - status = analyze_node(iter_context, iter->expr, errbuf); - SDB_AST_OP(iter->expr)->left = NULL; - if (status) - return -1; + /* determine the data-type for better error messages */ + analyze_node(iter_context, SDB_AST_OP(iter->expr)->right, NULL); if (iter->iter->type == SDB_AST_TYPE_TYPED) { int iter_type = SDB_AST_TYPED(iter->iter)->type; + c.value.type = iter->iter->data_type; + if (iter_type == SDB_ATTRIBUTE) { /* attributes are always iterable */ } @@ -262,12 +258,9 @@ analyze_iter(int context, sdb_ast_iter_t *iter, sdb_strbuf_t *errbuf) else if (iter->iter->type == SDB_AST_TYPE_VALUE) { int iter_type = SDB_AST_VALUE(iter->iter)->type; - if (iter_type == SDB_FIELD_BACKEND) { - /* backends are always iterable */ - } - else if ((context != SDB_HOST) && (context != SDB_SERVICE) - && (context != SDB_METRIC) && (context != SDB_ATTRIBUTE) - && (context != UNSPEC_CONTEXT)) { + c.value.type = iter->iter->data_type & 0xff; + + if (iter_type != SDB_FIELD_BACKEND) { iter_error(errbuf, iter, "%s not iterable in %s context", (iter_type == SDB_ATTRIBUTE) ? "attribute" @@ -277,12 +270,27 @@ analyze_iter(int context, sdb_ast_iter_t *iter, sdb_strbuf_t *errbuf) } } else if (iter->iter->type == SDB_AST_TYPE_CONST) { + c.value.type = iter->iter->data_type & 0xff; + if (! (SDB_AST_CONST(iter->iter)->value.type & SDB_TYPE_ARRAY)) { iter_error(errbuf, iter, "%s not iterable", SDB_TYPE_TO_STRING(SDB_AST_CONST(iter->iter)->value.type)); return -1; } } + else { + /* TODO: if we know the data-type of iter->iter and it's an array, + * we should support an iterator for it as well */ + iter_error(errbuf, iter, "%s expression not iterable", + SDB_AST_TYPE_TO_STRING(iter->iter)); + return -1; + } + + SDB_AST_OP(iter->expr)->left = SDB_AST_NODE(&c); + status = analyze_node(context, iter->expr, errbuf); + SDB_AST_OP(iter->expr)->left = NULL; + if (status) + return -1; return 0; } /* analyze_iter */ @@ -295,21 +303,72 @@ analyze_const(int __attribute__((unused)) context, sdb_ast_const_t *c, } /* analyze_const */ static int -analyze_value(int __attribute__((unused)) context, sdb_ast_value_t *v, - sdb_strbuf_t __attribute__((unused)) *errbuf) +analyze_value(int context, sdb_ast_value_t *v, sdb_strbuf_t *errbuf) { if (v->type != SDB_ATTRIBUTE) SDB_AST_NODE(v)->data_type = SDB_FIELD_TYPE(v->type); + + if ((v->type != SDB_ATTRIBUTE) && v->name) { + sdb_strbuf_sprintf(errbuf, "Invalid expression %s[%s]", + SDB_FIELD_TO_NAME(v->type), v->name); + return -1; + } + else if ((v->type == SDB_ATTRIBUTE) && (! v->name)) { + sdb_strbuf_sprintf(errbuf, "Invalid expression attribute[] " + "(missing name)"); + return -1; + } + + if (context != UNSPEC_CONTEXT) { + /* skip these checks if we don't know the context; it's up to the + * caller to check again once the right context information is + * available */ + if ((context != SDB_ATTRIBUTE) && (v->type == SDB_FIELD_VALUE)) { + sdb_strbuf_sprintf(errbuf, "Invalid expression %s.value", + SDB_FIELD_TO_NAME(context)); + return -1; + } + if ((context != SDB_METRIC) && (v->type == SDB_FIELD_TIMESERIES)) { + sdb_strbuf_sprintf(errbuf, "Invalid expression %s.timeseries", + SDB_FIELD_TO_NAME(context)); + return -1; + } + } return 0; } /* analyze_value */ static int -analyze_typed(int __attribute__((unused)) context, sdb_ast_typed_t *t, - sdb_strbuf_t *errbuf) +analyze_typed(int context, sdb_ast_typed_t *t, sdb_strbuf_t *errbuf) { + if ((t->expr->type != SDB_AST_TYPE_VALUE) + && (t->expr->type != SDB_AST_TYPE_TYPED)) { + sdb_strbuf_sprintf(errbuf, "Invalid expression %s.%s", + SDB_STORE_TYPE_TO_NAME(t->type), + SDB_AST_TYPE_TO_STRING(t->expr)); + return -1; + } if (analyze_node(t->type, t->expr, errbuf)) return -1; SDB_AST_NODE(t)->data_type = t->expr->data_type; + + if ((t->type != SDB_ATTRIBUTE) && (! VALID_OBJ_TYPE(t->type))) { + sdb_strbuf_sprintf(errbuf, "Invalid expression %#x.%s", + t->type, SDB_AST_TYPE_TO_STRING(t->expr)); + return -1; + } + + /* self-references are allowed and services and metrics may reference + * their parent host; everything may reference attributes */ + if ((context != t->type) && (context > 0) + && (((context != SDB_SERVICE) && (context != SDB_METRIC)) + || (t->type != SDB_HOST)) + && (t->type != SDB_ATTRIBUTE)) { + sdb_strbuf_sprintf(errbuf, "Invalid expression %s.%s in %s context", + SDB_STORE_TYPE_TO_NAME(t->type), + SDB_AST_TYPE_TO_STRING(t->expr), + context == -1 ? "generic" : SDB_STORE_TYPE_TO_NAME(context)); + return -1; + } return 0; } /* analyze_typed */