X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ffrontend%2Fanalyzer.c;h=b5d0e0825ce785dd09468d2474676bd7888749b8;hb=b072d9b2786422fcb8f068dd5076bd108a6228e9;hp=20864cae4d348ca2e3072e1e48945fd157cb6c66;hpb=2ebe67e1b7d71c3e7e9b7ab06944637b143daba9;p=sysdb.git diff --git a/src/frontend/analyzer.c b/src/frontend/analyzer.c index 20864ca..b5d0e08 100644 --- a/src/frontend/analyzer.c +++ b/src/frontend/analyzer.c @@ -48,17 +48,17 @@ iter_error(sdb_strbuf_t *errbuf, int op, int oper, int 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) @@ -68,8 +68,67 @@ cmp_error(sdb_strbuf_t *errbuf, int op, int left, int right) SDB_TYPE_TO_STRING(right)); } /* cmp_error */ +static void +op_error(sdb_strbuf_t *errbuf, int op, int left, int right) +{ + sdb_strbuf_sprintf(errbuf, "Invalid operator %s for types %s and %s", + SDB_DATA_OP_TO_STRING(op), SDB_TYPE_TO_STRING(left), + SDB_TYPE_TO_STRING(right)); +} /* cmp_error */ + +static int +analyze_expr(int context, sdb_store_expr_t *e, sdb_strbuf_t *errbuf) +{ + if (! e) + return 0; + + if ((e->type < TYPED_EXPR) || (SDB_DATA_CONCAT < e->type)) { + sdb_strbuf_sprintf(errbuf, "Invalid expression of type %d", e->type); + return -1; + } + + switch (e->type) { + case TYPED_EXPR: + if (analyze_expr((int)e->data.data.integer, e->left, errbuf)) + return -1; + if (context == (int)e->data.data.integer) + return 0; + if ((e->data.data.integer == SDB_HOST) && + ((context == SDB_SERVICE) || (context == SDB_METRIC))) + return 0; + 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)); + return -1; + + case ATTR_VALUE: + case FIELD_VALUE: + case 0: + break; + + default: + if (analyze_expr(context, e->left, errbuf)) + return -1; + if (analyze_expr(context, e->right, errbuf)) + return -1; + + if ((e->left->data_type > 0) && (e->right->data_type > 0)) { + if (sdb_data_expr_type(e->type, e->left->data_type, + e->right->data_type) < 0) { + op_error(errbuf, e->type, e->left->data_type, + e->right->data_type); + return -1; + } + } + break; + } + return 0; +} /* 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; @@ -78,66 +137,77 @@ 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 type; assert(ITER_M(m)->m); + if ((ITER_M(m)->iter->type == TYPED_EXPR) + || (ITER_M(m)->iter->type == FIELD_VALUE)) { + type = (int)ITER_M(m)->iter->data.data.integer; + } + else { + iter_error(errbuf, m->type, -1, context); + return -1; + } if ((context != SDB_HOST) && (context != SDB_SERVICE) && (context != SDB_METRIC)) { - iter_error(errbuf, m->type, ITER_M(m)->type, context); + iter_error(errbuf, m->type, type, context); return -1; } - if (ITER_M(m)->type == context) { - iter_error(errbuf, m->type, ITER_M(m)->type, context); + if (type == context) { + iter_error(errbuf, m->type, type, 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); + if ((type != SDB_SERVICE) + && (type != SDB_METRIC) + && (type != SDB_ATTRIBUTE) + && (type != SDB_FIELD_BACKEND)) { + iter_error(errbuf, m->type, type, context); return -1; } - if ((context == SDB_SERVICE) - && (ITER_M(m)->type == SDB_METRIC)) { - iter_error(errbuf, m->type, ITER_M(m)->type, context); + if ((context == SDB_SERVICE) && (type == SDB_METRIC)) { + iter_error(errbuf, m->type, type, context); return -1; } - else if ((context == SDB_METRIC) - && (ITER_M(m)->type == SDB_SERVICE)) { - iter_error(errbuf, m->type, ITER_M(m)->type, context); + else if ((context == SDB_METRIC) && (type == SDB_SERVICE)) { + iter_error(errbuf, m->type, type, context); 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_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; - } + /* 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, + 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 (type == SDB_FIELD_BACKEND) { 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, + iter_op_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); @@ -145,16 +215,17 @@ analyze_matcher(int context, sdb_store_matcher_t *m, sdb_strbuf_t *errbuf) } 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, + iter_op_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; } } - else if (analyze_matcher(ITER_M(m)->type, ITER_M(m)->m, errbuf)) + else if (analyze_matcher(type, m->type, ITER_M(m)->m, errbuf)) return -1; break; + } case MATCHER_LT: case MATCHER_LE: @@ -162,7 +233,28 @@ 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); + assert(CMP_M(m)->right); + if ((parent_type == MATCHER_ALL) + || (parent_type == MATCHER_ANY)) { + // TODO: assert(! CMP_M(m)->left); + } + else { + assert(CMP_M(m)->left); + } + + 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) + return 0; + 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)->left->data_type & SDB_TYPE_ARRAY)) { cmp_error(errbuf, m->type, CMP_M(m)->left->data_type, @@ -178,22 +270,38 @@ analyze_matcher(int context, sdb_store_matcher_t *m, sdb_strbuf_t *errbuf) break; case MATCHER_IN: - 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); + 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; + + /* 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: case MATCHER_NREGEX: + if (analyze_expr(context, CMP_M(m)->left, errbuf)) + return -1; + if (analyze_expr(context, CMP_M(m)->right, errbuf)) + return -1; + /* all types are supported for the left operand */ if ((CMP_M(m)->right->data_type > 0) && (CMP_M(m)->right->data_type != SDB_TYPE_REGEX) @@ -206,6 +314,8 @@ analyze_matcher(int context, sdb_store_matcher_t *m, sdb_strbuf_t *errbuf) case MATCHER_ISNULL: case MATCHER_ISNNULL: + if (analyze_expr(context, ISNULL_M(m)->expr, errbuf)) + return -1; break; default: @@ -231,7 +341,7 @@ sdb_fe_analyze(sdb_conn_node_t *node, sdb_strbuf_t *errbuf) /* 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); @@ -246,26 +356,36 @@ sdb_fe_analyze(sdb_conn_node_t *node, sdb_strbuf_t *errbuf) 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_STORE_HOST) + || (node->cmd == SDB_CONNECTION_STORE_SERVICE) + || (node->cmd == SDB_CONNECTION_STORE_METRIC) + || (node->cmd == SDB_CONNECTION_STORE_ATTRIBUTE)) { return 0; - else + } + else if (node->cmd == SDB_CONNECTION_TIMESERIES) { + return 0; + } + else { + sdb_strbuf_sprintf(errbuf, + "Don't know how to analyze command %#x", node->cmd); return -1; + } - if (analyze_matcher(context, m, errbuf)) + 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 */