summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: ea5d74f)
raw | patch | inline | side by side (parent: ea5d74f)
author | Sebastian Harl <sh@tokkee.org> | |
Sun, 9 Nov 2014 09:39:13 +0000 (10:39 +0100) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sun, 9 Nov 2014 10:38:02 +0000 (11:38 +0100) |
Currently, this is limited to the 'backend' field of an object. Also, only
simple statements like 'ANY/ALL <array> <cmp> <value>' are supported by the
store (in contrast to service/metric iterators which support arbitrary
matchers to be applied). Given that matchers are object based, this limitation
should feel natural, though.
simple statements like 'ANY/ALL <array> <cmp> <value>' are supported by the
store (in contrast to service/metric iterators which support arbitrary
matchers to be applied). Given that matchers are object based, this limitation
should feel natural, though.
src/core/store_lookup.c | patch | blob | history | |
src/frontend/analyzer.c | patch | blob | history | |
src/frontend/grammar.y | patch | blob | history |
index 3d509b0511f026276cfa55194aafad34435164e2..e2ec1b14936b3c6586bdd698bdd0c792519c61aa 100644 (file)
--- a/src/core/store_lookup.c
+++ b/src/core/store_lookup.c
return !sdb_store_matcher_matches(UOP_M(m)->op, obj, filter);
} /* match_unary */
+/* iterate arrays: ANY/ALL <array> <cmp> <value> */
+static int
+match_iter_array(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
+ sdb_store_matcher_t *filter)
+{
+ sdb_store_expr_t *e1, *e2;
+ sdb_data_t v1 = SDB_DATA_INIT;
+ sdb_data_t v2 = SDB_DATA_INIT;
+
+ int status;
+
+ /* TODO: fully support arbitrary operators (?) */
+ if ((ITER_M(m)->m->type < MATCHER_LT) || (MATCHER_GT < ITER_M(m)->m->type))
+ return 0;
+
+ e1 = CMP_M(ITER_M(m)->m)->left;
+ e2 = CMP_M(ITER_M(m)->m)->right;
+
+ if (sdb_store_expr_eval(e1, obj, &v1, filter))
+ return 0;
+ if (sdb_store_expr_eval(e2, obj, &v2, filter)) {
+ sdb_data_free_datum(&v1);
+ return 0;
+ }
+
+ if ((! (v1.type & SDB_TYPE_ARRAY)) || (v2.type & SDB_TYPE_ARRAY))
+ status = 0;
+ else if (sdb_data_isnull(&v1) || (sdb_data_isnull(&v2)))
+ status = 0;
+ else {
+ size_t i;
+ int all = (int)(m->type == MATCHER_ALL);
+
+ status = all;
+ for (i = 0; i < v1.data.array.length; ++i) {
+ sdb_data_t v = SDB_DATA_INIT;
+ if (sdb_data_array_get(&v1, i, &v)) {
+ status = 0;
+ break;
+ }
+
+ if (cmp_value(ITER_M(m)->m->type, &v, &v2,
+ (e1->data_type) < 0 || (e2->data_type < 0))) {
+ if (! all) {
+ status = 1;
+ break;
+ }
+ }
+ else if (all) {
+ status = 0;
+ break;
+ }
+ }
+ }
+
+ sdb_data_free_datum(&v1);
+ sdb_data_free_datum(&v2);
+ return status;
+} /* match_iter_array */
+
static int
match_iter(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
sdb_store_matcher_t *filter)
assert((m->type == MATCHER_ANY) || (m->type == MATCHER_ALL));
+ if (ITER_M(m)->type == SDB_FIELD_BACKEND)
+ return match_iter_array(m, obj, filter);
+
if (obj->type == SDB_HOST) {
if (ITER_M(m)->type == SDB_SERVICE)
iter = sdb_avltree_get_iter(HOST(obj)->services);
sdb_store_any_matcher(int type, sdb_store_matcher_t *m)
{
if ((type != SDB_SERVICE) && (type != SDB_METRIC)
- && (type != SDB_ATTRIBUTE))
+ && (type != SDB_ATTRIBUTE) && (type != SDB_FIELD_BACKEND))
return NULL;
return M(sdb_object_create("any-matcher", iter_type,
MATCHER_ANY, type, m));
sdb_store_all_matcher(int type, sdb_store_matcher_t *m)
{
if ((type != SDB_SERVICE) && (type != SDB_METRIC)
- && (type != SDB_ATTRIBUTE))
+ && (type != SDB_ATTRIBUTE) && (type != SDB_FIELD_BACKEND))
return NULL;
return M(sdb_object_create("all-matcher", iter_type,
MATCHER_ALL, type, m));
index 5cb1f7f7538564398fbf731c2aaecd9e1315e90d..20864cae4d348ca2e3072e1e48945fd157cb6c66 100644 (file)
--- a/src/frontend/analyzer.c
+++ b/src/frontend/analyzer.c
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)
+{
+ sdb_strbuf_sprintf(errbuf, "Invalid array iterator %s %s %s %s",
+ MATCHER_SYM(op), SDB_TYPE_TO_STRING(array_type),
+ MATCHER_SYM(cmp), SDB_TYPE_TO_STRING(value_type));
+ if ((array_type & 0xff) != value_type)
+ sdb_strbuf_append(errbuf, " (type mismatch)");
+ else
+ sdb_strbuf_append(errbuf, " (invalid operator)");
+} /* iter_array_error */
+
static void
cmp_error(sdb_strbuf_t *errbuf, int op, int left, int right)
{
sdb_strbuf_sprintf(errbuf, "Invalid operator %s for types %s and %s",
MATCHER_SYM(op), SDB_TYPE_TO_STRING(left),
SDB_TYPE_TO_STRING(right));
-} /* iter_error */
+} /* cmp_error */
static int
analyze_matcher(int context, sdb_store_matcher_t *m, sdb_strbuf_t *errbuf)
}
if ((ITER_M(m)->type != SDB_SERVICE)
&& (ITER_M(m)->type != SDB_METRIC)
- && (ITER_M(m)->type != SDB_ATTRIBUTE)) {
+ && (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;
}
iter_error(errbuf, m->type, ITER_M(m)->type, context);
return -1;
}
- if (analyze_matcher(ITER_M(m)->type, ITER_M(m)->m, errbuf))
+ 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;
+ }
+ 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,
+ CMP_M(ITER_M(m)->m)->right->data_type);
+ return -1;
+ }
+ }
+ else if (analyze_matcher(ITER_M(m)->type, ITER_M(m)->m, errbuf))
return -1;
break;
diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y
index 6791806b0bf473593330a7c057b75644268d7d0e..80fb249684e0120be85cd421905fec666d277bc4 100644 (file)
--- a/src/frontend/grammar.y
+++ b/src/frontend/grammar.y
METRIC_T { $$ = SDB_METRIC; }
|
ATTRIBUTE_T { $$ = SDB_ATTRIBUTE; }
+ |
+ BACKEND_T { $$ = SDB_FIELD_BACKEND; }
;
field:
sdb_store_matcher_t *m, *tmp = NULL;
assert(cb);
- /* TODO: this only works as long as queries
- * are limited to hosts */
+ /* hosts are never iterable */
if (type == SDB_HOST) {
return NULL;
}
- e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME);
+ if (type == SDB_FIELD_BACKEND)
+ e = sdb_store_expr_fieldvalue(type);
+ else
+ e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME);
m = cb(e, expr);
if (m_type == MATCHER_ANY)
tmp = sdb_store_any_matcher(type, m);