From 57ec5be33f0a1ac234dc1d1852e8e5e79253e726 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Thu, 31 Jul 2014 23:38:51 +0200 Subject: [PATCH] frontend/grammar: Added support for field names in expressions. --- src/core/store_lookup.c | 26 ++++++++++++++++---------- src/frontend/grammar.y | 7 +++++++ src/include/core/store.h | 11 +++++++++++ t/unit/frontend/parser_test.c | 5 +++++ 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/core/store_lookup.c b/src/core/store_lookup.c index 0ef5f46..9841783 100644 --- a/src/core/store_lookup.c +++ b/src/core/store_lookup.c @@ -854,6 +854,20 @@ sdb_store_isnull_matcher(const char *attr_name) MATCHER_ISNULL, attr_name)); } /* sdb_store_isnull_matcher */ +int +sdb_store_parse_field_name(const char *name) +{ + if (! strcasecmp(name, "last_update")) + return SDB_FIELD_LAST_UPDATE; + else if (! strcasecmp(name, "age")) + return SDB_FIELD_AGE; + else if (! strcasecmp(name, "interval")) + return SDB_FIELD_INTERVAL; + else if (! strcasecmp(name, "backend")) + return SDB_FIELD_BACKEND; + return -1; +} /* sdb_store_parse_field_name */ + static sdb_store_matcher_t * maybe_inv_matcher(sdb_store_matcher_t *m, _Bool inv) { @@ -996,20 +1010,12 @@ sdb_store_matcher_parse_field_cmp(const char *name, const char *op, if (! expr) return NULL; - if (! strcasecmp(name, "last_update")) - field = SDB_FIELD_LAST_UPDATE; - else if (! strcasecmp(name, "age")) - field = SDB_FIELD_AGE; - else if (! strcasecmp(name, "interval")) - field = SDB_FIELD_INTERVAL; - else if (! strcasecmp(name, "backend")) - field = SDB_FIELD_BACKEND; - else + field = sdb_store_parse_field_name(name); + if (field < 0) return NULL; if (parse_cond_op(op, &matcher, &inv)) return NULL; - cond = sdb_store_obj_cond(field, expr); if (! cond) return NULL; diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 92bfd1f..08d194d 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -414,6 +414,13 @@ expression: sdb_object_deref(SDB_OBJ($3)); $3 = NULL; } | + ':' IDENTIFIER + { + int field = sdb_store_parse_field_name($2); + free($2); $2 = NULL; + $$ = sdb_store_expr_fieldvalue(field); + } + | data { $$ = sdb_store_expr_constvalue(&$1); diff --git a/src/include/core/store.h b/src/include/core/store.h index 760c23d..cb7f3e4 100644 --- a/src/include/core/store.h +++ b/src/include/core/store.h @@ -335,6 +335,17 @@ sdb_store_ge_matcher(sdb_store_cond_t *cond); sdb_store_matcher_t * sdb_store_gt_matcher(sdb_store_cond_t *cond); +/* + * sdb_store_parse_field_name: + * Parse the name of a stored object's queryable field. + * + * Returns: + * - the field id on success + * - a negative value else + */ +int +sdb_store_parse_field_name(const char *name); + /* * sdb_store_matcher_parse_cmp: * Parse a simple compare expression (. ). diff --git a/t/unit/frontend/parser_test.c b/t/unit/frontend/parser_test.c index a101854..dade011 100644 --- a/t/unit/frontend/parser_test.c +++ b/t/unit/frontend/parser_test.c @@ -86,6 +86,10 @@ START_TEST(test_parse) { "LOOKUP hosts MATCHING " "host =~ 'p' " "FILTER NOT :age>1D", -1, 1, CONNECTION_LOOKUP }, + { "LOOKUP hosts MATCHING " + "host =~ 'p' " + "FILTER :age>" + ":interval", -1, 1, CONNECTION_LOOKUP }, /* numeric constants */ { "LOOKUP hosts MATCHING " @@ -275,6 +279,7 @@ START_TEST(test_parse_matcher) { ":age > 1M", -1, MATCHER_GT }, { ":age != 20Y", -1, MATCHER_NOT }, { ":backend != 'be'", -1, MATCHER_NOT }, + { ":age <= 2 * :interval", -1, MATCHER_LE }, /* check operator precedence */ { "host = 'name' OR " -- 2.30.2