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)
137 {
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_IN:
181 m = sdb_store_in_matcher(left, right);
182 break;
184 default:
185 sdb_log(SDB_LOG_ERR, "store: Invalid matcher node of type %s (%#x)",
186 SDB_AST_TYPE_TO_STRING(n), n->type);
187 m = NULL;
188 }
190 /* matchers take a reference */
191 sdb_object_deref(SDB_OBJ(left));
192 sdb_object_deref(SDB_OBJ(right));
193 return m;
194 } /* cmp_to_matcher */
196 static sdb_store_matcher_t *
197 iter_to_matcher(sdb_ast_node_t *n)
198 {
199 sdb_store_expr_t *iter;
200 sdb_store_matcher_t *expr, *m;
202 assert((SDB_AST_ITER(n)->expr->type == SDB_AST_TYPE_OPERATOR)
203 && (! SDB_AST_OP(SDB_AST_ITER(n)->expr)->left));
205 iter = node_to_expr(SDB_AST_ITER(n)->iter);
206 if (! iter)
207 return NULL;
208 expr = cmp_to_matcher(SDB_AST_ITER(n)->expr);
209 if (! expr) {
210 sdb_object_deref(SDB_OBJ(iter));
211 return NULL;
212 }
214 switch (SDB_AST_ITER(n)->kind) {
215 case SDB_AST_ALL:
216 m = sdb_store_all_matcher(iter, expr);
217 break;
218 case SDB_AST_ANY:
219 m = sdb_store_any_matcher(iter, expr);
220 break;
222 default:
223 sdb_log(SDB_LOG_ERR, "store: Invalid iterator node of type %s (%#x)",
224 SDB_AST_OP_TO_STRING(SDB_AST_ITER(n)->kind), SDB_AST_ITER(n)->kind);
225 m = NULL;
226 }
228 /* matchers take a reference */
229 sdb_object_deref(SDB_OBJ(iter));
230 sdb_object_deref(SDB_OBJ(expr));
231 return m;
232 } /* iter_to_matcher */
234 static sdb_store_matcher_t *
235 node_to_matcher(sdb_ast_node_t *n)
236 {
237 int kind;
239 if (! n) {
240 sdb_log(SDB_LOG_ERR, "store: Encountered empty AST matcher node");
241 return NULL;
242 }
244 switch (n->type) {
245 case SDB_AST_TYPE_OPERATOR:
246 if (! SDB_AST_IS_LOGICAL(n)) {
247 sdb_log(SDB_LOG_ERR, "store: Invalid logical operator of "
248 "type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type);
249 return NULL;
250 }
252 kind = SDB_AST_OP(n)->kind;
253 if ((kind == SDB_AST_AND) || (kind == SDB_AST_OR) || (kind == SDB_AST_NOT))
254 return logical_to_matcher(n);
255 else
256 return cmp_to_matcher(n);
258 case SDB_AST_TYPE_ITERATOR:
259 return iter_to_matcher(n);
260 }
262 sdb_log(SDB_LOG_ERR, "store: Invalid matcher node of type %s (%#x)",
263 SDB_AST_TYPE_TO_STRING(n), n->type);
264 return NULL;
265 } /* node_to_matcher */
267 /*
268 * matcher type
269 */
271 static int
272 query_matcher_init(sdb_object_t *obj, va_list ap)
273 {
274 sdb_ast_node_t *ast = va_arg(ap, sdb_ast_node_t *);
275 sdb_ast_node_t *matcher = NULL, *filter = NULL;
277 M(obj)->type = MATCHER_QUERY;
279 QUERY_M(obj)->ast = ast;
280 sdb_object_ref(SDB_OBJ(ast));
282 switch (ast->type) {
283 case SDB_AST_TYPE_FETCH:
284 filter = SDB_AST_FETCH(ast)->filter;
285 break;
286 case SDB_AST_TYPE_LIST:
287 filter = SDB_AST_LIST(ast)->filter;
288 break;
289 case SDB_AST_TYPE_LOOKUP:
290 matcher = SDB_AST_LOOKUP(ast)->matcher;
291 filter = SDB_AST_LOOKUP(ast)->filter;
292 break;
293 case SDB_AST_TYPE_STORE:
294 case SDB_AST_TYPE_TIMESERIES:
295 /* nothing to do */
296 break;
298 default:
299 sdb_log(SDB_LOG_ERR, "store: Invalid top-level AST node "
300 "of type %#x", ast->type);
301 return -1;
302 }
304 if (matcher) {
305 QUERY_M(obj)->matcher = node_to_matcher(matcher);
306 if (! QUERY_M(obj)->matcher)
307 return -1;
308 }
309 if (filter) {
310 QUERY_M(obj)->filter = node_to_matcher(filter);
311 if (! QUERY_M(obj)->filter)
312 return -1;
313 }
315 return 0;
316 } /* query_matcher_init */
318 static void
319 query_matcher_destroy(sdb_object_t *obj)
320 {
321 sdb_object_deref(SDB_OBJ(QUERY_M(obj)->ast));
322 sdb_object_deref(SDB_OBJ(QUERY_M(obj)->matcher));
323 sdb_object_deref(SDB_OBJ(QUERY_M(obj)->filter));
324 } /* query_matcher_destroy */
326 static sdb_type_t query_type = {
327 /* size = */ sizeof(query_matcher_t),
328 /* init = */ query_matcher_init,
329 /* destroy = */ query_matcher_destroy,
330 };
332 /*
333 * public API
334 */
336 sdb_store_matcher_t *
337 sdb_store_query_prepare(sdb_ast_node_t *ast)
338 {
339 if (! ast)
340 return NULL;
341 return M(sdb_object_create(SDB_AST_TYPE_TO_STRING(ast), query_type, ast));
342 } /* sdb_store_query_prepare */
344 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */