Code

store/frontend: Added support for integer and float comparison.
authorSebastian Harl <sh@tokkee.org>
Mon, 23 Jun 2014 20:47:01 +0000 (22:47 +0200)
committerSebastian Harl <sh@tokkee.org>
Mon, 23 Jun 2014 20:47:01 +0000 (22:47 +0200)
This is supported only for comparing attribute values.

src/core/store_lookup.c
src/frontend/grammar.y
src/frontend/scanner.l
t/unit/core/store_lookup_test.c
t/unit/frontend/parser_test.c

index 658f931ab30bc3fe64dd30b53e439416ad6a9ae6..3920b80127c5a228792b299e06bc5e6e51f1187b 100644 (file)
@@ -673,6 +673,7 @@ parse_attr_cmp(const char *attr, const char *op, const sdb_data_t *value)
        sdb_store_matcher_t *(*matcher)(sdb_store_cond_t *) = NULL;
        sdb_store_matcher_t *m;
        sdb_store_cond_t *cond;
+       _Bool inv = 0;
 
        /* TODO: this will reject any attributes called "name";
         * use a different syntax for querying objects by name */
@@ -684,12 +685,15 @@ parse_attr_cmp(const char *attr, const char *op, const sdb_data_t *value)
        else if (! strcasecmp(op, "<="))
                matcher = sdb_store_le_matcher;
        else if (! strcasecmp(op, "="))
-               /* XXX: this is still handled by sdb_store_matcher_parse_cmp */
                matcher = sdb_store_eq_matcher;
        else if (! strcasecmp(op, ">="))
                matcher = sdb_store_ge_matcher;
        else if (! strcasecmp(op, ">"))
                matcher = sdb_store_gt_matcher;
+       else if (! strcasecmp(op, "!=")) {
+               matcher = sdb_store_eq_matcher;
+               inv = 1;
+       }
        else
                return NULL;
 
@@ -700,6 +704,16 @@ parse_attr_cmp(const char *attr, const char *op, const sdb_data_t *value)
        m = matcher(cond);
        /* pass ownership to 'm' or destroy in case of an error */
        sdb_object_deref(SDB_OBJ(cond));
+       if (! m)
+               return NULL;
+
+       if (inv) {
+               sdb_store_matcher_t *tmp;
+               tmp = sdb_store_inv_matcher(m);
+               /* pass ownership to the inverse matcher */
+               sdb_object_deref(SDB_OBJ(m));
+               m = tmp;
+       }
        return m;
 } /* parse_attr_cmp */
 
@@ -741,8 +755,11 @@ sdb_store_matcher_parse_cmp(const char *obj_type, const char *attr,
        else
                return NULL;
 
-       if (value->type != SDB_TYPE_STRING)
+       if (value->type != SDB_TYPE_STRING) {
+               if (type == SDB_ATTRIBUTE)
+                       return parse_attr_cmp(attr, op, value);
                return NULL;
+       }
 
        if (! strcasecmp(attr, "name"))
                m = sdb_store_name_matcher(type, value->data.string, re);
index c4c47755caa9b2c032ff0593b2a2134130a2c607..34a9c6b6474502d9fc059df45a6ed93a79890567 100644 (file)
@@ -83,16 +83,20 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg);
 
 %token AND OR NOT WHERE
 %token CMP_EQUAL CMP_NEQUAL CMP_REGEX CMP_NREGEX
+%token CMP_LT CMP_LE CMP_GE CMP_GT
 
 %token FETCH LIST LOOKUP
 
 %token <str> IDENTIFIER STRING
 
+%token <data> INTEGER FLOAT
+
 /* Precedence (lowest first): */
 %left OR
 %left AND
-%left NOT
+%right NOT
 %left CMP_EQUAL CMP_NEQUAL
+%left CMP_LT CMP_LE CMP_GE CMP_GT
 %left CMP_REGEX CMP_NREGEX
 %left '(' ')'
 %left '.'
@@ -311,10 +315,22 @@ op:
        CMP_REGEX { $$ = "=~"; }
        |
        CMP_NREGEX { $$ = "!~"; }
+       |
+       CMP_LT { $$ = "<"; }
+       |
+       CMP_LE { $$ = "<="; }
+       |
+       CMP_GE { $$ = ">="; }
+       |
+       CMP_GT { $$ = ">"; }
        ;
 
 data:
        STRING { $$.type = SDB_TYPE_STRING; $$.data.string = $1; }
+       |
+       INTEGER { $$ = $1; }
+       |
+       FLOAT { $$ = $1; }
        ;
 
 %%
index dd2a86cf5273b4e5e3c450c02306820b282a1a46..0396db53e0d742f17ca12de0fcec788da4c24045 100644 (file)
@@ -31,6 +31,7 @@
 #      include "config.h"
 #endif /* HAVE_CONFIG_H */
 
+#include "core/data.h"
 #include "frontend/connection.h"
 #include "frontend/parser.h"
 #include "frontend/grammar.h"
@@ -39,6 +40,7 @@
 #include <errno.h>
 
 #include <string.h>
+#include <stdlib.h>
 
 #define YY_EXTRA_TYPE sdb_fe_yyextra_t *
 
@@ -77,6 +79,16 @@ identifier   ([A-Za-z_][A-Za-z_0-9$]*)
 /* TODO: fully support SQL strings */
 string         ('[^']*')
 
+dec                    ([\+\-]?[0-9]+)
+exp                    ([\+\-]?[0-9]+[Ee]\+?[0-9]+)
+integer                ({dec}|{exp})
+float1         ([\+\-]?[0-9]+\.[0-9]*([Ee][\+\-]?[0-9]+)?)
+float2         ([\+\-]?[0-9]*\.[0-9]+([Ee][\+\-]?[0-9]+)?)
+float3         ([\+\-]?[0-9]+[Ee]\-[0-9]+)
+float4         ([\+\-]?[Ii][Nn][Ff]([Ii][Nn][Ii][Tt][Yy])?)
+float5         ([Nn][Aa][Nn])
+float          ({float1}|{float2}|{float3}|{float4}|{float5})
+
 %%
 
 {whitespace} |
@@ -115,11 +127,25 @@ string            ('[^']*')
                yylval->str = strdup(yytext + 1);
                return STRING;
        }
+{integer} {
+               yylval->data.data.integer = (int64_t)strtoll(yytext, NULL, 10);
+               yylval->data.type = SDB_TYPE_INTEGER;
+               return INTEGER;
+       }
+{float} {
+               yylval->data.data.decimal = strtod(yytext, NULL);
+               yylval->data.type = SDB_TYPE_DECIMAL;
+               return FLOAT;
+       }
 
 =      { return CMP_EQUAL; }
 !=     { return CMP_NEQUAL; }
 =~     { return CMP_REGEX; }
 !~     { return CMP_NREGEX; }
+\<     { return CMP_LT; }
+\<=    { return CMP_LE; }
+\>=    { return CMP_GE; }
+\>     { return CMP_GT; }
 
 .      { /* XXX: */ return yytext[0]; }
 
index 4a935429923bb4dd1118c092756387cf1393fc0e..6dd7bb3fa1916a2119cc1985f9c2dc7393a3db47 100644 (file)
@@ -534,6 +534,18 @@ START_TEST(test_lookup)
                        "OBJ\\[attribute\\]\\{ NAME\\{ 'x', \\(nil\\) \\}" },
                { "attribute.k1 = 'v1'",   1,
                        "ATTR\\[k1\\]\\{ VALUE\\{ 'v1', \\(nil\\) \\} \\}" },
+               { "attribute.k2 < 123",    0,
+                       "ATTR\\[k2\\]\\{ < 123 \\}" },
+               { "attribute.k2 <= 123",   1,
+                       "ATTR\\[k2\\]\\{ <= 123 \\}" },
+               { "attribute.k2 >= 123",   1,
+                       "ATTR\\[k2\\]\\{ >= 123 \\}" },
+               { "attribute.k2 > 123",    0,
+                       "ATTR\\[k2\\]\\{ > 123 \\}" },
+               { "attribute.k2 = 123",    1,
+                       "ATTR\\[k2\\]\\{ = 123 \\}" },
+               { "attribute.k2 != 123",   2,
+                       "\\(NOT, ATTR\\[k2\\]\\{ = 123 \\}\\)" },
                { "attribute.k1 != 'v1'",  2,
                        "\\(NOT, ATTR\\[k1\\]\\{ VALUE\\{ 'v1', \\(nil\\) \\} \\}\\)" },
                { "attribute.k1 != 'v2'",  3,
index e245c29e56f1b89d279c5c7052c63208dae7b2a2..8c626606c3c2d1900aa580a6f721a180fd66c382 100644 (file)
@@ -77,6 +77,53 @@ START_TEST(test_parse)
                  "service.name =~ 'p' OR "
                  "service.name =~ 'r'", -1,  1, CONNECTION_LOOKUP },
 
+               /* numeric constants */
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo = "
+                 "1234",                -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo != "
+                 "+234",                -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo < "
+                 "-234",                -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo > "
+                 "12.4",                -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo <= "
+                 "12.",                 -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo >= "
+                 ".4",                  -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo = "
+                 "+12e3",               -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo = "
+                 "+12e-3",              -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo = "
+                 "-12e+3",              -1,  1, CONNECTION_LOOKUP },
+
+               /* invalid numeric constants */
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo = "
+                 "+-12e+3",             -1, -1, 0 },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo = "
+                 "-12e-+3",             -1, -1, 0 },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo = "
+                 "e+3",                 -1, -1, 0 },
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo = "
+                 "3e",                  -1, -1, 0 },
+               /* following SQL standard, we don't support hex numbers */
+               { "LOOKUP hosts WHERE "
+                 "attribute.foo = "
+                 "0x12",                -1, -1, 0 },
+
                /* comments */
                { "/* some comment */",  -1,  0, 0 },
                { "-- another comment",  -1,  0, 0 },