1 | /* -*- c-basic-offset: 2 -*- */ |
2 | /* |
3 | Copyright(C) 2015 Brazil |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License version 2.1 as published by the Free Software Foundation. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with this library; if not, write to the Free Software |
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ |
18 | |
19 | #include "ts_expr.h" |
20 | |
21 | #include <string.h> |
22 | |
23 | #include "../grn_ctx.h" |
24 | |
25 | #include "ts_log.h" |
26 | #include "ts_str.h" |
27 | #include "ts_util.h" |
28 | #include "ts_expr_parser.h" |
29 | |
30 | /* grn_ts_expr_init() initializes an expression. */ |
31 | static void |
32 | grn_ts_expr_init(grn_ctx *ctx, grn_ts_expr *expr) |
33 | { |
34 | memset(expr, 0, sizeof(*expr)); |
35 | expr->table = NULL; |
36 | expr->root = NULL; |
37 | } |
38 | |
39 | /* grn_ts_expr_fin() finalizes an expression. */ |
40 | static void |
41 | grn_ts_expr_fin(grn_ctx *ctx, grn_ts_expr *expr) |
42 | { |
43 | if (expr->root) { |
44 | grn_ts_expr_node_close(ctx, expr->root); |
45 | } |
46 | if (expr->table) { |
47 | grn_obj_unlink(ctx, expr->table); |
48 | } |
49 | } |
50 | |
51 | grn_rc |
52 | grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_node *root, |
53 | grn_ts_expr **expr) |
54 | { |
55 | grn_rc rc; |
56 | grn_ts_expr *new_expr; |
57 | grn_ts_expr_type type; |
58 | if (!ctx) { |
59 | return GRN_INVALID_ARGUMENT; |
60 | } |
61 | if (!table || !grn_ts_obj_is_table(ctx, table) || !root || !expr) { |
62 | GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument" ); |
63 | } |
64 | switch (root->type) { |
65 | case GRN_TS_EXPR_ID_NODE: { |
66 | type = GRN_TS_EXPR_ID; |
67 | break; |
68 | } |
69 | case GRN_TS_EXPR_SCORE_NODE: { |
70 | type = GRN_TS_EXPR_SCORE; |
71 | break; |
72 | } |
73 | case GRN_TS_EXPR_KEY_NODE: |
74 | case GRN_TS_EXPR_VALUE_NODE: { |
75 | type = GRN_TS_EXPR_VARIABLE; |
76 | break; |
77 | } |
78 | case GRN_TS_EXPR_CONST_NODE: { |
79 | type = GRN_TS_EXPR_CONST; |
80 | break; |
81 | } |
82 | case GRN_TS_EXPR_COLUMN_NODE: |
83 | case GRN_TS_EXPR_OP_NODE: |
84 | case GRN_TS_EXPR_BRIDGE_NODE: { |
85 | type = GRN_TS_EXPR_VARIABLE; |
86 | break; |
87 | } |
88 | default: { |
89 | GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument" ); |
90 | } |
91 | } |
92 | new_expr = GRN_MALLOCN(grn_ts_expr, 1); |
93 | if (!new_expr) { |
94 | GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, |
95 | "GRN_MALLOCN failed: %" GRN_FMT_SIZE, |
96 | sizeof(grn_ts_expr)); |
97 | } |
98 | rc = grn_ts_obj_increment_ref_count(ctx, table); |
99 | if (rc != GRN_SUCCESS) { |
100 | GRN_FREE(new_expr); |
101 | return rc; |
102 | } |
103 | grn_ts_expr_init(ctx, new_expr); |
104 | new_expr->table = table; |
105 | new_expr->type = type; |
106 | new_expr->data_kind = root->data_kind; |
107 | new_expr->data_type = root->data_type; |
108 | new_expr->root = root; |
109 | *expr = new_expr; |
110 | return GRN_SUCCESS; |
111 | } |
112 | |
113 | grn_rc |
114 | grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, grn_ts_str str, |
115 | grn_ts_expr **expr) |
116 | { |
117 | grn_rc rc; |
118 | grn_ts_expr *new_expr; |
119 | grn_ts_expr_parser *parser; |
120 | if (!ctx) { |
121 | return GRN_INVALID_ARGUMENT; |
122 | } |
123 | if (!table || !grn_ts_obj_is_table(ctx, table) || |
124 | (!str.ptr && str.size) || !expr) { |
125 | GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument" ); |
126 | } |
127 | rc = grn_ts_expr_parser_open(ctx, table, &parser); |
128 | if (rc != GRN_SUCCESS) { |
129 | return rc; |
130 | } |
131 | rc = grn_ts_expr_parser_parse(ctx, parser, str, &new_expr); |
132 | grn_ts_expr_parser_close(ctx, parser); |
133 | if (rc != GRN_SUCCESS) { |
134 | return rc; |
135 | } |
136 | *expr = new_expr; |
137 | return GRN_SUCCESS; |
138 | } |
139 | |
140 | grn_rc |
141 | grn_ts_expr_close(grn_ctx *ctx, grn_ts_expr *expr) |
142 | { |
143 | if (!ctx) { |
144 | return GRN_INVALID_ARGUMENT; |
145 | } |
146 | if (!expr) { |
147 | GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument" ); |
148 | } |
149 | grn_ts_expr_fin(ctx, expr); |
150 | GRN_FREE(expr); |
151 | return GRN_SUCCESS; |
152 | } |
153 | |
154 | grn_rc |
155 | grn_ts_expr_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr *expr, |
156 | const grn_ts_record *in, size_t n_in, |
157 | grn_ts_buf *out) |
158 | { |
159 | if (!ctx) { |
160 | return GRN_INVALID_ARGUMENT; |
161 | } |
162 | if (!expr || (!in && n_in) || !out) { |
163 | GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument" ); |
164 | } |
165 | if (!n_in) { |
166 | return GRN_SUCCESS; |
167 | } |
168 | return grn_ts_expr_node_evaluate_to_buf(ctx, expr->root, in, n_in, out); |
169 | } |
170 | |
171 | grn_rc |
172 | grn_ts_expr_evaluate(grn_ctx *ctx, grn_ts_expr *expr, |
173 | const grn_ts_record *in, size_t n_in, void *out) |
174 | { |
175 | if (!ctx) { |
176 | return GRN_INVALID_ARGUMENT; |
177 | } |
178 | if (!expr || (!in && n_in) || (n_in && !out)) { |
179 | GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument" ); |
180 | } |
181 | if (!n_in) { |
182 | return GRN_SUCCESS; |
183 | } |
184 | return grn_ts_expr_node_evaluate(ctx, expr->root, in, n_in, out); |
185 | } |
186 | |
187 | grn_rc |
188 | grn_ts_expr_filter(grn_ctx *ctx, grn_ts_expr *expr, |
189 | grn_ts_record *in, size_t n_in, |
190 | grn_ts_record *out, size_t *n_out) |
191 | { |
192 | if (!ctx) { |
193 | return GRN_INVALID_ARGUMENT; |
194 | } |
195 | if (!expr || (!in && n_in) || !out || !n_out) { |
196 | GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument" ); |
197 | } |
198 | if (!n_in) { |
199 | *n_out = 0; |
200 | return GRN_SUCCESS; |
201 | } |
202 | return grn_ts_expr_node_filter(ctx, expr->root, in, n_in, out, n_out); |
203 | } |
204 | |
205 | grn_rc |
206 | grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr, |
207 | grn_ts_record *io, size_t n_io) |
208 | { |
209 | if (!ctx) { |
210 | return GRN_INVALID_ARGUMENT; |
211 | } |
212 | if (!expr || (!io && n_io)) { |
213 | GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument" ); |
214 | } |
215 | if (!n_io) { |
216 | return GRN_SUCCESS; |
217 | } |
218 | return grn_ts_expr_node_adjust(ctx, expr->root, io, n_io); |
219 | } |
220 | |