Code

93debf5e4530d800a0ad2dc020c6256934f2c6fd
[sysdb.git] / src / frontend / analyzer.c
1 /*
2  * SysDB - src/frontend/analyzer.c
3  * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 #include "sysdb.h"
30 #include <core/store-private.h>
31 #include <frontend/connection-private.h>
32 #include <frontend/parser.h>
34 #include <assert.h>
36 /*
37  * private helper functions
38  */
40 static int
41 analyze_matcher(int context, sdb_store_matcher_t *m)
42 {
43         int status = 0;
45         if (! m)
46                 return 0;
48         switch (m->type) {
49                 case MATCHER_OR:
50                 case MATCHER_AND:
51                         assert(OP_M(m)->left && OP_M(m)->right);
52                         if (analyze_matcher(context, OP_M(m)->left))
53                                 status = -1;
54                         if (analyze_matcher(context, OP_M(m)->right))
55                                 status = -1;
56                         break;
58                 case MATCHER_NOT:
59                         assert(UOP_M(m)->op);
60                         if (analyze_matcher(context, UOP_M(m)->op))
61                                 status = -1;
62                         break;
64                 case MATCHER_ANY:
65                 case MATCHER_ALL:
66                         assert(ITER_M(m)->m);
67                         if (ITER_M(m)->type == context)
68                                 status = -1;
69                         if ((context != SDB_HOST)
70                                         && (context != SDB_SERVICE)
71                                         && (context != SDB_METRIC))
72                                 status = -1;
73                         if ((ITER_M(m)->type != SDB_SERVICE)
74                                         && (ITER_M(m)->type != SDB_METRIC)
75                                         && (ITER_M(m)->type != SDB_ATTRIBUTE))
76                                 status = -1;
77                         if ((context == SDB_SERVICE)
78                                         && (ITER_M(m)->type == SDB_METRIC))
79                                 status = -1;
80                         else if ((context == SDB_METRIC)
81                                         && (ITER_M(m)->type == SDB_SERVICE))
82                                 status = -1;
83                         if (analyze_matcher(ITER_M(m)->type, ITER_M(m)->m))
84                                 status = -1;
85                         break;
87                 case MATCHER_LT:
88                 case MATCHER_LE:
89                 case MATCHER_EQ:
90                 case MATCHER_NE:
91                 case MATCHER_GE:
92                 case MATCHER_GT:
93                         assert(CMP_M(m)->left && CMP_M(m)->right);
94                         if ((CMP_M(m)->left->data_type > 0)
95                                         && (CMP_M(m)->left->data_type & SDB_TYPE_ARRAY))
96                                 status = -1;
97                         if ((CMP_M(m)->right->data_type > 0)
98                                         && (CMP_M(m)->right->data_type & SDB_TYPE_ARRAY))
99                                 status = -1;
100                         break;
102                 case MATCHER_IN:
103                         if ((CMP_M(m)->left->data_type > 0)
104                                         && (CMP_M(m)->left->data_type & SDB_TYPE_ARRAY))
105                                 status = -1;
106                         if ((CMP_M(m)->right->data_type > 0)
107                                         && (! (CMP_M(m)->right->data_type & SDB_TYPE_ARRAY)))
108                                 status = -1;
109                         break;
111                 case MATCHER_REGEX:
112                 case MATCHER_NREGEX:
113                         /* all types are supported for the left operand */
114                         if ((CMP_M(m)->right->data_type > 0)
115                                         && (CMP_M(m)->right->data_type != SDB_TYPE_REGEX)
116                                         && (CMP_M(m)->right->data_type != SDB_TYPE_STRING))
117                                 status = -1;
118                         break;
120                 case MATCHER_ISNULL:
121                 case MATCHER_ISNNULL:
122                         break;
124                 default:
125                         return -1;
126         }
127         return status;
128 } /* analyze_matcher */
130 /*
131  * public API
132  */
134 int
135 sdb_fe_analyze(sdb_conn_node_t *node)
137         sdb_store_matcher_t *m = NULL, *filter = NULL;
138         int context = -1;
139         int status = 0;
141         if (! node)
142                 return -1;
144         /* For now, this function checks basic matcher attributes only;
145          * later, this may be turned into one of multiple AST visitors. */
146         if (node->cmd == CONNECTION_FETCH) {
147                 conn_fetch_t *fetch = CONN_FETCH(node);
148                 if (((fetch->type == SDB_HOST) && fetch->name)
149                                 || ((fetch->type != SDB_HOST) && (! fetch->name)))
150                         return -1;
151                 if (fetch->filter)
152                         filter = fetch->filter->matcher;
153                 context = fetch->type;
154         }
155         else if (node->cmd == CONNECTION_LIST) {
156                 if (CONN_LIST(node)->filter)
157                         filter = CONN_LIST(node)->filter->matcher;
158                 context = CONN_LIST(node)->type;
159         }
160         else if (node->cmd == CONNECTION_LOOKUP) {
161                 if (CONN_LOOKUP(node)->matcher)
162                         m = CONN_LOOKUP(node)->matcher->matcher;
163                 if (CONN_LOOKUP(node)->filter)
164                         filter = CONN_LOOKUP(node)->filter->matcher;
165                 context = CONN_LOOKUP(node)->type;
166         }
167         else if (node->cmd == CONNECTION_TIMESERIES)
168                 return 0;
169         else
170                 return -1;
172         if (analyze_matcher(context, m))
173                 status = -1;
174         if (analyze_matcher(-1, filter))
175                 status = -1;
176         return status;
177 } /* sdb_fe_analyze */
179 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */