1 | /* -*- c-basic-offset: 2 -*- */ |
2 | /* |
3 | Copyright(C) 2009-2016 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 | #pragma once |
20 | |
21 | #include "grn.h" |
22 | #include "grn_ctx.h" |
23 | #include "grn_store.h" |
24 | #include "grn_rset.h" |
25 | |
26 | #include <groonga/command.h> |
27 | #include <groonga/token_filter.h> |
28 | #include <groonga/scorer.h> |
29 | |
30 | #include <float.h> |
31 | |
32 | #ifdef __cplusplus |
33 | extern "C" { |
34 | #endif |
35 | |
36 | #define GRN_DB_DELIMITER '.' |
37 | #define GRN_DB_PSEUDO_COLUMN_PREFIX '_' |
38 | |
39 | #define GRN_N_RESERVED_TYPES 256 |
40 | |
41 | typedef struct _grn_db grn_db; |
42 | typedef struct _grn_proc grn_proc; |
43 | |
44 | struct _grn_db { |
45 | grn_db_obj obj; |
46 | grn_obj *keys; |
47 | grn_ja *specs; |
48 | grn_hash *config; |
49 | grn_tiny_array values; |
50 | grn_critical_section lock; |
51 | }; |
52 | |
53 | #define GRN_SERIALIZED_SPEC_INDEX_SPEC 0 |
54 | #define GRN_SERIALIZED_SPEC_INDEX_PATH 1 |
55 | #define GRN_SERIALIZED_SPEC_INDEX_SOURCE 2 |
56 | #define GRN_SERIALIZED_SPEC_INDEX_HOOK 3 |
57 | #define GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS 4 |
58 | #define GRN_SERIALIZED_SPEC_INDEX_EXPR 4 |
59 | |
60 | typedef struct { |
61 | grn_obj_header ; |
62 | grn_id range; |
63 | } grn_obj_spec; |
64 | |
65 | grn_bool grn_db_spec_unpack(grn_ctx *ctx, |
66 | grn_id id, |
67 | void *encoded_spec, |
68 | uint32_t encoded_spec_size, |
69 | grn_obj_spec **spec, |
70 | grn_obj *decoded_spec, |
71 | const char *error_message_tag); |
72 | |
73 | #define GRN_DB_SPEC_EACH_BEGIN(ctx, cursor, id, spec) do { \ |
74 | grn_obj *db = grn_ctx_db((ctx)); \ |
75 | grn_db *db_raw = (grn_db *)db; \ |
76 | grn_obj decoded_spec; \ |
77 | grn_io_win iw; \ |
78 | grn_bool iw_need_unref = GRN_FALSE; \ |
79 | GRN_OBJ_INIT(&decoded_spec, GRN_VECTOR, 0, GRN_DB_TEXT); \ |
80 | GRN_TABLE_EACH_BEGIN((ctx), db, cursor, id) { \ |
81 | void *encoded_spec; \ |
82 | uint32_t encoded_spec_size; \ |
83 | grn_bool success; \ |
84 | grn_obj_spec *spec; \ |
85 | \ |
86 | if (iw_need_unref) { \ |
87 | grn_ja_unref(ctx, &iw); \ |
88 | iw_need_unref = GRN_FALSE; \ |
89 | } \ |
90 | encoded_spec = grn_ja_ref((ctx), \ |
91 | db_raw->specs, \ |
92 | id, \ |
93 | &iw, \ |
94 | &encoded_spec_size); \ |
95 | if (!encoded_spec) { \ |
96 | continue; \ |
97 | } \ |
98 | iw_need_unref = GRN_TRUE; \ |
99 | \ |
100 | GRN_BULK_REWIND(&decoded_spec); \ |
101 | success = grn_db_spec_unpack(ctx, \ |
102 | id, \ |
103 | encoded_spec, \ |
104 | encoded_spec_size, \ |
105 | &spec, \ |
106 | &decoded_spec, \ |
107 | __FUNCTION__); \ |
108 | if (!success) { \ |
109 | continue; \ |
110 | } \ |
111 | |
112 | #define GRN_DB_SPEC_EACH_END(ctx, cursor) \ |
113 | } GRN_TABLE_EACH_END(ctx, cursor); \ |
114 | if (iw_need_unref) { \ |
115 | grn_ja_unref(ctx, &iw); \ |
116 | } \ |
117 | GRN_OBJ_FIN((ctx), &decoded_spec); \ |
118 | } while(GRN_FALSE) |
119 | |
120 | void grn_db_init_from_env(void); |
121 | |
122 | GRN_API grn_rc grn_db_close(grn_ctx *ctx, grn_obj *db); |
123 | |
124 | grn_obj *grn_db_keys(grn_obj *s); |
125 | |
126 | void grn_db_generate_pathname(grn_ctx *ctx, |
127 | grn_obj *db, |
128 | grn_id id, |
129 | char *buffer); |
130 | |
131 | grn_rc _grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, |
132 | grn_table_delete_optarg *optarg); |
133 | |
134 | grn_id grn_table_get_v(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, |
135 | void **value); |
136 | grn_id grn_table_add_v(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, |
137 | void **value, int *added); |
138 | grn_id grn_table_add_by_key(grn_ctx *ctx, |
139 | grn_obj *table, |
140 | grn_obj *key, |
141 | int *added); |
142 | GRN_API grn_rc grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_table_flags *flags, |
143 | grn_encoding *encoding, grn_obj **tokenizer, |
144 | grn_obj **normalizer, |
145 | grn_obj **token_filters); |
146 | const char *_grn_table_key(grn_ctx *ctx, grn_obj *table, grn_id id, uint32_t *key_size); |
147 | |
148 | grn_rc grn_table_search(grn_ctx *ctx, grn_obj *table, |
149 | const void *key, uint32_t key_size, |
150 | grn_operator mode, grn_obj *res, grn_operator op); |
151 | |
152 | grn_rc grn_table_fuzzy_search(grn_ctx *ctx, grn_obj *table, |
153 | const void *key, uint32_t key_size, |
154 | grn_fuzzy_search_optarg *args, grn_obj *res, grn_operator op); |
155 | |
156 | grn_id grn_table_next(grn_ctx *ctx, grn_obj *table, grn_id id); |
157 | |
158 | int grn_table_get_key2(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *bulk); |
159 | |
160 | grn_table_cursor *grn_table_cursor_open_by_id(grn_ctx *ctx, grn_obj *table, |
161 | grn_id min, grn_id max, int flags); |
162 | |
163 | void grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, double score, |
164 | grn_rset_posinfo *pi, int dir); |
165 | |
166 | grn_obj *grn_obj_graft(grn_ctx *ctx, grn_obj *obj); |
167 | |
168 | grn_rc grn_column_name_(grn_ctx *ctx, grn_obj *obj, grn_obj *buf); |
169 | |
170 | |
171 | typedef enum { |
172 | PROC_INIT = 0, |
173 | PROC_NEXT, |
174 | PROC_FIN |
175 | } grn_proc_phase; |
176 | |
177 | struct _grn_type { |
178 | grn_db_obj obj; |
179 | }; |
180 | |
181 | #define GRN_TYPE_SIZE(type) ((type)->range) |
182 | |
183 | #define GRN_TABLE_SORT_GEO (0x02<<0) |
184 | |
185 | #define GRN_OBJ_TMP_OBJECT 0x80000000 |
186 | #define GRN_OBJ_TMP_COLUMN 0x40000000 |
187 | |
188 | #define GRN_DB_OBJP(obj) \ |
189 | (obj &&\ |
190 | ((GRN_SNIP == ((grn_db_obj *)obj)->header.type) ||\ |
191 | ((GRN_CURSOR_TABLE_HASH_KEY <= ((grn_db_obj *)obj)->header.type) &&\ |
192 | (((grn_db_obj *)obj)->header.type <= GRN_COLUMN_INDEX)))) |
193 | |
194 | #define GRN_OBJ_TABLEP(obj) \ |
195 | (obj &&\ |
196 | (GRN_TABLE_HASH_KEY <= ((grn_db_obj *)obj)->header.type) &&\ |
197 | (((grn_db_obj *)obj)->header.type <= GRN_DB)) |
198 | |
199 | #define GRN_OBJ_INDEX_COLUMNP(obj) \ |
200 | (obj &&\ |
201 | DB_OBJ(obj)->header.type == GRN_COLUMN_INDEX) |
202 | |
203 | #define GRN_OBJ_VECTOR_COLUMNP(obj) \ |
204 | (obj &&\ |
205 | DB_OBJ(obj)->header.type == GRN_COLUMN_VAR_SIZE &&\ |
206 | (DB_OBJ(obj)->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) |
207 | |
208 | #define GRN_OBJ_WEIGHT_VECTOR_COLUMNP(obj) \ |
209 | (GRN_OBJ_VECTOR_COLUMNP(obj) &&\ |
210 | (DB_OBJ(obj)->header.flags & GRN_OBJ_WITH_WEIGHT)) |
211 | |
212 | struct _grn_hook { |
213 | grn_hook *next; |
214 | grn_proc *proc; |
215 | uint32_t hld_size; |
216 | }; |
217 | |
218 | typedef struct _grn_proc_ctx grn_proc_ctx; |
219 | |
220 | struct _grn_proc_ctx { |
221 | grn_user_data user_data; |
222 | grn_proc *proc; |
223 | grn_obj *caller; |
224 | // grn_obj *obj; |
225 | grn_hook *hooks; |
226 | grn_hook *currh; |
227 | grn_proc_phase phase; |
228 | unsigned short nargs; |
229 | unsigned short offset; |
230 | grn_user_data data[16]; |
231 | }; |
232 | |
233 | struct _grn_proc { |
234 | grn_db_obj obj; |
235 | grn_obj name_buf; |
236 | grn_expr_var *vars; |
237 | uint32_t nvars; |
238 | /* -- compatible with grn_expr -- */ |
239 | grn_proc_type type; |
240 | grn_proc_func *funcs[3]; |
241 | |
242 | union { |
243 | struct { |
244 | grn_selector_func *selector; |
245 | grn_operator selector_op; |
246 | grn_bool is_stable; |
247 | } function; |
248 | struct { |
249 | grn_command_run_func *run; |
250 | } command; |
251 | struct { |
252 | grn_token_filter_init_func *init; |
253 | grn_token_filter_filter_func *filter; |
254 | grn_token_filter_fin_func *fin; |
255 | } token_filter; |
256 | struct { |
257 | grn_scorer_score_func *score; |
258 | } scorer; |
259 | grn_window_function_func *window_function; |
260 | } callbacks; |
261 | |
262 | void *user_data; |
263 | |
264 | grn_id module; |
265 | // uint32_t nargs; |
266 | // uint32_t nresults; |
267 | // grn_obj results[16]; |
268 | }; |
269 | |
270 | #define GRN_PROC_GET_VARS() (grn_proc_get_vars(ctx, user_data)) |
271 | #define GRN_PROC_GET_VAR(name) (grn_proc_get_var(ctx, user_data, name, strlen(name))) |
272 | #define GRN_PROC_GET_VAR_BY_OFFSET(offset) (grn_proc_get_var_by_offset(ctx, user_data, offset)) |
273 | #define GRN_PROC_GET_OR_ADD_VAR(name) (grn_proc_get_or_add_var(ctx, user_data, name, strlen(name))) |
274 | #define GRN_PROC_ALLOC(domain, flags) (grn_proc_alloc(ctx, user_data, domain, flags)) |
275 | |
276 | grn_obj *grn_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data); |
277 | |
278 | grn_obj *grn_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, |
279 | const char *name, unsigned int name_size); |
280 | |
281 | GRN_API grn_obj *grn_proc_get_var_by_offset(grn_ctx *ctx, grn_user_data *user_data, |
282 | unsigned int offset); |
283 | GRN_API grn_obj *grn_proc_get_or_add_var(grn_ctx *ctx, grn_user_data *user_data, |
284 | const char *name, unsigned int name_size); |
285 | |
286 | GRN_API grn_obj *grn_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, |
287 | grn_id domain, unsigned char flags); |
288 | |
289 | GRN_API grn_rc grn_proc_call(grn_ctx *ctx, grn_obj *proc, |
290 | int nargs, grn_obj *caller); |
291 | |
292 | grn_obj *grn_expr_get_or_add_var(grn_ctx *ctx, grn_obj *expr, |
293 | const char *name, unsigned int name_size); |
294 | |
295 | |
296 | typedef struct _grn_accessor grn_accessor; |
297 | |
298 | struct _grn_accessor { |
299 | grn_obj_header ; |
300 | grn_id range; |
301 | /* -- compatible with grn_db_obj -- */ |
302 | uint8_t action; |
303 | int offset; |
304 | grn_obj *obj; |
305 | grn_accessor *next; |
306 | }; |
307 | |
308 | enum { |
309 | GRN_ACCESSOR_VOID = 0, |
310 | GRN_ACCESSOR_GET_ID, |
311 | GRN_ACCESSOR_GET_KEY, |
312 | GRN_ACCESSOR_GET_VALUE, |
313 | GRN_ACCESSOR_GET_SCORE, |
314 | GRN_ACCESSOR_GET_NSUBRECS, |
315 | GRN_ACCESSOR_GET_MAX, |
316 | GRN_ACCESSOR_GET_MIN, |
317 | GRN_ACCESSOR_GET_SUM, |
318 | GRN_ACCESSOR_GET_AVG, |
319 | GRN_ACCESSOR_GET_COLUMN_VALUE, |
320 | GRN_ACCESSOR_GET_DB_OBJ, |
321 | GRN_ACCESSOR_LOOKUP, |
322 | GRN_ACCESSOR_FUNCALL |
323 | }; |
324 | |
325 | #define DB_OBJ(obj) ((grn_db_obj *)obj) |
326 | |
327 | GRN_API const char *grn_obj_get_value_(grn_ctx *ctx, grn_obj *obj, grn_id id, uint32_t *size); |
328 | |
329 | /* vector */ |
330 | |
331 | /* |
332 | typedef struct _grn_vector grn_vector; |
333 | |
334 | struct _grn_vector { |
335 | grn_obj str; |
336 | uint32_t *offsets; |
337 | int n_entries; |
338 | }; |
339 | |
340 | const char *grn_vector_fetch(grn_ctx *ctx, grn_obj *vector, int i, unsigned int *size); |
341 | int grn_vector_delimit(grn_ctx *ctx, grn_obj *vector); |
342 | int grn_vector_size(grn_ctx *ctx, grn_obj *vector); |
343 | */ |
344 | |
345 | grn_rc grn_vector_delimit(grn_ctx *ctx, grn_obj *v, unsigned int weight, grn_id domain); |
346 | grn_rc grn_vector_decode(grn_ctx *ctx, grn_obj *v, const char *data, uint32_t data_size); |
347 | |
348 | |
349 | grn_rc grn_db_init_builtin_types(grn_ctx *ctx); |
350 | |
351 | /* flag value used for grn_obj.header.flags */ |
352 | |
353 | #define GRN_OBJ_CUSTOM_NAME (0x01<<12) /* db_obj which has custom name */ |
354 | |
355 | #define GRN_OBJ_RESOLVE(ctx,obj) \ |
356 | (((obj)->header.type != GRN_PTR)\ |
357 | ? (obj)\ |
358 | : GRN_PTR_VALUE(obj)\ |
359 | ? GRN_PTR_VALUE(obj)\ |
360 | : grn_ctx_at((ctx), (obj)->header.domain)) |
361 | |
362 | /* expr */ |
363 | |
364 | typedef struct _grn_expr grn_expr; |
365 | |
366 | #define GRN_EXPR_CODE_RELATIONAL_EXPRESSION (0x01) |
367 | |
368 | typedef struct { |
369 | grn_obj *value; |
370 | int32_t nargs; |
371 | grn_operator op; |
372 | uint8_t flags; |
373 | int32_t modify; |
374 | } grn_expr_code; |
375 | |
376 | #define GRN_EXPR_CONST_BLK_SIZE GRN_STACK_SIZE |
377 | |
378 | struct _grn_expr { |
379 | grn_db_obj obj; |
380 | grn_obj name_buf; |
381 | grn_expr_var *vars; |
382 | uint32_t nvars; |
383 | /* -- compatible with grn_proc -- */ |
384 | |
385 | uint16_t cacheable; |
386 | uint16_t taintable; |
387 | grn_obj **const_blks; |
388 | grn_obj *values; |
389 | grn_expr_code *codes; |
390 | uint32_t nconsts; |
391 | uint32_t values_curr; |
392 | uint32_t values_tail; |
393 | uint32_t values_size; |
394 | uint32_t codes_curr; |
395 | uint32_t codes_size; |
396 | |
397 | grn_obj objs; |
398 | grn_obj dfi; |
399 | grn_expr_code *code0; |
400 | }; |
401 | |
402 | grn_rc grn_expr_parser_close(grn_ctx *ctx); |
403 | |
404 | /** |
405 | * grn_table_open: |
406 | * @name: The table name to be opened. `NULL` means anonymous table. |
407 | * @path: The path of the table to be opened. |
408 | * |
409 | * Opens an existing table. The table is associated with @name in DB |
410 | * that is used by @ctx. grn_ctx_get() is better rather than this |
411 | * function when you want to open a permanent named table that is |
412 | * registered in DB. |
413 | **/ |
414 | GRN_API grn_obj *grn_table_open(grn_ctx *ctx, |
415 | const char *name, unsigned int name_size, |
416 | const char *path); |
417 | |
418 | /** |
419 | * grn_column_open: |
420 | * @table: The table for the opened column. |
421 | * @name: The column name to be opened. |
422 | * @path: The path of the column to be opened. |
423 | * @type: The type of the column value. |
424 | * |
425 | * Opens an existing permanent column. The column is associated with |
426 | * @name in @table. grn_ctx_get() is better rather than this function |
427 | * when you want to open a column of an permanent table in DB. |
428 | **/ |
429 | grn_obj *grn_column_open(grn_ctx *ctx, grn_obj *table, |
430 | const char *name, unsigned int name_size, |
431 | const char *path, grn_obj *type); |
432 | |
433 | /** |
434 | * grn_obj_path_rename: |
435 | * @old_path: The current file path. |
436 | * @new_path: The new file path. |
437 | * |
438 | * It renames object's path that is stored in @old_path to @new_path. |
439 | **/ |
440 | grn_rc grn_obj_path_rename(grn_ctx *ctx, const char *old_path, const char *new_path); |
441 | |
442 | grn_rc grn_db_check_name(grn_ctx *ctx, const char *name, unsigned int name_size); |
443 | #define GRN_DB_CHECK_NAME_ERR(error_context, name, name_size) \ |
444 | ERR(GRN_INVALID_ARGUMENT,\ |
445 | "%s name can't start with '%c' and contains only 0-9, A-Z, a-z, #, @, - or _: <%.*s>",\ |
446 | error_context, GRN_DB_PSEUDO_COLUMN_PREFIX, name_size, name) |
447 | |
448 | #define GRN_DB_P(s) ((s) && ((grn_db *)s)->obj.header.type == GRN_DB) |
449 | #define GRN_DB_PERSISTENT_P(s) (((grn_db *)s)->specs) |
450 | |
451 | #define GRN_OBJ_GET_VALUE_IMD (0xffffffffU) |
452 | |
453 | grn_rc grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj); |
454 | |
455 | #define GRN_ACCESSORP(obj) \ |
456 | ((obj) && (((grn_obj *)(obj))->header.type == GRN_ACCESSOR)) |
457 | |
458 | grn_id grn_obj_register(grn_ctx *ctx, grn_obj *db, const char *name, unsigned int name_size); |
459 | int grn_obj_is_persistent(grn_ctx *ctx, grn_obj *obj); |
460 | void grn_obj_spec_save(grn_ctx *ctx, grn_db_obj *obj); |
461 | |
462 | grn_rc grn_obj_reinit_for(grn_ctx *ctx, grn_obj *obj, grn_obj *domain_obj); |
463 | |
464 | void grn_expr_pack(grn_ctx *ctx, grn_obj *buf, grn_obj *expr); |
465 | GRN_API grn_rc grn_expr_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *expr); |
466 | grn_hash *grn_expr_get_vars(grn_ctx *ctx, grn_obj *expr, unsigned int *nvars); |
467 | grn_obj *grn_expr_open(grn_ctx *ctx, grn_obj_spec *spec, const uint8_t *p, const uint8_t *pe); |
468 | |
469 | GRN_API grn_rc grn_table_group_with_range_gap(grn_ctx *ctx, grn_obj *table, |
470 | grn_table_sort_key *group_key, |
471 | grn_obj *result_set, |
472 | uint32_t range_gap); |
473 | |
474 | GRN_API grn_rc grn_column_filter(grn_ctx *ctx, grn_obj *column, |
475 | grn_operator op, |
476 | grn_obj *value, grn_obj *result_set, |
477 | grn_operator set_op); |
478 | |
479 | typedef struct { |
480 | grn_id target; |
481 | unsigned int section; |
482 | } grn_obj_default_set_value_hook_data; |
483 | |
484 | grn_obj *grn_obj_default_set_value_hook(grn_ctx *ctx, |
485 | int nargs, |
486 | grn_obj **args, |
487 | grn_user_data *user_data); |
488 | |
489 | grn_rc grn_pvector_fin(grn_ctx *ctx, grn_obj *obj); |
490 | |
491 | #ifdef __cplusplus |
492 | } |
493 | #endif |
494 | |