diff --git a/src/parser/analyzer.c b/src/parser/analyzer.c
index dea83d7e0c828d8966fbffe9e91a2895c466fdf7..4adeafc66f02651bbc85c665059503647d792ffb 100644 (file)
--- a/src/parser/analyzer.c
+++ b/src/parser/analyzer.c
#include <assert.h>
#include <stdarg.h>
#include <assert.h>
#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
#define VALID_OBJ_TYPE(t) ((SDB_HOST <= (t)) && ((t) <= SDB_METRIC))
#define VALID_OBJ_TYPE(t) ((SDB_HOST <= (t)) && ((t) <= SDB_METRIC))
+typedef struct {
+ int type;
+ bool iter;
+} context_t;
+
#define FILTER_CONTEXT -1
#define FILTER_CONTEXT -1
-#define UNSPEC_CONTEXT -2
+static const context_t FILTER_CTX = { FILTER_CONTEXT, 0 };
static int
static int
-analyze_node(int context, sdb_ast_node_t *node, sdb_strbuf_t *errbuf);
+analyze_node(context_t ctx, sdb_ast_node_t *node, sdb_strbuf_t *errbuf);
/*
* error reporting
/*
* error reporting
r);
} /* iter_error */
r);
} /* iter_error */
+/*
+ * generic checks
+ */
+
+typedef struct {
+ int obj_type;
+ const char *hostname;
+ int parent_type;
+ const char *parent;
+ const char *name;
+} parent_child_t;
+
+static int
+analyze_parent_child(const char *cmd, parent_child_t *pc, sdb_strbuf_t *errbuf)
+{
+ if ((pc->obj_type != SDB_ATTRIBUTE)
+ && (! VALID_OBJ_TYPE(pc->obj_type))) {
+ sdb_strbuf_sprintf(errbuf, "Invalid object type %#x "
+ "in %s command", pc->obj_type, cmd);
+ return -1;
+ }
+ if (! pc->name) {
+ sdb_strbuf_sprintf(errbuf, "Missing object name in "
+ "%s %s command", cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type));
+ return -1;
+ }
+
+ if ((pc->obj_type == SDB_HOST) && pc->hostname) {
+ sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' "
+ "in %s HOST command", pc->hostname, cmd);
+ return -1;
+ }
+ else if ((pc->obj_type != SDB_HOST) && (! pc->hostname)) {
+ sdb_strbuf_sprintf(errbuf, "Missing parent hostname for '%s' "
+ "in %s %s command", pc->name,
+ cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type));
+ return -1;
+ }
+
+ if (pc->obj_type == SDB_ATTRIBUTE) {
+ if ((pc->parent_type <= 0) && pc->parent) {
+ sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' "
+ "in %s %s command", pc->parent,
+ cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type));
+ return -1;
+ }
+ else if (pc->parent_type > 0) {
+ if (! VALID_OBJ_TYPE(pc->parent_type)) {
+ sdb_strbuf_sprintf(errbuf, "Invalid parent type %#x "
+ "in %s %s command", pc->parent_type,
+ cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type));
+ return -1;
+ }
+ if (! pc->parent) {
+ sdb_strbuf_sprintf(errbuf, "Missing %s parent name "
+ "in %s %s command",
+ SDB_STORE_TYPE_TO_NAME(pc->parent_type),
+ cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type));
+ return -1;
+ }
+ }
+ }
+ else if ((pc->parent_type > 0) || pc->parent) {
+ sdb_strbuf_sprintf(errbuf, "Unexpected %s parent name '%s' "
+ "in %s %s command",
+ SDB_STORE_TYPE_TO_NAME(pc->parent_type),
+ pc->parent ? pc->parent : "<unknown>",
+ cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type));
+ return -1;
+ }
+ return 0;
+} /* analyze_parent_child */
+
/*
* expression nodes
*/
static int
/*
* expression nodes
*/
static int
-analyze_logical(int context, sdb_ast_op_t *op, sdb_strbuf_t *errbuf)
+analyze_logical(context_t ctx, sdb_ast_op_t *op, sdb_strbuf_t *errbuf)
{
{
+ if (ctx.iter) {
+ op_error(errbuf, op, "cannot evaluate in iterator context");
+ return -1;
+ }
+
switch (op->kind) {
case SDB_AST_OR:
case SDB_AST_AND:
switch (op->kind) {
case SDB_AST_OR:
case SDB_AST_AND:
SDB_AST_OP_TO_STRING(op->kind));
return -1;
}
SDB_AST_OP_TO_STRING(op->kind));
return -1;
}
- if (analyze_node(context, op->left, errbuf))
+ if (analyze_node(ctx, op->left, errbuf))
return -1;
/* fallthrough */
case SDB_AST_NOT:
return -1;
/* fallthrough */
case SDB_AST_NOT:
SDB_AST_OP_TO_STRING(op->kind));
return -1;
}
SDB_AST_OP_TO_STRING(op->kind));
return -1;
}
- if (analyze_node(context, op->right, errbuf))
+ if (analyze_node(ctx, op->right, errbuf))
return -1;
break;
return -1;
break;
case SDB_AST_GE:
case SDB_AST_GT:
{
case SDB_AST_GE:
case SDB_AST_GT:
{
- if (analyze_node(context, op->left, errbuf))
+ if (analyze_node(ctx, op->left, errbuf))
return -1;
return -1;
- if (analyze_node(context, op->right, errbuf))
+ if (analyze_node(ctx, op->right, errbuf))
return -1;
if ((op->left->data_type > 0) && (op->right->data_type > 0)) {
return -1;
if ((op->left->data_type > 0) && (op->right->data_type > 0)) {
case SDB_AST_REGEX:
case SDB_AST_NREGEX:
case SDB_AST_REGEX:
case SDB_AST_NREGEX:
- if (analyze_node(context, op->left, errbuf))
+ if (analyze_node(ctx, op->left, errbuf))
return -1;
return -1;
- if (analyze_node(context, op->right, errbuf))
+ if (analyze_node(ctx, op->right, errbuf))
return -1;
/* all types are supported for the left operand
return -1;
/* all types are supported for the left operand
case SDB_AST_ISNULL:
case SDB_AST_ISTRUE:
case SDB_AST_ISFALSE:
case SDB_AST_ISNULL:
case SDB_AST_ISTRUE:
case SDB_AST_ISFALSE:
- if (analyze_node(context, op->right, errbuf))
+ if (analyze_node(ctx, op->right, errbuf))
return -1;
break;
case SDB_AST_IN:
return -1;
break;
case SDB_AST_IN:
- if (analyze_node(context, op->left, errbuf))
+ if (analyze_node(ctx, op->left, errbuf))
return -1;
return -1;
- if (analyze_node(context, op->right, errbuf))
+ if (analyze_node(ctx, op->right, errbuf))
return -1;
if ((op->right->data_type > 0) && (! (op->right->data_type & SDB_TYPE_ARRAY))) {
return -1;
if ((op->right->data_type > 0) && (! (op->right->data_type & SDB_TYPE_ARRAY))) {
} /* analyze_logical */
static int
} /* analyze_logical */
static int
-analyze_arith(int context, sdb_ast_op_t *op, sdb_strbuf_t *errbuf)
+analyze_arith(context_t ctx, sdb_ast_op_t *op, sdb_strbuf_t *errbuf)
{
{
- if (analyze_node(context, op->left, errbuf))
+ if (analyze_node(ctx, op->left, errbuf))
return -1;
return -1;
- if (analyze_node(context, op->right, errbuf))
+ if (analyze_node(ctx, op->right, errbuf))
return -1;
SDB_AST_NODE(op)->data_type = sdb_data_expr_type(SDB_AST_OP_TO_DATA_OP(op->kind),
op->left->data_type, op->right->data_type);
return -1;
SDB_AST_NODE(op)->data_type = sdb_data_expr_type(SDB_AST_OP_TO_DATA_OP(op->kind),
op->left->data_type, op->right->data_type);
} /* analyze_arith */
static int
} /* analyze_arith */
static int
-analyze_iter(int context, sdb_ast_iter_t *iter, sdb_strbuf_t *errbuf)
+analyze_iter(context_t ctx, sdb_ast_iter_t *iter, sdb_strbuf_t *errbuf)
{
sdb_ast_const_t c = SDB_AST_CONST_INIT;
{
sdb_ast_const_t c = SDB_AST_CONST_INIT;
- int iter_context = context;
+ context_t iter_ctx = ctx;
int status;
int status;
- if (iter->iter->type == SDB_AST_TYPE_TYPED)
- iter_context = SDB_AST_TYPED(iter->iter)->type;
-
- if (analyze_node(iter_context, iter->iter, errbuf))
+ if (ctx.iter) {
+ iter_error(errbuf, iter, "nested iterators are not supported");
return -1;
return -1;
- /* TODO: support other setups as well */
- assert((iter->expr->type == SDB_AST_TYPE_OPERATOR)
- && (! SDB_AST_OP(iter->expr)->left));
- /* 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 */
- }
- else if ((context != SDB_HOST) && (context != SDB_SERVICE)
- && (context != SDB_METRIC) && (context != UNSPEC_CONTEXT)) {
- iter_error(errbuf, iter, "%s not iterable in %s context",
- SDB_STORE_TYPE_TO_NAME(iter_type),
- SDB_STORE_TYPE_TO_NAME(context));
- return -1;
- }
-
- if ((context == iter_type)
- || ((iter_type != SDB_SERVICE)
- && (iter_type != SDB_METRIC)
- && (iter_type != SDB_ATTRIBUTE))
- || ((context == SDB_SERVICE)
- && (iter_type == SDB_METRIC))
- || ((context == SDB_METRIC)
- && (iter_type == SDB_SERVICE))) {
- iter_error(errbuf, iter, "%s not iterable in %s context",
- SDB_STORE_TYPE_TO_NAME(iter_type),
- SDB_STORE_TYPE_TO_NAME(context));
- return -1;
- }
}
}
- else if (iter->iter->type == SDB_AST_TYPE_VALUE) {
- int iter_type = SDB_AST_VALUE(iter->iter)->type;
- c.value.type = iter->iter->data_type & 0xff;
+ iter_ctx.iter = 1;
+ if (analyze_node(iter_ctx, iter->iter, errbuf))
+ return -1;
- if (iter_type != SDB_FIELD_BACKEND) {
- iter_error(errbuf, iter, "%s not iterable in %s context",
- (iter_type == SDB_ATTRIBUTE)
- ? "attribute"
- : SDB_FIELD_TO_NAME(iter_type),
- SDB_STORE_TYPE_TO_NAME(context));
+ if (iter->iter->data_type > 0) {
+ if (! (iter->iter->data_type & SDB_TYPE_ARRAY)) {
+ iter_error(errbuf, iter, "cannot iterate values of type %s",
+ SDB_TYPE_TO_STRING(iter->iter->data_type));
return -1;
}
return -1;
}
- }
- else if (iter->iter->type == SDB_AST_TYPE_CONST) {
c.value.type = iter->iter->data_type & 0xff;
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;
}
}
+ /* 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);
SDB_AST_OP(iter->expr)->left = SDB_AST_NODE(&c);
- status = analyze_node(context, iter->expr, errbuf);
+ status = analyze_node(ctx, iter->expr, errbuf);
SDB_AST_OP(iter->expr)->left = NULL;
if (status)
return -1;
SDB_AST_OP(iter->expr)->left = NULL;
if (status)
return -1;
} /* analyze_iter */
static int
} /* analyze_iter */
static int
-analyze_const(int __attribute__((unused)) context, sdb_ast_const_t *c,
+analyze_const(context_t __attribute__((unused)) ctx, sdb_ast_const_t *c,
sdb_strbuf_t __attribute__((unused)) *errbuf)
{
SDB_AST_NODE(c)->data_type = c->value.type;
sdb_strbuf_t __attribute__((unused)) *errbuf)
{
SDB_AST_NODE(c)->data_type = c->value.type;
} /* analyze_const */
static int
} /* analyze_const */
static int
-analyze_value(int context, sdb_ast_value_t *v, sdb_strbuf_t *errbuf)
+analyze_value(context_t ctx, 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)
SDB_AST_NODE(v)->data_type = SDB_FIELD_TYPE(v->type);
return -1;
}
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;
- }
+ /* this would be caught by the type check in analyze_iter but we're able
+ * to provide a more specific error message here */
+ if (ctx.iter && (v->type != SDB_FIELD_BACKEND)) {
+ /* only backend values are iterable */
+ char value_str[64 + (v->name ? strlen(v->name) : 0)];
+ if (v->type == SDB_ATTRIBUTE)
+ snprintf(value_str, sizeof(value_str), "attribute[%s]", v->name);
+ else
+ snprintf(value_str, sizeof(value_str), "'%s'", SDB_FIELD_TO_NAME(v->type));
+ sdb_strbuf_sprintf(errbuf, "Cannot iterate %s (scalar value)", value_str);
+ return -1;
+ }
+
+ if ((ctx.type != SDB_ATTRIBUTE) && (v->type == SDB_FIELD_VALUE)) {
+ sdb_strbuf_sprintf(errbuf, "Invalid expression %s.value",
+ SDB_FIELD_TO_NAME(ctx.type));
+ return -1;
+ }
+ if ((ctx.type != SDB_METRIC) && (v->type == SDB_FIELD_TIMESERIES)) {
+ sdb_strbuf_sprintf(errbuf, "Invalid expression %s.timeseries",
+ SDB_FIELD_TO_NAME(ctx.type));
+ return -1;
}
return 0;
} /* analyze_value */
static int
}
return 0;
} /* analyze_value */
static int
-analyze_typed(int context, sdb_ast_typed_t *t, sdb_strbuf_t *errbuf)
+analyze_typed(context_t ctx, sdb_ast_typed_t *t, sdb_strbuf_t *errbuf)
{
{
+ context_t child_ctx = ctx;
+ bool needs_iter = 0;
+ bool valid = 1;
+
if ((t->expr->type != SDB_AST_TYPE_VALUE)
&& (t->expr->type != SDB_AST_TYPE_TYPED)) {
sdb_strbuf_sprintf(errbuf, "Invalid expression %s.%s",
if ((t->expr->type != SDB_AST_TYPE_VALUE)
&& (t->expr->type != SDB_AST_TYPE_TYPED)) {
sdb_strbuf_sprintf(errbuf, "Invalid expression %s.%s",
SDB_AST_TYPE_TO_STRING(t->expr));
return -1;
}
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;
}
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)) {
+ if (ctx.type > 0) {
+ if ((ctx.type == t->type)
+ || ((t->type == SDB_HOST) && (ctx.type != SDB_ATTRIBUTE))) {
+ /* self-references and references to the parent host are always fine */
+ }
+ else if (t->type == SDB_ATTRIBUTE) {
+ /* references to attributes are always fine */
+ needs_iter = 1;
+ }
+ else if ((ctx.type == SDB_HOST)
+ && ((t->type == SDB_SERVICE) || (t->type == SDB_METRIC))) {
+ /* only hosts may reference services and metrics */
+ needs_iter = 1;
+ }
+ else {
+ valid = 0;
+ }
+ }
+ else if (ctx.type == FILTER_CONTEXT) {
+ if (t->type == SDB_ATTRIBUTE) {
+ /* all objects have attributes */
+ needs_iter = 1;
+ }
+ else if ((t->type == SDB_SERVICE) || (t->type == SDB_METRIC)) {
+ /* these will be iterators for *some* operations;
+ * better forbid this altogether */
+ valid = 0;
+ }
+ }
+
+ if (needs_iter) {
+ if (! ctx.iter)
+ valid = 0;
+ else
+ child_ctx.iter = 0;
+ } /* else: push ctx.iter down to the child node */
+
+ if (! valid) {
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),
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));
+ SDB_STORE_TYPE_TO_NAME(ctx.type));
return -1;
}
return -1;
}
+
+ child_ctx.type = t->type;
+ if (analyze_node(child_ctx, t->expr, errbuf))
+ return -1;
+ SDB_AST_NODE(t)->data_type = t->expr->data_type;
+
+ if (needs_iter && (SDB_AST_NODE(t)->data_type > 0)) {
+ if (SDB_AST_NODE(t)->data_type & SDB_TYPE_ARRAY) {
+ sdb_strbuf_sprintf(errbuf, "Cannot access array inside iterator");
+ return -1;
+ }
+ /* Tell the caller that we're accessing an iterator. */
+ SDB_AST_NODE(t)->data_type |= SDB_TYPE_ARRAY;
+ }
return 0;
} /* analyze_typed */
static int
return 0;
} /* analyze_typed */
static int
-analyze_node(int context, sdb_ast_node_t *node, sdb_strbuf_t *errbuf)
+analyze_node(context_t ctx, sdb_ast_node_t *node, sdb_strbuf_t *errbuf)
{
if (! node) {
sdb_strbuf_sprintf(errbuf, "Empty AST node");
{
if (! node) {
sdb_strbuf_sprintf(errbuf, "Empty AST node");
if ((node->type == SDB_AST_TYPE_OPERATOR)
&& (SDB_AST_IS_LOGICAL(node)))
if ((node->type == SDB_AST_TYPE_OPERATOR)
&& (SDB_AST_IS_LOGICAL(node)))
- return analyze_logical(context, SDB_AST_OP(node), errbuf);
+ return analyze_logical(ctx, SDB_AST_OP(node), errbuf);
else if ((node->type == SDB_AST_TYPE_OPERATOR)
&& (SDB_AST_IS_ARITHMETIC(node)))
else if ((node->type == SDB_AST_TYPE_OPERATOR)
&& (SDB_AST_IS_ARITHMETIC(node)))
- return analyze_arith(context, SDB_AST_OP(node), errbuf);
+ return analyze_arith(ctx, SDB_AST_OP(node), errbuf);
else if (node->type == SDB_AST_TYPE_ITERATOR)
else if (node->type == SDB_AST_TYPE_ITERATOR)
- return analyze_iter(context, SDB_AST_ITER(node), errbuf);
+ return analyze_iter(ctx, SDB_AST_ITER(node), errbuf);
else if (node->type == SDB_AST_TYPE_CONST)
else if (node->type == SDB_AST_TYPE_CONST)
- return analyze_const(context, SDB_AST_CONST(node), errbuf);
+ return analyze_const(ctx, SDB_AST_CONST(node), errbuf);
else if (node->type == SDB_AST_TYPE_VALUE)
else if (node->type == SDB_AST_TYPE_VALUE)
- return analyze_value(context, SDB_AST_VALUE(node), errbuf);
+ return analyze_value(ctx, SDB_AST_VALUE(node), errbuf);
else if (node->type == SDB_AST_TYPE_TYPED)
else if (node->type == SDB_AST_TYPE_TYPED)
- return analyze_typed(context, SDB_AST_TYPED(node), errbuf);
+ return analyze_typed(ctx, SDB_AST_TYPED(node), errbuf);
sdb_strbuf_sprintf(errbuf, "Invalid expression node "
"of type %#x", node->type);
sdb_strbuf_sprintf(errbuf, "Invalid expression node "
"of type %#x", node->type);
static int
analyze_fetch(sdb_ast_fetch_t *fetch, sdb_strbuf_t *errbuf)
{
static int
analyze_fetch(sdb_ast_fetch_t *fetch, sdb_strbuf_t *errbuf)
{
- if (! VALID_OBJ_TYPE(fetch->obj_type)) {
- sdb_strbuf_sprintf(errbuf, "Invalid object type %#x "
- "in FETCH command", fetch->obj_type);
- return -1;
- }
- if (! fetch->name) {
- sdb_strbuf_sprintf(errbuf, "Missing object name in "
- "FETCH %s command", SDB_STORE_TYPE_TO_NAME(fetch->obj_type));
- return -1;
- }
+ parent_child_t pc = {
+ fetch->obj_type, fetch->hostname,
+ fetch->parent_type, fetch->parent, fetch->name,
+ };
- if ((fetch->obj_type == SDB_HOST) && fetch->hostname) {
- sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' "
- "in FETCH HOST command", fetch->hostname);
- return -1;
- }
- else if ((fetch->obj_type != SDB_HOST) && (! fetch->hostname)) {
- sdb_strbuf_sprintf(errbuf, "Missing parent hostname for '%s' "
- "in FETCH %s command", fetch->name,
- SDB_STORE_TYPE_TO_NAME(fetch->obj_type));
+ if (analyze_parent_child("FETCH", &pc, errbuf))
return -1;
return -1;
- }
if (fetch->filter)
if (fetch->filter)
- return analyze_node(FILTER_CONTEXT, fetch->filter, errbuf);
+ return analyze_node(FILTER_CTX, fetch->filter, errbuf);
return 0;
} /* analyze_fetch */
return 0;
} /* analyze_fetch */
return -1;
}
if (list->filter)
return -1;
}
if (list->filter)
- return analyze_node(FILTER_CONTEXT, list->filter, errbuf);
+ return analyze_node(FILTER_CTX, list->filter, errbuf);
return 0;
} /* analyze_list */
return 0;
} /* analyze_list */
"in LOOKUP command", lookup->obj_type);
return -1;
}
"in LOOKUP command", lookup->obj_type);
return -1;
}
- if (lookup->matcher)
- if (analyze_node(lookup->obj_type, lookup->matcher, errbuf))
+ if (lookup->matcher) {
+ context_t ctx = { lookup->obj_type, 0 };
+ if (analyze_node(ctx, lookup->matcher, errbuf))
return -1;
return -1;
+ }
if (lookup->filter)
if (lookup->filter)
- return analyze_node(FILTER_CONTEXT, lookup->filter, errbuf);
+ return analyze_node(FILTER_CTX, lookup->filter, errbuf);
return 0;
} /* analyze_lookup */
static int
analyze_store(sdb_ast_store_t *st, sdb_strbuf_t *errbuf)
{
return 0;
} /* analyze_lookup */
static int
analyze_store(sdb_ast_store_t *st, sdb_strbuf_t *errbuf)
{
- if ((st->obj_type != SDB_ATTRIBUTE)
- && (! VALID_OBJ_TYPE(st->obj_type))) {
- sdb_strbuf_sprintf(errbuf, "Invalid object type %#x "
- "in STORE command", st->obj_type);
- return -1;
- }
- if (! st->name) {
- sdb_strbuf_sprintf(errbuf, "Missing object name in "
- "STORE %s command", SDB_STORE_TYPE_TO_NAME(st->obj_type));
- return -1;
- }
+ parent_child_t pc = {
+ st->obj_type, st->hostname,
+ st->parent_type, st->parent, st->name,
+ };
- if ((st->obj_type == SDB_HOST) && st->hostname) {
- sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' "
- "in STORE HOST command", st->hostname);
+ if (analyze_parent_child("STORE", &pc, errbuf))
return -1;
return -1;
- }
- else if ((st->obj_type != SDB_HOST) && (! st->hostname)) {
- sdb_strbuf_sprintf(errbuf, "Missing parent hostname for '%s' "
- "in STORE %s command", st->name,
- SDB_STORE_TYPE_TO_NAME(st->obj_type));
- return -1;
- }
-
- if (st->obj_type == SDB_ATTRIBUTE) {
- if ((st->parent_type <= 0) && st->parent) {
- sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' "
- "in STORE %s command", st->parent,
- SDB_STORE_TYPE_TO_NAME(st->obj_type));
- return -1;
- }
- else if (st->parent_type > 0) {
- if (! VALID_OBJ_TYPE(st->parent_type)) {
- sdb_strbuf_sprintf(errbuf, "Invalid parent type %#x "
- "in STORE %s command", st->parent_type,
- SDB_STORE_TYPE_TO_NAME(st->obj_type));
- return -1;
- }
- if (! st->parent) {
- sdb_strbuf_sprintf(errbuf, "Missing %s parent name "
- "in STORE %s command",
- SDB_STORE_TYPE_TO_NAME(st->parent_type),
- SDB_STORE_TYPE_TO_NAME(st->obj_type));
- return -1;
- }
- }
- }
- else if ((st->parent_type > 0) || st->parent) {
- sdb_strbuf_sprintf(errbuf, "Unexpected %s parent name '%s' "
- "in STORE %s command",
- SDB_STORE_TYPE_TO_NAME(st->parent_type),
- st->parent ? st->parent : "<unknown>",
- SDB_STORE_TYPE_TO_NAME(st->obj_type));
- return -1;
- }
if (st->obj_type == SDB_METRIC) {
if ((! st->store_type) != (! st->store_id)) {
if (st->obj_type == SDB_METRIC) {
if ((! st->store_type) != (! st->store_id)) {
analyze_timeseries(sdb_ast_timeseries_t *ts, sdb_strbuf_t *errbuf)
{
if (! ts->hostname) {
analyze_timeseries(sdb_ast_timeseries_t *ts, sdb_strbuf_t *errbuf)
{
if (! ts->hostname) {
- sdb_strbuf_sprintf(errbuf, "Missing hostname in STORE command");
+ sdb_strbuf_sprintf(errbuf, "Missing hostname in TIMESERIES command");
return -1;
}
if (! ts->metric) {
return -1;
}
if (! ts->metric) {
- sdb_strbuf_sprintf(errbuf, "Missing metric name in STORE command");
+ sdb_strbuf_sprintf(errbuf, "Missing metric name in TIMESERIES command");
return -1;
}
if (ts->end <= ts->start) {
char start_str[64], end_str[64];
return -1;
}
if (ts->end <= ts->start) {
char start_str[64], end_str[64];
- sdb_strftime(start_str, sizeof(start_str), "%F %T Tz", ts->start);
- sdb_strftime(end_str, sizeof(end_str), "%F %T Tz", ts->end);
+ sdb_strftime(start_str, sizeof(start_str), ts->start);
+ sdb_strftime(end_str, sizeof(end_str), ts->end);
sdb_strbuf_sprintf(errbuf, "Start time (%s) greater than "
sdb_strbuf_sprintf(errbuf, "Start time (%s) greater than "
- "end time (%s) in STORE command", start_str, end_str);
+ "end time (%s) in TIMESERIES command", start_str, end_str);
return -1;
}
return 0;
return -1;
}
return 0;
} /* sdb_parser_analyze */
int
} /* sdb_parser_analyze */
int
-sdb_parser_analyze_conditional(sdb_ast_node_t *node, sdb_strbuf_t *errbuf)
+sdb_parser_analyze_conditional(int context,
+ sdb_ast_node_t *node, sdb_strbuf_t *errbuf)
{
{
+ context_t ctx = { context, 0 };
+ if (! VALID_OBJ_TYPE(context)) {
+ sdb_strbuf_sprintf(errbuf, "Invalid object type %#x", context);
+ return -1;
+ }
if (! node) {
sdb_strbuf_sprintf(errbuf, "Empty conditional node");
return -1;
if (! node) {
sdb_strbuf_sprintf(errbuf, "Empty conditional node");
return -1;
SDB_AST_TYPE_TO_STRING(node));
return -1;
}
SDB_AST_TYPE_TO_STRING(node));
return -1;
}
- return analyze_node(UNSPEC_CONTEXT, node, errbuf);
+ return analyze_node(ctx, node, errbuf);
} /* sdb_parser_analyze_conditional */
int
} /* sdb_parser_analyze_conditional */
int
-sdb_parser_analyze_arith(sdb_ast_node_t *node, sdb_strbuf_t *errbuf)
+sdb_parser_analyze_arith(int context,
+ sdb_ast_node_t *node, sdb_strbuf_t *errbuf)
{
{
+ context_t ctx = { context, 0 };
+ if (! VALID_OBJ_TYPE(context)) {
+ sdb_strbuf_sprintf(errbuf, "Invalid object type %#x", context);
+ return -1;
+ }
if (! node) {
sdb_strbuf_sprintf(errbuf, "Empty arithmetic node");
return -1;
if (! node) {
sdb_strbuf_sprintf(errbuf, "Empty arithmetic node");
return -1;
SDB_AST_TYPE_TO_STRING(node));
return -1;
}
SDB_AST_TYPE_TO_STRING(node));
return -1;
}
- return analyze_node(UNSPEC_CONTEXT, node, errbuf);
+ return analyze_node(ctx, node, errbuf);
} /* sdb_parser_analyze_arith */
/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
} /* sdb_parser_analyze_arith */
/* vim: set tw=78 sw=4 ts=4 noexpandtab : */