1 /*
2 * SysDB - src/core/memstore_query.c
3 * Copyright (C) 2014-2015 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 "core/object.h"
29 #include "core/memstore-private.h"
30 #include "parser/ast.h"
31 #include "utils/error.h"
33 #include <assert.h>
35 static sdb_memstore_matcher_t *
36 node_to_matcher(sdb_ast_node_t *n);
38 static sdb_memstore_expr_t *
39 node_to_expr(sdb_ast_node_t *n)
40 {
41 sdb_memstore_expr_t *left = NULL, *right = NULL;
42 sdb_memstore_expr_t *e;
43 int op;
45 if (! n) {
46 sdb_log(SDB_LOG_ERR, "memstore: Encountered empty AST expression node");
47 return NULL;
48 }
50 switch (n->type) {
51 case SDB_AST_TYPE_OPERATOR:
52 if (! SDB_AST_IS_ARITHMETIC(n)) {
53 sdb_log(SDB_LOG_ERR, "memstore: Invalid arithmetic operator of "
54 "type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type);
55 return NULL;
56 }
58 left = node_to_expr(SDB_AST_OP(n)->left);
59 if (! left)
60 return NULL;
61 right = node_to_expr(SDB_AST_OP(n)->right);
62 if (! right) {
63 sdb_object_deref(SDB_OBJ(left));
64 return NULL;
65 }
66 op = SDB_AST_OP_TO_DATA_OP(SDB_AST_OP(n)->kind);
67 e = sdb_memstore_expr_create(op, left, right);
68 break;
70 case SDB_AST_TYPE_CONST:
71 return sdb_memstore_expr_constvalue(&SDB_AST_CONST(n)->value);
73 case SDB_AST_TYPE_VALUE:
74 if (SDB_AST_VALUE(n)->type == SDB_ATTRIBUTE)
75 return sdb_memstore_expr_attrvalue(SDB_AST_VALUE(n)->name);
76 return sdb_memstore_expr_fieldvalue(SDB_AST_VALUE(n)->type);
78 case SDB_AST_TYPE_TYPED:
79 right = node_to_expr(SDB_AST_TYPED(n)->expr);
80 if (! right)
81 return NULL;
82 e = sdb_memstore_expr_typed(SDB_AST_TYPED(n)->type, right);
83 break;
85 default:
86 sdb_log(SDB_LOG_ERR, "memstore: Invalid matcher node of type %s (%#x)",
87 SDB_AST_TYPE_TO_STRING(n), n->type);
88 e = NULL;
89 }
91 /* expressions take a reference */
92 sdb_object_deref(SDB_OBJ(left));
93 sdb_object_deref(SDB_OBJ(right));
94 return e;
95 } /* node_to_expr */
97 static sdb_memstore_matcher_t *
98 logical_to_matcher(sdb_ast_node_t *n)
99 {
100 sdb_memstore_matcher_t *left = NULL, *right;
101 sdb_memstore_matcher_t *m;
103 if (SDB_AST_OP(n)->left) {
104 left = node_to_matcher(SDB_AST_OP(n)->left);
105 if (! left)
106 return NULL;
107 }
108 right = node_to_matcher(SDB_AST_OP(n)->right);
109 if (! right) {
110 sdb_object_deref(SDB_OBJ(left));
111 return NULL;
112 }
114 switch (SDB_AST_OP(n)->kind) {
115 case SDB_AST_AND:
116 m = sdb_memstore_con_matcher(left, right);
117 break;
118 case SDB_AST_OR:
119 m = sdb_memstore_dis_matcher(left, right);
120 break;
121 case SDB_AST_NOT:
122 m = sdb_memstore_inv_matcher(right);
123 break;
125 default:
126 m = NULL;
127 }
129 /* matchers take a reference */
130 sdb_object_deref(SDB_OBJ(left));
131 sdb_object_deref(SDB_OBJ(right));
132 return m;
133 } /* logical_to_matcher */
135 static sdb_memstore_matcher_t *
136 cmp_to_matcher(sdb_ast_node_t *n)
137 {
138 sdb_memstore_expr_t *left = NULL, *right;
139 sdb_memstore_matcher_t *m;
141 if (SDB_AST_OP(n)->left) {
142 left = node_to_expr(SDB_AST_OP(n)->left);
143 if (! left)
144 return NULL;
145 }
146 right = node_to_expr(SDB_AST_OP(n)->right);
147 if (! right) {
148 sdb_object_deref(SDB_OBJ(left));
149 return NULL;
150 }
152 switch (SDB_AST_OP(n)->kind) {
153 case SDB_AST_LT:
154 m = sdb_memstore_lt_matcher(left, right);
155 break;
156 case SDB_AST_LE:
157 m = sdb_memstore_le_matcher(left, right);
158 break;
159 case SDB_AST_EQ:
160 m = sdb_memstore_eq_matcher(left, right);
161 break;
162 case SDB_AST_NE:
163 m = sdb_memstore_ne_matcher(left, right);
164 break;
165 case SDB_AST_GE:
166 m = sdb_memstore_ge_matcher(left, right);
167 break;
168 case SDB_AST_GT:
169 m = sdb_memstore_gt_matcher(left, right);
170 break;
171 case SDB_AST_REGEX:
172 m = sdb_memstore_regex_matcher(left, right);
173 break;
174 case SDB_AST_NREGEX:
175 m = sdb_memstore_nregex_matcher(left, right);
176 break;
177 case SDB_AST_ISNULL:
178 m = sdb_memstore_isnull_matcher(right);
179 break;
180 case SDB_AST_ISTRUE:
181 m = sdb_memstore_istrue_matcher(right);
182 break;
183 case SDB_AST_ISFALSE:
184 m = sdb_memstore_isfalse_matcher(right);
185 break;
186 case SDB_AST_IN:
187 m = sdb_memstore_in_matcher(left, right);
188 break;
190 default:
191 sdb_log(SDB_LOG_ERR, "memstore: Invalid matcher node of type %s (%#x)",
192 SDB_AST_TYPE_TO_STRING(n), n->type);
193 m = NULL;
194 }
196 /* matchers take a reference */
197 sdb_object_deref(SDB_OBJ(left));
198 sdb_object_deref(SDB_OBJ(right));
199 return m;
200 } /* cmp_to_matcher */
202 static sdb_memstore_matcher_t *
203 iter_to_matcher(sdb_ast_node_t *n)
204 {
205 sdb_memstore_expr_t *iter;
206 sdb_memstore_matcher_t *expr, *m;
208 assert((SDB_AST_ITER(n)->expr->type == SDB_AST_TYPE_OPERATOR)
209 && (! SDB_AST_OP(SDB_AST_ITER(n)->expr)->left));
211 iter = node_to_expr(SDB_AST_ITER(n)->iter);
212 if (! iter)
213 return NULL;
214 expr = cmp_to_matcher(SDB_AST_ITER(n)->expr);
215 if (! expr) {
216 sdb_object_deref(SDB_OBJ(iter));
217 return NULL;
218 }
220 switch (SDB_AST_ITER(n)->kind) {
221 case SDB_AST_ALL:
222 m = sdb_memstore_all_matcher(iter, expr);
223 break;
224 case SDB_AST_ANY:
225 m = sdb_memstore_any_matcher(iter, expr);
226 break;
228 default:
229 sdb_log(SDB_LOG_ERR, "memstore: Invalid iterator node of type %s (%#x)",
230 SDB_AST_OP_TO_STRING(SDB_AST_ITER(n)->kind), SDB_AST_ITER(n)->kind);
231 m = NULL;
232 }
234 /* matchers take a reference */
235 sdb_object_deref(SDB_OBJ(iter));
236 sdb_object_deref(SDB_OBJ(expr));
237 return m;
238 } /* iter_to_matcher */
240 static sdb_memstore_matcher_t *
241 node_to_matcher(sdb_ast_node_t *n)
242 {
243 int kind;
245 if (! n) {
246 sdb_log(SDB_LOG_ERR, "memstore: Encountered empty AST matcher node");
247 return NULL;
248 }
250 switch (n->type) {
251 case SDB_AST_TYPE_OPERATOR:
252 if (! SDB_AST_IS_LOGICAL(n)) {
253 sdb_log(SDB_LOG_ERR, "memstore: Invalid logical operator of "
254 "type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type);
255 return NULL;
256 }
258 kind = SDB_AST_OP(n)->kind;
259 if ((kind == SDB_AST_AND) || (kind == SDB_AST_OR) || (kind == SDB_AST_NOT))
260 return logical_to_matcher(n);
261 else
262 return cmp_to_matcher(n);
264 case SDB_AST_TYPE_ITERATOR:
265 return iter_to_matcher(n);
266 }
268 sdb_log(SDB_LOG_ERR, "memstore: Invalid matcher node of type %s (%#x)",
269 SDB_AST_TYPE_TO_STRING(n), n->type);
270 return NULL;
271 } /* node_to_matcher */
273 /*
274 * query type
275 */
277 static int
278 query_init(sdb_object_t *obj, va_list ap)
279 {
280 sdb_ast_node_t *ast = va_arg(ap, sdb_ast_node_t *);
281 sdb_ast_node_t *matcher = NULL, *filter = NULL;
283 QUERY(obj)->ast = ast;
284 sdb_object_ref(SDB_OBJ(ast));
286 switch (ast->type) {
287 case SDB_AST_TYPE_FETCH:
288 filter = SDB_AST_FETCH(ast)->filter;
289 break;
290 case SDB_AST_TYPE_LIST:
291 filter = SDB_AST_LIST(ast)->filter;
292 break;
293 case SDB_AST_TYPE_LOOKUP:
294 matcher = SDB_AST_LOOKUP(ast)->matcher;
295 filter = SDB_AST_LOOKUP(ast)->filter;
296 break;
297 case SDB_AST_TYPE_STORE:
298 case SDB_AST_TYPE_TIMESERIES:
299 /* nothing to do */
300 break;
302 default:
303 sdb_log(SDB_LOG_ERR, "memstore: Invalid top-level AST node "
304 "of type %#x", ast->type);
305 return -1;
306 }
308 if (matcher) {
309 QUERY(obj)->matcher = node_to_matcher(matcher);
310 if (! QUERY(obj)->matcher)
311 return -1;
312 }
313 if (filter) {
314 QUERY(obj)->filter = node_to_matcher(filter);
315 if (! QUERY(obj)->filter)
316 return -1;
317 }
319 return 0;
320 } /* query_init */
322 static void
323 query_destroy(sdb_object_t *obj)
324 {
325 sdb_object_deref(SDB_OBJ(QUERY(obj)->ast));
326 sdb_object_deref(SDB_OBJ(QUERY(obj)->matcher));
327 sdb_object_deref(SDB_OBJ(QUERY(obj)->filter));
328 } /* query_destroy */
330 static sdb_type_t query_type = {
331 /* size = */ sizeof(sdb_memstore_query_t),
332 /* init = */ query_init,
333 /* destroy = */ query_destroy,
334 };
336 /*
337 * public API
338 */
340 sdb_memstore_query_t *
341 sdb_memstore_query_prepare(sdb_ast_node_t *ast)
342 {
343 if (! ast)
344 return NULL;
345 return QUERY(sdb_object_create(SDB_AST_TYPE_TO_STRING(ast), query_type, ast));
346 } /* sdb_memstore_query_prepare */
348 sdb_memstore_matcher_t *
349 sdb_memstore_query_prepare_matcher(sdb_ast_node_t *ast)
350 {
351 return node_to_matcher(ast);
352 } /* sdb_memstore_query_prepare_matcher */
354 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */