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. */
31static void
32grn_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. */
40static void
41grn_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
51grn_rc
52grn_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
113grn_rc
114grn_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
140grn_rc
141grn_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
154grn_rc
155grn_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
171grn_rc
172grn_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
187grn_rc
188grn_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
205grn_rc
206grn_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