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