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)
136 {
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 if (CONN_FETCH(node)->filter)
148 filter = CONN_FETCH(node)->filter->matcher;
149 context = CONN_FETCH(node)->type;
150 }
151 else if (node->cmd == CONNECTION_LIST) {
152 if (CONN_LIST(node)->filter)
153 filter = CONN_LIST(node)->filter->matcher;
154 context = CONN_LIST(node)->type;
155 }
156 else if (node->cmd == CONNECTION_LOOKUP) {
157 if (CONN_LOOKUP(node)->matcher)
158 m = CONN_LOOKUP(node)->matcher->matcher;
159 if (CONN_LOOKUP(node)->filter)
160 filter = CONN_LOOKUP(node)->filter->matcher;
161 context = CONN_LOOKUP(node)->type;
162 }
163 else if (node->cmd == CONNECTION_TIMESERIES)
164 return 0;
165 else
166 return -1;
168 if (analyze_matcher(context, m))
169 status = -1;
170 if (analyze_matcher(-1, filter))
171 status = -1;
172 return status;
173 } /* sdb_fe_analyze */
175 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */