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-1335 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
grn_ts_expr_init(grn_ctx * ctx,grn_ts_expr * expr)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
grn_ts_expr_fin(grn_ctx * ctx,grn_ts_expr * expr)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
grn_ts_expr_open(grn_ctx * ctx,grn_obj * table,grn_ts_expr_node * root,grn_ts_expr ** expr)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
grn_ts_expr_parse(grn_ctx * ctx,grn_obj * table,grn_ts_str str,grn_ts_expr ** expr)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
grn_ts_expr_close(grn_ctx * ctx,grn_ts_expr * expr)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
grn_ts_expr_evaluate_to_buf(grn_ctx * ctx,grn_ts_expr * expr,const grn_ts_record * in,size_t n_in,grn_ts_buf * out)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
grn_ts_expr_evaluate(grn_ctx * ctx,grn_ts_expr * expr,const grn_ts_record * in,size_t n_in,void * out)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
grn_ts_expr_filter(grn_ctx * ctx,grn_ts_expr * expr,grn_ts_record * in,size_t n_in,grn_ts_record * out,size_t * n_out)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
grn_ts_expr_adjust(grn_ctx * ctx,grn_ts_expr * expr,grn_ts_record * io,size_t n_io)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