Code

store, plugin: Let the plugin module determine an objects backends.
[sysdb.git] / src / core / store_query.c
1 /*
2  * SysDB - src/core/store_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/store-private.h"
30 #include "parser/ast.h"
31 #include "utils/error.h"
33 #include <assert.h>
35 static sdb_store_matcher_t *
36 node_to_matcher(sdb_ast_node_t *n);
38 static sdb_store_expr_t *
39 node_to_expr(sdb_ast_node_t *n)
40 {
41         sdb_store_expr_t *left = NULL, *right = NULL;
42         sdb_store_expr_t *e;
43         int op;
45         if (! n) {
46                 sdb_log(SDB_LOG_ERR, "store: 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, "store: 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_store_expr_create(op, left, right);
68                 break;
70         case SDB_AST_TYPE_CONST:
71                 return sdb_store_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_store_expr_attrvalue(SDB_AST_VALUE(n)->name);
76                 return sdb_store_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_store_expr_typed(SDB_AST_TYPED(n)->type, right);
83                 break;
85         default:
86                 sdb_log(SDB_LOG_ERR, "store: 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_store_matcher_t *
98 logical_to_matcher(sdb_ast_node_t *n)
99 {
100         sdb_store_matcher_t *left = NULL, *right;
101         sdb_store_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_store_con_matcher(left, right);
117                 break;
118         case SDB_AST_OR:
119                 m = sdb_store_dis_matcher(left, right);
120                 break;
121         case SDB_AST_NOT:
122                 m = sdb_store_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_store_matcher_t *
136 cmp_to_matcher(sdb_ast_node_t *n)
138         sdb_store_expr_t *left = NULL, *right;
139         sdb_store_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_store_lt_matcher(left, right);
155                 break;
156         case SDB_AST_LE:
157                 m = sdb_store_le_matcher(left, right);
158                 break;
159         case SDB_AST_EQ:
160                 m = sdb_store_eq_matcher(left, right);
161                 break;
162         case SDB_AST_NE:
163                 m = sdb_store_ne_matcher(left, right);
164                 break;
165         case SDB_AST_GE:
166                 m = sdb_store_ge_matcher(left, right);
167                 break;
168         case SDB_AST_GT:
169                 m = sdb_store_gt_matcher(left, right);
170                 break;
171         case SDB_AST_REGEX:
172                 m = sdb_store_regex_matcher(left, right);
173                 break;
174         case SDB_AST_NREGEX:
175                 m = sdb_store_nregex_matcher(left, right);
176                 break;
177         case SDB_AST_ISNULL:
178                 m = sdb_store_isnull_matcher(right);
179                 break;
180         case SDB_AST_ISTRUE:
181                 m = sdb_store_istrue_matcher(right);
182                 break;
183         case SDB_AST_ISFALSE:
184                 m = sdb_store_isfalse_matcher(right);
185                 break;
186         case SDB_AST_IN:
187                 m = sdb_store_in_matcher(left, right);
188                 break;
190         default:
191                 sdb_log(SDB_LOG_ERR, "store: 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_store_matcher_t *
203 iter_to_matcher(sdb_ast_node_t *n)
205         sdb_store_expr_t *iter;
206         sdb_store_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_store_all_matcher(iter, expr);
223                 break;
224         case SDB_AST_ANY:
225                 m = sdb_store_any_matcher(iter, expr);
226                 break;
228         default:
229                 sdb_log(SDB_LOG_ERR, "store: 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_store_matcher_t *
241 node_to_matcher(sdb_ast_node_t *n)
243         int kind;
245         if (! n) {
246                 sdb_log(SDB_LOG_ERR, "store: 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, "store: 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, "store: 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)
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, "store: 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)
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_store_query_t),
332         /* init = */ query_init,
333         /* destroy = */ query_destroy,
334 };
336 /*
337  * public API
338  */
340 sdb_store_query_t *
341 sdb_store_query_prepare(sdb_ast_node_t *ast)
343         if (! ast)
344                 return NULL;
345         return QUERY(sdb_object_create(SDB_AST_TYPE_TO_STRING(ast), query_type, ast));
346 } /* sdb_store_query_prepare */
348 sdb_store_matcher_t *
349 sdb_store_query_prepare_matcher(sdb_ast_node_t *ast)
351         return node_to_matcher(ast);
352 } /* sdb_store_query_prepare_matcher */
354 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */