X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Ffrontend%2Fanalyzer.c;h=4bd370222e8e11d4a41e9a3b297a1e35412155be;hp=75aa94d1579da92f8f9e25b3ee03c74273d70b74;hb=da760b7c730635befe5d3876641dd826f7abf9d3;hpb=722e33e4e698c1fa4d93d3f34e9460162aa21d49 diff --git a/src/frontend/analyzer.c b/src/frontend/analyzer.c index 75aa94d..4bd3702 100644 --- a/src/frontend/analyzer.c +++ b/src/frontend/analyzer.c @@ -40,25 +40,26 @@ */ static void -iter_error(sdb_strbuf_t *errbuf, int op, int oper, int context) +iter_error(sdb_strbuf_t *errbuf, int op, sdb_store_expr_t *iter, int context) { - sdb_strbuf_sprintf(errbuf, "Cannot use %s %s in %s context", - MATCHER_SYM(op), SDB_STORE_TYPE_TO_NAME(oper), - SDB_STORE_TYPE_TO_NAME(context)); + sdb_strbuf_sprintf(errbuf, "Invalid %s iterator: %s %s " + "not iterable in %s context", MATCHER_SYM(op), + EXPR_TO_STRING(iter), SDB_STORE_TYPE_TO_NAME(iter->data_type), + context == -1 ? "generic" : SDB_STORE_TYPE_TO_NAME(context)); } /* iter_error */ static void -iter_array_error(sdb_strbuf_t *errbuf, int op, - int array_type, int cmp, int value_type) +iter_op_error(sdb_strbuf_t *errbuf, int op, + int iter_type, int cmp, int value_type) { - sdb_strbuf_sprintf(errbuf, "Invalid array iterator %s %s %s %s", - MATCHER_SYM(op), SDB_TYPE_TO_STRING(array_type), + sdb_strbuf_sprintf(errbuf, "Invalid iterator %s %s %s %s", + MATCHER_SYM(op), SDB_TYPE_TO_STRING(iter_type), MATCHER_SYM(cmp), SDB_TYPE_TO_STRING(value_type)); - if ((array_type & 0xff) != value_type) + if ((iter_type & 0xff) != value_type) sdb_strbuf_append(errbuf, " (type mismatch)"); else sdb_strbuf_append(errbuf, " (invalid operator)"); -} /* iter_array_error */ +} /* iter_op_error */ static void cmp_error(sdb_strbuf_t *errbuf, int op, int left, int right) @@ -99,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; @@ -127,7 +138,8 @@ analyze_expr(int context, sdb_store_expr_t *e, sdb_strbuf_t *errbuf) } /* analyze_expr */ static int -analyze_matcher(int context, sdb_store_matcher_t *m, sdb_strbuf_t *errbuf) +analyze_matcher(int context, int parent_type, + sdb_store_matcher_t *m, sdb_strbuf_t *errbuf) { if (! m) return 0; @@ -136,85 +148,104 @@ analyze_matcher(int context, sdb_store_matcher_t *m, sdb_strbuf_t *errbuf) case MATCHER_OR: case MATCHER_AND: assert(OP_M(m)->left && OP_M(m)->right); - if (analyze_matcher(context, OP_M(m)->left, errbuf)) + if (analyze_matcher(context, m->type, OP_M(m)->left, errbuf)) return -1; - if (analyze_matcher(context, OP_M(m)->right, errbuf)) + if (analyze_matcher(context, m->type, OP_M(m)->right, errbuf)) return -1; break; case MATCHER_NOT: assert(UOP_M(m)->op); - if (analyze_matcher(context, UOP_M(m)->op, errbuf)) + if (analyze_matcher(context, m->type, UOP_M(m)->op, errbuf)) return -1; break; case MATCHER_ANY: case MATCHER_ALL: + { + int child_context = -1; + int left_type = -1; + int type = -1; + assert(ITER_M(m)->m); - if ((context != SDB_HOST) - && (context != SDB_SERVICE) - && (context != SDB_METRIC)) { - iter_error(errbuf, m->type, ITER_M(m)->type, context); - return -1; + + if ((ITER_M(m)->iter->type == TYPED_EXPR) + || (ITER_M(m)->iter->type == FIELD_VALUE)) + type = (int)ITER_M(m)->iter->data.data.integer; + + if (context == -1) { /* inside a filter */ + /* attributes are always iterable */ + if ((ITER_M(m)->iter->type == TYPED_EXPR) + && (type != SDB_ATTRIBUTE)) { + iter_error(errbuf, m->type, ITER_M(m)->iter, context); + return -1; + } + /* backends are always iterable */ + if ((ITER_M(m)->iter->type == FIELD_VALUE) + && (! (type != SDB_FIELD_BACKEND))) { + iter_error(errbuf, m->type, ITER_M(m)->iter, context); + return -1; + } } - if (ITER_M(m)->type == context) { - iter_error(errbuf, m->type, ITER_M(m)->type, context); + else if (! sdb_store_expr_iterable(ITER_M(m)->iter, context)) { + iter_error(errbuf, m->type, ITER_M(m)->iter, context); return -1; } - if ((ITER_M(m)->type != SDB_SERVICE) - && (ITER_M(m)->type != SDB_METRIC) - && (ITER_M(m)->type != SDB_ATTRIBUTE) - && (ITER_M(m)->type != SDB_FIELD_BACKEND)) { - iter_error(errbuf, m->type, ITER_M(m)->type, context); - return -1; + + if (ITER_M(m)->iter->type == TYPED_EXPR) { + child_context = type; + left_type = ITER_M(m)->iter->data_type; } - if ((context == SDB_SERVICE) - && (ITER_M(m)->type == SDB_METRIC)) { - iter_error(errbuf, m->type, ITER_M(m)->type, context); + else if (ITER_M(m)->iter->type == FIELD_VALUE) { + child_context = context; + /* element type of the field */ + left_type = ITER_M(m)->iter->data_type & 0xff; + } + else if (! ITER_M(m)->iter->type) { + child_context = context; + /* elements of the array constant */ + left_type = ITER_M(m)->iter->data.type & 0xff; + } + else { + iter_error(errbuf, m->type, ITER_M(m)->iter, context); return -1; } - else if ((context == SDB_METRIC) - && (ITER_M(m)->type == SDB_SERVICE)) { - iter_error(errbuf, m->type, ITER_M(m)->type, context); + + /* any ary operator will do but these are the once + * we currently support */ + if ((ITER_M(m)->m->type != MATCHER_LT) + && (ITER_M(m)->m->type != MATCHER_LE) + && (ITER_M(m)->m->type != MATCHER_EQ) + && (ITER_M(m)->m->type != MATCHER_NE) + && (ITER_M(m)->m->type != MATCHER_GE) + && (ITER_M(m)->m->type != MATCHER_GT) + && (ITER_M(m)->m->type != MATCHER_REGEX) + && (ITER_M(m)->m->type != MATCHER_NREGEX)) { + iter_op_error(errbuf, m->type, + left_type, ITER_M(m)->m->type, + CMP_M(ITER_M(m)->m)->right->data_type); return -1; } - if (ITER_M(m)->type == SDB_FIELD_BACKEND) { - /* array iterators only support simple comparison atm */ - if ((ITER_M(m)->m->type != MATCHER_LT) - && (ITER_M(m)->m->type != MATCHER_LE) - && (ITER_M(m)->m->type != MATCHER_EQ) - && (ITER_M(m)->m->type != MATCHER_NE) - && (ITER_M(m)->m->type != MATCHER_GE) - && (ITER_M(m)->m->type != MATCHER_GT) - && (ITER_M(m)->m->type != MATCHER_REGEX) - && (ITER_M(m)->m->type != MATCHER_NREGEX)) { - iter_array_error(errbuf, m->type, - CMP_M(ITER_M(m)->m)->left->data_type, - ITER_M(m)->m->type, - CMP_M(ITER_M(m)->m)->right->data_type); - return -1; - } - if (CMP_M(ITER_M(m)->m)->right->data_type < 0) - return 0; /* skip further type checks */ - if (CMP_M(ITER_M(m)->m)->right->data_type & SDB_TYPE_ARRAY) { - iter_array_error(errbuf, m->type, - CMP_M(ITER_M(m)->m)->left->data_type, - ITER_M(m)->m->type, - CMP_M(ITER_M(m)->m)->right->data_type); - return -1; - } - if ((CMP_M(ITER_M(m)->m)->left->data_type & 0xff) - != CMP_M(ITER_M(m)->m)->right->data_type) { - iter_array_error(errbuf, m->type, - CMP_M(ITER_M(m)->m)->left->data_type, - ITER_M(m)->m->type, + if ((left_type >= 0) + && (CMP_M(ITER_M(m)->m)->right->data_type >= 0)) { + if (left_type != CMP_M(ITER_M(m)->m)->right->data_type) { + iter_op_error(errbuf, m->type, + left_type, ITER_M(m)->m->type, CMP_M(ITER_M(m)->m)->right->data_type); return -1; } } - else if (analyze_matcher(ITER_M(m)->type, ITER_M(m)->m, errbuf)) + if (child_context <= 0) { + sdb_strbuf_sprintf(errbuf, "Unable to determine the context " + "(object type) of iterator %s %s %s %s", + MATCHER_SYM(m->type), SDB_TYPE_TO_STRING(left_type), + MATCHER_SYM(ITER_M(m)->m->type), + SDB_TYPE_TO_STRING(CMP_M(ITER_M(m)->m)->right->data_type)); + } + if (analyze_matcher(child_context, m->type, ITER_M(m)->m, errbuf)) return -1; break; + } case MATCHER_LT: case MATCHER_LE: @@ -222,52 +253,69 @@ analyze_matcher(int context, sdb_store_matcher_t *m, sdb_strbuf_t *errbuf) case MATCHER_NE: case MATCHER_GE: case MATCHER_GT: - assert(CMP_M(m)->left && CMP_M(m)->right); + { + int left_type = -1; + + assert(CMP_M(m)->right); + if ((parent_type == MATCHER_ALL) + || (parent_type == MATCHER_ANY)) { + assert(! CMP_M(m)->left); + } + else { + assert(CMP_M(m)->left); + left_type = CMP_M(m)->left->data_type; + } + if (analyze_expr(context, CMP_M(m)->left, errbuf)) return -1; if (analyze_expr(context, CMP_M(m)->right, errbuf)) return -1; - if ((CMP_M(m)->left->data_type > 0) - && (CMP_M(m)->right->data_type > 0)) { - if (CMP_M(m)->left->data_type == CMP_M(m)->right->data_type) + if ((left_type > 0) && (CMP_M(m)->right->data_type > 0)) { + if (left_type == CMP_M(m)->right->data_type) return 0; - cmp_error(errbuf, m->type, CMP_M(m)->left->data_type, + cmp_error(errbuf, m->type, left_type, CMP_M(m)->right->data_type); return -1; } - 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, + if ((left_type > 0) && (left_type & SDB_TYPE_ARRAY)) { + cmp_error(errbuf, m->type, left_type, CMP_M(m)->right->data_type); return -1; } if ((CMP_M(m)->right->data_type > 0) && (CMP_M(m)->right->data_type & SDB_TYPE_ARRAY)) { - cmp_error(errbuf, m->type, CMP_M(m)->left->data_type, + cmp_error(errbuf, m->type, left_type, CMP_M(m)->right->data_type); return -1; } break; + } case MATCHER_IN: + case MATCHER_NIN: if (analyze_expr(context, CMP_M(m)->left, errbuf)) return -1; if (analyze_expr(context, CMP_M(m)->right, errbuf)) return -1; - 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, - CMP_M(m)->right->data_type); - return -1; - } + /* the left operand may be a scalar or an array but the element + * type has to match */ if ((CMP_M(m)->right->data_type > 0) && (! (CMP_M(m)->right->data_type & SDB_TYPE_ARRAY))) { cmp_error(errbuf, m->type, CMP_M(m)->left->data_type, CMP_M(m)->right->data_type); return -1; } + if ((CMP_M(m)->left->data_type > 0) + && (CMP_M(m)->right->data_type > 0)) { + if ((CMP_M(m)->left->data_type & 0xff) + != (CMP_M(m)->right->data_type & 0xff)) { + cmp_error(errbuf, m->type, CMP_M(m)->left->data_type, + CMP_M(m)->right->data_type); + return -1; + } + } break; case MATCHER_REGEX: @@ -354,13 +402,20 @@ sdb_fe_analyze(sdb_conn_node_t *node, sdb_strbuf_t *errbuf) } else { sdb_strbuf_sprintf(errbuf, - "Don't know how to analyze command %#x", node->cmd); + "Don't know how to analyze %s command (id=%#x)", + SDB_CONN_MSGTYPE_TO_STRING(node->cmd), node->cmd); return -1; } - if (analyze_matcher(context, m, errbuf)) + if (context <= 0) { + sdb_strbuf_sprintf(errbuf, "Unable to determine the context " + "(object type) for %s command (id=%#x)", + SDB_CONN_MSGTYPE_TO_STRING(node->cmd), node->cmd); + return -1; + } + if (analyze_matcher(context, -1, m, errbuf)) status = -1; - if (analyze_matcher(-1, filter, errbuf)) + if (analyze_matcher(-1, -1, filter, errbuf)) status = -1; return status; } /* sdb_fe_analyze */