Code

parser: Add support for <expr> IS [NOT] TRUE / FALSE queries.
authorSebastian Harl <sh@tokkee.org>
Tue, 19 May 2015 21:11:35 +0000 (23:11 +0200)
committerSebastian Harl <sh@tokkee.org>
Tue, 19 May 2015 21:11:35 +0000 (23:11 +0200)
src/core/store_query.c
src/include/parser/ast.h
src/parser/analyzer.c
src/parser/grammar.y
src/parser/scanner.l
t/unit/core/store_lookup_test.c
t/unit/parser/parser_test.c

index 17ee17f6e4178845734657c2ac7951c26d999beb..ff7089c42e51b0294eae53b4780e4d517bfcd6cb 100644 (file)
@@ -177,6 +177,12 @@ cmp_to_matcher(sdb_ast_node_t *n)
        case SDB_AST_ISNULL:
                m = sdb_store_isnull_matcher(right);
                break;
+       case SDB_AST_ISTRUE:
+               m = sdb_store_istrue_matcher(right);
+               break;
+       case SDB_AST_ISFALSE:
+               m = sdb_store_isfalse_matcher(right);
+               break;
        case SDB_AST_IN:
                m = sdb_store_in_matcher(left, right);
                break;
index 80b5a533a539ed57b0c656458b7bf6d6f7b42690..8533fc705e6467b91840ce97b86cc20a09f14b14 100644 (file)
@@ -76,20 +76,22 @@ typedef enum {
                || (((n)->type == SDB_AST_TYPE_ITERATOR) \
                        && ((SDB_AST_ALL <= SDB_AST_ITER(n)->kind) \
                                && (SDB_AST_ITER(n)->kind <= SDB_AST_ANY))))
-       SDB_AST_AND    = 1000,
-       SDB_AST_OR     = 1001,
-       SDB_AST_NOT    = 1002,
-
-       SDB_AST_LT     = 1010,
-       SDB_AST_LE     = 1011,
-       SDB_AST_EQ     = 1012,
-       SDB_AST_NE     = 1013,
-       SDB_AST_GE     = 1014,
-       SDB_AST_GT     = 1015,
-       SDB_AST_REGEX  = 1016,
-       SDB_AST_NREGEX = 1017,
-       SDB_AST_ISNULL = 1018,
-       SDB_AST_IN     = 1019,
+       SDB_AST_AND     = 1000,
+       SDB_AST_OR      = 1001,
+       SDB_AST_NOT     = 1002,
+
+       SDB_AST_LT      = 1010,
+       SDB_AST_LE      = 1011,
+       SDB_AST_EQ      = 1012,
+       SDB_AST_NE      = 1013,
+       SDB_AST_GE      = 1014,
+       SDB_AST_GT      = 1015,
+       SDB_AST_REGEX   = 1016,
+       SDB_AST_NREGEX  = 1017,
+       SDB_AST_ISNULL  = 1018,
+       SDB_AST_ISTRUE  = 1019,
+       SDB_AST_ISFALSE = 1020,
+       SDB_AST_IN      = 1021,
 
        /* arithmetic expressions */
 #define SDB_AST_IS_ARITHMETIC(n) \
@@ -99,20 +101,20 @@ typedef enum {
                || (((n)->type == SDB_AST_TYPE_OPERATOR) \
                        && ((SDB_AST_ADD <= SDB_AST_OP(n)->kind) \
                                && (SDB_AST_OP(n)->kind <= SDB_AST_CONCAT))))
-       SDB_AST_ADD    = 2000,
-       SDB_AST_SUB    = 2001,
-       SDB_AST_MUL    = 2002,
-       SDB_AST_DIV    = 2003,
-       SDB_AST_MOD    = 2004,
-       SDB_AST_CONCAT = 2005,
+       SDB_AST_ADD     = 2000,
+       SDB_AST_SUB     = 2001,
+       SDB_AST_MUL     = 2002,
+       SDB_AST_DIV     = 2003,
+       SDB_AST_MOD     = 2004,
+       SDB_AST_CONCAT  = 2005,
 
        /* iterators */
 #define SDB_AST_IS_ITERATOR(n) \
        (((n)->type == SDB_AST_TYPE_ITERATOR) \
                && ((SDB_AST_ALL <= SDB_AST_ITER(n)->kind) \
                        && (SDB_AST_ITER(n)->kind <= SDB_AST_ANY)))
-       SDB_AST_ALL    = 3000,
-       SDB_AST_ANY    = 3001,
+       SDB_AST_ALL     = 3000,
+       SDB_AST_ANY     = 3001,
 } sdb_ast_operator_t;
 
 #define SDB_AST_OP_TO_STRING(op) \
@@ -127,7 +129,9 @@ typedef enum {
                : ((op) == SDB_AST_GT) ? "GT" \
                : ((op) == SDB_AST_REGEX) ? "REGEX" \
                : ((op) == SDB_AST_NREGEX) ? "NREGEX" \
-               : ((op) == SDB_AST_ISNULL) ? "ISNULL" \
+               : ((op) == SDB_AST_ISNULL) ? "IS NULL" \
+               : ((op) == SDB_AST_ISTRUE) ? "IS TRUE" \
+               : ((op) == SDB_AST_ISFALSE) ? "IS FALSE" \
                : ((op) == SDB_AST_IN) ? "IN" \
                : ((op) == SDB_AST_ADD) ? "ADD" \
                : ((op) == SDB_AST_SUB) ? "SUB" \
index e03cbdbc3d2e9ff259e9d18f6729bf9751e920b7..f352a0d630cf2ae5d7e69534658e4493724a1e3e 100644 (file)
@@ -155,6 +155,8 @@ analyze_logical(int context, sdb_ast_op_t *op, sdb_strbuf_t *errbuf)
                break;
 
        case SDB_AST_ISNULL:
+       case SDB_AST_ISTRUE:
+       case SDB_AST_ISFALSE:
                if (analyze_node(context, op->right, errbuf))
                        return -1;
                break;
index 801462617755d305739e4ef28ac237dd8ce4d5cd..339f17ae43432dbcafd9fe6c2d1b5d7aead796c6 100644 (file)
@@ -127,6 +127,8 @@ sdb_parser_yyerrorf(YYLTYPE *lval, sdb_parser_yyscan_t scanner, const char *fmt,
 /* NULL token */
 %token NULL_T
 
+%token TRUE FALSE
+
 %token FETCH LIST LOOKUP STORE TIMESERIES
 
 %token <str> IDENTIFIER STRING
@@ -481,6 +483,34 @@ comparison:
                        CK_OOM($$);
                }
        |
+       expression IS TRUE
+               {
+                       $$ = sdb_ast_op_create(SDB_AST_ISTRUE, NULL, $1);
+                       CK_OOM($$);
+               }
+       |
+       expression IS NOT TRUE
+               {
+                       $$ = sdb_ast_op_create(SDB_AST_ISTRUE, NULL, $1);
+                       CK_OOM($$);
+                       $$ = sdb_ast_op_create(SDB_AST_NOT, NULL, $$);
+                       CK_OOM($$);
+               }
+       |
+       expression IS FALSE
+               {
+                       $$ = sdb_ast_op_create(SDB_AST_ISFALSE, NULL, $1);
+                       CK_OOM($$);
+               }
+       |
+       expression IS NOT FALSE
+               {
+                       $$ = sdb_ast_op_create(SDB_AST_ISFALSE, NULL, $1);
+                       CK_OOM($$);
+                       $$ = sdb_ast_op_create(SDB_AST_NOT, NULL, $$);
+                       CK_OOM($$);
+               }
+       |
        expression IN expression
                {
                        $$ = sdb_ast_op_create(SDB_AST_IN, $1, $3);
index 43ec844e4792b8032e26d17fe4e4195fcae5091d..8fce7d960f9e12893a9403019a595d74f8f956db 100644 (file)
@@ -56,6 +56,7 @@ static struct {
        { "AND",         AND },
        { "ANY",         ANY },
        { "END",         END },
+       { "FALSE",       FALSE },
        { "FETCH",       FETCH },
        { "FILTER",      FILTER },
        { "IN",          IN },
@@ -70,6 +71,7 @@ static struct {
        { "START",       START },
        { "STORE",       STORE },
        { "TIMESERIES",  TIMESERIES },
+       { "TRUE",        TRUE },
        { "UPDATE",      UPDATE },
 
        /* object types */
index 14d2209a933e0e398a620532a419fae0c27e0e19..33c9268cb01d29fc561987b9838eb86f12b213f6 100644 (file)
@@ -592,8 +592,13 @@ struct {
        { "attribute['x1'] !~ 'v'", NULL,      0 },
        { "attribute['k1'] IS NULL", NULL,     1 },
        { "attribute['x1'] IS NULL", NULL,     3 },
+       { "attribute['k1'] IS TRUE", NULL,     0 },
+       { "attribute['x1'] IS TRUE", NULL,     0 },
+       { "attribute['k1'] IS FALSE", NULL,    0 },
+       { "attribute['x1'] IS FALSE", NULL,    0 },
        { "attribute['k1'] IS NOT NULL", NULL, 2 },
        { "attribute['x1'] IS NOT NULL", NULL, 0 },
+       { "attribute['x1'] IS NOT TRUE", NULL, 3 },
        { "attribute['k2'] < 123", NULL,       0 },
        { "attribute['k2'] <= 123", NULL,      1 },
        { "attribute['k2'] >= 123", NULL,      1 },
index cbcbe2c6b2716d628adade52a9f659f6ca28e370..4dcf684de06cc6c3b508fff98401883913bf7e6d 100644 (file)
@@ -372,7 +372,7 @@ struct {
          "ANY service.service.name = 's'",
                                 -1,  1, SDB_AST_TYPE_LOOKUP, SDB_HOST },
 
-       /* NULL */
+       /* NULL / TRUE / FALSE */
        { "LOOKUP hosts MATCHING "
          "attribute['foo'] "
          "IS NULL",             -1,  1, SDB_AST_TYPE_LOOKUP, SDB_HOST },
@@ -384,6 +384,24 @@ struct {
          "IS NULL",             -1,  1, SDB_AST_TYPE_LOOKUP, SDB_HOST },
        { "LOOKUP hosts MATCHING "
          "ANY service.name IS NULL", -1, -1, 0, 0 },
+       { "LOOKUP hosts MATCHING "
+         "attribute['foo'] "
+         "IS TRUE",             -1,  1, SDB_AST_TYPE_LOOKUP, SDB_HOST },
+       { "LOOKUP hosts MATCHING "
+         "attribute['foo'] "
+         "IS NOT TRUE",         -1,  1, SDB_AST_TYPE_LOOKUP, SDB_HOST },
+       { "LOOKUP hosts MATCHING "
+         "NOT attribute['foo'] "
+         "IS TRUE",             -1,  1, SDB_AST_TYPE_LOOKUP, SDB_HOST },
+       { "LOOKUP hosts MATCHING "
+         "attribute['foo'] "
+         "IS FALSE",            -1,  1, SDB_AST_TYPE_LOOKUP, SDB_HOST },
+       { "LOOKUP hosts MATCHING "
+         "attribute['foo'] "
+         "IS NOT FALSE",        -1,  1, SDB_AST_TYPE_LOOKUP, SDB_HOST },
+       { "LOOKUP hosts MATCHING "
+         "NOT attribute['foo'] "
+         "IS FALSE",            -1,  1, SDB_AST_TYPE_LOOKUP, SDB_HOST },
 
        /* invalid numeric constants */
        { "LOOKUP hosts MATCHING "
@@ -530,6 +548,14 @@ struct {
          "name + 1 IS NULL",    -1, -1, 0, 0 },
        { "LOOKUP hosts FILTER "
          "name + 1 IS NULL",    -1, -1, 0, 0 },
+       { "LOOKUP hosts MATCHING "
+         "name + 1 IS TRUE",    -1, -1, 0, 0 },
+       { "LOOKUP hosts FILTER "
+         "name + 1 IS TRUE",    -1, -1, 0, 0 },
+       { "LOOKUP hosts MATCHING "
+         "name + 1 IS FALSE",   -1, -1, 0, 0 },
+       { "LOOKUP hosts FILTER "
+         "name + 1 IS FALSE",   -1, -1, 0, 0 },
 
        /* invalid iterators */
        { "LOOKUP hosts MATCHING "
@@ -832,9 +858,13 @@ struct {
          "2014-08-16 17:23",               -1,  SDB_AST_EQ },
        { "attribute['foo'] = "
          "2014-08-16 17:23:53",            -1,  SDB_AST_EQ },
-       /* NULL */
+       /* NULL / TRUE / FALSE */
        { "attribute['foo'] IS NULL",       -1,  SDB_AST_ISNULL },
        { "attribute['foo'] IS NOT NULL",   -1,  SDB_AST_NOT },
+       { "attribute['foo'] IS TRUE",       -1,  SDB_AST_ISTRUE },
+       { "attribute['foo'] IS NOT TRUE",   -1,  SDB_AST_NOT },
+       { "attribute['foo'] IS FALSE",      -1,  SDB_AST_ISFALSE },
+       { "attribute['foo'] IS NOT FALSE",  -1,  SDB_AST_NOT },
        /* array expressions */
        { "backend < ['a']",                -1,  SDB_AST_LT },
        { "backend <= ['a']",               -1,  SDB_AST_LE },