diff --git a/src/parser/analyzer.c b/src/parser/analyzer.c
index 273463d8ce3a2037d2e7211dbb9113c9eec30676..9bbd9ba7c9fe31c1575a1160f3ffd218c6ba04fa 100644 (file)
--- a/src/parser/analyzer.c
+++ b/src/parser/analyzer.c
break;
case SDB_AST_ISNULL:
+ case SDB_AST_ISTRUE:
+ case SDB_AST_ISFALSE:
if (analyze_node(context, op->right, errbuf))
return -1;
break;
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(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 */
}
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"
}
}
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 */
return -1;
}
- if ((context != SDB_ATTRIBUTE) && (v->type == SDB_FIELD_VALUE)) {
- sdb_strbuf_sprintf(errbuf, "Invalid expression %s.value",
- SDB_FIELD_TO_NAME(v->type));
- 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 */
/* self-references are allowed and services and metrics may reference
* their parent host; everything may reference attributes */
- if ((context != t->type) && (context != UNSPEC_CONTEXT)
+ if ((context != t->type) && (context > 0)
&& (((context != SDB_SERVICE) && (context != SDB_METRIC))
|| (t->type != SDB_HOST))
&& (t->type != SDB_ATTRIBUTE)) {
}
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 "
"end time (%s) in STORE command", start_str, end_str);
return -1;