1 | /* -*- c-basic-offset: 2 -*- */ |
2 | /* |
3 | Copyright(C) 2009-2017 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 | #include "grn.h" |
19 | #include "grn_config.h" |
20 | #include "grn_db.h" |
21 | #include "grn_obj.h" |
22 | #include "grn_hash.h" |
23 | #include "grn_pat.h" |
24 | #include "grn_dat.h" |
25 | #include "grn_ii.h" |
26 | #include "grn_index_column.h" |
27 | #include "grn_ctx_impl.h" |
28 | #include "grn_token_cursor.h" |
29 | #include "grn_tokenizers.h" |
30 | #include "grn_proc.h" |
31 | #include "grn_plugin.h" |
32 | #include "grn_geo.h" |
33 | #include "grn_scorers.h" |
34 | #include "grn_snip.h" |
35 | #include "grn_string.h" |
36 | #include "grn_normalizer.h" |
37 | #include "grn_report.h" |
38 | #include "grn_util.h" |
39 | #include "grn_cache.h" |
40 | #include "grn_window_functions.h" |
41 | #include <string.h> |
42 | #include <math.h> |
43 | |
44 | typedef struct { |
45 | grn_id id; |
46 | unsigned int weight; |
47 | } weight_uvector_entry; |
48 | |
49 | #define IS_WEIGHT_UVECTOR(obj) ((obj)->header.flags & GRN_OBJ_WITH_WEIGHT) |
50 | |
51 | #define GRN_TABLE_GROUPED (0x01<<0) |
52 | #define GRN_TABLE_IS_GROUPED(table)\ |
53 | ((table)->header.impl_flags & GRN_TABLE_GROUPED) |
54 | #define GRN_TABLE_GROUPED_ON(table)\ |
55 | ((table)->header.impl_flags |= GRN_TABLE_GROUPED) |
56 | #define GRN_TABLE_IS_MULTI_KEYS_GROUPED(table)\ |
57 | (GRN_TABLE_IS_GROUPED(table) &&\ |
58 | table->header.domain == GRN_ID_NIL) |
59 | |
60 | #define WITH_NORMALIZE(table,key,key_size,block) do {\ |
61 | if ((table)->normalizer && key && key_size > 0) {\ |
62 | grn_obj *nstr;\ |
63 | if ((nstr = grn_string_open(ctx, key, key_size,\ |
64 | (table)->normalizer, 0))) {\ |
65 | const char *key;\ |
66 | unsigned int key_size;\ |
67 | grn_string_get_normalized(ctx, nstr, &key, &key_size, NULL);\ |
68 | block\ |
69 | grn_obj_close(ctx, nstr);\ |
70 | }\ |
71 | } else {\ |
72 | block\ |
73 | }\ |
74 | } while (0) |
75 | |
76 | inline static grn_id |
77 | grn_table_add_v_inline(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, |
78 | void **value, int *added); |
79 | inline static void |
80 | grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, double score, |
81 | grn_rset_posinfo *pi, int dir); |
82 | inline static grn_id |
83 | grn_table_cursor_next_inline(grn_ctx *ctx, grn_table_cursor *tc); |
84 | inline static int |
85 | grn_table_cursor_get_value_inline(grn_ctx *ctx, grn_table_cursor *tc, void **value); |
86 | |
87 | static void grn_obj_ensure_bulk(grn_ctx *ctx, grn_obj *obj); |
88 | static void grn_obj_ensure_vector(grn_ctx *ctx, grn_obj *obj); |
89 | |
90 | inline static void |
91 | grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj, |
92 | grn_id *range_id, grn_obj_flags *range_flags); |
93 | |
94 | static char grn_db_key[GRN_ENV_BUFFER_SIZE]; |
95 | |
96 | void |
97 | grn_db_init_from_env(void) |
98 | { |
99 | grn_getenv("GRN_DB_KEY" , |
100 | grn_db_key, |
101 | GRN_ENV_BUFFER_SIZE); |
102 | } |
103 | |
104 | inline static void |
105 | gen_pathname(const char *path, char *buffer, int fno) |
106 | { |
107 | size_t len = strlen(path); |
108 | grn_memcpy(buffer, path, len); |
109 | if (fno >= 0) { |
110 | buffer[len] = '.'; |
111 | grn_itoh(fno, buffer + len + 1, 7); |
112 | buffer[len + 8] = '\0'; |
113 | } else { |
114 | buffer[len] = '\0'; |
115 | } |
116 | } |
117 | |
118 | void |
119 | grn_db_generate_pathname(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer) |
120 | { |
121 | gen_pathname(grn_obj_get_io(ctx, db)->path, buffer, id); |
122 | } |
123 | |
124 | typedef struct { |
125 | grn_obj *ptr; |
126 | uint32_t lock; |
127 | uint32_t done; |
128 | } db_value; |
129 | |
130 | static const char *GRN_DB_CONFIG_PATH_FORMAT = "%s.conf" ; |
131 | |
132 | static grn_bool |
133 | grn_db_config_create(grn_ctx *ctx, grn_db *s, const char *path, |
134 | const char *context_tag) |
135 | { |
136 | char *config_path; |
137 | char config_path_buffer[PATH_MAX]; |
138 | uint32_t flags = GRN_OBJ_KEY_VAR_SIZE; |
139 | |
140 | if (path) { |
141 | grn_snprintf(config_path_buffer, PATH_MAX, PATH_MAX, |
142 | GRN_DB_CONFIG_PATH_FORMAT, path); |
143 | config_path = config_path_buffer; |
144 | } else { |
145 | config_path = NULL; |
146 | } |
147 | s->config = grn_hash_create(ctx, config_path, |
148 | GRN_CONFIG_MAX_KEY_SIZE, |
149 | GRN_CONFIG_VALUE_SPACE_SIZE, |
150 | flags); |
151 | if (!s->config) { |
152 | ERR(GRN_NO_MEMORY_AVAILABLE, |
153 | "%s failed to create data store for configuration: <%s>" , |
154 | context_tag, |
155 | config_path ? config_path : "(temporary)" ); |
156 | return GRN_FALSE; |
157 | } |
158 | |
159 | return GRN_TRUE; |
160 | } |
161 | |
162 | static grn_bool |
163 | grn_db_config_open(grn_ctx *ctx, grn_db *s, const char *path) |
164 | { |
165 | char config_path[PATH_MAX]; |
166 | |
167 | grn_snprintf(config_path, PATH_MAX, PATH_MAX, GRN_DB_CONFIG_PATH_FORMAT, path); |
168 | if (grn_path_exist(config_path)) { |
169 | s->config = grn_hash_open(ctx, config_path); |
170 | if (!s->config) { |
171 | ERR(GRN_NO_MEMORY_AVAILABLE, |
172 | "[db][open] failed to open data store for configuration: <%s>" , |
173 | config_path); |
174 | return GRN_FALSE; |
175 | } |
176 | return GRN_TRUE; |
177 | } else { |
178 | return grn_db_config_create(ctx, s, path, "[db][open]" ); |
179 | } |
180 | } |
181 | |
182 | static grn_rc |
183 | grn_db_config_remove(grn_ctx *ctx, const char *path) |
184 | { |
185 | char config_path[PATH_MAX]; |
186 | |
187 | grn_snprintf(config_path, PATH_MAX, PATH_MAX, GRN_DB_CONFIG_PATH_FORMAT, path); |
188 | return grn_hash_remove(ctx, config_path); |
189 | } |
190 | |
191 | grn_obj * |
192 | grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg) |
193 | { |
194 | grn_db *s = NULL; |
195 | |
196 | GRN_API_ENTER; |
197 | |
198 | if (path && strlen(path) > PATH_MAX - 14) { |
199 | ERR(GRN_INVALID_ARGUMENT, "too long path" ); |
200 | goto exit; |
201 | } |
202 | |
203 | s = GRN_MALLOC(sizeof(grn_db)); |
204 | if (!s) { |
205 | ERR(GRN_NO_MEMORY_AVAILABLE, "grn_db alloc failed" ); |
206 | goto exit; |
207 | } |
208 | |
209 | CRITICAL_SECTION_INIT(s->lock); |
210 | grn_tiny_array_init(ctx, &s->values, sizeof(db_value), |
211 | GRN_TINY_ARRAY_CLEAR| |
212 | GRN_TINY_ARRAY_THREADSAFE| |
213 | GRN_TINY_ARRAY_USE_MALLOC); |
214 | s->keys = NULL; |
215 | s->specs = NULL; |
216 | s->config = NULL; |
217 | |
218 | { |
219 | grn_bool use_default_db_key = GRN_TRUE; |
220 | grn_bool use_pat_as_db_keys = GRN_FALSE; |
221 | if (grn_db_key[0]) { |
222 | if (!strcmp(grn_db_key, "pat" )) { |
223 | use_default_db_key = GRN_FALSE; |
224 | use_pat_as_db_keys = GRN_TRUE; |
225 | } else if (!strcmp(grn_db_key, "dat" )) { |
226 | use_default_db_key = GRN_FALSE; |
227 | } |
228 | } |
229 | |
230 | if (use_default_db_key && !strcmp(GRN_DEFAULT_DB_KEY, "pat" )) { |
231 | use_pat_as_db_keys = GRN_TRUE; |
232 | } |
233 | if (use_pat_as_db_keys) { |
234 | s->keys = (grn_obj *)grn_pat_create(ctx, path, GRN_TABLE_MAX_KEY_SIZE, |
235 | 0, GRN_OBJ_KEY_VAR_SIZE); |
236 | } else { |
237 | s->keys = (grn_obj *)grn_dat_create(ctx, path, GRN_TABLE_MAX_KEY_SIZE, |
238 | 0, GRN_OBJ_KEY_VAR_SIZE); |
239 | } |
240 | } |
241 | |
242 | if (!s->keys) { |
243 | goto exit; |
244 | } |
245 | |
246 | GRN_DB_OBJ_SET_TYPE(s, GRN_DB); |
247 | s->obj.db = (grn_obj *)s; |
248 | s->obj.header.domain = GRN_ID_NIL; |
249 | DB_OBJ(&s->obj)->range = GRN_ID_NIL; |
250 | /* prepare builtin classes and load builtin plugins. */ |
251 | if (path) { |
252 | { |
253 | char specs_path[PATH_MAX]; |
254 | gen_pathname(path, specs_path, 0); |
255 | s->specs = grn_ja_create(ctx, specs_path, 65536, 0); |
256 | if (!s->specs) { |
257 | ERR(GRN_NO_MEMORY_AVAILABLE, |
258 | "failed to create specs: <%s>" , specs_path); |
259 | goto exit; |
260 | } |
261 | } |
262 | if (!grn_db_config_create(ctx, s, path, "[db][create]" )) { |
263 | goto exit; |
264 | } |
265 | grn_ctx_use(ctx, (grn_obj *)s); |
266 | grn_db_init_builtin_types(ctx); |
267 | grn_obj_flush(ctx, (grn_obj *)s); |
268 | GRN_API_RETURN((grn_obj *)s); |
269 | } else { |
270 | if (!grn_db_config_create(ctx, s, NULL, "[db][create]" )) { |
271 | goto exit; |
272 | } |
273 | grn_ctx_use(ctx, (grn_obj *)s); |
274 | grn_db_init_builtin_types(ctx); |
275 | GRN_API_RETURN((grn_obj *)s); |
276 | } |
277 | |
278 | exit: |
279 | if (s) { |
280 | if (s->keys) { |
281 | if (s->keys->header.type == GRN_TABLE_PAT_KEY) { |
282 | grn_pat_close(ctx, (grn_pat *)s->keys); |
283 | grn_pat_remove(ctx, path); |
284 | } else { |
285 | grn_dat_close(ctx, (grn_dat *)s->keys); |
286 | grn_dat_remove(ctx, path); |
287 | } |
288 | } |
289 | if (s->specs) { |
290 | const char *specs_path; |
291 | specs_path = grn_obj_path(ctx, (grn_obj *)(s->specs)); |
292 | grn_ja_close(ctx, s->specs); |
293 | grn_ja_remove(ctx, specs_path); |
294 | } |
295 | grn_tiny_array_fin(&s->values); |
296 | CRITICAL_SECTION_FIN(s->lock); |
297 | GRN_FREE(s); |
298 | } |
299 | |
300 | GRN_API_RETURN(NULL); |
301 | } |
302 | |
303 | grn_obj * |
304 | grn_db_open(grn_ctx *ctx, const char *path) |
305 | { |
306 | grn_db *s = NULL; |
307 | |
308 | GRN_API_ENTER; |
309 | |
310 | if (!path) { |
311 | ERR(GRN_INVALID_ARGUMENT, "[db][open] path is missing" ); |
312 | goto exit; |
313 | } |
314 | |
315 | if (strlen(path) > PATH_MAX - 14) { |
316 | ERR(GRN_INVALID_ARGUMENT, "inappropriate path" ); |
317 | goto exit; |
318 | } |
319 | |
320 | s = GRN_MALLOC(sizeof(grn_db)); |
321 | if (!s) { |
322 | ERR(GRN_NO_MEMORY_AVAILABLE, "grn_db alloc failed" ); |
323 | goto exit; |
324 | } |
325 | |
326 | CRITICAL_SECTION_INIT(s->lock); |
327 | grn_tiny_array_init(ctx, &s->values, sizeof(db_value), |
328 | GRN_TINY_ARRAY_CLEAR| |
329 | GRN_TINY_ARRAY_THREADSAFE| |
330 | GRN_TINY_ARRAY_USE_MALLOC); |
331 | s->keys = NULL; |
332 | s->specs = NULL; |
333 | s->config = NULL; |
334 | |
335 | { |
336 | uint32_t type = grn_io_detect_type(ctx, path); |
337 | switch (type) { |
338 | case GRN_TABLE_PAT_KEY : |
339 | s->keys = (grn_obj *)grn_pat_open(ctx, path); |
340 | break; |
341 | case GRN_TABLE_DAT_KEY : |
342 | s->keys = (grn_obj *)grn_dat_open(ctx, path); |
343 | break; |
344 | default : |
345 | s->keys = NULL; |
346 | if (ctx->rc == GRN_SUCCESS) { |
347 | ERR(GRN_INVALID_ARGUMENT, |
348 | "[db][open] invalid keys table's type: %#x" , type); |
349 | goto exit; |
350 | } |
351 | break; |
352 | } |
353 | } |
354 | |
355 | if (!s->keys) { |
356 | goto exit; |
357 | } |
358 | |
359 | { |
360 | char specs_path[PATH_MAX]; |
361 | gen_pathname(path, specs_path, 0); |
362 | s->specs = grn_ja_open(ctx, specs_path); |
363 | if (!s->specs) { |
364 | ERR(GRN_NO_MEMORY_AVAILABLE, |
365 | "[db][open] failed to open specs: <%s>" , specs_path); |
366 | goto exit; |
367 | } |
368 | } |
369 | if (!grn_db_config_open(ctx, s, path)) { |
370 | goto exit; |
371 | } |
372 | |
373 | GRN_DB_OBJ_SET_TYPE(s, GRN_DB); |
374 | s->obj.db = (grn_obj *)s; |
375 | s->obj.header.domain = GRN_ID_NIL; |
376 | DB_OBJ(&s->obj)->range = GRN_ID_NIL; |
377 | grn_ctx_use(ctx, (grn_obj *)s); |
378 | { |
379 | unsigned int n_records; |
380 | |
381 | n_records = grn_table_size(ctx, (grn_obj *)s); |
382 | #ifdef GRN_WITH_MECAB |
383 | if (grn_db_init_mecab_tokenizer(ctx)) { |
384 | ERRCLR(ctx); |
385 | } |
386 | #endif |
387 | grn_db_init_builtin_tokenizers(ctx); |
388 | grn_db_init_builtin_normalizers(ctx); |
389 | grn_db_init_builtin_scorers(ctx); |
390 | grn_db_init_builtin_commands(ctx); |
391 | grn_db_init_builtin_window_functions(ctx); |
392 | |
393 | if (grn_table_size(ctx, (grn_obj *)s) > n_records) { |
394 | grn_obj_flush(ctx, (grn_obj *)s); |
395 | } |
396 | } |
397 | GRN_API_RETURN((grn_obj *)s); |
398 | |
399 | exit: |
400 | if (s) { |
401 | if (s->specs) { |
402 | grn_ja_close(ctx, s->specs); |
403 | } |
404 | if (s->keys) { |
405 | if (s->keys->header.type == GRN_TABLE_PAT_KEY) { |
406 | grn_pat_close(ctx, (grn_pat *)s->keys); |
407 | } else { |
408 | grn_dat_close(ctx, (grn_dat *)s->keys); |
409 | } |
410 | } |
411 | grn_tiny_array_fin(&s->values); |
412 | CRITICAL_SECTION_FIN(s->lock); |
413 | GRN_FREE(s); |
414 | } |
415 | |
416 | GRN_API_RETURN(NULL); |
417 | } |
418 | |
419 | static grn_id |
420 | grn_db_curr_id(grn_ctx *ctx, grn_obj *db) |
421 | { |
422 | grn_id curr_id = GRN_ID_NIL; |
423 | grn_db *s = (grn_db *)db; |
424 | switch (s->keys->header.type) { |
425 | case GRN_TABLE_PAT_KEY : |
426 | curr_id = grn_pat_curr_id(ctx, (grn_pat *)s->keys); |
427 | break; |
428 | case GRN_TABLE_DAT_KEY : |
429 | curr_id = grn_dat_curr_id(ctx, (grn_dat *)s->keys); |
430 | break; |
431 | } |
432 | return curr_id; |
433 | } |
434 | |
435 | /* s must be validated by caller */ |
436 | grn_rc |
437 | grn_db_close(grn_ctx *ctx, grn_obj *db) |
438 | { |
439 | grn_id id; |
440 | db_value *vp; |
441 | grn_db *s = (grn_db *)db; |
442 | grn_bool ctx_used_db; |
443 | if (!s) { return GRN_INVALID_ARGUMENT; } |
444 | GRN_API_ENTER; |
445 | |
446 | ctx_used_db = ctx->impl && ctx->impl->db == db; |
447 | if (ctx_used_db) { |
448 | grn_ctx_loader_clear(ctx); |
449 | if (ctx->impl->parser) { |
450 | grn_expr_parser_close(ctx); |
451 | } |
452 | } |
453 | |
454 | GRN_TINY_ARRAY_EACH(&s->values, 1, grn_db_curr_id(ctx, db), id, vp, { |
455 | if (vp->ptr) { grn_obj_close(ctx, vp->ptr); } |
456 | }); |
457 | |
458 | if (ctx_used_db) { |
459 | if (ctx->impl->values) { |
460 | grn_db_obj *o; |
461 | GRN_ARRAY_EACH(ctx, ctx->impl->values, 0, 0, id, &o, { |
462 | grn_obj_close(ctx, *((grn_obj **)o)); |
463 | }); |
464 | grn_array_truncate(ctx, ctx->impl->values); |
465 | } |
466 | } |
467 | |
468 | /* grn_tiny_array_fin should be refined.. */ |
469 | #ifdef WIN32 |
470 | { |
471 | grn_tiny_array *a = &s->values; |
472 | CRITICAL_SECTION_FIN(a->lock); |
473 | } |
474 | #endif |
475 | grn_tiny_array_fin(&s->values); |
476 | |
477 | switch (s->keys->header.type) { |
478 | case GRN_TABLE_PAT_KEY : |
479 | grn_pat_close(ctx, (grn_pat *)s->keys); |
480 | break; |
481 | case GRN_TABLE_DAT_KEY : |
482 | grn_dat_close(ctx, (grn_dat *)s->keys); |
483 | break; |
484 | } |
485 | CRITICAL_SECTION_FIN(s->lock); |
486 | if (s->specs) { grn_ja_close(ctx, s->specs); } |
487 | grn_hash_close(ctx, s->config); |
488 | GRN_FREE(s); |
489 | |
490 | if (ctx_used_db) { |
491 | grn_cache *cache; |
492 | cache = grn_cache_current_get(ctx); |
493 | if (cache) { |
494 | grn_cache_expire(cache, -1); |
495 | } |
496 | ctx->impl->db = NULL; |
497 | } |
498 | |
499 | GRN_API_RETURN(GRN_SUCCESS); |
500 | } |
501 | |
502 | grn_obj * |
503 | grn_ctx_get(grn_ctx *ctx, const char *name, int name_size) |
504 | { |
505 | grn_obj *obj = NULL; |
506 | grn_obj *db; |
507 | if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { |
508 | return NULL; |
509 | } |
510 | GRN_API_ENTER; |
511 | if (GRN_DB_P(db)) { |
512 | grn_db *s = (grn_db *)db; |
513 | grn_obj *alias_table = NULL; |
514 | grn_obj *alias_column = NULL; |
515 | grn_obj alias_name_buffer; |
516 | |
517 | if (name_size < 0) { |
518 | name_size = strlen(name); |
519 | } |
520 | GRN_TEXT_INIT(&alias_name_buffer, 0); |
521 | while (GRN_TRUE) { |
522 | grn_id id; |
523 | |
524 | id = grn_table_get(ctx, s->keys, name, name_size); |
525 | if (id) { |
526 | obj = grn_ctx_at(ctx, id); |
527 | break; |
528 | } |
529 | |
530 | if (!alias_column) { |
531 | grn_id alias_column_id; |
532 | const char *alias_column_name; |
533 | uint32_t alias_column_name_size; |
534 | |
535 | grn_config_get(ctx, |
536 | "alias.column" , -1, |
537 | &alias_column_name, &alias_column_name_size); |
538 | if (!alias_column_name) { |
539 | break; |
540 | } |
541 | alias_column_id = grn_table_get(ctx, |
542 | s->keys, |
543 | alias_column_name, |
544 | alias_column_name_size); |
545 | if (!alias_column_id) { |
546 | break; |
547 | } |
548 | alias_column = grn_ctx_at(ctx, alias_column_id); |
549 | if (alias_column->header.type != GRN_COLUMN_VAR_SIZE) { |
550 | break; |
551 | } |
552 | if (alias_column->header.flags & GRN_OBJ_VECTOR) { |
553 | break; |
554 | } |
555 | if (DB_OBJ(alias_column)->range != GRN_DB_SHORT_TEXT) { |
556 | break; |
557 | } |
558 | alias_table = grn_ctx_at(ctx, alias_column->header.domain); |
559 | if (alias_table->header.type == GRN_TABLE_NO_KEY) { |
560 | break; |
561 | } |
562 | } |
563 | |
564 | { |
565 | grn_id alias_id; |
566 | alias_id = grn_table_get(ctx, alias_table, name, name_size); |
567 | if (!alias_id) { |
568 | break; |
569 | } |
570 | GRN_BULK_REWIND(&alias_name_buffer); |
571 | grn_obj_get_value(ctx, alias_column, alias_id, &alias_name_buffer); |
572 | name = GRN_TEXT_VALUE(&alias_name_buffer); |
573 | name_size = GRN_TEXT_LEN(&alias_name_buffer); |
574 | } |
575 | } |
576 | GRN_OBJ_FIN(ctx, &alias_name_buffer); |
577 | } |
578 | GRN_API_RETURN(obj); |
579 | } |
580 | |
581 | grn_obj * |
582 | grn_ctx_db(grn_ctx *ctx) |
583 | { |
584 | return (ctx && ctx->impl) ? ctx->impl->db : NULL; |
585 | } |
586 | |
587 | grn_obj * |
588 | grn_db_keys(grn_obj *s) |
589 | { |
590 | return (grn_obj *)(((grn_db *)s)->keys); |
591 | } |
592 | |
593 | uint32_t |
594 | grn_obj_get_last_modified(grn_ctx *ctx, grn_obj *obj) |
595 | { |
596 | if (!obj) { |
597 | return 0; |
598 | } |
599 | |
600 | return grn_obj_get_io(ctx, obj)->header->last_modified; |
601 | } |
602 | |
603 | grn_bool |
604 | grn_obj_is_dirty(grn_ctx *ctx, grn_obj *obj) |
605 | { |
606 | if (!obj) { |
607 | return GRN_FALSE; |
608 | } |
609 | |
610 | switch (obj->header.type) { |
611 | case GRN_DB : |
612 | return grn_db_is_dirty(ctx, obj); |
613 | case GRN_TABLE_PAT_KEY : |
614 | return grn_pat_is_dirty(ctx, (grn_pat *)obj); |
615 | case GRN_TABLE_DAT_KEY : |
616 | return grn_dat_is_dirty(ctx, (grn_dat *)obj); |
617 | default : |
618 | return GRN_FALSE; |
619 | } |
620 | } |
621 | |
622 | uint32_t |
623 | grn_db_get_last_modified(grn_ctx *ctx, grn_obj *db) |
624 | { |
625 | return grn_obj_get_last_modified(ctx, db); |
626 | } |
627 | |
628 | grn_bool |
629 | grn_db_is_dirty(grn_ctx *ctx, grn_obj *db) |
630 | { |
631 | grn_obj *keys; |
632 | |
633 | if (!db) { |
634 | return GRN_FALSE; |
635 | } |
636 | |
637 | keys = ((grn_db *)db)->keys; |
638 | return grn_obj_is_dirty(ctx, keys); |
639 | } |
640 | |
641 | static grn_rc |
642 | grn_db_dirty(grn_ctx *ctx, grn_obj *db) |
643 | { |
644 | grn_obj *keys; |
645 | |
646 | if (!db) { |
647 | return GRN_SUCCESS; |
648 | } |
649 | |
650 | keys = ((grn_db *)db)->keys; |
651 | switch (keys->header.type) { |
652 | case GRN_TABLE_PAT_KEY : |
653 | return grn_pat_dirty(ctx, (grn_pat *)keys); |
654 | case GRN_TABLE_DAT_KEY : |
655 | return grn_dat_dirty(ctx, (grn_dat *)keys); |
656 | default : |
657 | return GRN_SUCCESS; |
658 | } |
659 | } |
660 | |
661 | static grn_rc |
662 | grn_db_clean(grn_ctx *ctx, grn_obj *db) |
663 | { |
664 | grn_obj *keys; |
665 | |
666 | if (!db) { |
667 | return GRN_SUCCESS; |
668 | } |
669 | |
670 | keys = ((grn_db *)db)->keys; |
671 | switch (keys->header.type) { |
672 | case GRN_TABLE_PAT_KEY : |
673 | return grn_pat_clean(ctx, (grn_pat *)keys); |
674 | case GRN_TABLE_DAT_KEY : |
675 | return grn_dat_clean(ctx, (grn_dat *)keys); |
676 | default : |
677 | return GRN_SUCCESS; |
678 | } |
679 | } |
680 | |
681 | static grn_rc |
682 | grn_db_clear_dirty(grn_ctx *ctx, grn_obj *db) |
683 | { |
684 | grn_obj *keys; |
685 | |
686 | if (!db) { |
687 | return GRN_SUCCESS; |
688 | } |
689 | |
690 | keys = ((grn_db *)db)->keys; |
691 | switch (keys->header.type) { |
692 | case GRN_TABLE_PAT_KEY : |
693 | return grn_pat_clear_dirty(ctx, (grn_pat *)keys); |
694 | case GRN_TABLE_DAT_KEY : |
695 | return grn_dat_clear_dirty(ctx, (grn_dat *)keys); |
696 | default : |
697 | return GRN_SUCCESS; |
698 | } |
699 | } |
700 | |
701 | void |
702 | grn_db_touch(grn_ctx *ctx, grn_obj *s) |
703 | { |
704 | grn_obj_touch(ctx, s, NULL); |
705 | } |
706 | |
707 | grn_bool |
708 | grn_obj_is_corrupt(grn_ctx *ctx, grn_obj *obj) |
709 | { |
710 | grn_bool is_corrupt = GRN_FALSE; |
711 | |
712 | GRN_API_ENTER; |
713 | |
714 | if (!obj) { |
715 | ERR(GRN_INVALID_ARGUMENT, "[object][corrupt] object must not be NULL" ); |
716 | GRN_API_RETURN(GRN_FALSE); |
717 | } |
718 | |
719 | switch (obj->header.type) { |
720 | case GRN_DB : |
721 | is_corrupt = grn_io_is_corrupt(ctx, grn_obj_get_io(ctx, obj)); |
722 | if (!is_corrupt) { |
723 | is_corrupt = grn_io_is_corrupt(ctx, ((grn_db *)obj)->specs->io); |
724 | } |
725 | if (!is_corrupt) { |
726 | is_corrupt = grn_io_is_corrupt(ctx, ((grn_db *)obj)->config->io); |
727 | } |
728 | break; |
729 | case GRN_TABLE_HASH_KEY : |
730 | case GRN_TABLE_PAT_KEY : |
731 | is_corrupt = grn_io_is_corrupt(ctx, grn_obj_get_io(ctx, obj)); |
732 | break; |
733 | case GRN_TABLE_DAT_KEY : |
734 | is_corrupt = grn_dat_is_corrupt(ctx, (grn_dat *)obj); |
735 | break; |
736 | case GRN_COLUMN_FIX_SIZE : |
737 | case GRN_COLUMN_VAR_SIZE : |
738 | is_corrupt = grn_io_is_corrupt(ctx, grn_obj_get_io(ctx, obj)); |
739 | break; |
740 | case GRN_COLUMN_INDEX : |
741 | is_corrupt = grn_io_is_corrupt(ctx, ((grn_ii *)obj)->seg); |
742 | if (!is_corrupt) { |
743 | is_corrupt = grn_io_is_corrupt(ctx, ((grn_ii *)obj)->chunk); |
744 | } |
745 | break; |
746 | default : |
747 | break; |
748 | } |
749 | |
750 | GRN_API_RETURN(is_corrupt); |
751 | } |
752 | |
753 | #define IS_TEMP(obj) (DB_OBJ(obj)->id & GRN_OBJ_TMP_OBJECT) |
754 | |
755 | static inline void |
756 | grn_obj_touch_db(grn_ctx *ctx, grn_obj *obj, grn_timeval *tv) |
757 | { |
758 | grn_obj_get_io(ctx, obj)->header->last_modified = tv->tv_sec; |
759 | grn_db_dirty(ctx, obj); |
760 | } |
761 | |
762 | void |
763 | grn_obj_touch(grn_ctx *ctx, grn_obj *obj, grn_timeval *tv) |
764 | { |
765 | grn_timeval tv_; |
766 | if (!tv) { |
767 | grn_timeval_now(ctx, &tv_); |
768 | tv = &tv_; |
769 | } |
770 | if (obj) { |
771 | switch (obj->header.type) { |
772 | case GRN_DB : |
773 | grn_obj_touch_db(ctx, obj, tv); |
774 | break; |
775 | case GRN_TABLE_HASH_KEY : |
776 | case GRN_TABLE_PAT_KEY : |
777 | case GRN_TABLE_DAT_KEY : |
778 | case GRN_TABLE_NO_KEY : |
779 | case GRN_COLUMN_VAR_SIZE : |
780 | case GRN_COLUMN_FIX_SIZE : |
781 | case GRN_COLUMN_INDEX : |
782 | if (!IS_TEMP(obj)) { |
783 | grn_obj_get_io(ctx, obj)->header->last_modified = tv->tv_sec; |
784 | grn_obj_touch(ctx, DB_OBJ(obj)->db, tv); |
785 | } |
786 | break; |
787 | } |
788 | } |
789 | } |
790 | |
791 | grn_rc |
792 | grn_db_check_name(grn_ctx *ctx, const char *name, unsigned int name_size) |
793 | { |
794 | int len; |
795 | const char *name_end = name + name_size; |
796 | if (name_size > 0 && |
797 | *name == GRN_DB_PSEUDO_COLUMN_PREFIX) { |
798 | return GRN_INVALID_ARGUMENT; |
799 | } |
800 | while (name < name_end) { |
801 | char c = *name; |
802 | if ((unsigned int)((c | 0x20) - 'a') >= 26u && |
803 | (unsigned int)(c - '0') >= 10u && |
804 | c != '_' && |
805 | c != '-' && |
806 | c != '#' && |
807 | c != '@') { |
808 | return GRN_INVALID_ARGUMENT; |
809 | } |
810 | if (!(len = grn_charlen(ctx, name, name_end))) { break; } |
811 | name += len; |
812 | } |
813 | return GRN_SUCCESS; |
814 | } |
815 | |
816 | static grn_obj * |
817 | grn_type_open(grn_ctx *ctx, grn_obj_spec *spec) |
818 | { |
819 | struct _grn_type *res; |
820 | res = GRN_MALLOC(sizeof(struct _grn_type)); |
821 | if (res) { |
822 | GRN_DB_OBJ_SET_TYPE(res, GRN_TYPE); |
823 | res->obj.header = spec->header; |
824 | GRN_TYPE_SIZE(&res->obj) = GRN_TYPE_SIZE(spec); |
825 | } |
826 | return (grn_obj *)res; |
827 | } |
828 | |
829 | grn_obj * |
830 | grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type type, |
831 | grn_proc_func *init, grn_proc_func *next, grn_proc_func *fin, |
832 | unsigned int nvars, grn_expr_var *vars) |
833 | { |
834 | grn_proc *res = NULL; |
835 | grn_id id = GRN_ID_NIL; |
836 | grn_id range = GRN_ID_NIL; |
837 | int added = 0; |
838 | grn_obj *db; |
839 | const char *path; |
840 | if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { |
841 | ERR(GRN_INVALID_ARGUMENT, "db not initialized" ); |
842 | return NULL; |
843 | } |
844 | GRN_API_ENTER; |
845 | path = ctx->impl->plugin_path; |
846 | if (path) { |
847 | range = grn_plugin_reference(ctx, path); |
848 | } |
849 | if (name_size < 0) { |
850 | name_size = strlen(name); |
851 | } |
852 | if (grn_db_check_name(ctx, name, name_size)) { |
853 | GRN_DB_CHECK_NAME_ERR("[proc][create]" , name, name_size); |
854 | GRN_API_RETURN(NULL); |
855 | } |
856 | if (!GRN_DB_P(db)) { |
857 | ERR(GRN_INVALID_ARGUMENT, "invalid db assigned" ); |
858 | GRN_API_RETURN(NULL); |
859 | } |
860 | if (name && name_size) { |
861 | grn_db *s = (grn_db *)db; |
862 | if (!(id = grn_table_get(ctx, s->keys, name, name_size))) { |
863 | if (!(id = grn_table_add(ctx, s->keys, name, name_size, &added))) { |
864 | ERR(GRN_NO_MEMORY_AVAILABLE, "grn_table_add failed" ); |
865 | GRN_API_RETURN(NULL); |
866 | } |
867 | } |
868 | if (!added) { |
869 | db_value *vp; |
870 | if ((vp = grn_tiny_array_at(&s->values, id)) && (res = (grn_proc *)vp->ptr)) { |
871 | /* TODO: Do more robust check. */ |
872 | if (res->funcs[PROC_INIT] || |
873 | res->funcs[PROC_NEXT] || |
874 | res->funcs[PROC_FIN]) { |
875 | ERR(GRN_INVALID_ARGUMENT, "already used name" ); |
876 | GRN_API_RETURN(NULL); |
877 | } |
878 | if (range != GRN_ID_NIL) { |
879 | grn_plugin_close(ctx, range); |
880 | } |
881 | GRN_API_RETURN((grn_obj *)res); |
882 | } else { |
883 | added = 1; |
884 | } |
885 | } |
886 | } else if (ctx->impl && ctx->impl->values) { |
887 | id = grn_array_add(ctx, ctx->impl->values, NULL) | GRN_OBJ_TMP_OBJECT; |
888 | added = 1; |
889 | } |
890 | if (!res) { res = GRN_MALLOCN(grn_proc, 1); } |
891 | if (res) { |
892 | GRN_DB_OBJ_SET_TYPE(res, GRN_PROC); |
893 | res->obj.db = db; |
894 | res->obj.id = id; |
895 | res->obj.header.domain = GRN_ID_NIL; |
896 | res->obj.header.flags = path ? GRN_OBJ_CUSTOM_NAME : 0; |
897 | res->obj.range = range; |
898 | res->type = type; |
899 | res->funcs[PROC_INIT] = init; |
900 | res->funcs[PROC_NEXT] = next; |
901 | res->funcs[PROC_FIN] = fin; |
902 | memset(&(res->callbacks), 0, sizeof(res->callbacks)); |
903 | res->callbacks.function.selector_op = GRN_OP_NOP; |
904 | res->callbacks.function.is_stable = GRN_TRUE; |
905 | GRN_TEXT_INIT(&res->name_buf, 0); |
906 | res->vars = NULL; |
907 | res->nvars = 0; |
908 | if (added) { |
909 | if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) { |
910 | // grn_obj_delete(ctx, db, id); |
911 | GRN_FREE(res); |
912 | GRN_API_RETURN(NULL); |
913 | } |
914 | } |
915 | while (nvars--) { |
916 | grn_obj *v = grn_expr_add_var(ctx, (grn_obj *)res, vars->name, vars->name_size); |
917 | GRN_OBJ_INIT(v, vars->value.header.type, 0, vars->value.header.domain); |
918 | GRN_TEXT_PUT(ctx, v, GRN_TEXT_VALUE(&vars->value), GRN_TEXT_LEN(&vars->value)); |
919 | vars++; |
920 | } |
921 | } |
922 | GRN_API_RETURN((grn_obj *)res); |
923 | } |
924 | |
925 | /* grn_table */ |
926 | |
927 | static void |
928 | calc_rec_size(grn_table_flags flags, uint32_t max_n_subrecs, uint32_t range_size, |
929 | uint32_t additional_value_size, |
930 | uint8_t *subrec_size, uint8_t *subrec_offset, |
931 | uint32_t *key_size, uint32_t *value_size) |
932 | { |
933 | *subrec_size = 0; |
934 | *subrec_offset = 0; |
935 | if (flags & GRN_OBJ_WITH_SUBREC) { |
936 | switch (flags & GRN_OBJ_UNIT_MASK) { |
937 | case GRN_OBJ_UNIT_DOCUMENT_NONE : |
938 | break; |
939 | case GRN_OBJ_UNIT_DOCUMENT_SECTION : |
940 | *subrec_offset = sizeof(grn_id); |
941 | *subrec_size = sizeof(uint32_t); |
942 | break; |
943 | case GRN_OBJ_UNIT_DOCUMENT_POSITION : |
944 | *subrec_offset = sizeof(grn_id); |
945 | *subrec_size = sizeof(uint32_t) + sizeof(uint32_t); |
946 | break; |
947 | case GRN_OBJ_UNIT_SECTION_NONE : |
948 | *key_size += sizeof(uint32_t); |
949 | break; |
950 | case GRN_OBJ_UNIT_SECTION_POSITION : |
951 | *key_size += sizeof(uint32_t); |
952 | *subrec_offset = sizeof(grn_id) + sizeof(uint32_t); |
953 | *subrec_size = sizeof(uint32_t); |
954 | break; |
955 | case GRN_OBJ_UNIT_POSITION_NONE : |
956 | *key_size += sizeof(uint32_t) + sizeof(uint32_t); |
957 | break; |
958 | case GRN_OBJ_UNIT_USERDEF_DOCUMENT : |
959 | *subrec_size = range_size; |
960 | break; |
961 | case GRN_OBJ_UNIT_USERDEF_SECTION : |
962 | *subrec_size = range_size + sizeof(uint32_t); |
963 | break; |
964 | case GRN_OBJ_UNIT_USERDEF_POSITION : |
965 | *subrec_size = range_size + sizeof(uint32_t) + sizeof(uint32_t); |
966 | break; |
967 | } |
968 | *value_size = (uintptr_t)GRN_RSET_SUBRECS_NTH((((grn_rset_recinfo *)0)->subrecs), |
969 | *subrec_size, max_n_subrecs); |
970 | } else { |
971 | *value_size = range_size; |
972 | } |
973 | *value_size += additional_value_size; |
974 | } |
975 | |
976 | static grn_rc _grn_obj_remove(grn_ctx *ctx, grn_obj *obj, grn_bool dependent); |
977 | |
978 | static grn_rc |
979 | grn_table_create_validate(grn_ctx *ctx, const char *name, unsigned int name_size, |
980 | const char *path, grn_table_flags flags, |
981 | grn_obj *key_type, grn_obj *value_type) |
982 | { |
983 | grn_table_flags table_type; |
984 | const char *table_type_name = NULL; |
985 | |
986 | table_type = (flags & GRN_OBJ_TABLE_TYPE_MASK); |
987 | switch (table_type) { |
988 | case GRN_OBJ_TABLE_HASH_KEY : |
989 | table_type_name = "TABLE_HASH_KEY" ; |
990 | break; |
991 | case GRN_OBJ_TABLE_PAT_KEY : |
992 | table_type_name = "TABLE_PAT_KEY" ; |
993 | break; |
994 | case GRN_OBJ_TABLE_DAT_KEY : |
995 | table_type_name = "TABLE_DAT_KEY" ; |
996 | break; |
997 | case GRN_OBJ_TABLE_NO_KEY : |
998 | table_type_name = "TABLE_NO_KEY" ; |
999 | break; |
1000 | default : |
1001 | table_type_name = "unknown" ; |
1002 | break; |
1003 | } |
1004 | |
1005 | if (!key_type && table_type != GRN_OBJ_TABLE_NO_KEY && |
1006 | !(flags & GRN_OBJ_KEY_VAR_SIZE)) { |
1007 | ERR(GRN_INVALID_ARGUMENT, |
1008 | "[table][create] " |
1009 | "key type is required for TABLE_HASH_KEY, TABLE_PAT_KEY or " |
1010 | "TABLE_DAT_KEY: <%.*s>" , name_size, name); |
1011 | return ctx->rc; |
1012 | } |
1013 | |
1014 | if (key_type && table_type == GRN_OBJ_TABLE_NO_KEY) { |
1015 | int key_name_size; |
1016 | char key_name[GRN_TABLE_MAX_KEY_SIZE]; |
1017 | key_name_size = grn_obj_name(ctx, key_type, key_name, |
1018 | GRN_TABLE_MAX_KEY_SIZE); |
1019 | ERR(GRN_INVALID_ARGUMENT, |
1020 | "[table][create] " |
1021 | "key isn't available for TABLE_NO_KEY table: <%.*s> (%.*s)" , |
1022 | name_size, name, key_name_size, key_name); |
1023 | return ctx->rc; |
1024 | } |
1025 | |
1026 | if ((flags & GRN_OBJ_KEY_WITH_SIS) && |
1027 | table_type != GRN_OBJ_TABLE_PAT_KEY) { |
1028 | ERR(GRN_INVALID_ARGUMENT, |
1029 | "[table][create] " |
1030 | "key with SIS is available only for TABLE_PAT_KEY table: " |
1031 | "<%.*s>(%s)" , |
1032 | name_size, name, |
1033 | table_type_name); |
1034 | return ctx->rc; |
1035 | } |
1036 | |
1037 | if ((flags & GRN_OBJ_KEY_NORMALIZE) && |
1038 | table_type == GRN_OBJ_TABLE_NO_KEY) { |
1039 | ERR(GRN_INVALID_ARGUMENT, |
1040 | "[table][create] " |
1041 | "key normalization isn't available for TABLE_NO_KEY table: <%.*s>" , |
1042 | name_size, name); |
1043 | return ctx->rc; |
1044 | } |
1045 | |
1046 | if ((flags & GRN_OBJ_KEY_LARGE) && |
1047 | table_type != GRN_OBJ_TABLE_HASH_KEY) { |
1048 | ERR(GRN_INVALID_ARGUMENT, |
1049 | "[table][create] " |
1050 | "large key support is available only for TABLE_HASH_KEY key table: " |
1051 | "<%.*s>(%s)" , |
1052 | name_size, name, |
1053 | table_type_name); |
1054 | return ctx->rc; |
1055 | } |
1056 | |
1057 | return ctx->rc; |
1058 | } |
1059 | |
1060 | static grn_obj * |
1061 | grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name, |
1062 | unsigned int name_size, const char *path, |
1063 | grn_table_flags flags, grn_obj *key_type, |
1064 | grn_obj *value_type, |
1065 | uint32_t max_n_subrecs, |
1066 | uint32_t additional_value_size) |
1067 | { |
1068 | grn_id id; |
1069 | grn_id domain = GRN_ID_NIL, range = GRN_ID_NIL; |
1070 | uint32_t key_size, value_size = 0, range_size = 0; |
1071 | uint8_t subrec_size, subrec_offset; |
1072 | grn_obj *res = NULL; |
1073 | grn_obj *db; |
1074 | char buffer[PATH_MAX]; |
1075 | if (!ctx->impl || !(db = ctx->impl->db)) { |
1076 | ERR(GRN_INVALID_ARGUMENT, "[table][create] db not initialized" ); |
1077 | return NULL; |
1078 | } |
1079 | if (grn_db_check_name(ctx, name, name_size)) { |
1080 | GRN_DB_CHECK_NAME_ERR("[table][create]" , name, name_size); |
1081 | return NULL; |
1082 | } |
1083 | if (!GRN_DB_P(db)) { |
1084 | ERR(GRN_INVALID_ARGUMENT, "[table][create] invalid db assigned" ); |
1085 | return NULL; |
1086 | } |
1087 | if (grn_table_create_validate(ctx, name, name_size, path, flags, |
1088 | key_type, value_type)) { |
1089 | return NULL; |
1090 | } |
1091 | if (key_type) { |
1092 | domain = DB_OBJ(key_type)->id; |
1093 | switch (key_type->header.type) { |
1094 | case GRN_TYPE : |
1095 | { |
1096 | grn_db_obj *t = (grn_db_obj *)key_type; |
1097 | flags |= t->header.flags; |
1098 | key_size = GRN_TYPE_SIZE(t); |
1099 | if (key_size > GRN_TABLE_MAX_KEY_SIZE) { |
1100 | int type_name_size; |
1101 | char type_name[GRN_TABLE_MAX_KEY_SIZE]; |
1102 | type_name_size = grn_obj_name(ctx, key_type, type_name, |
1103 | GRN_TABLE_MAX_KEY_SIZE); |
1104 | ERR(GRN_INVALID_ARGUMENT, |
1105 | "[table][create] key size too big: <%.*s> <%.*s>(%u) (max:%u)" , |
1106 | name_size, name, |
1107 | type_name_size, type_name, |
1108 | key_size, GRN_TABLE_MAX_KEY_SIZE); |
1109 | return NULL; |
1110 | } |
1111 | } |
1112 | break; |
1113 | case GRN_TABLE_HASH_KEY : |
1114 | case GRN_TABLE_PAT_KEY : |
1115 | case GRN_TABLE_DAT_KEY : |
1116 | case GRN_TABLE_NO_KEY : |
1117 | key_size = sizeof(grn_id); |
1118 | break; |
1119 | default : |
1120 | { |
1121 | int key_name_size; |
1122 | char key_name[GRN_TABLE_MAX_KEY_SIZE]; |
1123 | key_name_size = grn_obj_name(ctx, key_type, key_name, |
1124 | GRN_TABLE_MAX_KEY_SIZE); |
1125 | ERR(GRN_INVALID_ARGUMENT, |
1126 | "[table][create] key type must be type or table: <%.*s> (%.*s)" , |
1127 | name_size, name, key_name_size, key_name); |
1128 | return NULL; |
1129 | } |
1130 | break; |
1131 | } |
1132 | } else { |
1133 | key_size = (flags & GRN_OBJ_KEY_VAR_SIZE) ? GRN_TABLE_MAX_KEY_SIZE : sizeof(grn_id); |
1134 | } |
1135 | if (value_type) { |
1136 | range = DB_OBJ(value_type)->id; |
1137 | switch (value_type->header.type) { |
1138 | case GRN_TYPE : |
1139 | { |
1140 | grn_db_obj *t = (grn_db_obj *)value_type; |
1141 | if (t->header.flags & GRN_OBJ_KEY_VAR_SIZE) { |
1142 | int type_name_size; |
1143 | char type_name[GRN_TABLE_MAX_KEY_SIZE]; |
1144 | type_name_size = grn_obj_name(ctx, value_type, type_name, |
1145 | GRN_TABLE_MAX_KEY_SIZE); |
1146 | ERR(GRN_INVALID_ARGUMENT, |
1147 | "[table][create] value type must be fixed size: <%.*s> (%.*s)" , |
1148 | name_size, name, type_name_size, type_name); |
1149 | return NULL; |
1150 | } |
1151 | range_size = GRN_TYPE_SIZE(t); |
1152 | } |
1153 | break; |
1154 | case GRN_TABLE_HASH_KEY : |
1155 | case GRN_TABLE_PAT_KEY : |
1156 | case GRN_TABLE_DAT_KEY : |
1157 | case GRN_TABLE_NO_KEY : |
1158 | range_size = sizeof(grn_id); |
1159 | break; |
1160 | default : |
1161 | { |
1162 | int value_name_size; |
1163 | char value_name[GRN_TABLE_MAX_KEY_SIZE]; |
1164 | value_name_size = grn_obj_name(ctx, value_type, value_name, |
1165 | GRN_TABLE_MAX_KEY_SIZE); |
1166 | ERR(GRN_INVALID_ARGUMENT, |
1167 | "[table][create] value type must be type or table: <%.*s> (%.*s)" , |
1168 | name_size, name, value_name_size, value_name); |
1169 | return NULL; |
1170 | } |
1171 | break; |
1172 | } |
1173 | } |
1174 | |
1175 | id = grn_obj_register(ctx, db, name, name_size); |
1176 | if (ERRP(ctx, GRN_ERROR)) { return NULL; } |
1177 | if (GRN_OBJ_PERSISTENT & flags) { |
1178 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
1179 | "DDL:%u:table_create %.*s" , id, name_size, name); |
1180 | if (!path) { |
1181 | if (GRN_DB_PERSISTENT_P(db)) { |
1182 | grn_db_generate_pathname(ctx, db, id, buffer); |
1183 | path = buffer; |
1184 | } else { |
1185 | ERR(GRN_INVALID_ARGUMENT, "path not assigned for persistent table" ); |
1186 | grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
1187 | return NULL; |
1188 | } |
1189 | } else { |
1190 | flags |= GRN_OBJ_CUSTOM_NAME; |
1191 | } |
1192 | } else { |
1193 | if (path) { |
1194 | ERR(GRN_INVALID_ARGUMENT, "path assigned for temporary table" ); |
1195 | grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
1196 | return NULL; |
1197 | } |
1198 | if (GRN_DB_PERSISTENT_P(db) && name && name_size) { |
1199 | ERR(GRN_INVALID_ARGUMENT, "name assigned for temporary table" ); |
1200 | grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
1201 | return NULL; |
1202 | } |
1203 | } |
1204 | calc_rec_size(flags, max_n_subrecs, range_size, additional_value_size, |
1205 | &subrec_size, &subrec_offset, &key_size, &value_size); |
1206 | switch (flags & GRN_OBJ_TABLE_TYPE_MASK) { |
1207 | case GRN_OBJ_TABLE_HASH_KEY : |
1208 | res = (grn_obj *)grn_hash_create(ctx, path, key_size, value_size, flags); |
1209 | break; |
1210 | case GRN_OBJ_TABLE_PAT_KEY : |
1211 | res = (grn_obj *)grn_pat_create(ctx, path, key_size, value_size, flags); |
1212 | break; |
1213 | case GRN_OBJ_TABLE_DAT_KEY : |
1214 | res = (grn_obj *)grn_dat_create(ctx, path, key_size, value_size, flags); |
1215 | break; |
1216 | case GRN_OBJ_TABLE_NO_KEY : |
1217 | domain = range; |
1218 | res = (grn_obj *)grn_array_create(ctx, path, value_size, flags); |
1219 | break; |
1220 | } |
1221 | if (res) { |
1222 | DB_OBJ(res)->header.impl_flags = 0; |
1223 | DB_OBJ(res)->header.domain = domain; |
1224 | DB_OBJ(res)->range = range; |
1225 | DB_OBJ(res)->max_n_subrecs = max_n_subrecs; |
1226 | DB_OBJ(res)->subrec_size = subrec_size; |
1227 | DB_OBJ(res)->subrec_offset = subrec_offset; |
1228 | DB_OBJ(res)->flags.group = 0; |
1229 | if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) { |
1230 | _grn_obj_remove(ctx, res, GRN_FALSE); |
1231 | res = NULL; |
1232 | } |
1233 | } else { |
1234 | grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
1235 | } |
1236 | return res; |
1237 | } |
1238 | |
1239 | grn_obj * |
1240 | grn_table_create(grn_ctx *ctx, const char *name, unsigned int name_size, |
1241 | const char *path, grn_table_flags flags, |
1242 | grn_obj *key_type, grn_obj *value_type) |
1243 | { |
1244 | grn_obj *res; |
1245 | GRN_API_ENTER; |
1246 | res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path, |
1247 | flags, key_type, value_type, |
1248 | 0, 0); |
1249 | GRN_API_RETURN(res); |
1250 | } |
1251 | |
1252 | grn_obj * |
1253 | grn_table_create_for_group(grn_ctx *ctx, const char *name, |
1254 | unsigned int name_size, const char *path, |
1255 | grn_obj *group_key, grn_obj *value_type, |
1256 | unsigned int max_n_subrecs) |
1257 | { |
1258 | grn_obj *res = NULL; |
1259 | GRN_API_ENTER; |
1260 | if (group_key) { |
1261 | grn_obj *key_type; |
1262 | key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, group_key)); |
1263 | if (key_type) { |
1264 | res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path, |
1265 | GRN_TABLE_HASH_KEY| |
1266 | GRN_OBJ_WITH_SUBREC| |
1267 | GRN_OBJ_UNIT_USERDEF_DOCUMENT, |
1268 | key_type, value_type, |
1269 | max_n_subrecs, 0); |
1270 | grn_obj_unlink(ctx, key_type); |
1271 | } |
1272 | } else { |
1273 | res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path, |
1274 | GRN_TABLE_HASH_KEY| |
1275 | GRN_OBJ_KEY_VAR_SIZE| |
1276 | GRN_OBJ_WITH_SUBREC| |
1277 | GRN_OBJ_UNIT_USERDEF_DOCUMENT, |
1278 | NULL, value_type, |
1279 | max_n_subrecs, 0); |
1280 | } |
1281 | GRN_API_RETURN(res); |
1282 | } |
1283 | |
1284 | unsigned int |
1285 | grn_table_get_subrecs(grn_ctx *ctx, grn_obj *table, grn_id id, |
1286 | grn_id *subrecbuf, int *scorebuf, int buf_size) |
1287 | { |
1288 | unsigned int count = 0; |
1289 | GRN_API_ENTER; |
1290 | if (GRN_OBJ_TABLEP(table)) { |
1291 | uint32_t value_size; |
1292 | grn_rset_recinfo *ri; |
1293 | uint32_t subrec_size = DB_OBJ(table)->subrec_size; |
1294 | uint32_t max_n_subrecs = DB_OBJ(table)->max_n_subrecs; |
1295 | if (subrec_size < sizeof(grn_id)) { goto exit; } |
1296 | if (!max_n_subrecs) { goto exit; } |
1297 | ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, table, id, &value_size); |
1298 | if (ri) { |
1299 | byte *psubrec = (byte *)ri->subrecs; |
1300 | uint32_t n_subrecs = (uint32_t)GRN_RSET_N_SUBRECS(ri); |
1301 | uint32_t limit = value_size / (GRN_RSET_SCORE_SIZE + subrec_size); |
1302 | if (limit > buf_size) { |
1303 | limit = buf_size; |
1304 | } |
1305 | if (limit > n_subrecs) { |
1306 | limit = n_subrecs; |
1307 | } |
1308 | if (limit > max_n_subrecs) { |
1309 | limit = max_n_subrecs; |
1310 | } |
1311 | for (; count < limit; count++) { |
1312 | if (scorebuf) { |
1313 | scorebuf[count] = *((double *)psubrec); |
1314 | } |
1315 | psubrec += GRN_RSET_SCORE_SIZE; |
1316 | if (subrecbuf) { |
1317 | subrecbuf[count] = *((grn_id *)psubrec); |
1318 | } |
1319 | psubrec += subrec_size; |
1320 | } |
1321 | } |
1322 | } |
1323 | exit : |
1324 | GRN_API_RETURN(count); |
1325 | } |
1326 | |
1327 | grn_obj * |
1328 | grn_table_open(grn_ctx *ctx, const char *name, unsigned int name_size, const char *path) |
1329 | { |
1330 | grn_obj *db; |
1331 | if (!ctx->impl || !(db = ctx->impl->db)) { |
1332 | ERR(GRN_INVALID_ARGUMENT, "db not initialized" ); |
1333 | return NULL; |
1334 | } |
1335 | GRN_API_ENTER; |
1336 | if (!GRN_DB_P(db)) { |
1337 | ERR(GRN_INVALID_ARGUMENT, "invalid db assigned" ); |
1338 | GRN_API_RETURN(NULL); |
1339 | } else { |
1340 | grn_obj *res = grn_ctx_get(ctx, name, name_size); |
1341 | if (res) { |
1342 | const char *path2 = grn_obj_path(ctx, res); |
1343 | if (path && (!path2 || strcmp(path, path2))) { |
1344 | ERR(GRN_INVALID_ARGUMENT, "path unmatch" ); |
1345 | GRN_API_RETURN(NULL); |
1346 | } |
1347 | } else if (path) { |
1348 | uint32_t type = grn_io_detect_type(ctx, path); |
1349 | if (!type) { GRN_API_RETURN(NULL); } |
1350 | switch (type) { |
1351 | case GRN_TABLE_HASH_KEY : |
1352 | res = (grn_obj *)grn_hash_open(ctx, path); |
1353 | break; |
1354 | case GRN_TABLE_PAT_KEY : |
1355 | res = (grn_obj *)grn_pat_open(ctx, path); |
1356 | break; |
1357 | case GRN_TABLE_DAT_KEY : |
1358 | res = (grn_obj *)grn_dat_open(ctx, path); |
1359 | break; |
1360 | case GRN_TABLE_NO_KEY : |
1361 | res = (grn_obj *)grn_array_open(ctx, path); |
1362 | break; |
1363 | } |
1364 | if (res) { |
1365 | grn_id id = grn_obj_register(ctx, db, name, name_size); |
1366 | res->header.flags |= GRN_OBJ_CUSTOM_NAME; |
1367 | res->header.domain = GRN_ID_NIL; /* unknown */ |
1368 | DB_OBJ(res)->range = GRN_ID_NIL; /* unknown */ |
1369 | grn_db_obj_init(ctx, db, id, DB_OBJ(res)); |
1370 | } |
1371 | } else { |
1372 | ERR(GRN_INVALID_ARGUMENT, "path is missing" ); |
1373 | } |
1374 | GRN_API_RETURN(res); |
1375 | } |
1376 | } |
1377 | |
1378 | grn_id |
1379 | grn_table_lcp_search(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size) |
1380 | { |
1381 | grn_id id = GRN_ID_NIL; |
1382 | GRN_API_ENTER; |
1383 | switch (table->header.type) { |
1384 | case GRN_TABLE_PAT_KEY : |
1385 | { |
1386 | grn_pat *pat = (grn_pat *)table; |
1387 | WITH_NORMALIZE(pat, key, key_size, { |
1388 | id = grn_pat_lcp_search(ctx, pat, key, key_size); |
1389 | }); |
1390 | } |
1391 | break; |
1392 | case GRN_TABLE_DAT_KEY : |
1393 | { |
1394 | grn_dat *dat = (grn_dat *)table; |
1395 | WITH_NORMALIZE(dat, key, key_size, { |
1396 | id = grn_dat_lcp_search(ctx, dat, key, key_size); |
1397 | }); |
1398 | } |
1399 | break; |
1400 | case GRN_TABLE_HASH_KEY : |
1401 | { |
1402 | grn_hash *hash = (grn_hash *)table; |
1403 | WITH_NORMALIZE(hash, key, key_size, { |
1404 | id = grn_hash_get(ctx, hash, key, key_size, NULL); |
1405 | }); |
1406 | } |
1407 | break; |
1408 | } |
1409 | GRN_API_RETURN(id); |
1410 | } |
1411 | |
1412 | grn_obj * |
1413 | grn_obj_default_set_value_hook(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) |
1414 | { |
1415 | grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; |
1416 | if (!pctx) { |
1417 | ERR(GRN_INVALID_ARGUMENT, "default_set_value_hook failed" ); |
1418 | } else { |
1419 | grn_obj *flags = grn_ctx_pop(ctx); |
1420 | grn_obj *newvalue = grn_ctx_pop(ctx); |
1421 | grn_obj *oldvalue = grn_ctx_pop(ctx); |
1422 | grn_obj *id = grn_ctx_pop(ctx); |
1423 | grn_hook *h = pctx->currh; |
1424 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(h); |
1425 | grn_obj *target = grn_ctx_at(ctx, data->target); |
1426 | int section = data->section; |
1427 | if (flags) { /* todo */ } |
1428 | if (target) { |
1429 | switch (target->header.type) { |
1430 | case GRN_COLUMN_INDEX : |
1431 | grn_ii_column_update(ctx, (grn_ii *)target, |
1432 | GRN_UINT32_VALUE(id), |
1433 | section, oldvalue, newvalue, NULL); |
1434 | } |
1435 | } |
1436 | } |
1437 | return NULL; |
1438 | } |
1439 | |
1440 | grn_id |
1441 | grn_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size, int *added) |
1442 | { |
1443 | grn_id id = GRN_ID_NIL; |
1444 | GRN_API_ENTER; |
1445 | if (table) { |
1446 | int added_ = 0; |
1447 | switch (table->header.type) { |
1448 | case GRN_TABLE_PAT_KEY : |
1449 | { |
1450 | grn_pat *pat = (grn_pat *)table; |
1451 | WITH_NORMALIZE(pat, key, key_size, { |
1452 | if (pat->io && !(pat->io->flags & GRN_IO_TEMPORARY)) { |
1453 | if (grn_io_lock(ctx, pat->io, grn_lock_timeout)) { |
1454 | id = GRN_ID_NIL; |
1455 | } else { |
1456 | id = grn_pat_add(ctx, pat, key, key_size, NULL, &added_); |
1457 | grn_io_unlock(pat->io); |
1458 | } |
1459 | } else { |
1460 | id = grn_pat_add(ctx, pat, key, key_size, NULL, &added_); |
1461 | } |
1462 | }); |
1463 | if (added) { *added = added_; } |
1464 | } |
1465 | break; |
1466 | case GRN_TABLE_DAT_KEY : |
1467 | { |
1468 | grn_dat *dat = (grn_dat *)table; |
1469 | WITH_NORMALIZE(dat, key, key_size, { |
1470 | if (dat->io && !(dat->io->flags & GRN_IO_TEMPORARY)) { |
1471 | if (grn_io_lock(ctx, dat->io, grn_lock_timeout)) { |
1472 | id = GRN_ID_NIL; |
1473 | } else { |
1474 | id = grn_dat_add(ctx, dat, key, key_size, NULL, &added_); |
1475 | grn_io_unlock(dat->io); |
1476 | } |
1477 | } else { |
1478 | id = grn_dat_add(ctx, dat, key, key_size, NULL, &added_); |
1479 | } |
1480 | }); |
1481 | if (added) { *added = added_; } |
1482 | } |
1483 | break; |
1484 | case GRN_TABLE_HASH_KEY : |
1485 | { |
1486 | grn_hash *hash = (grn_hash *)table; |
1487 | WITH_NORMALIZE(hash, key, key_size, { |
1488 | if (hash->io && !(hash->io->flags & GRN_IO_TEMPORARY)) { |
1489 | if (grn_io_lock(ctx, hash->io, grn_lock_timeout)) { |
1490 | id = GRN_ID_NIL; |
1491 | } else { |
1492 | id = grn_hash_add(ctx, hash, key, key_size, NULL, &added_); |
1493 | grn_io_unlock(hash->io); |
1494 | } |
1495 | } else { |
1496 | id = grn_hash_add(ctx, hash, key, key_size, NULL, &added_); |
1497 | } |
1498 | }); |
1499 | if (added) { *added = added_; } |
1500 | } |
1501 | break; |
1502 | case GRN_TABLE_NO_KEY : |
1503 | { |
1504 | grn_array *array = (grn_array *)table; |
1505 | if (array->io && !(array->io->flags & GRN_IO_TEMPORARY)) { |
1506 | if (grn_io_lock(ctx, array->io, grn_lock_timeout)) { |
1507 | id = GRN_ID_NIL; |
1508 | } else { |
1509 | id = grn_array_add(ctx, array, NULL); |
1510 | grn_io_unlock(array->io); |
1511 | } |
1512 | } else { |
1513 | id = grn_array_add(ctx, array, NULL); |
1514 | } |
1515 | added_ = id ? 1 : 0; |
1516 | if (added) { *added = added_; } |
1517 | } |
1518 | break; |
1519 | } |
1520 | if (added_) { |
1521 | grn_hook *hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; |
1522 | if (hooks) { |
1523 | // todo : grn_proc_ctx_open() |
1524 | grn_obj id_, flags_, oldvalue_, value_; |
1525 | grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4}; |
1526 | GRN_UINT32_INIT(&id_, 0); |
1527 | GRN_UINT32_INIT(&flags_, 0); |
1528 | GRN_TEXT_INIT(&oldvalue_, 0); |
1529 | GRN_TEXT_INIT(&value_, GRN_OBJ_DO_SHALLOW_COPY); |
1530 | GRN_TEXT_SET_REF(&value_, key, key_size); |
1531 | GRN_UINT32_SET(ctx, &id_, id); |
1532 | GRN_UINT32_SET(ctx, &flags_, GRN_OBJ_SET); |
1533 | while (hooks) { |
1534 | grn_ctx_push(ctx, &id_); |
1535 | grn_ctx_push(ctx, &oldvalue_); |
1536 | grn_ctx_push(ctx, &value_); |
1537 | grn_ctx_push(ctx, &flags_); |
1538 | pctx.caller = NULL; |
1539 | pctx.currh = hooks; |
1540 | if (hooks->proc) { |
1541 | hooks->proc->funcs[PROC_INIT](ctx, 1, &table, &pctx.user_data); |
1542 | } else { |
1543 | grn_obj_default_set_value_hook(ctx, 1, &table, &pctx.user_data); |
1544 | } |
1545 | if (ctx->rc) { break; } |
1546 | hooks = hooks->next; |
1547 | pctx.offset++; |
1548 | } |
1549 | } |
1550 | } |
1551 | } |
1552 | GRN_API_RETURN(id); |
1553 | } |
1554 | |
1555 | grn_id |
1556 | grn_table_get_by_key(grn_ctx *ctx, grn_obj *table, grn_obj *key) |
1557 | { |
1558 | grn_id id = GRN_ID_NIL; |
1559 | if (table->header.domain == key->header.domain) { |
1560 | id = grn_table_get(ctx, table, GRN_TEXT_VALUE(key), GRN_TEXT_LEN(key)); |
1561 | } else { |
1562 | grn_rc rc; |
1563 | grn_obj buf; |
1564 | GRN_OBJ_INIT(&buf, GRN_BULK, 0, table->header.domain); |
1565 | if ((rc = grn_obj_cast(ctx, key, &buf, GRN_TRUE))) { |
1566 | grn_obj *domain = grn_ctx_at(ctx, table->header.domain); |
1567 | ERR_CAST(table, domain, key); |
1568 | } else { |
1569 | id = grn_table_get(ctx, table, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); |
1570 | } |
1571 | GRN_OBJ_FIN(ctx, &buf); |
1572 | } |
1573 | return id; |
1574 | } |
1575 | |
1576 | grn_id |
1577 | grn_table_add_by_key(grn_ctx *ctx, grn_obj *table, grn_obj *key, int *added) |
1578 | { |
1579 | grn_id id = GRN_ID_NIL; |
1580 | if (table->header.domain == key->header.domain) { |
1581 | id = grn_table_add(ctx, table, GRN_TEXT_VALUE(key), GRN_TEXT_LEN(key), added); |
1582 | } else { |
1583 | grn_rc rc; |
1584 | grn_obj buf; |
1585 | GRN_OBJ_INIT(&buf, GRN_BULK, 0, table->header.domain); |
1586 | if ((rc = grn_obj_cast(ctx, key, &buf, GRN_TRUE))) { |
1587 | grn_obj *domain = grn_ctx_at(ctx, table->header.domain); |
1588 | ERR_CAST(table, domain, key); |
1589 | } else { |
1590 | id = grn_table_add(ctx, table, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf), added); |
1591 | } |
1592 | GRN_OBJ_FIN(ctx, &buf); |
1593 | } |
1594 | return id; |
1595 | } |
1596 | |
1597 | grn_id |
1598 | grn_table_get(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size) |
1599 | { |
1600 | grn_id id = GRN_ID_NIL; |
1601 | GRN_API_ENTER; |
1602 | if (table) { |
1603 | if (table->header.type == GRN_DB) { |
1604 | grn_db *db = (grn_db *)table; |
1605 | table = db->keys; |
1606 | } |
1607 | switch (table->header.type) { |
1608 | case GRN_TABLE_PAT_KEY : |
1609 | WITH_NORMALIZE((grn_pat *)table, key, key_size, { |
1610 | id = grn_pat_get(ctx, (grn_pat *)table, key, key_size, NULL); |
1611 | }); |
1612 | break; |
1613 | case GRN_TABLE_DAT_KEY : |
1614 | WITH_NORMALIZE((grn_dat *)table, key, key_size, { |
1615 | id = grn_dat_get(ctx, (grn_dat *)table, key, key_size, NULL); |
1616 | }); |
1617 | break; |
1618 | case GRN_TABLE_HASH_KEY : |
1619 | WITH_NORMALIZE((grn_hash *)table, key, key_size, { |
1620 | id = grn_hash_get(ctx, (grn_hash *)table, key, key_size, NULL); |
1621 | }); |
1622 | break; |
1623 | } |
1624 | } |
1625 | GRN_API_RETURN(id); |
1626 | } |
1627 | |
1628 | grn_id |
1629 | grn_table_at(grn_ctx *ctx, grn_obj *table, grn_id id) |
1630 | { |
1631 | GRN_API_ENTER; |
1632 | if (table) { |
1633 | switch (table->header.type) { |
1634 | case GRN_DB : |
1635 | { |
1636 | grn_db *db = (grn_db *)table; |
1637 | id = grn_table_at(ctx, db->keys, id); |
1638 | } |
1639 | break; |
1640 | case GRN_TABLE_PAT_KEY : |
1641 | id = grn_pat_at(ctx, (grn_pat *)table, id); |
1642 | break; |
1643 | case GRN_TABLE_DAT_KEY : |
1644 | id = grn_dat_at(ctx, (grn_dat *)table, id); |
1645 | break; |
1646 | case GRN_TABLE_HASH_KEY : |
1647 | id = grn_hash_at(ctx, (grn_hash *)table, id); |
1648 | break; |
1649 | case GRN_TABLE_NO_KEY : |
1650 | id = grn_array_at(ctx, (grn_array *)table, id); |
1651 | break; |
1652 | default : |
1653 | id = GRN_ID_NIL; |
1654 | } |
1655 | } |
1656 | GRN_API_RETURN(id); |
1657 | } |
1658 | |
1659 | inline static grn_id |
1660 | grn_table_add_v_inline(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, |
1661 | void **value, int *added) |
1662 | { |
1663 | grn_id id = GRN_ID_NIL; |
1664 | if (!key || !key_size) { return GRN_ID_NIL; } |
1665 | if (table) { |
1666 | switch (table->header.type) { |
1667 | case GRN_TABLE_PAT_KEY : |
1668 | WITH_NORMALIZE((grn_pat *)table, key, key_size, { |
1669 | id = grn_pat_add(ctx, (grn_pat *)table, key, key_size, value, added); |
1670 | }); |
1671 | break; |
1672 | case GRN_TABLE_DAT_KEY : |
1673 | WITH_NORMALIZE((grn_dat *)table, key, key_size, { |
1674 | id = grn_dat_add(ctx, (grn_dat *)table, key, key_size, value, added); |
1675 | }); |
1676 | break; |
1677 | case GRN_TABLE_HASH_KEY : |
1678 | WITH_NORMALIZE((grn_hash *)table, key, key_size, { |
1679 | id = grn_hash_add(ctx, (grn_hash *)table, key, key_size, value, added); |
1680 | }); |
1681 | break; |
1682 | case GRN_TABLE_NO_KEY : |
1683 | id = grn_array_add(ctx, (grn_array *)table, value); |
1684 | if (added) { *added = id ? 1 : 0; } |
1685 | break; |
1686 | } |
1687 | } |
1688 | return id; |
1689 | } |
1690 | |
1691 | grn_id |
1692 | grn_table_add_v(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, |
1693 | void **value, int *added) { |
1694 | grn_id id; |
1695 | GRN_API_ENTER; |
1696 | id = grn_table_add_v_inline(ctx, table, key, key_size, value, added); |
1697 | GRN_API_RETURN(id); |
1698 | } |
1699 | |
1700 | grn_id |
1701 | grn_table_get_v(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, |
1702 | void **value) |
1703 | { |
1704 | grn_id id = GRN_ID_NIL; |
1705 | GRN_API_ENTER; |
1706 | if (table) { |
1707 | switch (table->header.type) { |
1708 | case GRN_TABLE_PAT_KEY : |
1709 | WITH_NORMALIZE((grn_pat *)table, key, key_size, { |
1710 | id = grn_pat_get(ctx, (grn_pat *)table, key, key_size, value); |
1711 | }); |
1712 | break; |
1713 | case GRN_TABLE_DAT_KEY : |
1714 | WITH_NORMALIZE((grn_dat *)table, key, key_size, { |
1715 | id = grn_dat_get(ctx, (grn_dat *)table, key, key_size, value); |
1716 | }); |
1717 | break; |
1718 | case GRN_TABLE_HASH_KEY : |
1719 | WITH_NORMALIZE((grn_hash *)table, key, key_size, { |
1720 | id = grn_hash_get(ctx, (grn_hash *)table, key, key_size, value); |
1721 | }); |
1722 | break; |
1723 | } |
1724 | } |
1725 | GRN_API_RETURN(id); |
1726 | } |
1727 | |
1728 | int |
1729 | grn_table_get_key(grn_ctx *ctx, grn_obj *table, grn_id id, void *keybuf, int buf_size) |
1730 | { |
1731 | int r = 0; |
1732 | GRN_API_ENTER; |
1733 | if (table) { |
1734 | if (table->header.type == GRN_DB) { |
1735 | table = ((grn_db *)table)->keys; |
1736 | } |
1737 | switch (table->header.type) { |
1738 | case GRN_TABLE_HASH_KEY : |
1739 | r = grn_hash_get_key(ctx, (grn_hash *)table, id, keybuf, buf_size); |
1740 | break; |
1741 | case GRN_TABLE_PAT_KEY : |
1742 | r = grn_pat_get_key(ctx, (grn_pat *)table, id, keybuf, buf_size); |
1743 | break; |
1744 | case GRN_TABLE_DAT_KEY : |
1745 | r = grn_dat_get_key(ctx, (grn_dat *)table, id, keybuf, buf_size); |
1746 | break; |
1747 | case GRN_TABLE_NO_KEY : |
1748 | { |
1749 | grn_array *a = (grn_array *)table; |
1750 | if (a->obj.header.domain) { |
1751 | if (buf_size >= a->value_size) { |
1752 | r = grn_array_get_value(ctx, a, id, keybuf); |
1753 | } else { |
1754 | r = a->value_size; |
1755 | } |
1756 | } |
1757 | } |
1758 | break; |
1759 | } |
1760 | } |
1761 | GRN_API_RETURN(r); |
1762 | } |
1763 | |
1764 | int |
1765 | grn_table_get_key2(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *bulk) |
1766 | { |
1767 | int r = 0; |
1768 | GRN_API_ENTER; |
1769 | if (table) { |
1770 | if (table->header.type == GRN_DB) { |
1771 | table = ((grn_db *)table)->keys; |
1772 | } |
1773 | switch (table->header.type) { |
1774 | case GRN_TABLE_HASH_KEY : |
1775 | r = grn_hash_get_key2(ctx, (grn_hash *)table, id, bulk); |
1776 | break; |
1777 | case GRN_TABLE_PAT_KEY : |
1778 | r = grn_pat_get_key2(ctx, (grn_pat *)table, id, bulk); |
1779 | break; |
1780 | case GRN_TABLE_DAT_KEY : |
1781 | r = grn_dat_get_key2(ctx, (grn_dat *)table, id, bulk); |
1782 | break; |
1783 | case GRN_TABLE_NO_KEY : |
1784 | { |
1785 | grn_array *a = (grn_array *)table; |
1786 | if (a->obj.header.domain) { |
1787 | if (!grn_bulk_space(ctx, bulk, a->value_size)) { |
1788 | char *curr = GRN_BULK_CURR(bulk); |
1789 | r = grn_array_get_value(ctx, a, id, curr - a->value_size); |
1790 | } |
1791 | } |
1792 | } |
1793 | break; |
1794 | } |
1795 | } |
1796 | GRN_API_RETURN(r); |
1797 | } |
1798 | |
1799 | static grn_rc |
1800 | grn_obj_clear_value(grn_ctx *ctx, grn_obj *obj, grn_id id) |
1801 | { |
1802 | grn_rc rc = GRN_SUCCESS; |
1803 | if (GRN_DB_OBJP(obj)) { |
1804 | grn_obj buf; |
1805 | grn_id range = DB_OBJ(obj)->range; |
1806 | GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); |
1807 | switch (obj->header.type) { |
1808 | case GRN_COLUMN_VAR_SIZE : |
1809 | case GRN_COLUMN_FIX_SIZE : |
1810 | rc = grn_obj_set_value(ctx, obj, id, &buf, GRN_OBJ_SET); |
1811 | break; |
1812 | } |
1813 | GRN_OBJ_FIN(ctx, &buf); |
1814 | } |
1815 | return rc; |
1816 | } |
1817 | |
1818 | static void |
1819 | call_delete_hook(grn_ctx *ctx, grn_obj *table, grn_id rid, const void *key, unsigned int key_size) |
1820 | { |
1821 | if (rid) { |
1822 | grn_hook *hooks = DB_OBJ(table)->hooks[GRN_HOOK_DELETE]; |
1823 | if (hooks) { |
1824 | // todo : grn_proc_ctx_open() |
1825 | grn_obj id_, flags_, oldvalue_, value_; |
1826 | grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4}; |
1827 | GRN_UINT32_INIT(&id_, 0); |
1828 | GRN_UINT32_INIT(&flags_, 0); |
1829 | GRN_TEXT_INIT(&oldvalue_, GRN_OBJ_DO_SHALLOW_COPY); |
1830 | GRN_TEXT_INIT(&value_, 0); |
1831 | GRN_TEXT_SET_REF(&oldvalue_, key, key_size); |
1832 | GRN_UINT32_SET(ctx, &id_, rid); |
1833 | GRN_UINT32_SET(ctx, &flags_, GRN_OBJ_SET); |
1834 | while (hooks) { |
1835 | grn_ctx_push(ctx, &id_); |
1836 | grn_ctx_push(ctx, &oldvalue_); |
1837 | grn_ctx_push(ctx, &value_); |
1838 | grn_ctx_push(ctx, &flags_); |
1839 | pctx.caller = NULL; |
1840 | pctx.currh = hooks; |
1841 | if (hooks->proc) { |
1842 | hooks->proc->funcs[PROC_INIT](ctx, 1, &table, &pctx.user_data); |
1843 | } else { |
1844 | grn_obj_default_set_value_hook(ctx, 1, &table, &pctx.user_data); |
1845 | } |
1846 | if (ctx->rc) { break; } |
1847 | hooks = hooks->next; |
1848 | pctx.offset++; |
1849 | } |
1850 | } |
1851 | } |
1852 | } |
1853 | |
1854 | static void |
1855 | clear_column_values(grn_ctx *ctx, grn_obj *table, grn_id rid) |
1856 | { |
1857 | if (rid) { |
1858 | grn_hash *cols; |
1859 | if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
1860 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { |
1861 | if (grn_table_columns(ctx, table, "" , 0, (grn_obj *)cols)) { |
1862 | grn_id *key; |
1863 | GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { |
1864 | grn_obj *col = grn_ctx_at(ctx, *key); |
1865 | if (col) { grn_obj_clear_value(ctx, col, rid); } |
1866 | }); |
1867 | } |
1868 | grn_hash_close(ctx, cols); |
1869 | } |
1870 | } |
1871 | } |
1872 | |
1873 | static void |
1874 | delete_reference_records_in_index(grn_ctx *ctx, grn_obj *table, grn_id id, |
1875 | grn_obj *index) |
1876 | { |
1877 | grn_ii *ii = (grn_ii *)index; |
1878 | grn_ii_cursor *ii_cursor = NULL; |
1879 | grn_posting *posting; |
1880 | grn_obj source_ids; |
1881 | unsigned int i, n_ids; |
1882 | grn_obj sources; |
1883 | grn_bool have_reference_source = GRN_FALSE; |
1884 | |
1885 | GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); |
1886 | GRN_PTR_INIT(&sources, GRN_OBJ_VECTOR, 0); |
1887 | |
1888 | grn_obj_get_info(ctx, index, GRN_INFO_SOURCE, &source_ids); |
1889 | n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); |
1890 | if (n_ids == 0) { |
1891 | goto exit; |
1892 | } |
1893 | |
1894 | for (i = 0; i < n_ids; i++) { |
1895 | grn_id source_id; |
1896 | grn_obj *source; |
1897 | |
1898 | source_id = GRN_UINT32_VALUE_AT(&source_ids, i); |
1899 | source = grn_ctx_at(ctx, source_id); |
1900 | if (grn_obj_get_range(ctx, source) == index->header.domain) { |
1901 | GRN_PTR_PUT(ctx, &sources, source); |
1902 | have_reference_source = GRN_TRUE; |
1903 | } else { |
1904 | grn_obj_unlink(ctx, source); |
1905 | GRN_PTR_PUT(ctx, &sources, NULL); |
1906 | } |
1907 | } |
1908 | |
1909 | if (!have_reference_source) { |
1910 | goto exit; |
1911 | } |
1912 | |
1913 | ii_cursor = grn_ii_cursor_open(ctx, ii, id, GRN_ID_NIL, GRN_ID_MAX, |
1914 | ii->n_elements, 0); |
1915 | if (!ii_cursor) { |
1916 | goto exit; |
1917 | } |
1918 | |
1919 | while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) { |
1920 | grn_obj *source = GRN_PTR_VALUE_AT(&sources, posting->sid - 1); |
1921 | if (!source) { |
1922 | continue; |
1923 | } |
1924 | switch (source->header.type) { |
1925 | case GRN_COLUMN_VAR_SIZE : |
1926 | switch (source->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { |
1927 | case GRN_OBJ_COLUMN_SCALAR : |
1928 | grn_obj_clear_value(ctx, source, posting->rid); |
1929 | break; |
1930 | case GRN_OBJ_COLUMN_VECTOR : |
1931 | { |
1932 | grn_obj value; |
1933 | grn_obj new_value; |
1934 | GRN_TEXT_INIT(&value, 0); |
1935 | grn_obj_get_value(ctx, source, posting->rid, &value); |
1936 | if (value.header.type == GRN_UVECTOR) { |
1937 | int i, n_ids; |
1938 | GRN_RECORD_INIT(&new_value, GRN_OBJ_VECTOR, value.header.domain); |
1939 | n_ids = GRN_BULK_VSIZE(&value) / sizeof(grn_id); |
1940 | for (i = 0; i < n_ids; i++) { |
1941 | grn_id reference_id = GRN_RECORD_VALUE_AT(&value, i); |
1942 | if (reference_id == id) { |
1943 | continue; |
1944 | } |
1945 | GRN_RECORD_PUT(ctx, &new_value, reference_id); |
1946 | } |
1947 | } else { |
1948 | unsigned int i, n_elements; |
1949 | GRN_TEXT_INIT(&new_value, GRN_OBJ_VECTOR); |
1950 | n_elements = grn_vector_size(ctx, &value); |
1951 | for (i = 0; i < n_elements; i++) { |
1952 | const char *content; |
1953 | unsigned int content_length; |
1954 | unsigned int weight; |
1955 | grn_id domain; |
1956 | content_length = |
1957 | grn_vector_get_element(ctx, &value, i, |
1958 | &content, &weight, &domain); |
1959 | if (grn_table_get(ctx, table, content, content_length) == id) { |
1960 | continue; |
1961 | } |
1962 | grn_vector_add_element(ctx, &new_value, content, content_length, |
1963 | weight, domain); |
1964 | } |
1965 | } |
1966 | grn_obj_set_value(ctx, source, posting->rid, &new_value, |
1967 | GRN_OBJ_SET); |
1968 | GRN_OBJ_FIN(ctx, &new_value); |
1969 | GRN_OBJ_FIN(ctx, &value); |
1970 | } |
1971 | break; |
1972 | } |
1973 | break; |
1974 | case GRN_COLUMN_FIX_SIZE : |
1975 | grn_obj_clear_value(ctx, source, posting->rid); |
1976 | break; |
1977 | } |
1978 | } |
1979 | |
1980 | exit: |
1981 | if (ii_cursor) { |
1982 | grn_ii_cursor_close(ctx, ii_cursor); |
1983 | } |
1984 | grn_obj_unlink(ctx, &source_ids); |
1985 | { |
1986 | int i, n_sources; |
1987 | n_sources = GRN_BULK_VSIZE(&sources) / sizeof(grn_obj *); |
1988 | for (i = 0; i < n_sources; i++) { |
1989 | grn_obj *source = GRN_PTR_VALUE_AT(&sources, i); |
1990 | grn_obj_unlink(ctx, source); |
1991 | } |
1992 | grn_obj_unlink(ctx, &sources); |
1993 | } |
1994 | } |
1995 | |
1996 | static grn_rc |
1997 | delete_reference_records(grn_ctx *ctx, grn_obj *table, grn_id id) |
1998 | { |
1999 | grn_hash *cols; |
2000 | grn_id *key; |
2001 | |
2002 | cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
2003 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); |
2004 | if (!cols) { |
2005 | return ctx->rc; |
2006 | } |
2007 | |
2008 | if (!grn_table_columns(ctx, table, "" , 0, (grn_obj *)cols)) { |
2009 | grn_hash_close(ctx, cols); |
2010 | return ctx->rc; |
2011 | } |
2012 | |
2013 | GRN_HASH_EACH(ctx, cols, tid, &key, NULL, NULL, { |
2014 | grn_obj *col = grn_ctx_at(ctx, *key); |
2015 | if (!col) { |
2016 | continue; |
2017 | } |
2018 | if (col->header.type != GRN_COLUMN_INDEX) { |
2019 | continue; |
2020 | } |
2021 | delete_reference_records_in_index(ctx, table, id, col); |
2022 | if (ctx->rc != GRN_SUCCESS) { |
2023 | break; |
2024 | } |
2025 | }); |
2026 | |
2027 | grn_hash_close(ctx, cols); |
2028 | |
2029 | return ctx->rc; |
2030 | } |
2031 | |
2032 | static grn_rc |
2033 | grn_table_delete_prepare(grn_ctx *ctx, grn_obj *table, |
2034 | grn_id id, const void *key, unsigned int key_size) |
2035 | { |
2036 | grn_rc rc; |
2037 | |
2038 | rc = delete_reference_records(ctx, table, id); |
2039 | if (rc != GRN_SUCCESS) { |
2040 | return rc; |
2041 | } |
2042 | call_delete_hook(ctx, table, id, key, key_size); |
2043 | clear_column_values(ctx, table, id); |
2044 | |
2045 | return rc; |
2046 | } |
2047 | |
2048 | grn_rc |
2049 | grn_table_delete(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size) |
2050 | { |
2051 | grn_id rid = GRN_ID_NIL; |
2052 | grn_rc rc = GRN_INVALID_ARGUMENT; |
2053 | GRN_API_ENTER; |
2054 | if (table) { |
2055 | if (key && key_size) { rid = grn_table_get(ctx, table, key, key_size); } |
2056 | if (rid) { |
2057 | rc = grn_table_delete_prepare(ctx, table, rid, key, key_size); |
2058 | if (rc != GRN_SUCCESS) { |
2059 | goto exit; |
2060 | } |
2061 | switch (table->header.type) { |
2062 | case GRN_DB : |
2063 | /* todo : delete tables and columns from db */ |
2064 | break; |
2065 | case GRN_TABLE_PAT_KEY : |
2066 | WITH_NORMALIZE((grn_pat *)table, key, key_size, { |
2067 | grn_pat *pat = (grn_pat *)table; |
2068 | if (pat->io && !(pat->io->flags & GRN_IO_TEMPORARY)) { |
2069 | if (!(rc = grn_io_lock(ctx, pat->io, grn_lock_timeout))) { |
2070 | rc = grn_pat_delete(ctx, pat, key, key_size, NULL); |
2071 | grn_io_unlock(pat->io); |
2072 | } |
2073 | } else { |
2074 | rc = grn_pat_delete(ctx, pat, key, key_size, NULL); |
2075 | } |
2076 | }); |
2077 | break; |
2078 | case GRN_TABLE_DAT_KEY : |
2079 | WITH_NORMALIZE((grn_dat *)table, key, key_size, { |
2080 | grn_dat *dat = (grn_dat *)table; |
2081 | if (dat->io && !(dat->io->flags & GRN_IO_TEMPORARY)) { |
2082 | if (!(rc = grn_io_lock(ctx, dat->io, grn_lock_timeout))) { |
2083 | rc = grn_dat_delete(ctx, dat, key, key_size, NULL); |
2084 | grn_io_unlock(dat->io); |
2085 | } |
2086 | } else { |
2087 | rc = grn_dat_delete(ctx, dat, key, key_size, NULL); |
2088 | } |
2089 | }); |
2090 | break; |
2091 | case GRN_TABLE_HASH_KEY : |
2092 | WITH_NORMALIZE((grn_hash *)table, key, key_size, { |
2093 | grn_hash *hash = (grn_hash *)table; |
2094 | if (hash->io && !(hash->io->flags & GRN_IO_TEMPORARY)) { |
2095 | if (!(rc = grn_io_lock(ctx, hash->io, grn_lock_timeout))) { |
2096 | rc = grn_hash_delete(ctx, hash, key, key_size, NULL); |
2097 | grn_io_unlock(hash->io); |
2098 | } |
2099 | } else { |
2100 | rc = grn_hash_delete(ctx, hash, key, key_size, NULL); |
2101 | } |
2102 | }); |
2103 | break; |
2104 | } |
2105 | if (rc == GRN_SUCCESS) { |
2106 | grn_obj_touch(ctx, table, NULL); |
2107 | } |
2108 | } |
2109 | } |
2110 | exit : |
2111 | GRN_API_RETURN(rc); |
2112 | } |
2113 | |
2114 | grn_rc |
2115 | _grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, |
2116 | grn_table_delete_optarg *optarg) |
2117 | { |
2118 | grn_rc rc = GRN_INVALID_ARGUMENT; |
2119 | if (table) { |
2120 | if (id) { |
2121 | const void *key = NULL; |
2122 | unsigned int key_size = 0; |
2123 | |
2124 | if (table->header.type != GRN_TABLE_NO_KEY) { |
2125 | key = _grn_table_key(ctx, table, id, &key_size); |
2126 | } |
2127 | rc = grn_table_delete_prepare(ctx, table, id, key, key_size); |
2128 | if (rc != GRN_SUCCESS) { |
2129 | goto exit; |
2130 | } |
2131 | // todo : support optarg |
2132 | switch (table->header.type) { |
2133 | case GRN_TABLE_PAT_KEY : |
2134 | rc = grn_pat_delete_by_id(ctx, (grn_pat *)table, id, optarg); |
2135 | break; |
2136 | case GRN_TABLE_DAT_KEY : |
2137 | rc = grn_dat_delete_by_id(ctx, (grn_dat *)table, id, optarg); |
2138 | break; |
2139 | case GRN_TABLE_HASH_KEY : |
2140 | rc = grn_hash_delete_by_id(ctx, (grn_hash *)table, id, optarg); |
2141 | break; |
2142 | case GRN_TABLE_NO_KEY : |
2143 | rc = grn_array_delete_by_id(ctx, (grn_array *)table, id, optarg); |
2144 | break; |
2145 | } |
2146 | } |
2147 | } |
2148 | exit : |
2149 | return rc; |
2150 | } |
2151 | |
2152 | grn_rc |
2153 | grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id) |
2154 | { |
2155 | grn_rc rc; |
2156 | grn_io *io; |
2157 | GRN_API_ENTER; |
2158 | if ((io = grn_obj_get_io(ctx, table)) && !(io->flags & GRN_IO_TEMPORARY)) { |
2159 | if (!(rc = grn_io_lock(ctx, io, grn_lock_timeout))) { |
2160 | rc = _grn_table_delete_by_id(ctx, table, id, NULL); |
2161 | grn_io_unlock(io); |
2162 | } |
2163 | } else { |
2164 | rc = _grn_table_delete_by_id(ctx, table, id, NULL); |
2165 | } |
2166 | if (rc == GRN_SUCCESS) { |
2167 | grn_obj_touch(ctx, table, NULL); |
2168 | } |
2169 | GRN_API_RETURN(rc); |
2170 | } |
2171 | |
2172 | grn_rc grn_ja_truncate(grn_ctx *ctx, grn_ja *ja); |
2173 | grn_rc grn_ra_truncate(grn_ctx *ctx, grn_ra *ra); |
2174 | |
2175 | grn_rc |
2176 | grn_column_truncate(grn_ctx *ctx, grn_obj *column) |
2177 | { |
2178 | grn_rc rc = GRN_INVALID_ARGUMENT; |
2179 | GRN_API_ENTER; |
2180 | if (column) { |
2181 | grn_hook *hooks; |
2182 | switch (column->header.type) { |
2183 | case GRN_COLUMN_INDEX : |
2184 | rc = grn_ii_truncate(ctx, (grn_ii *)column); |
2185 | break; |
2186 | case GRN_COLUMN_VAR_SIZE : |
2187 | for (hooks = DB_OBJ(column)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) { |
2188 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
2189 | grn_obj *target = grn_ctx_at(ctx, data->target); |
2190 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
2191 | if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } |
2192 | } |
2193 | rc = grn_ja_truncate(ctx, (grn_ja *)column); |
2194 | break; |
2195 | case GRN_COLUMN_FIX_SIZE : |
2196 | for (hooks = DB_OBJ(column)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) { |
2197 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
2198 | grn_obj *target = grn_ctx_at(ctx, data->target); |
2199 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
2200 | if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } |
2201 | } |
2202 | rc = grn_ra_truncate(ctx, (grn_ra *)column); |
2203 | break; |
2204 | } |
2205 | if (rc == GRN_SUCCESS) { |
2206 | grn_obj_touch(ctx, column, NULL); |
2207 | } |
2208 | } |
2209 | exit : |
2210 | GRN_API_RETURN(rc); |
2211 | } |
2212 | |
2213 | grn_rc |
2214 | grn_table_truncate(grn_ctx *ctx, grn_obj *table) |
2215 | { |
2216 | grn_rc rc = GRN_INVALID_ARGUMENT; |
2217 | GRN_API_ENTER; |
2218 | if (table) { |
2219 | grn_hook *hooks; |
2220 | grn_hash *cols; |
2221 | grn_obj *tokenizer; |
2222 | grn_obj *normalizer; |
2223 | grn_obj token_filters; |
2224 | if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
2225 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { |
2226 | if (grn_table_columns(ctx, table, "" , 0, (grn_obj *)cols)) { |
2227 | grn_id *key; |
2228 | GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { |
2229 | grn_obj *col = grn_ctx_at(ctx, *key); |
2230 | if (col) { grn_column_truncate(ctx, col); } |
2231 | }); |
2232 | } |
2233 | grn_hash_close(ctx, cols); |
2234 | } |
2235 | if (table->header.type != GRN_TABLE_NO_KEY) { |
2236 | grn_table_get_info(ctx, table, NULL, NULL, &tokenizer, &normalizer, NULL); |
2237 | GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, GRN_ID_NIL); |
2238 | grn_obj_get_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); |
2239 | } |
2240 | switch (table->header.type) { |
2241 | case GRN_TABLE_PAT_KEY : |
2242 | for (hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; hooks; hooks = hooks->next) { |
2243 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
2244 | grn_obj *target = grn_ctx_at(ctx, data->target); |
2245 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
2246 | if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } |
2247 | } |
2248 | rc = grn_pat_truncate(ctx, (grn_pat *)table); |
2249 | break; |
2250 | case GRN_TABLE_DAT_KEY : |
2251 | for (hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; hooks; hooks = hooks->next) { |
2252 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
2253 | grn_obj *target = grn_ctx_at(ctx, data->target); |
2254 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
2255 | if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } |
2256 | } |
2257 | rc = grn_dat_truncate(ctx, (grn_dat *)table); |
2258 | break; |
2259 | case GRN_TABLE_HASH_KEY : |
2260 | for (hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; hooks; hooks = hooks->next) { |
2261 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
2262 | grn_obj *target = grn_ctx_at(ctx, data->target); |
2263 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
2264 | if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } |
2265 | } |
2266 | rc = grn_hash_truncate(ctx, (grn_hash *)table); |
2267 | break; |
2268 | case GRN_TABLE_NO_KEY : |
2269 | rc = grn_array_truncate(ctx, (grn_array *)table); |
2270 | break; |
2271 | } |
2272 | if (table->header.type != GRN_TABLE_NO_KEY) { |
2273 | grn_obj_set_info(ctx, table, GRN_INFO_DEFAULT_TOKENIZER, tokenizer); |
2274 | grn_obj_set_info(ctx, table, GRN_INFO_NORMALIZER, normalizer); |
2275 | grn_obj_set_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); |
2276 | GRN_OBJ_FIN(ctx, &token_filters); |
2277 | } |
2278 | if (rc == GRN_SUCCESS) { |
2279 | grn_obj_touch(ctx, table, NULL); |
2280 | } |
2281 | } |
2282 | exit : |
2283 | GRN_API_RETURN(rc); |
2284 | } |
2285 | |
2286 | grn_rc |
2287 | grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_table_flags *flags, |
2288 | grn_encoding *encoding, grn_obj **tokenizer, |
2289 | grn_obj **normalizer, |
2290 | grn_obj **token_filters) |
2291 | { |
2292 | grn_rc rc = GRN_INVALID_ARGUMENT; |
2293 | GRN_API_ENTER; |
2294 | if (table) { |
2295 | switch (table->header.type) { |
2296 | case GRN_TABLE_PAT_KEY : |
2297 | if (flags) { *flags = ((grn_pat *)table)->header->flags; } |
2298 | if (encoding) { *encoding = ((grn_pat *)table)->encoding; } |
2299 | if (tokenizer) { *tokenizer = ((grn_pat *)table)->tokenizer; } |
2300 | if (normalizer) { *normalizer = ((grn_pat *)table)->normalizer; } |
2301 | if (token_filters) { *token_filters = &(((grn_pat *)table)->token_filters); } |
2302 | rc = GRN_SUCCESS; |
2303 | break; |
2304 | case GRN_TABLE_DAT_KEY : |
2305 | if (flags) { *flags = ((grn_dat *)table)->header->flags; } |
2306 | if (encoding) { *encoding = ((grn_dat *)table)->encoding; } |
2307 | if (tokenizer) { *tokenizer = ((grn_dat *)table)->tokenizer; } |
2308 | if (normalizer) { *normalizer = ((grn_dat *)table)->normalizer; } |
2309 | if (token_filters) { *token_filters = &(((grn_dat *)table)->token_filters); } |
2310 | rc = GRN_SUCCESS; |
2311 | break; |
2312 | case GRN_TABLE_HASH_KEY : |
2313 | if (flags) { *flags = ((grn_hash *)table)->header.common->flags; } |
2314 | if (encoding) { *encoding = ((grn_hash *)table)->encoding; } |
2315 | if (tokenizer) { *tokenizer = ((grn_hash *)table)->tokenizer; } |
2316 | if (normalizer) { *normalizer = ((grn_hash *)table)->normalizer; } |
2317 | if (token_filters) { *token_filters = &(((grn_hash *)table)->token_filters); } |
2318 | rc = GRN_SUCCESS; |
2319 | break; |
2320 | case GRN_TABLE_NO_KEY : |
2321 | if (flags) { *flags = grn_array_get_flags(ctx, ((grn_array *)table)); } |
2322 | if (encoding) { *encoding = GRN_ENC_NONE; } |
2323 | if (tokenizer) { *tokenizer = NULL; } |
2324 | if (normalizer) { *normalizer = NULL; } |
2325 | if (token_filters) { *token_filters = NULL; } |
2326 | rc = GRN_SUCCESS; |
2327 | break; |
2328 | } |
2329 | } |
2330 | GRN_API_RETURN(rc); |
2331 | } |
2332 | |
2333 | unsigned int |
2334 | grn_table_size(grn_ctx *ctx, grn_obj *table) |
2335 | { |
2336 | unsigned int n = 0; |
2337 | GRN_API_ENTER; |
2338 | if (table) { |
2339 | switch (table->header.type) { |
2340 | case GRN_DB : |
2341 | n = grn_table_size(ctx, ((grn_db *)table)->keys); |
2342 | break; |
2343 | case GRN_TABLE_PAT_KEY : |
2344 | n = grn_pat_size(ctx, (grn_pat *)table); |
2345 | break; |
2346 | case GRN_TABLE_DAT_KEY : |
2347 | n = grn_dat_size(ctx, (grn_dat *)table); |
2348 | break; |
2349 | case GRN_TABLE_HASH_KEY : |
2350 | n = grn_hash_size(ctx, (grn_hash *)table); |
2351 | break; |
2352 | case GRN_TABLE_NO_KEY : |
2353 | n = grn_array_size(ctx, (grn_array *)table); |
2354 | break; |
2355 | default : |
2356 | ERR(GRN_INVALID_ARGUMENT, "not supported" ); |
2357 | break; |
2358 | } |
2359 | } else { |
2360 | ERR(GRN_INVALID_ARGUMENT, "invalid table assigned" ); |
2361 | } |
2362 | GRN_API_RETURN(n); |
2363 | } |
2364 | |
2365 | inline static void |
2366 | subrecs_push(byte *subrecs, int size, int n_subrecs, double score, void *body, int dir) |
2367 | { |
2368 | byte *v; |
2369 | double *c2; |
2370 | int n = n_subrecs - 1, n2; |
2371 | while (n) { |
2372 | n2 = (n - 1) >> 1; |
2373 | c2 = GRN_RSET_SUBRECS_NTH(subrecs,size,n2); |
2374 | if (GRN_RSET_SUBRECS_CMP(score, *c2, dir) >= 0) { break; } |
2375 | GRN_RSET_SUBRECS_COPY(subrecs,size,n,c2); |
2376 | n = n2; |
2377 | } |
2378 | v = subrecs + n * (GRN_RSET_SCORE_SIZE + size); |
2379 | *((double *)v) = score; |
2380 | grn_memcpy(v + GRN_RSET_SCORE_SIZE, body, size); |
2381 | } |
2382 | |
2383 | inline static void |
2384 | subrecs_replace_min(byte *subrecs, int size, int n_subrecs, double score, void *body, int dir) |
2385 | { |
2386 | byte *v; |
2387 | int n = 0, n1, n2; |
2388 | double *c1, *c2; |
2389 | for (;;) { |
2390 | n1 = n * 2 + 1; |
2391 | n2 = n1 + 1; |
2392 | c1 = n1 < n_subrecs ? GRN_RSET_SUBRECS_NTH(subrecs,size,n1) : NULL; |
2393 | c2 = n2 < n_subrecs ? GRN_RSET_SUBRECS_NTH(subrecs,size,n2) : NULL; |
2394 | if (c1 && GRN_RSET_SUBRECS_CMP(score, *c1, dir) > 0) { |
2395 | if (c2 && |
2396 | GRN_RSET_SUBRECS_CMP(score, *c2, dir) > 0 && |
2397 | GRN_RSET_SUBRECS_CMP(*c1, *c2, dir) > 0) { |
2398 | GRN_RSET_SUBRECS_COPY(subrecs,size,n,c2); |
2399 | n = n2; |
2400 | } else { |
2401 | GRN_RSET_SUBRECS_COPY(subrecs,size,n,c1); |
2402 | n = n1; |
2403 | } |
2404 | } else { |
2405 | if (c2 && GRN_RSET_SUBRECS_CMP(score, *c2, dir) > 0) { |
2406 | GRN_RSET_SUBRECS_COPY(subrecs,size,n,c2); |
2407 | n = n2; |
2408 | } else { |
2409 | break; |
2410 | } |
2411 | } |
2412 | } |
2413 | v = subrecs + n * (GRN_RSET_SCORE_SIZE + size); |
2414 | grn_memcpy(v, &score, GRN_RSET_SCORE_SIZE); |
2415 | grn_memcpy(v + GRN_RSET_SCORE_SIZE, body, size); |
2416 | } |
2417 | |
2418 | inline static void |
2419 | grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, double score, |
2420 | grn_rset_posinfo *pi, int dir) |
2421 | { |
2422 | if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { |
2423 | int limit = DB_OBJ(table)->max_n_subrecs; |
2424 | ri->score += score; |
2425 | ri->n_subrecs += 1; |
2426 | if (limit) { |
2427 | int subrec_size = DB_OBJ(table)->subrec_size; |
2428 | int n_subrecs = GRN_RSET_N_SUBRECS(ri); |
2429 | if (pi) { |
2430 | byte *body = (byte *)pi + DB_OBJ(table)->subrec_offset; |
2431 | if (limit < n_subrecs) { |
2432 | if (GRN_RSET_SUBRECS_CMP(score, *((double *)(ri->subrecs)), dir) > 0) { |
2433 | subrecs_replace_min((byte *)ri->subrecs, subrec_size, limit, score, body, dir); |
2434 | } |
2435 | } else { |
2436 | subrecs_push((byte *)ri->subrecs, subrec_size, n_subrecs, score, body, dir); |
2437 | } |
2438 | } |
2439 | } |
2440 | } |
2441 | } |
2442 | |
2443 | void |
2444 | grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, double score, |
2445 | grn_rset_posinfo *pi, int dir) |
2446 | { |
2447 | grn_table_add_subrec_inline(table, ri, score, pi, dir); |
2448 | } |
2449 | |
2450 | grn_table_cursor * |
2451 | grn_table_cursor_open(grn_ctx *ctx, grn_obj *table, |
2452 | const void *min, unsigned int min_size, |
2453 | const void *max, unsigned int max_size, |
2454 | int offset, int limit, int flags) |
2455 | { |
2456 | grn_rc rc; |
2457 | grn_table_cursor *tc = NULL; |
2458 | unsigned int table_size; |
2459 | if (!table) { return tc; } |
2460 | GRN_API_ENTER; |
2461 | table_size = grn_table_size(ctx, table); |
2462 | if (flags & GRN_CURSOR_PREFIX) { |
2463 | if (offset < 0) { |
2464 | ERR(GRN_TOO_SMALL_OFFSET, |
2465 | "can't use negative offset with GRN_CURSOR_PREFIX: %d" , offset); |
2466 | } else if (offset != 0 && offset >= table_size) { |
2467 | ERR(GRN_TOO_LARGE_OFFSET, |
2468 | "offset is not less than table size: offset:%d, table_size:%d" , |
2469 | offset, table_size); |
2470 | } else { |
2471 | if (limit < -1) { |
2472 | ERR(GRN_TOO_SMALL_LIMIT, |
2473 | "can't use smaller limit than -1 with GRN_CURSOR_PREFIX: %d" , |
2474 | limit); |
2475 | } else if (limit == -1) { |
2476 | limit = table_size; |
2477 | } |
2478 | } |
2479 | } else { |
2480 | rc = grn_normalize_offset_and_limit(ctx, table_size, &offset, &limit); |
2481 | if (rc) { |
2482 | ERR(rc, "grn_normalize_offset_and_limit failed" ); |
2483 | } |
2484 | } |
2485 | if (!ctx->rc) { |
2486 | if (table->header.type == GRN_DB) { table = ((grn_db *)table)->keys; } |
2487 | switch (table->header.type) { |
2488 | case GRN_TABLE_PAT_KEY : |
2489 | { |
2490 | grn_pat *pat = (grn_pat *)table; |
2491 | WITH_NORMALIZE(pat, min, min_size, { |
2492 | WITH_NORMALIZE(pat, max, max_size, { |
2493 | grn_pat_cursor *pat_cursor; |
2494 | pat_cursor = grn_pat_cursor_open(ctx, pat, |
2495 | min, min_size, |
2496 | max, max_size, |
2497 | offset, limit, flags); |
2498 | tc = (grn_table_cursor *)pat_cursor; |
2499 | }); |
2500 | }); |
2501 | } |
2502 | break; |
2503 | case GRN_TABLE_DAT_KEY : |
2504 | { |
2505 | grn_dat *dat = (grn_dat *)table; |
2506 | WITH_NORMALIZE(dat, min, min_size, { |
2507 | WITH_NORMALIZE(dat, max, max_size, { |
2508 | grn_dat_cursor *dat_cursor; |
2509 | dat_cursor = grn_dat_cursor_open(ctx, dat, |
2510 | min, min_size, |
2511 | max, max_size, |
2512 | offset, limit, flags); |
2513 | tc = (grn_table_cursor *)dat_cursor; |
2514 | }); |
2515 | }); |
2516 | } |
2517 | break; |
2518 | case GRN_TABLE_HASH_KEY : |
2519 | { |
2520 | grn_hash *hash = (grn_hash *)table; |
2521 | WITH_NORMALIZE(hash, min, min_size, { |
2522 | WITH_NORMALIZE(hash, max, max_size, { |
2523 | grn_hash_cursor *hash_cursor; |
2524 | hash_cursor = grn_hash_cursor_open(ctx, hash, |
2525 | min, min_size, |
2526 | max, max_size, |
2527 | offset, limit, flags); |
2528 | tc = (grn_table_cursor *)hash_cursor; |
2529 | }); |
2530 | }); |
2531 | } |
2532 | break; |
2533 | case GRN_TABLE_NO_KEY : |
2534 | tc = (grn_table_cursor *)grn_array_cursor_open(ctx, (grn_array *)table, |
2535 | GRN_ID_NIL, GRN_ID_NIL, |
2536 | offset, limit, flags); |
2537 | break; |
2538 | } |
2539 | } |
2540 | if (tc) { |
2541 | grn_id id = grn_obj_register(ctx, ctx->impl->db, NULL, 0); |
2542 | DB_OBJ(tc)->header.domain = GRN_ID_NIL; |
2543 | DB_OBJ(tc)->range = GRN_ID_NIL; |
2544 | grn_db_obj_init(ctx, ctx->impl->db, id, DB_OBJ(tc)); |
2545 | } |
2546 | GRN_API_RETURN(tc); |
2547 | } |
2548 | |
2549 | grn_table_cursor * |
2550 | grn_table_cursor_open_by_id(grn_ctx *ctx, grn_obj *table, |
2551 | grn_id min, grn_id max, int flags) |
2552 | { |
2553 | grn_table_cursor *tc = NULL; |
2554 | GRN_API_ENTER; |
2555 | if (table) { |
2556 | switch (table->header.type) { |
2557 | case GRN_TABLE_PAT_KEY : |
2558 | tc = (grn_table_cursor *)grn_pat_cursor_open(ctx, (grn_pat *)table, |
2559 | NULL, 0, NULL, 0, 0, -1, flags); |
2560 | break; |
2561 | case GRN_TABLE_DAT_KEY : |
2562 | tc = (grn_table_cursor *)grn_dat_cursor_open(ctx, (grn_dat *)table, |
2563 | NULL, 0, NULL, 0, 0, -1, flags); |
2564 | break; |
2565 | case GRN_TABLE_HASH_KEY : |
2566 | tc = (grn_table_cursor *)grn_hash_cursor_open(ctx, (grn_hash *)table, |
2567 | NULL, 0, NULL, 0, 0, -1, flags); |
2568 | break; |
2569 | case GRN_TABLE_NO_KEY : |
2570 | tc = (grn_table_cursor *)grn_array_cursor_open(ctx, (grn_array *)table, |
2571 | min, max, 0, -1, flags); |
2572 | break; |
2573 | } |
2574 | } |
2575 | GRN_API_RETURN(tc); |
2576 | } |
2577 | |
2578 | grn_rc |
2579 | grn_table_cursor_close(grn_ctx *ctx, grn_table_cursor *tc) |
2580 | { |
2581 | const char *tag = "[table][cursor][close]" ; |
2582 | grn_rc rc = GRN_SUCCESS; |
2583 | GRN_API_ENTER; |
2584 | if (!tc) { |
2585 | rc = GRN_INVALID_ARGUMENT; |
2586 | ERR(rc, "%s invalid cursor" , tag); |
2587 | } else { |
2588 | { |
2589 | if (DB_OBJ(tc)->finalizer) { |
2590 | DB_OBJ(tc)->finalizer(ctx, 1, (grn_obj **)&tc, &DB_OBJ(tc)->user_data); |
2591 | } |
2592 | if (DB_OBJ(tc)->source) { |
2593 | GRN_FREE(DB_OBJ(tc)->source); |
2594 | } |
2595 | /* |
2596 | grn_hook_entry entry; |
2597 | for (entry = 0; entry < N_HOOK_ENTRIES; entry++) { |
2598 | grn_hook_free(ctx, DB_OBJ(tc)->hooks[entry]); |
2599 | } |
2600 | */ |
2601 | grn_obj_delete_by_id(ctx, DB_OBJ(tc)->db, DB_OBJ(tc)->id, GRN_FALSE); |
2602 | } |
2603 | switch (tc->header.type) { |
2604 | case GRN_CURSOR_TABLE_PAT_KEY : |
2605 | grn_pat_cursor_close(ctx, (grn_pat_cursor *)tc); |
2606 | break; |
2607 | case GRN_CURSOR_TABLE_DAT_KEY : |
2608 | grn_dat_cursor_close(ctx, (grn_dat_cursor *)tc); |
2609 | break; |
2610 | case GRN_CURSOR_TABLE_HASH_KEY : |
2611 | grn_hash_cursor_close(ctx, (grn_hash_cursor *)tc); |
2612 | break; |
2613 | case GRN_CURSOR_TABLE_NO_KEY : |
2614 | grn_array_cursor_close(ctx, (grn_array_cursor *)tc); |
2615 | break; |
2616 | default : |
2617 | rc = GRN_INVALID_ARGUMENT; |
2618 | ERR(rc, "%s invalid type %d" , tag, tc->header.type); |
2619 | break; |
2620 | } |
2621 | } |
2622 | GRN_API_RETURN(rc); |
2623 | } |
2624 | |
2625 | inline static grn_id |
2626 | grn_table_cursor_next_inline(grn_ctx *ctx, grn_table_cursor *tc) |
2627 | { |
2628 | const char *tag = "[table][cursor][next]" ; |
2629 | grn_id id = GRN_ID_NIL; |
2630 | if (!tc) { |
2631 | ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor" , tag); |
2632 | } else { |
2633 | switch (tc->header.type) { |
2634 | case GRN_CURSOR_TABLE_PAT_KEY : |
2635 | id = grn_pat_cursor_next(ctx, (grn_pat_cursor *)tc); |
2636 | break; |
2637 | case GRN_CURSOR_TABLE_DAT_KEY : |
2638 | id = grn_dat_cursor_next(ctx, (grn_dat_cursor *)tc); |
2639 | break; |
2640 | case GRN_CURSOR_TABLE_HASH_KEY : |
2641 | id = grn_hash_cursor_next(ctx, (grn_hash_cursor *)tc); |
2642 | break; |
2643 | case GRN_CURSOR_TABLE_NO_KEY : |
2644 | id = grn_array_cursor_next(ctx, (grn_array_cursor *)tc); |
2645 | break; |
2646 | case GRN_CURSOR_COLUMN_INDEX : |
2647 | { |
2648 | grn_posting *ip = grn_index_cursor_next(ctx, (grn_obj *)tc, NULL); |
2649 | if (ip) { id = ip->rid; } |
2650 | } |
2651 | break; |
2652 | default : |
2653 | ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d" , tag, tc->header.type); |
2654 | break; |
2655 | } |
2656 | } |
2657 | return id; |
2658 | } |
2659 | |
2660 | grn_id |
2661 | grn_table_cursor_next(grn_ctx *ctx, grn_table_cursor *tc) |
2662 | { |
2663 | grn_id id; |
2664 | GRN_API_ENTER; |
2665 | id = grn_table_cursor_next_inline(ctx, tc); |
2666 | GRN_API_RETURN(id); |
2667 | } |
2668 | |
2669 | int |
2670 | grn_table_cursor_get_key(grn_ctx *ctx, grn_table_cursor *tc, void **key) |
2671 | { |
2672 | const char *tag = "[table][cursor][get-key]" ; |
2673 | int len = 0; |
2674 | GRN_API_ENTER; |
2675 | if (!tc) { |
2676 | ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor" , tag); |
2677 | } else { |
2678 | switch (tc->header.type) { |
2679 | case GRN_CURSOR_TABLE_PAT_KEY : |
2680 | len = grn_pat_cursor_get_key(ctx, (grn_pat_cursor *)tc, key); |
2681 | break; |
2682 | case GRN_CURSOR_TABLE_DAT_KEY : |
2683 | len = grn_dat_cursor_get_key(ctx, (grn_dat_cursor *)tc, (const void **)key); |
2684 | break; |
2685 | case GRN_CURSOR_TABLE_HASH_KEY : |
2686 | len = grn_hash_cursor_get_key(ctx, (grn_hash_cursor *)tc, key); |
2687 | break; |
2688 | default : |
2689 | ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d" , tag, tc->header.type); |
2690 | break; |
2691 | } |
2692 | } |
2693 | GRN_API_RETURN(len); |
2694 | } |
2695 | |
2696 | inline static int |
2697 | grn_table_cursor_get_value_inline(grn_ctx *ctx, grn_table_cursor *tc, void **value) |
2698 | { |
2699 | const char *tag = "[table][cursor][get-value]" ; |
2700 | int len = 0; |
2701 | if (!tc) { |
2702 | ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor" , tag); |
2703 | } else { |
2704 | switch (tc->header.type) { |
2705 | case GRN_CURSOR_TABLE_PAT_KEY : |
2706 | len = grn_pat_cursor_get_value(ctx, (grn_pat_cursor *)tc, value); |
2707 | break; |
2708 | case GRN_CURSOR_TABLE_DAT_KEY : |
2709 | *value = NULL; |
2710 | len = 0; |
2711 | break; |
2712 | case GRN_CURSOR_TABLE_HASH_KEY : |
2713 | len = grn_hash_cursor_get_value(ctx, (grn_hash_cursor *)tc, value); |
2714 | break; |
2715 | case GRN_CURSOR_TABLE_NO_KEY : |
2716 | len = grn_array_cursor_get_value(ctx, (grn_array_cursor *)tc, value); |
2717 | break; |
2718 | default : |
2719 | ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d" , tag, tc->header.type); |
2720 | break; |
2721 | } |
2722 | } |
2723 | return len; |
2724 | } |
2725 | |
2726 | int |
2727 | grn_table_cursor_get_value(grn_ctx *ctx, grn_table_cursor *tc, void **value) |
2728 | { |
2729 | int len; |
2730 | GRN_API_ENTER; |
2731 | len = grn_table_cursor_get_value_inline(ctx, tc, value); |
2732 | GRN_API_RETURN(len); |
2733 | } |
2734 | |
2735 | grn_rc |
2736 | grn_table_cursor_set_value(grn_ctx *ctx, grn_table_cursor *tc, |
2737 | const void *value, int flags) |
2738 | { |
2739 | const char *tag = "[table][cursor][set-value]" ; |
2740 | grn_rc rc = GRN_INVALID_ARGUMENT; |
2741 | GRN_API_ENTER; |
2742 | if (!tc) { |
2743 | ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor" , tag); |
2744 | } else { |
2745 | switch (tc->header.type) { |
2746 | case GRN_CURSOR_TABLE_PAT_KEY : |
2747 | rc = grn_pat_cursor_set_value(ctx, (grn_pat_cursor *)tc, value, flags); |
2748 | break; |
2749 | case GRN_CURSOR_TABLE_DAT_KEY : |
2750 | rc = GRN_OPERATION_NOT_SUPPORTED; |
2751 | break; |
2752 | case GRN_CURSOR_TABLE_HASH_KEY : |
2753 | rc = grn_hash_cursor_set_value(ctx, (grn_hash_cursor *)tc, value, flags); |
2754 | break; |
2755 | case GRN_CURSOR_TABLE_NO_KEY : |
2756 | rc = grn_array_cursor_set_value(ctx, (grn_array_cursor *)tc, value, flags); |
2757 | break; |
2758 | default : |
2759 | ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d" , tag, tc->header.type); |
2760 | break; |
2761 | } |
2762 | } |
2763 | GRN_API_RETURN(rc); |
2764 | } |
2765 | |
2766 | grn_rc |
2767 | grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc) |
2768 | { |
2769 | const char *tag = "[table][cursor][delete]" ; |
2770 | grn_rc rc = GRN_INVALID_ARGUMENT; |
2771 | GRN_API_ENTER; |
2772 | if (!tc) { |
2773 | ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor" , tag); |
2774 | } else { |
2775 | grn_id id; |
2776 | grn_obj *table; |
2777 | const void *key = NULL; |
2778 | unsigned int key_size = 0; |
2779 | switch (tc->header.type) { |
2780 | case GRN_CURSOR_TABLE_PAT_KEY : |
2781 | { |
2782 | grn_pat_cursor *pc = (grn_pat_cursor *)tc; |
2783 | id = pc->curr_rec; |
2784 | table = (grn_obj *)(pc->pat); |
2785 | key = _grn_pat_key(ctx, pc->pat, id, &key_size); |
2786 | rc = grn_table_delete_prepare(ctx, table, id, key, key_size); |
2787 | if (rc != GRN_SUCCESS) { |
2788 | goto exit; |
2789 | } |
2790 | rc = grn_pat_cursor_delete(ctx, pc, NULL); |
2791 | } |
2792 | break; |
2793 | case GRN_CURSOR_TABLE_DAT_KEY : |
2794 | rc = GRN_OPERATION_NOT_SUPPORTED; |
2795 | break; |
2796 | case GRN_CURSOR_TABLE_HASH_KEY : |
2797 | { |
2798 | grn_hash_cursor *hc = (grn_hash_cursor *)tc; |
2799 | id = hc->curr_rec; |
2800 | table = (grn_obj *)(hc->hash); |
2801 | key = _grn_hash_key(ctx, hc->hash, id, &key_size); |
2802 | rc = grn_table_delete_prepare(ctx, table, id, key, key_size); |
2803 | if (rc != GRN_SUCCESS) { |
2804 | goto exit; |
2805 | } |
2806 | rc = grn_hash_cursor_delete(ctx, hc, NULL); |
2807 | } |
2808 | break; |
2809 | case GRN_CURSOR_TABLE_NO_KEY : |
2810 | { |
2811 | grn_array_cursor *ac = (grn_array_cursor *)tc; |
2812 | id = ac->curr_rec; |
2813 | table = (grn_obj *)(ac->array); |
2814 | rc = grn_table_delete_prepare(ctx, table, id, key, key_size); |
2815 | if (rc != GRN_SUCCESS) { |
2816 | goto exit; |
2817 | } |
2818 | rc = grn_array_cursor_delete(ctx, ac, NULL); |
2819 | } |
2820 | break; |
2821 | default : |
2822 | ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d" , tag, tc->header.type); |
2823 | break; |
2824 | } |
2825 | } |
2826 | exit : |
2827 | GRN_API_RETURN(rc); |
2828 | } |
2829 | |
2830 | grn_obj * |
2831 | grn_table_cursor_table(grn_ctx *ctx, grn_table_cursor *tc) |
2832 | { |
2833 | const char *tag = "[table][cursor][table]" ; |
2834 | grn_obj *obj = NULL; |
2835 | GRN_API_ENTER; |
2836 | if (!tc) { |
2837 | ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor" , tag); |
2838 | } else { |
2839 | switch (tc->header.type) { |
2840 | case GRN_CURSOR_TABLE_PAT_KEY : |
2841 | obj = (grn_obj *)(((grn_pat_cursor *)tc)->pat); |
2842 | break; |
2843 | case GRN_CURSOR_TABLE_DAT_KEY : |
2844 | obj = (grn_obj *)(((grn_dat_cursor *)tc)->dat); |
2845 | break; |
2846 | case GRN_CURSOR_TABLE_HASH_KEY : |
2847 | obj = (grn_obj *)(((grn_hash_cursor *)tc)->hash); |
2848 | break; |
2849 | case GRN_CURSOR_TABLE_NO_KEY : |
2850 | obj = (grn_obj *)(((grn_array_cursor *)tc)->array); |
2851 | break; |
2852 | default : |
2853 | ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d" , tag, tc->header.type); |
2854 | break; |
2855 | } |
2856 | } |
2857 | GRN_API_RETURN(obj); |
2858 | } |
2859 | |
2860 | typedef struct { |
2861 | grn_db_obj obj; |
2862 | grn_obj *index; |
2863 | grn_table_cursor *tc; |
2864 | grn_ii_cursor *iic; |
2865 | grn_id tid; |
2866 | grn_id rid_min; |
2867 | grn_id rid_max; |
2868 | int flags; |
2869 | } grn_index_cursor; |
2870 | |
2871 | grn_obj * |
2872 | grn_index_cursor_open(grn_ctx *ctx, grn_table_cursor *tc, |
2873 | grn_obj *index, grn_id rid_min, grn_id rid_max, int flags) |
2874 | { |
2875 | grn_index_cursor *ic = NULL; |
2876 | GRN_API_ENTER; |
2877 | if (tc && (ic = GRN_MALLOCN(grn_index_cursor, 1))) { |
2878 | ic->tc = tc; |
2879 | ic->index = index; |
2880 | ic->iic = NULL; |
2881 | ic->tid = GRN_ID_NIL; |
2882 | ic->rid_min = rid_min; |
2883 | ic->rid_max = rid_max; |
2884 | ic->flags = flags; |
2885 | GRN_DB_OBJ_SET_TYPE(ic, GRN_CURSOR_COLUMN_INDEX); |
2886 | { |
2887 | grn_id id = grn_obj_register(ctx, ctx->impl->db, NULL, 0); |
2888 | DB_OBJ(ic)->header.domain = GRN_ID_NIL; |
2889 | DB_OBJ(ic)->range = GRN_ID_NIL; |
2890 | grn_db_obj_init(ctx, ctx->impl->db, id, DB_OBJ(ic)); |
2891 | } |
2892 | } |
2893 | GRN_API_RETURN((grn_obj *)ic); |
2894 | } |
2895 | |
2896 | grn_posting * |
2897 | grn_index_cursor_next(grn_ctx *ctx, grn_obj *c, grn_id *tid) |
2898 | { |
2899 | grn_posting *ip = NULL; |
2900 | grn_index_cursor *ic = (grn_index_cursor *)c; |
2901 | GRN_API_ENTER; |
2902 | if (ic->iic) { |
2903 | if (ic->flags & GRN_OBJ_WITH_POSITION) { |
2904 | ip = grn_ii_cursor_next_pos(ctx, ic->iic); |
2905 | while (!ip && grn_ii_cursor_next(ctx, ic->iic)) { |
2906 | ip = grn_ii_cursor_next_pos(ctx, ic->iic); |
2907 | break; |
2908 | } |
2909 | } else { |
2910 | ip = grn_ii_cursor_next(ctx, ic->iic); |
2911 | } |
2912 | } |
2913 | if (!ip) { |
2914 | while ((ic->tid = grn_table_cursor_next_inline(ctx, ic->tc))) { |
2915 | grn_ii *ii = (grn_ii *)ic->index; |
2916 | if (ic->iic) { grn_ii_cursor_close(ctx, ic->iic); } |
2917 | if ((ic->iic = grn_ii_cursor_open(ctx, ii, ic->tid, |
2918 | ic->rid_min, ic->rid_max, |
2919 | ii->n_elements, ic->flags))) { |
2920 | ip = grn_ii_cursor_next(ctx, ic->iic); |
2921 | if (ip && ic->flags & GRN_OBJ_WITH_POSITION) { |
2922 | ip = grn_ii_cursor_next_pos(ctx, ic->iic); |
2923 | } |
2924 | if (ip) { |
2925 | break; |
2926 | } |
2927 | } |
2928 | } |
2929 | } |
2930 | if (tid) { *tid = ic->tid; } |
2931 | GRN_API_RETURN((grn_posting *)ip); |
2932 | } |
2933 | |
2934 | grn_rc |
2935 | grn_table_search(grn_ctx *ctx, grn_obj *table, const void *key, uint32_t key_size, |
2936 | grn_operator mode, grn_obj *res, grn_operator op) |
2937 | { |
2938 | grn_rc rc = GRN_SUCCESS; |
2939 | GRN_API_ENTER; |
2940 | switch (table->header.type) { |
2941 | case GRN_TABLE_PAT_KEY : |
2942 | { |
2943 | grn_pat *pat = (grn_pat *)table; |
2944 | WITH_NORMALIZE(pat, key, key_size, { |
2945 | switch (mode) { |
2946 | case GRN_OP_EXACT : |
2947 | { |
2948 | grn_id id = grn_pat_get(ctx, pat, key, key_size, NULL); |
2949 | if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } |
2950 | } |
2951 | // todo : support op; |
2952 | break; |
2953 | case GRN_OP_LCP : |
2954 | { |
2955 | grn_id id = grn_pat_lcp_search(ctx, pat, key, key_size); |
2956 | if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } |
2957 | } |
2958 | // todo : support op; |
2959 | break; |
2960 | case GRN_OP_SUFFIX : |
2961 | rc = grn_pat_suffix_search(ctx, pat, key, key_size, (grn_hash *)res); |
2962 | // todo : support op; |
2963 | break; |
2964 | case GRN_OP_PREFIX : |
2965 | rc = grn_pat_prefix_search(ctx, pat, key, key_size, (grn_hash *)res); |
2966 | // todo : support op; |
2967 | break; |
2968 | case GRN_OP_TERM_EXTRACT : |
2969 | { |
2970 | int len; |
2971 | grn_id tid; |
2972 | const char *sp = key; |
2973 | const char *se = sp + key_size; |
2974 | for (; sp < se; sp += len) { |
2975 | if ((tid = grn_pat_lcp_search(ctx, pat, sp, se - sp))) { |
2976 | grn_table_add(ctx, res, &tid, sizeof(grn_id), NULL); |
2977 | /* todo : nsubrec++ if GRN_OBJ_TABLE_SUBSET assigned */ |
2978 | } |
2979 | if (!(len = grn_charlen(ctx, sp, se))) { break; } |
2980 | } |
2981 | } |
2982 | // todo : support op; |
2983 | break; |
2984 | default : |
2985 | rc = GRN_INVALID_ARGUMENT; |
2986 | ERR(rc, "invalid mode %d" , mode); |
2987 | } |
2988 | }); |
2989 | } |
2990 | break; |
2991 | case GRN_TABLE_DAT_KEY : |
2992 | { |
2993 | grn_dat *dat = (grn_dat *)table; |
2994 | WITH_NORMALIZE(dat, key, key_size, { |
2995 | switch (mode) { |
2996 | case GRN_OP_EXACT : |
2997 | { |
2998 | grn_id id = grn_dat_get(ctx, dat, key, key_size, NULL); |
2999 | if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } |
3000 | } |
3001 | break; |
3002 | case GRN_OP_PREFIX : |
3003 | { |
3004 | grn_dat_cursor *dc = grn_dat_cursor_open(ctx, dat, key, key_size, NULL, 0, |
3005 | 0, -1, GRN_CURSOR_PREFIX); |
3006 | if (dc) { |
3007 | grn_id id; |
3008 | while ((id = grn_dat_cursor_next(ctx, dc))) { |
3009 | grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); |
3010 | } |
3011 | grn_dat_cursor_close(ctx, dc); |
3012 | } |
3013 | } |
3014 | break; |
3015 | case GRN_OP_LCP : |
3016 | { |
3017 | grn_id id = grn_dat_lcp_search(ctx, dat, key, key_size); |
3018 | if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } |
3019 | } |
3020 | break; |
3021 | case GRN_OP_TERM_EXTRACT : |
3022 | { |
3023 | int len; |
3024 | grn_id tid; |
3025 | const char *sp = key; |
3026 | const char *se = sp + key_size; |
3027 | for (; sp < se; sp += len) { |
3028 | if ((tid = grn_dat_lcp_search(ctx, dat, sp, se - sp))) { |
3029 | grn_table_add(ctx, res, &tid, sizeof(grn_id), NULL); |
3030 | /* todo : nsubrec++ if GRN_OBJ_TABLE_SUBSET assigned */ |
3031 | } |
3032 | if (!(len = grn_charlen(ctx, sp, se))) { break; } |
3033 | } |
3034 | } |
3035 | // todo : support op; |
3036 | break; |
3037 | default : |
3038 | rc = GRN_INVALID_ARGUMENT; |
3039 | ERR(rc, "invalid mode %d" , mode); |
3040 | } |
3041 | }); |
3042 | } |
3043 | break; |
3044 | case GRN_TABLE_HASH_KEY : |
3045 | { |
3046 | grn_hash *hash = (grn_hash *)table; |
3047 | grn_id id = GRN_ID_NIL; |
3048 | WITH_NORMALIZE(hash, key, key_size, { |
3049 | id = grn_hash_get(ctx, hash, key, key_size, NULL); |
3050 | }); |
3051 | if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } |
3052 | } |
3053 | break; |
3054 | } |
3055 | GRN_API_RETURN(rc); |
3056 | } |
3057 | |
3058 | grn_rc |
3059 | grn_table_fuzzy_search(grn_ctx *ctx, grn_obj *table, const void *key, uint32_t key_size, |
3060 | grn_fuzzy_search_optarg *args, grn_obj *res, grn_operator op) |
3061 | { |
3062 | grn_rc rc = GRN_SUCCESS; |
3063 | GRN_API_ENTER; |
3064 | switch (table->header.type) { |
3065 | case GRN_TABLE_PAT_KEY : |
3066 | { |
3067 | grn_pat *pat = (grn_pat *)table; |
3068 | if (!grn_table_size(ctx, res) && op == GRN_OP_OR) { |
3069 | WITH_NORMALIZE(pat, key, key_size, { |
3070 | rc = grn_pat_fuzzy_search(ctx, pat, key, key_size, |
3071 | args, (grn_hash *)res); |
3072 | }); |
3073 | } else { |
3074 | grn_obj *hash; |
3075 | hash = grn_table_create(ctx, NULL, 0, NULL, |
3076 | GRN_OBJ_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, |
3077 | table, NULL); |
3078 | WITH_NORMALIZE(pat, key, key_size, { |
3079 | rc = grn_pat_fuzzy_search(ctx, pat, key, key_size, |
3080 | args, (grn_hash *)hash); |
3081 | }); |
3082 | if (rc == GRN_SUCCESS) { |
3083 | rc = grn_table_setoperation(ctx, res, hash, res, op); |
3084 | } |
3085 | grn_obj_unlink(ctx, hash); |
3086 | } |
3087 | } |
3088 | break; |
3089 | default : |
3090 | rc = GRN_OPERATION_NOT_SUPPORTED; |
3091 | break; |
3092 | } |
3093 | GRN_API_RETURN(rc); |
3094 | } |
3095 | |
3096 | grn_id |
3097 | grn_table_next(grn_ctx *ctx, grn_obj *table, grn_id id) |
3098 | { |
3099 | grn_id r = GRN_ID_NIL; |
3100 | GRN_API_ENTER; |
3101 | if (table) { |
3102 | switch (table->header.type) { |
3103 | case GRN_TABLE_PAT_KEY : |
3104 | r = grn_pat_next(ctx, (grn_pat *)table, id); |
3105 | break; |
3106 | case GRN_TABLE_DAT_KEY : |
3107 | r = grn_dat_next(ctx, (grn_dat *)table, id); |
3108 | break; |
3109 | case GRN_TABLE_HASH_KEY : |
3110 | r = grn_hash_next(ctx, (grn_hash *)table, id); |
3111 | break; |
3112 | case GRN_TABLE_NO_KEY : |
3113 | r = grn_array_next(ctx, (grn_array *)table, id); |
3114 | break; |
3115 | } |
3116 | } |
3117 | GRN_API_RETURN(r); |
3118 | } |
3119 | |
3120 | static grn_rc |
3121 | grn_accessor_resolve_one_index_column(grn_ctx *ctx, grn_accessor *accessor, |
3122 | grn_obj *current_res, grn_obj **next_res) |
3123 | { |
3124 | grn_rc rc = GRN_SUCCESS; |
3125 | grn_obj *column = NULL; |
3126 | grn_id next_res_domain_id = GRN_ID_NIL; |
3127 | |
3128 | { |
3129 | grn_obj *index; |
3130 | grn_obj source_ids; |
3131 | unsigned int i, n_ids; |
3132 | |
3133 | index = accessor->obj; |
3134 | next_res_domain_id = index->header.domain; |
3135 | |
3136 | GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); |
3137 | grn_obj_get_info(ctx, index, GRN_INFO_SOURCE, &source_ids); |
3138 | n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); |
3139 | for (i = 0; i < n_ids; i++) { |
3140 | grn_id source_id; |
3141 | grn_obj *source; |
3142 | |
3143 | source_id = GRN_UINT32_VALUE_AT(&source_ids, i); |
3144 | source = grn_ctx_at(ctx, source_id); |
3145 | if (DB_OBJ(source)->range == next_res_domain_id) { |
3146 | column = source; |
3147 | break; |
3148 | } |
3149 | grn_obj_unlink(ctx, source); |
3150 | } |
3151 | |
3152 | if (!column) { |
3153 | return GRN_INVALID_ARGUMENT; |
3154 | } |
3155 | } |
3156 | |
3157 | { |
3158 | grn_rc rc; |
3159 | grn_obj *next_res_domain = grn_ctx_at(ctx, next_res_domain_id); |
3160 | *next_res = grn_table_create(ctx, NULL, 0, NULL, |
3161 | GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, |
3162 | next_res_domain, NULL); |
3163 | rc = ctx->rc; |
3164 | grn_obj_unlink(ctx, next_res_domain); |
3165 | if (!*next_res) { |
3166 | return rc; |
3167 | } |
3168 | } |
3169 | |
3170 | { |
3171 | grn_obj_flags column_value_flags = 0; |
3172 | grn_obj column_value; |
3173 | grn_posting add_posting; |
3174 | grn_id *tid; |
3175 | grn_rset_recinfo *recinfo; |
3176 | |
3177 | if (column->header.type == GRN_COLUMN_VAR_SIZE) { |
3178 | column_value_flags |= GRN_OBJ_VECTOR; |
3179 | } |
3180 | GRN_VALUE_FIX_SIZE_INIT(&column_value, |
3181 | column_value_flags, |
3182 | next_res_domain_id); |
3183 | |
3184 | add_posting.sid = 0; |
3185 | add_posting.pos = 0; |
3186 | add_posting.weight = 0; |
3187 | |
3188 | GRN_HASH_EACH(ctx, (grn_hash *)current_res, id, &tid, NULL, &recinfo, { |
3189 | int i; |
3190 | int n_elements; |
3191 | |
3192 | add_posting.weight = recinfo->score - 1; |
3193 | |
3194 | GRN_BULK_REWIND(&column_value); |
3195 | grn_obj_get_value(ctx, column, *tid, &column_value); |
3196 | |
3197 | n_elements = GRN_BULK_VSIZE(&column_value) / sizeof(grn_id); |
3198 | for (i = 0; i < n_elements; i++) { |
3199 | add_posting.rid = GRN_RECORD_VALUE_AT(&column_value, i); |
3200 | rc = grn_ii_posting_add(ctx, |
3201 | &add_posting, |
3202 | (grn_hash *)*next_res, |
3203 | GRN_OP_OR); |
3204 | if (rc != GRN_SUCCESS) { |
3205 | break; |
3206 | } |
3207 | } |
3208 | if (rc != GRN_SUCCESS) { |
3209 | break; |
3210 | } |
3211 | }); |
3212 | |
3213 | GRN_OBJ_FIN(ctx, &column_value); |
3214 | } |
3215 | |
3216 | if (rc != GRN_SUCCESS) { |
3217 | grn_obj_unlink(ctx, *next_res); |
3218 | } |
3219 | |
3220 | return rc; |
3221 | } |
3222 | |
3223 | static grn_rc |
3224 | grn_accessor_resolve_one_table(grn_ctx *ctx, grn_accessor *accessor, |
3225 | grn_obj *current_res, grn_obj **next_res) |
3226 | { |
3227 | grn_rc rc = GRN_SUCCESS; |
3228 | grn_obj *table; |
3229 | |
3230 | table = accessor->obj; |
3231 | *next_res = grn_table_create(ctx, NULL, 0, NULL, |
3232 | GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, |
3233 | table, NULL); |
3234 | if (!*next_res) { |
3235 | return ctx->rc; |
3236 | } |
3237 | |
3238 | grn_report_table(ctx, |
3239 | "[accessor][resolve]" , |
3240 | "" , |
3241 | table); |
3242 | |
3243 | { |
3244 | grn_posting posting; |
3245 | |
3246 | memset(&posting, 0, sizeof(posting)); |
3247 | GRN_HASH_EACH_BEGIN(ctx, (grn_hash *)current_res, cursor, id) { |
3248 | void *key; |
3249 | void *value; |
3250 | grn_id *record_id; |
3251 | grn_rset_recinfo *recinfo; |
3252 | grn_id next_record_id; |
3253 | |
3254 | grn_hash_cursor_get_key_value(ctx, cursor, &key, NULL, &value); |
3255 | record_id = key; |
3256 | recinfo = value; |
3257 | next_record_id = grn_table_get(ctx, |
3258 | table, |
3259 | record_id, |
3260 | sizeof(grn_id)); |
3261 | if (next_record_id == GRN_ID_NIL) { |
3262 | continue; |
3263 | } |
3264 | |
3265 | posting.rid = next_record_id; |
3266 | posting.weight = recinfo->score; |
3267 | rc = grn_ii_posting_add(ctx, |
3268 | &posting, |
3269 | (grn_hash *)*next_res, |
3270 | GRN_OP_OR); |
3271 | if (rc != GRN_SUCCESS) { |
3272 | break; |
3273 | } |
3274 | } GRN_HASH_EACH_END(ctx, cursor); |
3275 | } |
3276 | |
3277 | if (rc != GRN_SUCCESS) { |
3278 | grn_obj_unlink(ctx, *next_res); |
3279 | } |
3280 | |
3281 | return rc; |
3282 | } |
3283 | |
3284 | static grn_rc |
3285 | grn_accessor_resolve_one_data_column(grn_ctx *ctx, grn_accessor *accessor, |
3286 | grn_obj *current_res, grn_obj **next_res) |
3287 | { |
3288 | grn_rc rc = GRN_SUCCESS; |
3289 | grn_index_datum index_datum; |
3290 | unsigned int n_index_data; |
3291 | grn_id next_res_domain_id = GRN_ID_NIL; |
3292 | |
3293 | n_index_data = grn_column_get_all_index_data(ctx, |
3294 | accessor->obj, |
3295 | &index_datum, |
3296 | 1); |
3297 | if (n_index_data == 0) { |
3298 | return GRN_INVALID_ARGUMENT; |
3299 | } |
3300 | |
3301 | { |
3302 | grn_obj *lexicon; |
3303 | lexicon = grn_ctx_at(ctx, index_datum.index->header.domain); |
3304 | if (grn_obj_id(ctx, lexicon) != current_res->header.domain) { |
3305 | char index_name[GRN_TABLE_MAX_KEY_SIZE]; |
3306 | int index_name_size; |
3307 | grn_obj *expected; |
3308 | char expected_name[GRN_TABLE_MAX_KEY_SIZE]; |
3309 | int expected_name_size; |
3310 | |
3311 | index_name_size = grn_obj_name(ctx, |
3312 | index_datum.index, |
3313 | index_name, |
3314 | GRN_TABLE_MAX_KEY_SIZE); |
3315 | expected = grn_ctx_at(ctx, current_res->header.domain); |
3316 | expected_name_size = grn_obj_name(ctx, |
3317 | expected, |
3318 | expected_name, |
3319 | GRN_TABLE_MAX_KEY_SIZE); |
3320 | ERR(GRN_INVALID_ARGUMENT, |
3321 | "[accessor][resolve][data-column] lexicon mismatch index: " |
3322 | "<%.*s> " |
3323 | "expected:<%.*s>" , |
3324 | index_name_size, |
3325 | index_name, |
3326 | expected_name_size, |
3327 | expected_name); |
3328 | return ctx->rc; |
3329 | } |
3330 | } |
3331 | |
3332 | next_res_domain_id = DB_OBJ(index_datum.index)->range; |
3333 | |
3334 | grn_report_index(ctx, |
3335 | "[accessor][resolve][data-column]" , |
3336 | "" , |
3337 | index_datum.index); |
3338 | { |
3339 | grn_rc rc; |
3340 | grn_obj *next_res_domain = grn_ctx_at(ctx, next_res_domain_id); |
3341 | *next_res = grn_table_create(ctx, NULL, 0, NULL, |
3342 | GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, |
3343 | next_res_domain, NULL); |
3344 | rc = ctx->rc; |
3345 | grn_obj_unlink(ctx, next_res_domain); |
3346 | if (!*next_res) { |
3347 | return rc; |
3348 | } |
3349 | } |
3350 | |
3351 | { |
3352 | grn_id *tid; |
3353 | grn_rset_recinfo *recinfo; |
3354 | |
3355 | GRN_HASH_EACH(ctx, (grn_hash *)current_res, id, &tid, NULL, &recinfo, { |
3356 | grn_ii *ii = (grn_ii *)(index_datum.index); |
3357 | grn_ii_cursor *ii_cursor; |
3358 | grn_posting *posting; |
3359 | |
3360 | ii_cursor = grn_ii_cursor_open(ctx, ii, *tid, |
3361 | GRN_ID_NIL, GRN_ID_MAX, |
3362 | ii->n_elements, |
3363 | 0); |
3364 | if (!ii_cursor) { |
3365 | continue; |
3366 | } |
3367 | |
3368 | while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) { |
3369 | grn_posting add_posting; |
3370 | |
3371 | if (index_datum.section > 0 && posting->sid != index_datum.section) { |
3372 | continue; |
3373 | } |
3374 | |
3375 | add_posting = *posting; |
3376 | add_posting.weight += recinfo->score - 1; |
3377 | rc = grn_ii_posting_add(ctx, |
3378 | &add_posting, |
3379 | (grn_hash *)*next_res, |
3380 | GRN_OP_OR); |
3381 | if (rc != GRN_SUCCESS) { |
3382 | break; |
3383 | } |
3384 | } |
3385 | grn_ii_cursor_close(ctx, ii_cursor); |
3386 | |
3387 | if (rc != GRN_SUCCESS) { |
3388 | break; |
3389 | } |
3390 | }); |
3391 | } |
3392 | |
3393 | if (rc != GRN_SUCCESS) { |
3394 | grn_obj_unlink(ctx, *next_res); |
3395 | } |
3396 | |
3397 | return rc; |
3398 | } |
3399 | |
3400 | grn_rc |
3401 | grn_accessor_resolve(grn_ctx *ctx, grn_obj *accessor, int deep, |
3402 | grn_obj *base_res, grn_obj *res, |
3403 | grn_operator op) |
3404 | { |
3405 | grn_rc rc = GRN_SUCCESS; |
3406 | grn_accessor *a; |
3407 | grn_obj accessor_stack; |
3408 | int i, n_accessors; |
3409 | grn_obj *current_res = base_res; |
3410 | |
3411 | GRN_PTR_INIT(&accessor_stack, GRN_OBJ_VECTOR, GRN_ID_NIL); |
3412 | n_accessors = 0; |
3413 | for (a = (grn_accessor *)accessor; a; a = a->next) { |
3414 | if (deep == n_accessors) { |
3415 | break; |
3416 | } |
3417 | GRN_PTR_PUT(ctx, &accessor_stack, a); |
3418 | n_accessors++; |
3419 | } |
3420 | |
3421 | for (i = n_accessors; i > 0; i--) { |
3422 | grn_obj *next_res = NULL; |
3423 | |
3424 | a = (grn_accessor *)GRN_PTR_VALUE_AT(&accessor_stack, i - 1); |
3425 | if (a->obj->header.type == GRN_COLUMN_INDEX) { |
3426 | rc = grn_accessor_resolve_one_index_column(ctx, a, |
3427 | current_res, &next_res); |
3428 | } else if (grn_obj_is_table(ctx, a->obj)) { |
3429 | rc = grn_accessor_resolve_one_table(ctx, a, |
3430 | current_res, &next_res); |
3431 | } else { |
3432 | rc = grn_accessor_resolve_one_data_column(ctx, a, |
3433 | current_res, &next_res); |
3434 | } |
3435 | |
3436 | if (current_res != base_res) { |
3437 | grn_obj_unlink(ctx, current_res); |
3438 | } |
3439 | |
3440 | if (rc != GRN_SUCCESS) { |
3441 | break; |
3442 | } |
3443 | |
3444 | current_res = next_res; |
3445 | } |
3446 | |
3447 | if (rc == GRN_SUCCESS && current_res != base_res) { |
3448 | grn_id *record_id; |
3449 | grn_rset_recinfo *recinfo; |
3450 | GRN_HASH_EACH(ctx, (grn_hash *)current_res, id, &record_id, NULL, &recinfo, { |
3451 | grn_posting posting; |
3452 | posting.rid = *record_id; |
3453 | posting.sid = 1; |
3454 | posting.pos = 0; |
3455 | posting.weight = recinfo->score - 1; |
3456 | grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); |
3457 | }); |
3458 | grn_obj_unlink(ctx, current_res); |
3459 | grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); |
3460 | } else { |
3461 | if (rc == GRN_SUCCESS) { |
3462 | rc = GRN_INVALID_ARGUMENT; |
3463 | } |
3464 | } |
3465 | |
3466 | GRN_OBJ_FIN(ctx, &accessor_stack); |
3467 | return rc; |
3468 | } |
3469 | |
3470 | static inline void |
3471 | grn_obj_search_index_report(grn_ctx *ctx, const char *tag, grn_obj *index) |
3472 | { |
3473 | grn_report_index(ctx, "[object][search]" , tag, index); |
3474 | } |
3475 | |
3476 | static inline grn_rc |
3477 | grn_obj_search_accessor(grn_ctx *ctx, grn_obj *obj, grn_obj *query, |
3478 | grn_obj *res, grn_operator op, grn_search_optarg *optarg) |
3479 | { |
3480 | grn_rc rc = GRN_SUCCESS; |
3481 | grn_accessor *a; |
3482 | grn_obj *last_obj = NULL; |
3483 | int n_accessors; |
3484 | |
3485 | for (a = (grn_accessor *)obj; a; a = a->next) { |
3486 | if (!a->next) { |
3487 | last_obj = a->obj; |
3488 | } |
3489 | } |
3490 | n_accessors = 0; |
3491 | for (a = (grn_accessor *)obj; a; a = a->next) { |
3492 | n_accessors++; |
3493 | if (GRN_OBJ_INDEX_COLUMNP(a->obj)) { |
3494 | break; |
3495 | } |
3496 | } |
3497 | |
3498 | { |
3499 | grn_obj *index; |
3500 | grn_operator index_op = GRN_OP_MATCH; |
3501 | if (optarg && optarg->mode != GRN_OP_EXACT) { |
3502 | index_op = optarg->mode; |
3503 | } |
3504 | if (grn_column_index(ctx, last_obj, index_op, &index, 1, NULL) == 0) { |
3505 | rc = GRN_INVALID_ARGUMENT; |
3506 | goto exit; |
3507 | } |
3508 | |
3509 | if (n_accessors == 1) { |
3510 | rc = grn_obj_search(ctx, index, query, res, op, optarg); |
3511 | } else { |
3512 | grn_obj *base_res; |
3513 | grn_obj *range = grn_ctx_at(ctx, DB_OBJ(index)->range); |
3514 | base_res = grn_table_create(ctx, NULL, 0, NULL, |
3515 | GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, |
3516 | range, |
3517 | NULL); |
3518 | rc = ctx->rc; |
3519 | grn_obj_unlink(ctx, range); |
3520 | if (!base_res) { |
3521 | goto exit; |
3522 | } |
3523 | if (optarg) { |
3524 | optarg->match_info.min = GRN_ID_NIL; |
3525 | } |
3526 | rc = grn_obj_search(ctx, index, query, base_res, GRN_OP_OR, optarg); |
3527 | if (rc != GRN_SUCCESS) { |
3528 | grn_obj_unlink(ctx, base_res); |
3529 | goto exit; |
3530 | } |
3531 | rc = grn_accessor_resolve(ctx, obj, n_accessors - 1, base_res, res, op); |
3532 | grn_obj_unlink(ctx, base_res); |
3533 | } |
3534 | } |
3535 | |
3536 | exit : |
3537 | return rc; |
3538 | } |
3539 | |
3540 | static grn_rc |
3541 | grn_obj_search_column_index_by_id(grn_ctx *ctx, grn_obj *obj, |
3542 | grn_id tid, |
3543 | grn_obj *res, grn_operator op, |
3544 | grn_search_optarg *optarg) |
3545 | { |
3546 | grn_ii_cursor *c; |
3547 | |
3548 | grn_obj_search_index_report(ctx, "[id]" , obj); |
3549 | |
3550 | c = grn_ii_cursor_open(ctx, (grn_ii *)obj, tid, |
3551 | GRN_ID_NIL, GRN_ID_MAX, 1, 0); |
3552 | if (c) { |
3553 | grn_posting *pos; |
3554 | grn_hash *s = (grn_hash *)res; |
3555 | while ((pos = grn_ii_cursor_next(ctx, c))) { |
3556 | /* todo: support orgarg(op) |
3557 | res_add(ctx, s, (grn_rset_posinfo *) pos, |
3558 | get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg), op); |
3559 | */ |
3560 | grn_hash_add(ctx, s, pos, s->key_size, NULL, NULL); |
3561 | } |
3562 | grn_ii_cursor_close(ctx, c); |
3563 | } |
3564 | |
3565 | return GRN_SUCCESS; |
3566 | } |
3567 | |
3568 | static grn_rc |
3569 | grn_obj_search_column_index_by_key(grn_ctx *ctx, grn_obj *obj, |
3570 | grn_obj *query, |
3571 | grn_obj *res, grn_operator op, |
3572 | grn_search_optarg *optarg) |
3573 | { |
3574 | grn_rc rc; |
3575 | unsigned int key_type = GRN_ID_NIL; |
3576 | const char *key; |
3577 | unsigned int key_len; |
3578 | grn_obj *table; |
3579 | grn_obj casted_query; |
3580 | grn_bool need_cast = GRN_FALSE; |
3581 | |
3582 | table = grn_ctx_at(ctx, obj->header.domain); |
3583 | if (table) { |
3584 | key_type = table->header.domain; |
3585 | need_cast = (query->header.domain != key_type); |
3586 | grn_obj_unlink(ctx, table); |
3587 | } |
3588 | if (need_cast) { |
3589 | GRN_OBJ_INIT(&casted_query, GRN_BULK, 0, key_type); |
3590 | rc = grn_obj_cast(ctx, query, &casted_query, GRN_FALSE); |
3591 | if (rc == GRN_SUCCESS) { |
3592 | key = GRN_BULK_HEAD(&casted_query); |
3593 | key_len = GRN_BULK_VSIZE(&casted_query); |
3594 | } |
3595 | } else { |
3596 | rc = GRN_SUCCESS; |
3597 | key = GRN_BULK_HEAD(query); |
3598 | key_len = GRN_BULK_VSIZE(query); |
3599 | } |
3600 | if (rc == GRN_SUCCESS) { |
3601 | if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { |
3602 | const char *tag; |
3603 | if (optarg) { |
3604 | switch (optarg->mode) { |
3605 | case GRN_OP_MATCH : |
3606 | tag = "[key][match]" ; |
3607 | break; |
3608 | case GRN_OP_EXACT : |
3609 | tag = "[key][exact]" ; |
3610 | break; |
3611 | case GRN_OP_NEAR : |
3612 | tag = "[key][near]" ; |
3613 | break; |
3614 | case GRN_OP_NEAR2 : |
3615 | tag = "[key][near2]" ; |
3616 | break; |
3617 | case GRN_OP_SIMILAR : |
3618 | tag = "[key][similar]" ; |
3619 | break; |
3620 | case GRN_OP_REGEXP : |
3621 | tag = "[key][regexp]" ; |
3622 | break; |
3623 | case GRN_OP_FUZZY : |
3624 | tag = "[key][fuzzy]" ; |
3625 | break; |
3626 | default : |
3627 | tag = "[key][unknown]" ; |
3628 | break; |
3629 | } |
3630 | } else { |
3631 | tag = "[key][exact]" ; |
3632 | } |
3633 | grn_obj_search_index_report(ctx, tag, obj); |
3634 | } |
3635 | rc = grn_ii_sel(ctx, (grn_ii *)obj, key, key_len, |
3636 | (grn_hash *)res, op, optarg); |
3637 | } |
3638 | if (need_cast) { |
3639 | GRN_OBJ_FIN(ctx, &casted_query); |
3640 | } |
3641 | |
3642 | return rc; |
3643 | } |
3644 | |
3645 | static grn_rc |
3646 | grn_obj_search_column_index(grn_ctx *ctx, grn_obj *obj, grn_obj *query, |
3647 | grn_obj *res, grn_operator op, |
3648 | grn_search_optarg *optarg) |
3649 | { |
3650 | grn_rc rc = GRN_INVALID_ARGUMENT; |
3651 | |
3652 | if (DB_OBJ(obj)->range == res->header.domain) { |
3653 | switch (query->header.type) { |
3654 | case GRN_BULK : |
3655 | if (query->header.domain == obj->header.domain && |
3656 | GRN_BULK_VSIZE(query) == sizeof(grn_id)) { |
3657 | grn_id tid = GRN_RECORD_VALUE(query); |
3658 | rc = grn_obj_search_column_index_by_id(ctx, obj, tid, res, op, optarg); |
3659 | } else { |
3660 | rc = grn_obj_search_column_index_by_key(ctx, obj, query, |
3661 | res, op, optarg); |
3662 | } |
3663 | break; |
3664 | case GRN_QUERY : |
3665 | rc = GRN_FUNCTION_NOT_IMPLEMENTED; |
3666 | break; |
3667 | } |
3668 | } |
3669 | |
3670 | return rc; |
3671 | } |
3672 | |
3673 | grn_rc |
3674 | grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query, |
3675 | grn_obj *res, grn_operator op, grn_search_optarg *optarg) |
3676 | { |
3677 | grn_rc rc = GRN_INVALID_ARGUMENT; |
3678 | GRN_API_ENTER; |
3679 | if (GRN_ACCESSORP(obj)) { |
3680 | rc = grn_obj_search_accessor(ctx, obj, query, res, op, optarg); |
3681 | } else if (GRN_DB_OBJP(obj)) { |
3682 | switch (obj->header.type) { |
3683 | case GRN_TABLE_PAT_KEY : |
3684 | case GRN_TABLE_DAT_KEY : |
3685 | case GRN_TABLE_HASH_KEY : |
3686 | { |
3687 | const void *key = GRN_BULK_HEAD(query); |
3688 | uint32_t key_size = GRN_BULK_VSIZE(query); |
3689 | grn_operator mode = optarg ? optarg->mode : GRN_OP_EXACT; |
3690 | if (key && key_size) { |
3691 | if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { |
3692 | const char *tag; |
3693 | if (optarg) { |
3694 | switch (optarg->mode) { |
3695 | case GRN_OP_EXACT : |
3696 | tag = "[table][exact]" ; |
3697 | break; |
3698 | case GRN_OP_LCP : |
3699 | tag = "[table][lcp]" ; |
3700 | break; |
3701 | case GRN_OP_SUFFIX : |
3702 | tag = "[table][suffix]" ; |
3703 | break; |
3704 | case GRN_OP_PREFIX : |
3705 | tag = "[table][prefix]" ; |
3706 | break; |
3707 | case GRN_OP_TERM_EXTRACT : |
3708 | tag = "[table][term-extract]" ; |
3709 | break; |
3710 | case GRN_OP_FUZZY : |
3711 | tag = "[table][fuzzy]" ; |
3712 | break; |
3713 | default : |
3714 | tag = "[table][unknown]" ; |
3715 | break; |
3716 | } |
3717 | } else { |
3718 | tag = "[table][exact]" ; |
3719 | } |
3720 | grn_obj_search_index_report(ctx, tag, obj); |
3721 | } |
3722 | if (optarg && optarg->mode == GRN_OP_FUZZY) { |
3723 | rc = grn_table_fuzzy_search(ctx, obj, key, key_size, |
3724 | &(optarg->fuzzy), res, op); |
3725 | } else { |
3726 | rc = grn_table_search(ctx, obj, key, key_size, mode, res, op); |
3727 | } |
3728 | } |
3729 | } |
3730 | break; |
3731 | case GRN_COLUMN_INDEX : |
3732 | rc = grn_obj_search_column_index(ctx, obj, query, res, op, optarg); |
3733 | break; |
3734 | } |
3735 | } |
3736 | GRN_API_RETURN(rc); |
3737 | } |
3738 | |
3739 | #define GRN_TABLE_GROUP_BY_KEY 0 |
3740 | #define GRN_TABLE_GROUP_BY_VALUE 1 |
3741 | #define GRN_TABLE_GROUP_BY_COLUMN_VALUE 2 |
3742 | |
3743 | #define GRN_TABLE_GROUP_FILTER_PREFIX 0 |
3744 | #define GRN_TABLE_GROUP_FILTER_SUFFIX (1L<<2) |
3745 | |
3746 | inline static void |
3747 | grn_table_group_add_subrec(grn_ctx *ctx, |
3748 | grn_obj *table, |
3749 | grn_rset_recinfo *ri, double score, |
3750 | grn_rset_posinfo *pi, int dir, |
3751 | grn_obj *calc_target, |
3752 | grn_obj *value_buffer) |
3753 | { |
3754 | grn_table_group_flags flags; |
3755 | |
3756 | if (!(DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC)) { |
3757 | return; |
3758 | } |
3759 | |
3760 | grn_table_add_subrec_inline(table, ri, score, pi, dir); |
3761 | |
3762 | flags = DB_OBJ(table)->flags.group; |
3763 | |
3764 | if (!(flags & (GRN_TABLE_GROUP_CALC_MAX | |
3765 | GRN_TABLE_GROUP_CALC_MIN | |
3766 | GRN_TABLE_GROUP_CALC_SUM | |
3767 | GRN_TABLE_GROUP_CALC_AVG))) { |
3768 | return; |
3769 | } |
3770 | |
3771 | GRN_BULK_REWIND(value_buffer); |
3772 | grn_obj_get_value(ctx, calc_target, pi->rid, value_buffer); |
3773 | grn_rset_recinfo_update_calc_values(ctx, ri, table, value_buffer); |
3774 | } |
3775 | |
3776 | static grn_bool |
3777 | accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, |
3778 | grn_table_group_result *result) |
3779 | { |
3780 | grn_obj *res = result->table; |
3781 | grn_obj *calc_target = result->calc_target; |
3782 | if (key->header.type == GRN_ACCESSOR) { |
3783 | grn_accessor *a = (grn_accessor *)key; |
3784 | if (a->action == GRN_ACCESSOR_GET_KEY && |
3785 | a->next && a->next->action == GRN_ACCESSOR_GET_COLUMN_VALUE && |
3786 | a->next->obj && !a->next->next) { |
3787 | grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, key)); |
3788 | int idp = GRN_OBJ_TABLEP(range); |
3789 | grn_table_cursor *tc; |
3790 | if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { |
3791 | grn_bool processed = GRN_TRUE; |
3792 | grn_obj value_buffer; |
3793 | GRN_VOID_INIT(&value_buffer); |
3794 | switch (a->next->obj->header.type) { |
3795 | case GRN_COLUMN_FIX_SIZE : |
3796 | { |
3797 | grn_id id; |
3798 | grn_ra *ra = (grn_ra *)a->next->obj; |
3799 | unsigned int element_size = (ra)->header->element_size; |
3800 | grn_ra_cache cache; |
3801 | GRN_RA_CACHE_INIT(ra, &cache); |
3802 | while ((id = grn_table_cursor_next_inline(ctx, tc))) { |
3803 | void *v, *value; |
3804 | grn_id *id_; |
3805 | uint32_t key_size; |
3806 | grn_rset_recinfo *ri = NULL; |
3807 | if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { |
3808 | grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); |
3809 | } |
3810 | id_ = (grn_id *)_grn_table_key(ctx, table, id, &key_size); |
3811 | v = grn_ra_ref_cache(ctx, ra, *id_, &cache); |
3812 | if (idp && *((grn_id *)v) && |
3813 | grn_table_at(ctx, range, *((grn_id *)v)) == GRN_ID_NIL) { |
3814 | continue; |
3815 | } |
3816 | if ((!idp || *((grn_id *)v)) && |
3817 | grn_table_add_v_inline(ctx, res, v, element_size, &value, NULL)) { |
3818 | grn_table_group_add_subrec(ctx, res, value, |
3819 | ri ? ri->score : 0, |
3820 | (grn_rset_posinfo *)&id, 0, |
3821 | calc_target, |
3822 | &value_buffer); |
3823 | } |
3824 | } |
3825 | GRN_RA_CACHE_FIN(ra, &cache); |
3826 | } |
3827 | break; |
3828 | case GRN_COLUMN_VAR_SIZE : |
3829 | if (idp) { /* todo : support other type */ |
3830 | grn_id id; |
3831 | grn_ja *ja = (grn_ja *)a->next->obj; |
3832 | while ((id = grn_table_cursor_next_inline(ctx, tc))) { |
3833 | grn_io_win jw; |
3834 | unsigned int len = 0; |
3835 | void *value; |
3836 | grn_id *v, *id_; |
3837 | uint32_t key_size; |
3838 | grn_rset_recinfo *ri = NULL; |
3839 | if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { |
3840 | grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); |
3841 | } |
3842 | id_ = (grn_id *)_grn_table_key(ctx, table, id, &key_size); |
3843 | if ((v = grn_ja_ref(ctx, ja, *id_, &jw, &len))) { |
3844 | while (len) { |
3845 | if ((*v != GRN_ID_NIL) && |
3846 | grn_table_add_v_inline(ctx, res, v, sizeof(grn_id), &value, NULL)) { |
3847 | grn_table_group_add_subrec(ctx, res, value, |
3848 | ri ? ri->score : 0, |
3849 | (grn_rset_posinfo *)&id, 0, |
3850 | calc_target, |
3851 | &value_buffer); |
3852 | } |
3853 | v++; |
3854 | len -= sizeof(grn_id); |
3855 | } |
3856 | grn_ja_unref(ctx, &jw); |
3857 | } |
3858 | } |
3859 | } else { |
3860 | processed = GRN_FALSE; |
3861 | } |
3862 | break; |
3863 | default : |
3864 | processed = GRN_FALSE; |
3865 | break; |
3866 | } |
3867 | GRN_OBJ_FIN(ctx, &value_buffer); |
3868 | grn_table_cursor_close(ctx, tc); |
3869 | return processed; |
3870 | } |
3871 | } |
3872 | } |
3873 | return GRN_FALSE; |
3874 | } |
3875 | |
3876 | static void |
3877 | grn_table_group_single_key_records(grn_ctx *ctx, grn_obj *table, |
3878 | grn_obj *key, grn_table_group_result *result) |
3879 | { |
3880 | grn_obj bulk; |
3881 | grn_obj value_buffer; |
3882 | grn_table_cursor *tc; |
3883 | grn_obj *res = result->table; |
3884 | grn_obj *calc_target = result->calc_target; |
3885 | |
3886 | GRN_TEXT_INIT(&bulk, 0); |
3887 | GRN_VOID_INIT(&value_buffer); |
3888 | if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { |
3889 | grn_id id; |
3890 | grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, key)); |
3891 | int idp = GRN_OBJ_TABLEP(range); |
3892 | while ((id = grn_table_cursor_next_inline(ctx, tc))) { |
3893 | void *value; |
3894 | grn_rset_recinfo *ri = NULL; |
3895 | GRN_BULK_REWIND(&bulk); |
3896 | if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { |
3897 | grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); |
3898 | } |
3899 | grn_obj_get_value(ctx, key, id, &bulk); |
3900 | switch (bulk.header.type) { |
3901 | case GRN_UVECTOR : |
3902 | { |
3903 | grn_bool is_reference; |
3904 | unsigned int element_size; |
3905 | uint8_t *elements; |
3906 | int i, n_elements; |
3907 | |
3908 | is_reference = !grn_type_id_is_builtin(ctx, bulk.header.type); |
3909 | |
3910 | element_size = grn_uvector_element_size(ctx, &bulk); |
3911 | elements = GRN_BULK_HEAD(&bulk); |
3912 | n_elements = GRN_BULK_VSIZE(&bulk) / element_size; |
3913 | for (i = 0; i < n_elements; i++) { |
3914 | uint8_t *element = elements + (element_size * i); |
3915 | |
3916 | if (is_reference) { |
3917 | grn_id id = *((grn_id *)element); |
3918 | if (id == GRN_ID_NIL) { |
3919 | continue; |
3920 | } |
3921 | } |
3922 | |
3923 | if (!grn_table_add_v_inline(ctx, res, element, element_size, |
3924 | &value, NULL)) { |
3925 | continue; |
3926 | } |
3927 | |
3928 | grn_table_group_add_subrec(ctx, res, value, |
3929 | ri ? ri->score : 0, |
3930 | (grn_rset_posinfo *)&id, 0, |
3931 | calc_target, |
3932 | &value_buffer); |
3933 | } |
3934 | } |
3935 | break; |
3936 | case GRN_VECTOR : |
3937 | { |
3938 | unsigned int i, n_elements; |
3939 | n_elements = grn_vector_size(ctx, &bulk); |
3940 | for (i = 0; i < n_elements; i++) { |
3941 | const char *content; |
3942 | unsigned int content_length; |
3943 | content_length = grn_vector_get_element(ctx, &bulk, i, |
3944 | &content, NULL, NULL); |
3945 | if (grn_table_add_v_inline(ctx, res, |
3946 | content, content_length, |
3947 | &value, NULL)) { |
3948 | grn_table_group_add_subrec(ctx, res, value, |
3949 | ri ? ri->score : 0, |
3950 | (grn_rset_posinfo *)&id, 0, |
3951 | calc_target, |
3952 | &value_buffer); |
3953 | } |
3954 | } |
3955 | } |
3956 | break; |
3957 | case GRN_BULK : |
3958 | { |
3959 | if ((!idp || *((grn_id *)GRN_BULK_HEAD(&bulk))) && |
3960 | grn_table_add_v_inline(ctx, res, |
3961 | GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), |
3962 | &value, NULL)) { |
3963 | grn_table_group_add_subrec(ctx, res, value, |
3964 | ri ? ri->score : 0, |
3965 | (grn_rset_posinfo *)&id, 0, |
3966 | calc_target, |
3967 | &value_buffer); |
3968 | } |
3969 | } |
3970 | break; |
3971 | default : |
3972 | ERR(GRN_INVALID_ARGUMENT, "invalid column" ); |
3973 | break; |
3974 | } |
3975 | } |
3976 | grn_table_cursor_close(ctx, tc); |
3977 | } |
3978 | GRN_OBJ_FIN(ctx, &value_buffer); |
3979 | GRN_OBJ_FIN(ctx, &bulk); |
3980 | } |
3981 | |
3982 | #define GRN_TABLE_GROUP_ALL_NAME "_all" |
3983 | #define GRN_TABLE_GROUP_ALL_NAME_LEN (sizeof(GRN_TABLE_GROUP_ALL_NAME) - 1) |
3984 | |
3985 | static void |
3986 | grn_table_group_all_records(grn_ctx *ctx, grn_obj *table, |
3987 | grn_table_group_result *result) |
3988 | { |
3989 | grn_obj value_buffer; |
3990 | grn_table_cursor *tc; |
3991 | grn_obj *res = result->table; |
3992 | grn_obj *calc_target = result->calc_target; |
3993 | |
3994 | GRN_VOID_INIT(&value_buffer); |
3995 | if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { |
3996 | grn_id id; |
3997 | void *value; |
3998 | if (grn_table_add_v_inline(ctx, res, |
3999 | GRN_TABLE_GROUP_ALL_NAME, |
4000 | GRN_TABLE_GROUP_ALL_NAME_LEN, |
4001 | &value, NULL)) { |
4002 | while ((id = grn_table_cursor_next_inline(ctx, tc))) { |
4003 | grn_rset_recinfo *ri = NULL; |
4004 | if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { |
4005 | grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); |
4006 | } |
4007 | grn_table_group_add_subrec(ctx, res, value, |
4008 | ri ? ri->score : 0, |
4009 | (grn_rset_posinfo *)&id, 0, |
4010 | calc_target, |
4011 | &value_buffer); |
4012 | } |
4013 | } |
4014 | grn_table_cursor_close(ctx, tc); |
4015 | } |
4016 | GRN_OBJ_FIN(ctx, &value_buffer); |
4017 | } |
4018 | |
4019 | grn_rc |
4020 | grn_table_group_with_range_gap(grn_ctx *ctx, grn_obj *table, |
4021 | grn_table_sort_key *group_key, |
4022 | grn_obj *res, uint32_t range_gap) |
4023 | { |
4024 | grn_obj *key = group_key->key; |
4025 | if (key->header.type == GRN_ACCESSOR) { |
4026 | grn_accessor *a = (grn_accessor *)key; |
4027 | if (a->action == GRN_ACCESSOR_GET_KEY && |
4028 | a->next && a->next->action == GRN_ACCESSOR_GET_COLUMN_VALUE && |
4029 | a->next->obj && !a->next->next) { |
4030 | grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, key)); |
4031 | int idp = GRN_OBJ_TABLEP(range); |
4032 | grn_table_cursor *tc; |
4033 | if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, |
4034 | 0, 0, -1, 0))) { |
4035 | switch (a->next->obj->header.type) { |
4036 | case GRN_COLUMN_FIX_SIZE : |
4037 | { |
4038 | grn_id id; |
4039 | grn_ra *ra = (grn_ra *)a->next->obj; |
4040 | unsigned int element_size = (ra)->header->element_size; |
4041 | grn_ra_cache cache; |
4042 | GRN_RA_CACHE_INIT(ra, &cache); |
4043 | while ((id = grn_table_cursor_next_inline(ctx, tc))) { |
4044 | void *v, *value; |
4045 | grn_id *id_; |
4046 | uint32_t key_size; |
4047 | grn_rset_recinfo *ri = NULL; |
4048 | if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { |
4049 | grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); |
4050 | } |
4051 | id_ = (grn_id *)_grn_table_key(ctx, table, id, &key_size); |
4052 | v = grn_ra_ref_cache(ctx, ra, *id_, &cache); |
4053 | if (idp && *((grn_id *)v) && |
4054 | grn_table_at(ctx, range, *((grn_id *)v)) == GRN_ID_NIL) { |
4055 | continue; |
4056 | } |
4057 | if ((!idp || *((grn_id *)v))) { |
4058 | grn_id id; |
4059 | if (element_size == sizeof(uint32_t)) { |
4060 | uint32_t quantized = (*(uint32_t *)v); |
4061 | quantized -= quantized % range_gap; |
4062 | id = grn_table_add_v_inline(ctx, res, &quantized, |
4063 | element_size, &value, NULL); |
4064 | } else { |
4065 | id = grn_table_add_v_inline(ctx, res, v, |
4066 | element_size, &value, NULL); |
4067 | } |
4068 | if (id) { |
4069 | grn_table_add_subrec_inline(res, value, |
4070 | ri ? ri->score : 0, |
4071 | (grn_rset_posinfo *)&id, 0); |
4072 | } |
4073 | } |
4074 | } |
4075 | GRN_RA_CACHE_FIN(ra, &cache); |
4076 | } |
4077 | break; |
4078 | case GRN_COLUMN_VAR_SIZE : |
4079 | if (idp) { /* todo : support other type */ |
4080 | grn_id id; |
4081 | grn_ja *ja = (grn_ja *)a->next->obj; |
4082 | while ((id = grn_table_cursor_next_inline(ctx, tc))) { |
4083 | grn_io_win jw; |
4084 | unsigned int len = 0; |
4085 | void *value; |
4086 | grn_id *v, *id_; |
4087 | uint32_t key_size; |
4088 | grn_rset_recinfo *ri = NULL; |
4089 | if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { |
4090 | grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); |
4091 | } |
4092 | id_ = (grn_id *)_grn_table_key(ctx, table, id, &key_size); |
4093 | if ((v = grn_ja_ref(ctx, ja, *id_, &jw, &len))) { |
4094 | while (len) { |
4095 | if ((*v != GRN_ID_NIL) && |
4096 | grn_table_add_v_inline(ctx, res, v, sizeof(grn_id), &value, NULL)) { |
4097 | grn_table_add_subrec_inline(res, value, ri ? ri->score : 0, |
4098 | (grn_rset_posinfo *)&id, 0); |
4099 | } |
4100 | v++; |
4101 | len -= sizeof(grn_id); |
4102 | } |
4103 | grn_ja_unref(ctx, &jw); |
4104 | } |
4105 | } |
4106 | } else { |
4107 | return 0; |
4108 | } |
4109 | break; |
4110 | default : |
4111 | return 0; |
4112 | } |
4113 | grn_table_cursor_close(ctx, tc); |
4114 | GRN_TABLE_GROUPED_ON(res); |
4115 | return 1; |
4116 | } |
4117 | } |
4118 | } |
4119 | return 0; |
4120 | } |
4121 | |
4122 | static inline void |
4123 | grn_table_group_multi_keys_add_record(grn_ctx *ctx, |
4124 | grn_table_sort_key *keys, |
4125 | int n_keys, |
4126 | grn_table_group_result *results, |
4127 | int n_results, |
4128 | grn_id id, |
4129 | grn_rset_recinfo *ri, |
4130 | grn_obj *vector, |
4131 | grn_obj *bulk) |
4132 | { |
4133 | int r; |
4134 | grn_table_group_result *rp; |
4135 | |
4136 | for (r = 0, rp = results; r < n_results; r++, rp++) { |
4137 | void *value; |
4138 | int i; |
4139 | int end; |
4140 | |
4141 | if (rp->key_end > n_keys) { |
4142 | end = n_keys; |
4143 | } else { |
4144 | end = rp->key_end + 1; |
4145 | } |
4146 | GRN_BULK_REWIND(bulk); |
4147 | grn_text_benc(ctx, bulk, end - rp->key_begin); |
4148 | for (i = rp->key_begin; i < end; i++) { |
4149 | grn_section section = vector->u.v.sections[i]; |
4150 | grn_text_benc(ctx, bulk, section.length); |
4151 | } |
4152 | { |
4153 | grn_obj *body = vector->u.v.body; |
4154 | if (body) { |
4155 | GRN_TEXT_PUT(ctx, bulk, GRN_BULK_HEAD(body), GRN_BULK_VSIZE(body)); |
4156 | } |
4157 | } |
4158 | for (i = rp->key_begin; i < end; i++) { |
4159 | grn_section section = vector->u.v.sections[i]; |
4160 | grn_text_benc(ctx, bulk, section.weight); |
4161 | grn_text_benc(ctx, bulk, section.domain); |
4162 | } |
4163 | |
4164 | // todo : cut off GRN_ID_NIL |
4165 | if (grn_table_add_v_inline(ctx, rp->table, |
4166 | GRN_BULK_HEAD(bulk), GRN_BULK_VSIZE(bulk), |
4167 | &value, NULL)) { |
4168 | grn_table_group_add_subrec(ctx, rp->table, value, |
4169 | ri ? ri->score : 0, |
4170 | (grn_rset_posinfo *)&id, 0, |
4171 | rp->calc_target, |
4172 | bulk); |
4173 | } |
4174 | } |
4175 | } |
4176 | |
4177 | static void |
4178 | grn_table_group_multi_keys_scalar_records(grn_ctx *ctx, |
4179 | grn_obj *table, |
4180 | grn_table_sort_key *keys, |
4181 | int n_keys, |
4182 | grn_table_group_result *results, |
4183 | int n_results) |
4184 | { |
4185 | grn_id id; |
4186 | grn_table_cursor *tc; |
4187 | grn_obj bulk; |
4188 | grn_obj vector; |
4189 | |
4190 | tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); |
4191 | if (!tc) { |
4192 | return; |
4193 | } |
4194 | |
4195 | GRN_TEXT_INIT(&bulk, 0); |
4196 | GRN_OBJ_INIT(&vector, GRN_VECTOR, 0, GRN_DB_VOID); |
4197 | while ((id = grn_table_cursor_next_inline(ctx, tc))) { |
4198 | int k; |
4199 | grn_table_sort_key *kp; |
4200 | grn_rset_recinfo *ri = NULL; |
4201 | |
4202 | if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { |
4203 | grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); |
4204 | } |
4205 | |
4206 | GRN_BULK_REWIND(&vector); |
4207 | for (k = 0, kp = keys; k < n_keys; k++, kp++) { |
4208 | GRN_BULK_REWIND(&bulk); |
4209 | grn_obj_get_value(ctx, kp->key, id, &bulk); |
4210 | grn_vector_add_element(ctx, &vector, |
4211 | GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), |
4212 | 0, |
4213 | bulk.header.domain); |
4214 | } |
4215 | |
4216 | grn_table_group_multi_keys_add_record(ctx, keys, n_keys, results, n_results, |
4217 | id, ri, &vector, &bulk); |
4218 | } |
4219 | GRN_OBJ_FIN(ctx, &vector); |
4220 | GRN_OBJ_FIN(ctx, &bulk); |
4221 | grn_table_cursor_close(ctx, tc); |
4222 | } |
4223 | |
4224 | static inline void |
4225 | grn_table_group_multi_keys_vector_record(grn_ctx *ctx, |
4226 | grn_table_sort_key *keys, |
4227 | grn_obj *key_buffers, |
4228 | int nth_key, |
4229 | int n_keys, |
4230 | grn_table_group_result *results, |
4231 | int n_results, |
4232 | grn_id id, |
4233 | grn_rset_recinfo *ri, |
4234 | grn_obj *vector, |
4235 | grn_obj *bulk) |
4236 | { |
4237 | int k; |
4238 | grn_table_sort_key *kp; |
4239 | |
4240 | for (k = nth_key, kp = &(keys[nth_key]); k < n_keys; k++, kp++) { |
4241 | grn_obj *key_buffer = &(key_buffers[k]); |
4242 | switch (key_buffer->header.type) { |
4243 | case GRN_UVECTOR : |
4244 | { |
4245 | unsigned int n_vector_elements; |
4246 | grn_id domain; |
4247 | grn_id *ids; |
4248 | unsigned int i, n_ids; |
4249 | |
4250 | n_vector_elements = grn_vector_size(ctx, vector); |
4251 | domain = key_buffer->header.domain; |
4252 | ids = (grn_id *)GRN_BULK_HEAD(key_buffer); |
4253 | n_ids = GRN_BULK_VSIZE(key_buffer) / sizeof(grn_id); |
4254 | for (i = 0; i < n_ids; i++) { |
4255 | grn_id element_id = ids[i]; |
4256 | grn_vector_add_element(ctx, vector, |
4257 | (const char *)(&element_id), sizeof(grn_id), |
4258 | 0, |
4259 | domain); |
4260 | grn_table_group_multi_keys_vector_record(ctx, |
4261 | keys, key_buffers, |
4262 | k + 1, n_keys, |
4263 | results, n_results, |
4264 | id, ri, vector, bulk); |
4265 | while (grn_vector_size(ctx, vector) != n_vector_elements) { |
4266 | const char *content; |
4267 | grn_vector_pop_element(ctx, vector, &content, NULL, NULL); |
4268 | } |
4269 | } |
4270 | return; |
4271 | } |
4272 | break; |
4273 | case GRN_VECTOR : |
4274 | { |
4275 | unsigned int n_vector_elements; |
4276 | unsigned int i, n_key_elements; |
4277 | |
4278 | n_vector_elements = grn_vector_size(ctx, vector); |
4279 | n_key_elements = grn_vector_size(ctx, key_buffer); |
4280 | for (i = 0; i < n_key_elements; i++) { |
4281 | const char *content; |
4282 | unsigned int content_length; |
4283 | grn_id domain; |
4284 | content_length = grn_vector_get_element(ctx, key_buffer, i, |
4285 | &content, NULL, &domain); |
4286 | grn_vector_add_element(ctx, vector, |
4287 | content, content_length, |
4288 | 0, |
4289 | domain); |
4290 | grn_table_group_multi_keys_vector_record(ctx, |
4291 | keys, key_buffers, |
4292 | k + 1, n_keys, |
4293 | results, n_results, |
4294 | id, ri, vector, bulk); |
4295 | while (grn_vector_size(ctx, vector) != n_vector_elements) { |
4296 | grn_vector_pop_element(ctx, vector, &content, NULL, NULL); |
4297 | } |
4298 | } |
4299 | return; |
4300 | } |
4301 | break; |
4302 | default : |
4303 | grn_vector_add_element(ctx, vector, |
4304 | GRN_BULK_HEAD(key_buffer), |
4305 | GRN_BULK_VSIZE(key_buffer), |
4306 | 0, |
4307 | key_buffer->header.domain); |
4308 | } |
4309 | } |
4310 | |
4311 | if (k == n_keys) { |
4312 | grn_table_group_multi_keys_add_record(ctx, |
4313 | keys, n_keys, |
4314 | results, n_results, |
4315 | id, ri, vector, bulk); |
4316 | } |
4317 | } |
4318 | |
4319 | static void |
4320 | grn_table_group_multi_keys_vector_records(grn_ctx *ctx, |
4321 | grn_obj *table, |
4322 | grn_table_sort_key *keys, |
4323 | int n_keys, |
4324 | grn_table_group_result *results, |
4325 | int n_results) |
4326 | { |
4327 | grn_id id; |
4328 | grn_table_cursor *tc; |
4329 | grn_obj bulk; |
4330 | grn_obj vector; |
4331 | grn_obj *key_buffers; |
4332 | int k; |
4333 | |
4334 | tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); |
4335 | if (!tc) { |
4336 | return; |
4337 | } |
4338 | |
4339 | key_buffers = GRN_MALLOCN(grn_obj, n_keys); |
4340 | if (!key_buffers) { |
4341 | grn_table_cursor_close(ctx, tc); |
4342 | return; |
4343 | } |
4344 | |
4345 | GRN_TEXT_INIT(&bulk, 0); |
4346 | GRN_OBJ_INIT(&vector, GRN_VECTOR, 0, GRN_DB_VOID); |
4347 | for (k = 0; k < n_keys; k++) { |
4348 | GRN_VOID_INIT(&(key_buffers[k])); |
4349 | } |
4350 | while ((id = grn_table_cursor_next_inline(ctx, tc))) { |
4351 | grn_table_sort_key *kp; |
4352 | grn_rset_recinfo *ri = NULL; |
4353 | |
4354 | if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { |
4355 | grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); |
4356 | } |
4357 | |
4358 | for (k = 0, kp = keys; k < n_keys; k++, kp++) { |
4359 | grn_obj *key_buffer = &(key_buffers[k]); |
4360 | GRN_BULK_REWIND(key_buffer); |
4361 | grn_obj_get_value(ctx, kp->key, id, key_buffer); |
4362 | } |
4363 | |
4364 | GRN_BULK_REWIND(&vector); |
4365 | grn_table_group_multi_keys_vector_record(ctx, |
4366 | keys, key_buffers, 0, n_keys, |
4367 | results, n_results, |
4368 | id, ri, &vector, &bulk); |
4369 | } |
4370 | for (k = 0; k < n_keys; k++) { |
4371 | GRN_OBJ_FIN(ctx, &(key_buffers[k])); |
4372 | } |
4373 | GRN_FREE(key_buffers); |
4374 | GRN_OBJ_FIN(ctx, &vector); |
4375 | GRN_OBJ_FIN(ctx, &bulk); |
4376 | grn_table_cursor_close(ctx, tc); |
4377 | } |
4378 | |
4379 | grn_rc |
4380 | grn_table_group(grn_ctx *ctx, grn_obj *table, |
4381 | grn_table_sort_key *keys, int n_keys, |
4382 | grn_table_group_result *results, int n_results) |
4383 | { |
4384 | grn_rc rc = GRN_SUCCESS; |
4385 | grn_bool group_by_all_records = GRN_FALSE; |
4386 | if (n_keys == 0 && n_results == 1) { |
4387 | group_by_all_records = GRN_TRUE; |
4388 | } else if (!table || !n_keys || !n_results) { |
4389 | ERR(GRN_INVALID_ARGUMENT, "table or n_keys or n_results is void" ); |
4390 | return GRN_INVALID_ARGUMENT; |
4391 | } |
4392 | GRN_API_ENTER; |
4393 | { |
4394 | int k, r; |
4395 | grn_table_sort_key *kp; |
4396 | grn_table_group_result *rp; |
4397 | for (k = 0, kp = keys; k < n_keys; k++, kp++) { |
4398 | if ((kp->flags & GRN_TABLE_GROUP_BY_COLUMN_VALUE) && !kp->key) { |
4399 | ERR(GRN_INVALID_ARGUMENT, "column missing in (%d)" , k); |
4400 | goto exit; |
4401 | } |
4402 | } |
4403 | for (r = 0, rp = results; r < n_results; r++, rp++) { |
4404 | if (!rp->table) { |
4405 | grn_table_flags flags; |
4406 | grn_obj *key_type = NULL; |
4407 | uint32_t additional_value_size; |
4408 | |
4409 | flags = GRN_TABLE_HASH_KEY| |
4410 | GRN_OBJ_WITH_SUBREC| |
4411 | GRN_OBJ_UNIT_USERDEF_DOCUMENT; |
4412 | if (group_by_all_records) { |
4413 | key_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT); |
4414 | } else if (n_keys == 1) { |
4415 | key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, keys[0].key)); |
4416 | } else { |
4417 | flags |= GRN_OBJ_KEY_VAR_SIZE; |
4418 | } |
4419 | additional_value_size = grn_rset_recinfo_calc_values_size(ctx, |
4420 | rp->flags); |
4421 | rp->table = grn_table_create_with_max_n_subrecs(ctx, NULL, 0, NULL, |
4422 | flags, |
4423 | key_type, table, |
4424 | rp->max_n_subrecs, |
4425 | additional_value_size); |
4426 | if (key_type) { |
4427 | grn_obj_unlink(ctx, key_type); |
4428 | } |
4429 | if (!rp->table) { |
4430 | goto exit; |
4431 | } |
4432 | DB_OBJ(rp->table)->flags.group = rp->flags; |
4433 | } |
4434 | } |
4435 | if (group_by_all_records) { |
4436 | grn_table_group_all_records(ctx, table, results); |
4437 | } else if (n_keys == 1 && n_results == 1) { |
4438 | if (!accelerated_table_group(ctx, table, keys->key, results)) { |
4439 | grn_table_group_single_key_records(ctx, table, keys->key, results); |
4440 | } |
4441 | } else { |
4442 | grn_bool have_vector = GRN_FALSE; |
4443 | for (k = 0, kp = keys; k < n_keys; k++, kp++) { |
4444 | grn_id range_id; |
4445 | grn_obj_flags range_flags = 0; |
4446 | grn_obj_get_range_info(ctx, kp->key, &range_id, &range_flags); |
4447 | if (range_flags == GRN_OBJ_VECTOR) { |
4448 | have_vector = GRN_TRUE; |
4449 | break; |
4450 | } |
4451 | } |
4452 | if (have_vector) { |
4453 | grn_table_group_multi_keys_vector_records(ctx, table, |
4454 | keys, n_keys, |
4455 | results, n_results); |
4456 | } else { |
4457 | grn_table_group_multi_keys_scalar_records(ctx, table, |
4458 | keys, n_keys, |
4459 | results, n_results); |
4460 | } |
4461 | } |
4462 | for (r = 0, rp = results; r < n_results; r++, rp++) { |
4463 | GRN_TABLE_GROUPED_ON(rp->table); |
4464 | } |
4465 | } |
4466 | exit : |
4467 | GRN_API_RETURN(rc); |
4468 | } |
4469 | |
4470 | grn_rc |
4471 | grn_table_setoperation(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, grn_obj *res, |
4472 | grn_operator op) |
4473 | { |
4474 | void *key = NULL, *value1 = NULL, *value2 = NULL; |
4475 | uint32_t value_size = 0; |
4476 | uint32_t key_size = 0; |
4477 | grn_bool have_subrec; |
4478 | |
4479 | GRN_API_ENTER; |
4480 | if (!table1) { |
4481 | ERR(GRN_INVALID_ARGUMENT, "[table][setoperation] table1 is NULL" ); |
4482 | GRN_API_RETURN(ctx->rc); |
4483 | } |
4484 | if (!table2) { |
4485 | ERR(GRN_INVALID_ARGUMENT, "[table][setoperation] table2 is NULL" ); |
4486 | GRN_API_RETURN(ctx->rc); |
4487 | } |
4488 | if (!res) { |
4489 | ERR(GRN_INVALID_ARGUMENT, "[table][setoperation] result table is NULL" ); |
4490 | GRN_API_RETURN(ctx->rc); |
4491 | } |
4492 | |
4493 | if (table1 != res) { |
4494 | if (table2 == res) { |
4495 | grn_obj *t = table1; |
4496 | table1 = table2; |
4497 | table2 = t; |
4498 | } else { |
4499 | ERR(GRN_INVALID_ARGUMENT, |
4500 | "[table][setoperation] table1 or table2 must be result table" ); |
4501 | GRN_API_RETURN(ctx->rc); |
4502 | } |
4503 | } |
4504 | have_subrec = ((DB_OBJ(table1)->header.flags & GRN_OBJ_WITH_SUBREC) && |
4505 | (DB_OBJ(table2)->header.flags & GRN_OBJ_WITH_SUBREC)); |
4506 | switch (table1->header.type) { |
4507 | case GRN_TABLE_HASH_KEY : |
4508 | value_size = ((grn_hash *)table1)->value_size; |
4509 | break; |
4510 | case GRN_TABLE_PAT_KEY : |
4511 | value_size = ((grn_pat *)table1)->value_size; |
4512 | break; |
4513 | case GRN_TABLE_DAT_KEY : |
4514 | value_size = 0; |
4515 | break; |
4516 | case GRN_TABLE_NO_KEY : |
4517 | value_size = ((grn_array *)table1)->value_size; |
4518 | break; |
4519 | } |
4520 | switch (table2->header.type) { |
4521 | case GRN_TABLE_HASH_KEY : |
4522 | if (value_size < ((grn_hash *)table2)->value_size) { |
4523 | value_size = ((grn_hash *)table2)->value_size; |
4524 | } |
4525 | break; |
4526 | case GRN_TABLE_PAT_KEY : |
4527 | if (value_size < ((grn_pat *)table2)->value_size) { |
4528 | value_size = ((grn_pat *)table2)->value_size; |
4529 | } |
4530 | break; |
4531 | case GRN_TABLE_DAT_KEY : |
4532 | value_size = 0; |
4533 | break; |
4534 | case GRN_TABLE_NO_KEY : |
4535 | if (value_size < ((grn_array *)table2)->value_size) { |
4536 | value_size = ((grn_array *)table2)->value_size; |
4537 | } |
4538 | break; |
4539 | } |
4540 | switch (op) { |
4541 | case GRN_OP_OR : |
4542 | if (have_subrec) { |
4543 | int added; |
4544 | GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { |
4545 | if (grn_table_add_v_inline(ctx, table1, key, key_size, &value1, &added)) { |
4546 | if (added) { |
4547 | grn_memcpy(value1, value2, value_size); |
4548 | } else { |
4549 | grn_rset_recinfo *ri1 = value1; |
4550 | grn_rset_recinfo *ri2 = value2; |
4551 | grn_table_add_subrec_inline(table1, ri1, ri2->score, NULL, 0); |
4552 | } |
4553 | } |
4554 | }); |
4555 | } else { |
4556 | GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { |
4557 | if (grn_table_add_v_inline(ctx, table1, key, key_size, &value1, NULL)) { |
4558 | grn_memcpy(value1, value2, value_size); |
4559 | } |
4560 | }); |
4561 | } |
4562 | break; |
4563 | case GRN_OP_AND : |
4564 | if (have_subrec) { |
4565 | GRN_TABLE_EACH(ctx, table1, 0, 0, id, &key, &key_size, &value1, { |
4566 | if (grn_table_get_v(ctx, table2, key, key_size, &value2)) { |
4567 | grn_rset_recinfo *ri1 = value1; |
4568 | grn_rset_recinfo *ri2 = value2; |
4569 | ri1->score += ri2->score; |
4570 | } else { |
4571 | _grn_table_delete_by_id(ctx, table1, id, NULL); |
4572 | } |
4573 | }); |
4574 | } else { |
4575 | GRN_TABLE_EACH(ctx, table1, 0, 0, id, &key, &key_size, &value1, { |
4576 | if (!grn_table_get_v(ctx, table2, key, key_size, &value2)) { |
4577 | _grn_table_delete_by_id(ctx, table1, id, NULL); |
4578 | } |
4579 | }); |
4580 | } |
4581 | break; |
4582 | case GRN_OP_AND_NOT : |
4583 | GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { |
4584 | grn_table_delete(ctx, table1, key, key_size); |
4585 | }); |
4586 | break; |
4587 | case GRN_OP_ADJUST : |
4588 | if (have_subrec) { |
4589 | GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { |
4590 | if (grn_table_get_v(ctx, table1, key, key_size, &value1)) { |
4591 | grn_rset_recinfo *ri1 = value1; |
4592 | grn_rset_recinfo *ri2 = value2; |
4593 | ri1->score += ri2->score; |
4594 | } |
4595 | }); |
4596 | } else { |
4597 | GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { |
4598 | if (grn_table_get_v(ctx, table1, key, key_size, &value1)) { |
4599 | grn_memcpy(value1, value2, value_size); |
4600 | } |
4601 | }); |
4602 | } |
4603 | break; |
4604 | default : |
4605 | break; |
4606 | } |
4607 | GRN_API_RETURN(ctx->rc); |
4608 | } |
4609 | |
4610 | grn_rc |
4611 | grn_table_difference(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, |
4612 | grn_obj *res1, grn_obj *res2) |
4613 | { |
4614 | void *key = NULL; |
4615 | uint32_t key_size = 0; |
4616 | if (table1 != res1 || table2 != res2) { return GRN_INVALID_ARGUMENT; } |
4617 | if (grn_table_size(ctx, table1) > grn_table_size(ctx, table2)) { |
4618 | GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, NULL, { |
4619 | grn_id id1; |
4620 | if ((id1 = grn_table_get(ctx, table1, key, key_size))) { |
4621 | _grn_table_delete_by_id(ctx, table1, id1, NULL); |
4622 | _grn_table_delete_by_id(ctx, table2, id, NULL); |
4623 | } |
4624 | }); |
4625 | } else { |
4626 | GRN_TABLE_EACH(ctx, table1, 0, 0, id, &key, &key_size, NULL, { |
4627 | grn_id id2; |
4628 | if ((id2 = grn_table_get(ctx, table2, key, key_size))) { |
4629 | _grn_table_delete_by_id(ctx, table1, id, NULL); |
4630 | _grn_table_delete_by_id(ctx, table2, id2, NULL); |
4631 | } |
4632 | }); |
4633 | } |
4634 | return GRN_SUCCESS; |
4635 | } |
4636 | |
4637 | static grn_obj *grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, |
4638 | const char *name, unsigned int name_size); |
4639 | |
4640 | static grn_obj * |
4641 | grn_obj_column_(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size) |
4642 | { |
4643 | grn_id table_id = DB_OBJ(table)->id; |
4644 | grn_obj *column = NULL; |
4645 | |
4646 | if (table_id & GRN_OBJ_TMP_OBJECT) { |
4647 | char column_name[GRN_TABLE_MAX_KEY_SIZE]; |
4648 | void *value = NULL; |
4649 | grn_snprintf(column_name, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, |
4650 | "%u%c%.*s" , table_id, GRN_DB_DELIMITER, name_size, name); |
4651 | grn_pat_get(ctx, ctx->impl->temporary_columns, |
4652 | column_name, strlen(column_name), |
4653 | &value); |
4654 | if (value) { |
4655 | column = *((grn_obj **)value); |
4656 | } |
4657 | } else { |
4658 | char buf[GRN_TABLE_MAX_KEY_SIZE]; |
4659 | int len = grn_obj_name(ctx, table, buf, GRN_TABLE_MAX_KEY_SIZE); |
4660 | if (len) { |
4661 | buf[len++] = GRN_DB_DELIMITER; |
4662 | if (len + name_size <= GRN_TABLE_MAX_KEY_SIZE) { |
4663 | grn_memcpy(buf + len, name, name_size); |
4664 | column = grn_ctx_get(ctx, buf, len + name_size); |
4665 | } else { |
4666 | ERR(GRN_INVALID_ARGUMENT, "name is too long" ); |
4667 | } |
4668 | } |
4669 | } |
4670 | |
4671 | return column; |
4672 | } |
4673 | |
4674 | grn_obj * |
4675 | grn_obj_column(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size) |
4676 | { |
4677 | grn_obj *column = NULL; |
4678 | GRN_API_ENTER; |
4679 | if (GRN_OBJ_TABLEP(table)) { |
4680 | if (grn_db_check_name(ctx, name, name_size) || |
4681 | !(column = grn_obj_column_(ctx, table, name, name_size))) { |
4682 | column = grn_obj_get_accessor(ctx, table, name, name_size); |
4683 | } |
4684 | } else if (GRN_ACCESSORP(table)) { |
4685 | column = grn_obj_get_accessor(ctx, table, name, name_size); |
4686 | } |
4687 | GRN_API_RETURN(column); |
4688 | } |
4689 | |
4690 | int |
4691 | grn_table_columns(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size, |
4692 | grn_obj *res) |
4693 | { |
4694 | int n = 0; |
4695 | grn_id id; |
4696 | |
4697 | GRN_API_ENTER; |
4698 | |
4699 | if (!GRN_OBJ_TABLEP(table)) { |
4700 | GRN_API_RETURN(n); |
4701 | } |
4702 | |
4703 | id = DB_OBJ(table)->id; |
4704 | |
4705 | if (id == GRN_ID_NIL) { |
4706 | GRN_API_RETURN(n); |
4707 | } |
4708 | |
4709 | if (id & GRN_OBJ_TMP_OBJECT) { |
4710 | char search_key[GRN_TABLE_MAX_KEY_SIZE]; |
4711 | grn_pat_cursor *cursor; |
4712 | grn_snprintf(search_key, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, |
4713 | "%u%c%.*s" , id, GRN_DB_DELIMITER, name_size, name); |
4714 | cursor = grn_pat_cursor_open(ctx, ctx->impl->temporary_columns, |
4715 | search_key, strlen(search_key), |
4716 | NULL, 0, |
4717 | 0, -1, GRN_CURSOR_PREFIX); |
4718 | if (cursor) { |
4719 | grn_id column_id; |
4720 | while ((column_id = grn_pat_cursor_next(ctx, cursor)) != GRN_ID_NIL) { |
4721 | column_id |= GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN; |
4722 | grn_hash_add(ctx, (grn_hash *)res, |
4723 | &column_id, sizeof(grn_id), |
4724 | NULL, NULL); |
4725 | n++; |
4726 | } |
4727 | grn_pat_cursor_close(ctx, cursor); |
4728 | } |
4729 | } else { |
4730 | grn_db *s = (grn_db *)DB_OBJ(table)->db; |
4731 | if (s->keys) { |
4732 | grn_obj bulk; |
4733 | GRN_TEXT_INIT(&bulk, 0); |
4734 | grn_table_get_key2(ctx, s->keys, id, &bulk); |
4735 | GRN_TEXT_PUTC(ctx, &bulk, GRN_DB_DELIMITER); |
4736 | grn_bulk_write(ctx, &bulk, name, name_size); |
4737 | grn_table_search(ctx, s->keys, GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), |
4738 | GRN_OP_PREFIX, res, GRN_OP_OR); |
4739 | grn_obj_close(ctx, &bulk); |
4740 | n = grn_table_size(ctx, res); |
4741 | } |
4742 | } |
4743 | |
4744 | GRN_API_RETURN(n); |
4745 | } |
4746 | |
4747 | const char * |
4748 | _grn_table_key(grn_ctx *ctx, grn_obj *table, grn_id id, uint32_t *key_size) |
4749 | { |
4750 | GRN_ASSERT(table); |
4751 | if (table->header.type == GRN_DB) { table = ((grn_db *)table)->keys; } |
4752 | switch (table->header.type) { |
4753 | case GRN_TABLE_HASH_KEY : |
4754 | return _grn_hash_key(ctx, (grn_hash *)table, id, key_size); |
4755 | case GRN_TABLE_PAT_KEY : |
4756 | return _grn_pat_key(ctx, (grn_pat *)table, id, key_size); |
4757 | case GRN_TABLE_DAT_KEY : |
4758 | return _grn_dat_key(ctx, (grn_dat *)table, id, key_size); |
4759 | case GRN_TABLE_NO_KEY : |
4760 | { |
4761 | grn_array *a = (grn_array *)table; |
4762 | const char *v; |
4763 | if (a->obj.header.domain && a->value_size && |
4764 | (v = _grn_array_get_value(ctx, a, id))) { |
4765 | *key_size = a->value_size; |
4766 | return v; |
4767 | } else { |
4768 | *key_size = 0; |
4769 | } |
4770 | } |
4771 | break; |
4772 | } |
4773 | return NULL; |
4774 | } |
4775 | |
4776 | /* column */ |
4777 | |
4778 | grn_obj * |
4779 | grn_column_create(grn_ctx *ctx, grn_obj *table, |
4780 | const char *name, unsigned int name_size, |
4781 | const char *path, grn_column_flags flags, grn_obj *type) |
4782 | { |
4783 | grn_db *s; |
4784 | uint32_t value_size; |
4785 | grn_obj *db= NULL, *res = NULL; |
4786 | grn_id id = GRN_ID_NIL; |
4787 | grn_id range = GRN_ID_NIL; |
4788 | grn_id domain = GRN_ID_NIL; |
4789 | grn_bool is_persistent_table; |
4790 | char fullname[GRN_TABLE_MAX_KEY_SIZE]; |
4791 | unsigned int fullname_size; |
4792 | char buffer[PATH_MAX]; |
4793 | |
4794 | GRN_API_ENTER; |
4795 | if (!table) { |
4796 | ERR(GRN_INVALID_ARGUMENT, "[column][create] table is missing" ); |
4797 | goto exit; |
4798 | } |
4799 | if (!type) { |
4800 | ERR(GRN_INVALID_ARGUMENT, "[column][create] type is missing" ); |
4801 | goto exit; |
4802 | } |
4803 | if (!name || !name_size) { |
4804 | ERR(GRN_INVALID_ARGUMENT, "[column][create] name is missing" ); |
4805 | goto exit; |
4806 | } |
4807 | db = DB_OBJ(table)->db; |
4808 | s = (grn_db *)db; |
4809 | if (!GRN_DB_P(s)) { |
4810 | int table_name_len; |
4811 | char table_name[GRN_TABLE_MAX_KEY_SIZE]; |
4812 | table_name_len = grn_obj_name(ctx, table, table_name, GRN_TABLE_MAX_KEY_SIZE); |
4813 | ERR(GRN_INVALID_ARGUMENT, |
4814 | "[column][create] invalid db assigned: <%.*s>.<%.*s>" , |
4815 | table_name_len, table_name, name_size, name); |
4816 | goto exit; |
4817 | } |
4818 | |
4819 | if (grn_db_check_name(ctx, name, name_size)) { |
4820 | GRN_DB_CHECK_NAME_ERR("[column][create]" , name, name_size); |
4821 | goto exit; |
4822 | } |
4823 | |
4824 | domain = DB_OBJ(table)->id; |
4825 | is_persistent_table = !(domain & GRN_OBJ_TMP_OBJECT); |
4826 | |
4827 | if (!domain) { |
4828 | ERR(GRN_FUNCTION_NOT_IMPLEMENTED, |
4829 | "[column][create] [todo] table-less column isn't supported yet" ); |
4830 | goto exit; |
4831 | } |
4832 | |
4833 | { |
4834 | int table_name_len; |
4835 | if (is_persistent_table) { |
4836 | table_name_len = grn_table_get_key(ctx, s->keys, domain, |
4837 | fullname, GRN_TABLE_MAX_KEY_SIZE); |
4838 | } else { |
4839 | grn_snprintf(fullname, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, |
4840 | "%u" , domain); |
4841 | table_name_len = strlen(fullname); |
4842 | } |
4843 | if (name_size + 1 + table_name_len > GRN_TABLE_MAX_KEY_SIZE) { |
4844 | ERR(GRN_INVALID_ARGUMENT, |
4845 | "[column][create] too long column name: required name_size(%d) < %d" |
4846 | ": <%.*s>.<%.*s>" , |
4847 | name_size, GRN_TABLE_MAX_KEY_SIZE - 1 - table_name_len, |
4848 | table_name_len, fullname, name_size, name); |
4849 | goto exit; |
4850 | } |
4851 | fullname[table_name_len] = GRN_DB_DELIMITER; |
4852 | grn_memcpy(fullname + table_name_len + 1, name, name_size); |
4853 | fullname_size = table_name_len + 1 + name_size; |
4854 | } |
4855 | |
4856 | range = DB_OBJ(type)->id; |
4857 | switch (type->header.type) { |
4858 | case GRN_TYPE : |
4859 | { |
4860 | grn_db_obj *t = (grn_db_obj *)type; |
4861 | flags |= t->header.flags & ~GRN_OBJ_KEY_MASK; |
4862 | value_size = GRN_TYPE_SIZE(t); |
4863 | } |
4864 | break; |
4865 | case GRN_TABLE_HASH_KEY : |
4866 | case GRN_TABLE_PAT_KEY : |
4867 | case GRN_TABLE_DAT_KEY : |
4868 | case GRN_TABLE_NO_KEY : |
4869 | value_size = sizeof(grn_id); |
4870 | break; |
4871 | default : |
4872 | /* |
4873 | if (type == grn_type_any) { |
4874 | value_size = sizeof(grn_id) + sizeof(grn_id); |
4875 | } |
4876 | */ |
4877 | value_size = sizeof(grn_id); |
4878 | } |
4879 | |
4880 | if (is_persistent_table) { |
4881 | id = grn_obj_register(ctx, db, fullname, fullname_size); |
4882 | if (ERRP(ctx, GRN_ERROR)) { goto exit; } |
4883 | |
4884 | { |
4885 | uint32_t table_name_size = 0; |
4886 | const char *table_name; |
4887 | table_name = _grn_table_key(ctx, ctx->impl->db, domain, &table_name_size); |
4888 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
4889 | "DDL:%u:column_create %.*s %.*s" , |
4890 | id, |
4891 | table_name_size, table_name, |
4892 | name_size, name); |
4893 | } |
4894 | } else { |
4895 | int added; |
4896 | id = grn_pat_add(ctx, ctx->impl->temporary_columns, |
4897 | fullname, fullname_size, NULL, |
4898 | &added); |
4899 | if (!id) { |
4900 | ERR(GRN_NO_MEMORY_AVAILABLE, |
4901 | "[column][create][temporary] " |
4902 | "failed to register temporary column name: <%.*s>" , |
4903 | fullname_size, fullname); |
4904 | goto exit; |
4905 | } else if (!added) { |
4906 | id = GRN_ID_NIL; |
4907 | ERR(GRN_NO_MEMORY_AVAILABLE, |
4908 | "[column][create][temporary] already used name was assigned: <%.*s>" , |
4909 | fullname_size, fullname); |
4910 | goto exit; |
4911 | } |
4912 | id |= GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN; |
4913 | } |
4914 | |
4915 | if (is_persistent_table && flags & GRN_OBJ_PERSISTENT) { |
4916 | if (!path) { |
4917 | if (GRN_DB_PERSISTENT_P(db)) { |
4918 | grn_db_generate_pathname(ctx, db, id, buffer); |
4919 | path = buffer; |
4920 | } else { |
4921 | int table_name_len; |
4922 | char table_name[GRN_TABLE_MAX_KEY_SIZE]; |
4923 | table_name_len = grn_obj_name(ctx, table, table_name, |
4924 | GRN_TABLE_MAX_KEY_SIZE); |
4925 | ERR(GRN_INVALID_ARGUMENT, |
4926 | "[column][create] path not assigned for persistent column" |
4927 | ": <%.*s>.<%.*s>" , |
4928 | table_name_len, table_name, name_size, name); |
4929 | goto exit; |
4930 | } |
4931 | } else { |
4932 | flags |= GRN_OBJ_CUSTOM_NAME; |
4933 | } |
4934 | } else { |
4935 | if (path) { |
4936 | int table_name_len; |
4937 | char table_name[GRN_TABLE_MAX_KEY_SIZE]; |
4938 | table_name_len = grn_obj_name(ctx, table, table_name, |
4939 | GRN_TABLE_MAX_KEY_SIZE); |
4940 | ERR(GRN_INVALID_ARGUMENT, |
4941 | "[column][create] path assigned for temporary column" |
4942 | ": <%.*s>.<%.*s>" , |
4943 | table_name_len, table_name, name_size, name); |
4944 | goto exit; |
4945 | } |
4946 | } |
4947 | switch (flags & GRN_OBJ_COLUMN_TYPE_MASK) { |
4948 | case GRN_OBJ_COLUMN_SCALAR : |
4949 | if ((flags & GRN_OBJ_KEY_VAR_SIZE) || value_size > sizeof(int64_t)) { |
4950 | res = (grn_obj *)grn_ja_create(ctx, path, value_size, flags); |
4951 | } else { |
4952 | res = (grn_obj *)grn_ra_create(ctx, path, value_size); |
4953 | } |
4954 | break; |
4955 | case GRN_OBJ_COLUMN_VECTOR : |
4956 | res = (grn_obj *)grn_ja_create(ctx, path, value_size * 30/*todo*/, flags); |
4957 | //todo : zlib support |
4958 | break; |
4959 | case GRN_OBJ_COLUMN_INDEX : |
4960 | res = (grn_obj *)grn_ii_create(ctx, path, table, flags); //todo : ii layout support |
4961 | break; |
4962 | } |
4963 | if (res) { |
4964 | DB_OBJ(res)->header.domain = domain; |
4965 | DB_OBJ(res)->header.impl_flags = 0; |
4966 | DB_OBJ(res)->range = range; |
4967 | DB_OBJ(res)->header.flags = flags; |
4968 | res->header.flags = flags; |
4969 | if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) { |
4970 | _grn_obj_remove(ctx, res, GRN_FALSE); |
4971 | res = NULL; |
4972 | } else { |
4973 | grn_obj_touch(ctx, res, NULL); |
4974 | } |
4975 | } |
4976 | exit : |
4977 | if (!res && id) { grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); } |
4978 | GRN_API_RETURN(res); |
4979 | } |
4980 | |
4981 | grn_obj * |
4982 | grn_column_open(grn_ctx *ctx, grn_obj *table, |
4983 | const char *name, unsigned int name_size, |
4984 | const char *path, grn_obj *type) |
4985 | { |
4986 | grn_id domain; |
4987 | grn_obj *res = NULL; |
4988 | grn_db *s; |
4989 | char fullname[GRN_TABLE_MAX_KEY_SIZE]; |
4990 | GRN_API_ENTER; |
4991 | if (!table || !type || !name || !name_size) { |
4992 | ERR(GRN_INVALID_ARGUMENT, "missing type or name" ); |
4993 | goto exit; |
4994 | } |
4995 | s = (grn_db *)DB_OBJ(table)->db; |
4996 | if (!GRN_DB_P(s)) { |
4997 | ERR(GRN_INVALID_ARGUMENT, "invalid db assigned" ); |
4998 | goto exit; |
4999 | } |
5000 | if (grn_db_check_name(ctx, name, name_size)) { |
5001 | GRN_DB_CHECK_NAME_ERR("[column][open]" , name, name_size); |
5002 | goto exit; |
5003 | } |
5004 | if ((domain = DB_OBJ(table)->id)) { |
5005 | int len = grn_table_get_key(ctx, s->keys, domain, fullname, GRN_TABLE_MAX_KEY_SIZE); |
5006 | if (name_size + 1 + len > GRN_TABLE_MAX_KEY_SIZE) { |
5007 | ERR(GRN_INVALID_ARGUMENT, "too long column name" ); |
5008 | goto exit; |
5009 | } |
5010 | fullname[len] = GRN_DB_DELIMITER; |
5011 | grn_memcpy(fullname + len + 1, name, name_size); |
5012 | name_size += len + 1; |
5013 | } else { |
5014 | ERR(GRN_INVALID_ARGUMENT, "todo : not supported yet" ); |
5015 | goto exit; |
5016 | } |
5017 | res = grn_ctx_get(ctx, fullname, name_size); |
5018 | if (res) { |
5019 | const char *path2 = grn_obj_path(ctx, res); |
5020 | if (path && (!path2 || strcmp(path, path2))) { goto exit; } |
5021 | } else if (path) { |
5022 | uint32_t dbtype = grn_io_detect_type(ctx, path); |
5023 | if (!dbtype) { goto exit; } |
5024 | switch (dbtype) { |
5025 | case GRN_COLUMN_VAR_SIZE : |
5026 | res = (grn_obj *)grn_ja_open(ctx, path); |
5027 | break; |
5028 | case GRN_COLUMN_FIX_SIZE : |
5029 | res = (grn_obj *)grn_ra_open(ctx, path); |
5030 | break; |
5031 | case GRN_COLUMN_INDEX : |
5032 | res = (grn_obj *)grn_ii_open(ctx, path, table); |
5033 | break; |
5034 | } |
5035 | if (res) { |
5036 | grn_id id = grn_obj_register(ctx, (grn_obj *)s, fullname, name_size); |
5037 | DB_OBJ(res)->header.domain = domain; |
5038 | DB_OBJ(res)->range = DB_OBJ(type)->id; |
5039 | res->header.flags |= GRN_OBJ_CUSTOM_NAME; |
5040 | grn_db_obj_init(ctx, (grn_obj *)s, id, DB_OBJ(res)); |
5041 | } |
5042 | } |
5043 | exit : |
5044 | GRN_API_RETURN(res); |
5045 | } |
5046 | |
5047 | /* |
5048 | typedef struct { |
5049 | grn_id id; |
5050 | int flags; |
5051 | } grn_column_set_value_arg; |
5052 | |
5053 | static grn_rc |
5054 | default_column_set_value(grn_ctx *ctx, grn_proc_ctx *pctx, grn_obj *in, grn_obj *out) |
5055 | { |
5056 | grn_user_data *data = grn_proc_ctx_get_local_data(pctx); |
5057 | if (data) { |
5058 | grn_column_set_value_arg *arg = data->ptr; |
5059 | unsigned int value_size = in->u.p.size; //todo |
5060 | if (!pctx->obj) { return GRN_ID_NIL; } |
5061 | switch (pctx->obj->header.type) { |
5062 | case GRN_COLUMN_VAR_SIZE : |
5063 | return grn_ja_put(ctx, (grn_ja *)pctx->obj, arg->id, |
5064 | in->u.p.ptr, value_size, 0, NULL); // todo type->flag |
5065 | case GRN_COLUMN_FIX_SIZE : |
5066 | if (((grn_ra *)pctx->obj)->header->element_size < value_size) { |
5067 | ERR(GRN_INVALID_ARGUMENT, "too long value (%d)", value_size); |
5068 | return GRN_INVALID_ARGUMENT; |
5069 | } else { |
5070 | void *v = grn_ra_ref(ctx, (grn_ra *)pctx->obj, arg->id); |
5071 | if (!v) { |
5072 | ERR(GRN_NO_MEMORY_AVAILABLE, "ra get failed"); |
5073 | return GRN_NO_MEMORY_AVAILABLE; |
5074 | } |
5075 | grn_memcpy(v, in->u.p.ptr, value_size); |
5076 | grn_ra_unref(ctx, (grn_ra *)pctx->obj, arg->id); |
5077 | } |
5078 | break; |
5079 | case GRN_COLUMN_INDEX : |
5080 | // todo : how?? |
5081 | break; |
5082 | } |
5083 | return GRN_SUCCESS; |
5084 | } else { |
5085 | ERR(GRN_OBJECT_CORRUPT, "grn_proc_ctx_get_local_data failed"); |
5086 | return ctx->rc; |
5087 | } |
5088 | } |
5089 | */ |
5090 | |
5091 | /**** grn_vector ****/ |
5092 | |
5093 | //#define VECTOR(obj) ((grn_vector *)obj) |
5094 | |
5095 | /* |
5096 | #define INITIAL_VECTOR_SIZE 256 |
5097 | |
5098 | int |
5099 | grn_vector_delimit(grn_ctx *ctx, grn_obj *vector) |
5100 | { |
5101 | grn_vector *v = VECTOR(vector); |
5102 | uint32_t *offsets; |
5103 | if (!(v->n_entries & (INITIAL_VECTOR_SIZE - 1))) { |
5104 | offsets = GRN_REALLOC(v->offsets, sizeof(uint32_t) * |
5105 | (v->n_entries + INITIAL_VECTOR_SIZE)); |
5106 | if (!offsets) { return -1; } |
5107 | v->offsets = offsets; |
5108 | } |
5109 | v->offsets[v->n_entries] = GRN_BULK_VSIZE(vector); |
5110 | return ++(v->n_entries); |
5111 | } |
5112 | */ |
5113 | |
5114 | static unsigned int |
5115 | grn_uvector_element_size_internal(grn_ctx *ctx, grn_obj *uvector) |
5116 | { |
5117 | unsigned int element_size; |
5118 | |
5119 | if (IS_WEIGHT_UVECTOR(uvector)) { |
5120 | element_size = sizeof(weight_uvector_entry); |
5121 | } else { |
5122 | switch (uvector->header.domain) { |
5123 | case GRN_DB_BOOL : |
5124 | element_size = sizeof(grn_bool); |
5125 | break; |
5126 | case GRN_DB_INT8 : |
5127 | element_size = sizeof(int8_t); |
5128 | break; |
5129 | case GRN_DB_UINT8 : |
5130 | element_size = sizeof(uint8_t); |
5131 | break; |
5132 | case GRN_DB_INT16 : |
5133 | element_size = sizeof(int16_t); |
5134 | break; |
5135 | case GRN_DB_UINT16 : |
5136 | element_size = sizeof(uint16_t); |
5137 | break; |
5138 | case GRN_DB_INT32 : |
5139 | element_size = sizeof(int32_t); |
5140 | break; |
5141 | case GRN_DB_UINT32 : |
5142 | element_size = sizeof(uint32_t); |
5143 | break; |
5144 | case GRN_DB_INT64 : |
5145 | element_size = sizeof(int64_t); |
5146 | break; |
5147 | case GRN_DB_UINT64 : |
5148 | element_size = sizeof(uint64_t); |
5149 | break; |
5150 | case GRN_DB_FLOAT : |
5151 | element_size = sizeof(double); |
5152 | break; |
5153 | case GRN_DB_TIME : |
5154 | element_size = sizeof(int64_t); |
5155 | break; |
5156 | case GRN_DB_TOKYO_GEO_POINT : |
5157 | case GRN_DB_WGS84_GEO_POINT : |
5158 | element_size = sizeof(grn_geo_point); |
5159 | break; |
5160 | default : |
5161 | element_size = sizeof(grn_id); |
5162 | break; |
5163 | } |
5164 | } |
5165 | |
5166 | return element_size; |
5167 | } |
5168 | |
5169 | static unsigned int |
5170 | grn_uvector_size_internal(grn_ctx *ctx, grn_obj *uvector) |
5171 | { |
5172 | unsigned int element_size; |
5173 | |
5174 | element_size = grn_uvector_element_size_internal(ctx, uvector); |
5175 | return GRN_BULK_VSIZE(uvector) / element_size; |
5176 | } |
5177 | |
5178 | unsigned int |
5179 | grn_vector_size(grn_ctx *ctx, grn_obj *vector) |
5180 | { |
5181 | unsigned int size; |
5182 | if (!vector) { |
5183 | ERR(GRN_INVALID_ARGUMENT, "vector is null" ); |
5184 | return 0; |
5185 | } |
5186 | GRN_API_ENTER; |
5187 | switch (vector->header.type) { |
5188 | case GRN_BULK : |
5189 | size = GRN_BULK_VSIZE(vector); |
5190 | break; |
5191 | case GRN_UVECTOR : |
5192 | size = grn_uvector_size_internal(ctx, vector); |
5193 | break; |
5194 | case GRN_VECTOR : |
5195 | size = vector->u.v.n_sections; |
5196 | break; |
5197 | default : |
5198 | ERR(GRN_INVALID_ARGUMENT, "not vector" ); |
5199 | size = 0; |
5200 | break; |
5201 | } |
5202 | GRN_API_RETURN(size); |
5203 | } |
5204 | |
5205 | static grn_obj * |
5206 | grn_vector_body(grn_ctx *ctx, grn_obj *v) |
5207 | { |
5208 | if (!v) { |
5209 | ERR(GRN_INVALID_ARGUMENT, "invalid argument" ); |
5210 | return NULL; |
5211 | } |
5212 | switch (v->header.type) { |
5213 | case GRN_VECTOR : |
5214 | if (!v->u.v.body) { |
5215 | v->u.v.body = grn_obj_open(ctx, GRN_BULK, 0, v->header.domain); |
5216 | } |
5217 | return v->u.v.body; |
5218 | case GRN_BULK : |
5219 | case GRN_UVECTOR : |
5220 | return v; |
5221 | default : |
5222 | return NULL; |
5223 | } |
5224 | } |
5225 | |
5226 | unsigned int |
5227 | grn_vector_get_element(grn_ctx *ctx, grn_obj *vector, |
5228 | unsigned int offset, const char **str, |
5229 | unsigned int *weight, grn_id *domain) |
5230 | { |
5231 | unsigned int length = 0; |
5232 | GRN_API_ENTER; |
5233 | if (!vector || vector->header.type != GRN_VECTOR) { |
5234 | ERR(GRN_INVALID_ARGUMENT, "invalid vector" ); |
5235 | goto exit; |
5236 | } |
5237 | if (vector->u.v.n_sections <= offset) { |
5238 | ERR(GRN_RANGE_ERROR, "offset out of range" ); |
5239 | goto exit; |
5240 | } |
5241 | { |
5242 | grn_section *vp = &vector->u.v.sections[offset]; |
5243 | grn_obj *body = grn_vector_body(ctx, vector); |
5244 | *str = GRN_BULK_HEAD(body) + vp->offset; |
5245 | if (weight) { *weight = vp->weight; } |
5246 | if (domain) { *domain = vp->domain; } |
5247 | length = vp->length; |
5248 | } |
5249 | exit : |
5250 | GRN_API_RETURN(length); |
5251 | } |
5252 | |
5253 | unsigned int |
5254 | grn_vector_pop_element(grn_ctx *ctx, grn_obj *vector, |
5255 | const char **str, unsigned int *weight, grn_id *domain) |
5256 | { |
5257 | unsigned int offset, length = 0; |
5258 | GRN_API_ENTER; |
5259 | if (!vector || vector->header.type != GRN_VECTOR) { |
5260 | ERR(GRN_INVALID_ARGUMENT, "invalid vector" ); |
5261 | goto exit; |
5262 | } |
5263 | if (!vector->u.v.n_sections) { |
5264 | ERR(GRN_RANGE_ERROR, "offset out of range" ); |
5265 | goto exit; |
5266 | } |
5267 | offset = --vector->u.v.n_sections; |
5268 | { |
5269 | grn_section *vp = &vector->u.v.sections[offset]; |
5270 | grn_obj *body = grn_vector_body(ctx, vector); |
5271 | *str = GRN_BULK_HEAD(body) + vp->offset; |
5272 | if (weight) { *weight = vp->weight; } |
5273 | if (domain) { *domain = vp->domain; } |
5274 | length = vp->length; |
5275 | grn_bulk_truncate(ctx, body, vp->offset); |
5276 | } |
5277 | exit : |
5278 | GRN_API_RETURN(length); |
5279 | } |
5280 | |
5281 | #define W_SECTIONS_UNIT 8 |
5282 | #define S_SECTIONS_UNIT (1 << W_SECTIONS_UNIT) |
5283 | #define M_SECTIONS_UNIT (S_SECTIONS_UNIT - 1) |
5284 | |
5285 | grn_rc |
5286 | grn_vector_delimit(grn_ctx *ctx, grn_obj *v, unsigned int weight, grn_id domain) |
5287 | { |
5288 | if (v->header.type != GRN_VECTOR) { return GRN_INVALID_ARGUMENT; } |
5289 | if (!(v->u.v.n_sections & M_SECTIONS_UNIT)) { |
5290 | grn_section *vp = GRN_REALLOC(v->u.v.sections, sizeof(grn_section) * |
5291 | (v->u.v.n_sections + S_SECTIONS_UNIT)); |
5292 | if (!vp) { return GRN_NO_MEMORY_AVAILABLE; } |
5293 | v->u.v.sections = vp; |
5294 | } |
5295 | { |
5296 | grn_obj *body = grn_vector_body(ctx, v); |
5297 | grn_section *vp = &v->u.v.sections[v->u.v.n_sections]; |
5298 | vp->offset = v->u.v.n_sections ? vp[-1].offset + vp[-1].length : 0; |
5299 | vp->length = GRN_BULK_VSIZE(body) - vp->offset; |
5300 | vp->weight = weight; |
5301 | vp->domain = domain; |
5302 | } |
5303 | v->u.v.n_sections++; |
5304 | return GRN_SUCCESS; |
5305 | } |
5306 | |
5307 | grn_rc |
5308 | grn_vector_decode(grn_ctx *ctx, grn_obj *v, const char *data, uint32_t data_size) |
5309 | { |
5310 | uint8_t *p = (uint8_t *)data; |
5311 | uint8_t *pe = p + data_size; |
5312 | uint32_t n, n0 = v->u.v.n_sections; |
5313 | GRN_B_DEC(n, p); |
5314 | if (((n0 + M_SECTIONS_UNIT) >> W_SECTIONS_UNIT) != |
5315 | ((n0 + n + M_SECTIONS_UNIT) >> W_SECTIONS_UNIT)) { |
5316 | grn_section *vp = GRN_REALLOC(v->u.v.sections, sizeof(grn_section) * |
5317 | ((n0 + n + M_SECTIONS_UNIT) & ~M_SECTIONS_UNIT)); |
5318 | if (!vp) { return GRN_NO_MEMORY_AVAILABLE; } |
5319 | v->u.v.sections = vp; |
5320 | } |
5321 | { |
5322 | grn_section *vp; |
5323 | grn_obj *body = grn_vector_body(ctx, v); |
5324 | uint32_t offset = GRN_BULK_VSIZE(body); |
5325 | uint32_t o = 0, l, i; |
5326 | for (i = n, vp = v->u.v.sections + n0; i; i--, vp++) { |
5327 | if (pe <= p) { return GRN_INVALID_ARGUMENT; } |
5328 | GRN_B_DEC(l, p); |
5329 | vp->length = l; |
5330 | vp->offset = offset + o; |
5331 | vp->weight = 0; |
5332 | vp->domain = 0; |
5333 | o += l; |
5334 | } |
5335 | if (pe < p + o) { return GRN_INVALID_ARGUMENT; } |
5336 | grn_bulk_write(ctx, body, (char *)p, o); |
5337 | p += o; |
5338 | if (p < pe) { |
5339 | for (i = n, vp = v->u.v.sections + n0; i; i--, vp++) { |
5340 | if (pe <= p) { return GRN_INVALID_ARGUMENT; } |
5341 | GRN_B_DEC(vp->weight, p); |
5342 | GRN_B_DEC(vp->domain, p); |
5343 | } |
5344 | } |
5345 | } |
5346 | v->u.v.n_sections += n; |
5347 | return GRN_SUCCESS; |
5348 | } |
5349 | |
5350 | grn_rc |
5351 | grn_vector_add_element(grn_ctx *ctx, grn_obj *vector, |
5352 | const char *str, unsigned int str_len, |
5353 | unsigned int weight, grn_id domain) |
5354 | { |
5355 | grn_obj *body; |
5356 | GRN_API_ENTER; |
5357 | if (!vector) { |
5358 | ERR(GRN_INVALID_ARGUMENT, "vector is null" ); |
5359 | goto exit; |
5360 | } |
5361 | if ((body = grn_vector_body(ctx, vector))) { |
5362 | grn_bulk_write(ctx, body, str, str_len); |
5363 | grn_vector_delimit(ctx, vector, weight, domain); |
5364 | } |
5365 | exit : |
5366 | GRN_API_RETURN(ctx->rc); |
5367 | } |
5368 | |
5369 | /* |
5370 | grn_obj * |
5371 | grn_sections_to_vector(grn_ctx *ctx, grn_obj *sections) |
5372 | { |
5373 | grn_obj *vector = grn_vector_open(ctx, 0); |
5374 | if (vector) { |
5375 | grn_section *vp; |
5376 | int i; |
5377 | for (i = sections->u.v.n_sections, vp = sections->u.v.sections; i; i--, vp++) { |
5378 | grn_text_benc(ctx, vector, vp->weight); |
5379 | grn_text_benc(ctx, vector, vp->domain); |
5380 | grn_bulk_write(ctx, vector, vp->str, vp->str_len); |
5381 | grn_vector_delimit(ctx, vector); |
5382 | } |
5383 | } |
5384 | return vector; |
5385 | } |
5386 | |
5387 | grn_obj * |
5388 | grn_vector_to_sections(grn_ctx *ctx, grn_obj *vector, grn_obj *sections) |
5389 | { |
5390 | if (!sections) { |
5391 | sections = grn_obj_open(ctx, GRN_VECTOR, GRN_OBJ_DO_SHALLOW_COPY, 0); |
5392 | } |
5393 | if (sections) { |
5394 | int i, n = grn_vector_size(ctx, vector); |
5395 | sections->u.v.src = vector; |
5396 | for (i = 0; i < n; i++) { |
5397 | unsigned int size; |
5398 | const uint8_t *pe, *p = (uint8_t *)grn_vector_fetch(ctx, vector, i, &size); |
5399 | if (p) { |
5400 | grn_id domain; |
5401 | unsigned int weight; |
5402 | pe = p + size; |
5403 | if (p < pe) { |
5404 | GRN_B_DEC(weight, p); |
5405 | if (p < pe) { |
5406 | GRN_B_DEC(domain, p); |
5407 | if (p <= pe) { |
5408 | grn_vector_add(ctx, sections, (char *)p, pe - p, weight, domain); |
5409 | } |
5410 | } |
5411 | } |
5412 | } |
5413 | } |
5414 | } |
5415 | return sections; |
5416 | } |
5417 | */ |
5418 | |
5419 | /**** uvector ****/ |
5420 | |
5421 | unsigned int |
5422 | grn_uvector_size(grn_ctx *ctx, grn_obj *uvector) |
5423 | { |
5424 | unsigned int size; |
5425 | |
5426 | if (!uvector) { |
5427 | ERR(GRN_INVALID_ARGUMENT, "uvector must not be NULL" ); |
5428 | return 0; |
5429 | } |
5430 | |
5431 | if (uvector->header.type != GRN_UVECTOR) { |
5432 | grn_obj type_name; |
5433 | GRN_TEXT_INIT(&type_name, 0); |
5434 | grn_inspect_type(ctx, &type_name, uvector->header.type); |
5435 | ERR(GRN_INVALID_ARGUMENT, "must be GRN_UVECTOR: %.*s" , |
5436 | (int)GRN_TEXT_LEN(&type_name), GRN_TEXT_VALUE(&type_name)); |
5437 | GRN_OBJ_FIN(ctx, &type_name); |
5438 | return 0; |
5439 | } |
5440 | |
5441 | GRN_API_ENTER; |
5442 | size = grn_uvector_size_internal(ctx, uvector); |
5443 | GRN_API_RETURN(size); |
5444 | } |
5445 | |
5446 | unsigned int |
5447 | grn_uvector_element_size(grn_ctx *ctx, grn_obj *uvector) |
5448 | { |
5449 | unsigned int element_size; |
5450 | |
5451 | if (!uvector) { |
5452 | ERR(GRN_INVALID_ARGUMENT, "uvector must not be NULL" ); |
5453 | return 0; |
5454 | } |
5455 | |
5456 | if (uvector->header.type != GRN_UVECTOR) { |
5457 | grn_obj type_name; |
5458 | GRN_TEXT_INIT(&type_name, 0); |
5459 | grn_inspect_type(ctx, &type_name, uvector->header.type); |
5460 | ERR(GRN_INVALID_ARGUMENT, "must be GRN_UVECTOR: %.*s" , |
5461 | (int)GRN_TEXT_LEN(&type_name), GRN_TEXT_VALUE(&type_name)); |
5462 | GRN_OBJ_FIN(ctx, &type_name); |
5463 | return 0; |
5464 | } |
5465 | |
5466 | GRN_API_ENTER; |
5467 | element_size = grn_uvector_element_size_internal(ctx, uvector); |
5468 | GRN_API_RETURN(element_size); |
5469 | } |
5470 | |
5471 | grn_rc |
5472 | grn_uvector_add_element(grn_ctx *ctx, grn_obj *uvector, |
5473 | grn_id id, unsigned int weight) |
5474 | { |
5475 | GRN_API_ENTER; |
5476 | if (!uvector) { |
5477 | ERR(GRN_INVALID_ARGUMENT, "uvector is null" ); |
5478 | goto exit; |
5479 | } |
5480 | if (IS_WEIGHT_UVECTOR(uvector)) { |
5481 | weight_uvector_entry entry; |
5482 | entry.id = id; |
5483 | entry.weight = weight; |
5484 | grn_bulk_write(ctx, uvector, |
5485 | (const char *)&entry, sizeof(weight_uvector_entry)); |
5486 | } else { |
5487 | grn_bulk_write(ctx, uvector, |
5488 | (const char *)&id, sizeof(grn_id)); |
5489 | } |
5490 | exit : |
5491 | GRN_API_RETURN(ctx->rc); |
5492 | } |
5493 | |
5494 | grn_id |
5495 | grn_uvector_get_element(grn_ctx *ctx, grn_obj *uvector, |
5496 | unsigned int offset, unsigned int *weight) |
5497 | { |
5498 | grn_id id = GRN_ID_NIL; |
5499 | |
5500 | GRN_API_ENTER; |
5501 | if (!uvector || uvector->header.type != GRN_UVECTOR) { |
5502 | ERR(GRN_INVALID_ARGUMENT, "invalid uvector" ); |
5503 | goto exit; |
5504 | } |
5505 | |
5506 | if (IS_WEIGHT_UVECTOR(uvector)) { |
5507 | const weight_uvector_entry *entry; |
5508 | const weight_uvector_entry *entries_start; |
5509 | const weight_uvector_entry *entries_end; |
5510 | |
5511 | entries_start = (const weight_uvector_entry *)GRN_BULK_HEAD(uvector); |
5512 | entries_end = (const weight_uvector_entry *)GRN_BULK_CURR(uvector); |
5513 | if (offset > entries_end - entries_start) { |
5514 | ERR(GRN_RANGE_ERROR, "offset out of range" ); |
5515 | goto exit; |
5516 | } |
5517 | |
5518 | entry = entries_start + offset; |
5519 | id = entry->id; |
5520 | if (weight) { *weight = entry->weight; } |
5521 | } else { |
5522 | const grn_id *ids_start; |
5523 | const grn_id *ids_end; |
5524 | |
5525 | ids_start = (const grn_id *)GRN_BULK_HEAD(uvector); |
5526 | ids_end = (const grn_id *)GRN_BULK_CURR(uvector); |
5527 | if (offset > ids_end - ids_start) { |
5528 | ERR(GRN_RANGE_ERROR, "offset out of range" ); |
5529 | goto exit; |
5530 | } |
5531 | id = ids_start[offset]; |
5532 | if (weight) { *weight = 0; } |
5533 | } |
5534 | exit : |
5535 | GRN_API_RETURN(id); |
5536 | } |
5537 | |
5538 | /**** accessor ****/ |
5539 | |
5540 | static grn_accessor * |
5541 | accessor_new(grn_ctx *ctx) |
5542 | { |
5543 | grn_accessor *res = GRN_MALLOCN(grn_accessor, 1); |
5544 | if (res) { |
5545 | res->header.type = GRN_ACCESSOR; |
5546 | res->header.impl_flags = GRN_OBJ_ALLOCATED; |
5547 | res->header.flags = 0; |
5548 | res->header.domain = GRN_ID_NIL; |
5549 | res->range = GRN_ID_NIL; |
5550 | res->action = GRN_ACCESSOR_VOID; |
5551 | res->offset = 0; |
5552 | res->obj = NULL; |
5553 | res->next = NULL; |
5554 | } |
5555 | return res; |
5556 | } |
5557 | |
5558 | inline static grn_bool |
5559 | grn_obj_get_accessor_rset_value(grn_ctx *ctx, grn_obj *obj, |
5560 | grn_accessor **res, uint8_t action) |
5561 | { |
5562 | grn_bool succeeded = GRN_FALSE; |
5563 | grn_accessor **rp; |
5564 | |
5565 | for (rp = res; GRN_TRUE; rp = &(*rp)->next) { |
5566 | *rp = accessor_new(ctx); |
5567 | (*rp)->obj = obj; |
5568 | |
5569 | #define CHECK_GROUP_CALC_FLAG(flag) do { \ |
5570 | if (GRN_TABLE_IS_GROUPED(obj)) { \ |
5571 | grn_table_group_flags flags; \ |
5572 | flags = DB_OBJ(obj)->flags.group; \ |
5573 | if (flags & flag) { \ |
5574 | succeeded = GRN_TRUE; \ |
5575 | (*rp)->action = action; \ |
5576 | goto exit; \ |
5577 | } \ |
5578 | } \ |
5579 | } while(GRN_FALSE) |
5580 | switch (action) { |
5581 | case GRN_ACCESSOR_GET_SCORE : |
5582 | if (DB_OBJ(obj)->header.flags & GRN_OBJ_WITH_SUBREC) { |
5583 | (*rp)->action = action; |
5584 | succeeded = GRN_TRUE; |
5585 | goto exit; |
5586 | } |
5587 | break; |
5588 | case GRN_ACCESSOR_GET_MAX : |
5589 | CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_MAX); |
5590 | break; |
5591 | case GRN_ACCESSOR_GET_MIN : |
5592 | CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_MIN); |
5593 | break; |
5594 | case GRN_ACCESSOR_GET_SUM : |
5595 | CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_SUM); |
5596 | break; |
5597 | case GRN_ACCESSOR_GET_AVG : |
5598 | CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_AVG); |
5599 | break; |
5600 | case GRN_ACCESSOR_GET_NSUBRECS : |
5601 | if (GRN_TABLE_IS_GROUPED(obj)) { |
5602 | (*rp)->action = action; |
5603 | succeeded = GRN_TRUE; |
5604 | goto exit; |
5605 | } |
5606 | break; |
5607 | } |
5608 | #undef CHECK_GROUP_CALC_FLAG |
5609 | |
5610 | switch (obj->header.type) { |
5611 | case GRN_TABLE_PAT_KEY : |
5612 | case GRN_TABLE_DAT_KEY : |
5613 | case GRN_TABLE_HASH_KEY : |
5614 | (*rp)->action = GRN_ACCESSOR_GET_KEY; |
5615 | break; |
5616 | case GRN_TABLE_NO_KEY : |
5617 | if (!obj->header.domain) { |
5618 | goto exit; |
5619 | } |
5620 | (*rp)->action = GRN_ACCESSOR_GET_VALUE; |
5621 | break; |
5622 | default : |
5623 | /* lookup failed */ |
5624 | goto exit; |
5625 | } |
5626 | if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { |
5627 | goto exit; |
5628 | } |
5629 | } |
5630 | |
5631 | exit : |
5632 | if (!succeeded) { |
5633 | grn_obj_close(ctx, (grn_obj *)*res); |
5634 | *res = NULL; |
5635 | } |
5636 | |
5637 | return succeeded; |
5638 | } |
5639 | |
5640 | static grn_obj * |
5641 | grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int name_size) |
5642 | { |
5643 | grn_accessor *res = NULL, **rp = NULL, **rp0 = NULL; |
5644 | grn_bool is_chained = GRN_FALSE; |
5645 | if (!obj) { return NULL; } |
5646 | GRN_API_ENTER; |
5647 | if (obj->header.type == GRN_ACCESSOR) { |
5648 | is_chained = GRN_TRUE; |
5649 | for (rp0 = (grn_accessor **)&obj; *rp0; rp0 = &(*rp0)->next) { |
5650 | res = *rp0; |
5651 | } |
5652 | switch (res->action) { |
5653 | case GRN_ACCESSOR_GET_KEY : |
5654 | obj = grn_ctx_at(ctx, res->obj->header.domain); |
5655 | break; |
5656 | case GRN_ACCESSOR_GET_VALUE : |
5657 | case GRN_ACCESSOR_GET_SCORE : |
5658 | case GRN_ACCESSOR_GET_NSUBRECS : |
5659 | case GRN_ACCESSOR_GET_MAX : |
5660 | case GRN_ACCESSOR_GET_MIN : |
5661 | case GRN_ACCESSOR_GET_SUM : |
5662 | case GRN_ACCESSOR_GET_AVG : |
5663 | obj = grn_ctx_at(ctx, DB_OBJ(res->obj)->range); |
5664 | break; |
5665 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
5666 | obj = grn_ctx_at(ctx, DB_OBJ(res->obj)->range); |
5667 | break; |
5668 | case GRN_ACCESSOR_LOOKUP : |
5669 | /* todo */ |
5670 | break; |
5671 | case GRN_ACCESSOR_FUNCALL : |
5672 | /* todo */ |
5673 | break; |
5674 | } |
5675 | } |
5676 | if (!obj) { |
5677 | res = NULL; |
5678 | goto exit; |
5679 | } |
5680 | { |
5681 | size_t len; |
5682 | const char *sp, *se = name + name_size; |
5683 | if (*name == GRN_DB_DELIMITER) { name++; } |
5684 | for (sp = name; (len = grn_charlen(ctx, sp, se)); sp += len) { |
5685 | if (*sp == GRN_DB_DELIMITER) { break; } |
5686 | } |
5687 | if (!(len = sp - name)) { goto exit; } |
5688 | if (*name == GRN_DB_PSEUDO_COLUMN_PREFIX) { /* pseudo column */ |
5689 | int done = 0; |
5690 | if (len < 2) { goto exit; } |
5691 | switch (name[1]) { |
5692 | case 'k' : /* key */ |
5693 | if (len != GRN_COLUMN_NAME_KEY_LEN || |
5694 | memcmp(name, GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_KEY_LEN)) { |
5695 | goto exit; |
5696 | } |
5697 | for (rp = &res; !done; rp = &(*rp)->next) { |
5698 | *rp = accessor_new(ctx); |
5699 | (*rp)->obj = obj; |
5700 | if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(obj)) { |
5701 | (*rp)->action = GRN_ACCESSOR_GET_KEY; |
5702 | done++; |
5703 | break; |
5704 | } |
5705 | if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { |
5706 | grn_obj_close(ctx, (grn_obj *)res); |
5707 | res = NULL; |
5708 | goto exit; |
5709 | } |
5710 | switch (obj->header.type) { |
5711 | case GRN_DB : |
5712 | (*rp)->action = GRN_ACCESSOR_GET_KEY; |
5713 | rp = &(*rp)->next; |
5714 | *rp = accessor_new(ctx); |
5715 | (*rp)->obj = obj; |
5716 | (*rp)->action = GRN_ACCESSOR_GET_DB_OBJ; |
5717 | done++; |
5718 | break; |
5719 | case GRN_TYPE : |
5720 | (*rp)->action = GRN_ACCESSOR_GET_KEY; |
5721 | done++; |
5722 | break; |
5723 | case GRN_TABLE_PAT_KEY : |
5724 | case GRN_TABLE_DAT_KEY : |
5725 | case GRN_TABLE_HASH_KEY : |
5726 | (*rp)->action = GRN_ACCESSOR_GET_KEY; |
5727 | break; |
5728 | case GRN_TABLE_NO_KEY : |
5729 | if (obj->header.domain) { |
5730 | (*rp)->action = GRN_ACCESSOR_GET_VALUE; |
5731 | break; |
5732 | } |
5733 | /* fallthru */ |
5734 | default : |
5735 | /* lookup failed */ |
5736 | grn_obj_close(ctx, (grn_obj *)res); |
5737 | res = NULL; |
5738 | goto exit; |
5739 | } |
5740 | } |
5741 | break; |
5742 | case 'i' : /* id */ |
5743 | if (len != GRN_COLUMN_NAME_ID_LEN || |
5744 | memcmp(name, GRN_COLUMN_NAME_ID, GRN_COLUMN_NAME_ID_LEN)) { |
5745 | goto exit; |
5746 | } |
5747 | for (rp = &res; !done; rp = &(*rp)->next) { |
5748 | *rp = accessor_new(ctx); |
5749 | (*rp)->obj = obj; |
5750 | if (!obj->header.domain) { |
5751 | (*rp)->action = GRN_ACCESSOR_GET_ID; |
5752 | done++; |
5753 | } else { |
5754 | if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { |
5755 | grn_obj_close(ctx, (grn_obj *)res); |
5756 | res = NULL; |
5757 | goto exit; |
5758 | } |
5759 | switch (obj->header.type) { |
5760 | case GRN_DB : |
5761 | case GRN_TYPE : |
5762 | (*rp)->action = GRN_ACCESSOR_GET_ID; |
5763 | done++; |
5764 | break; |
5765 | case GRN_TABLE_PAT_KEY : |
5766 | case GRN_TABLE_DAT_KEY : |
5767 | case GRN_TABLE_HASH_KEY : |
5768 | case GRN_TABLE_NO_KEY : |
5769 | (*rp)->action = GRN_ACCESSOR_GET_KEY; |
5770 | break; |
5771 | default : |
5772 | /* lookup failed */ |
5773 | grn_obj_close(ctx, (grn_obj *)res); |
5774 | res = NULL; |
5775 | goto exit; |
5776 | } |
5777 | } |
5778 | } |
5779 | break; |
5780 | case 'v' : /* value */ |
5781 | if (len != GRN_COLUMN_NAME_VALUE_LEN || |
5782 | memcmp(name, GRN_COLUMN_NAME_VALUE, GRN_COLUMN_NAME_VALUE_LEN)) { |
5783 | goto exit; |
5784 | } |
5785 | for (rp = &res; !done; rp = &(*rp)->next) { |
5786 | *rp = accessor_new(ctx); |
5787 | (*rp)->obj = obj; |
5788 | if (!obj->header.domain) { |
5789 | if (DB_OBJ((*rp)->obj)->range) { |
5790 | (*rp)->action = GRN_ACCESSOR_GET_VALUE; |
5791 | done++; |
5792 | } else { |
5793 | grn_obj_close(ctx, (grn_obj *)res); |
5794 | res = NULL; |
5795 | goto exit; |
5796 | } |
5797 | done++; |
5798 | } else { |
5799 | if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { |
5800 | grn_obj_close(ctx, (grn_obj *)res); |
5801 | res = NULL; |
5802 | goto exit; |
5803 | } |
5804 | switch (obj->header.type) { |
5805 | case GRN_DB : |
5806 | case GRN_TYPE : |
5807 | if (DB_OBJ((*rp)->obj)->range) { |
5808 | (*rp)->action = GRN_ACCESSOR_GET_VALUE; |
5809 | done++; |
5810 | } else { |
5811 | grn_obj_close(ctx, (grn_obj *)res); |
5812 | res = NULL; |
5813 | goto exit; |
5814 | } |
5815 | break; |
5816 | case GRN_TABLE_PAT_KEY : |
5817 | case GRN_TABLE_DAT_KEY : |
5818 | case GRN_TABLE_HASH_KEY : |
5819 | case GRN_TABLE_NO_KEY : |
5820 | (*rp)->action = GRN_ACCESSOR_GET_KEY; |
5821 | break; |
5822 | default : |
5823 | /* lookup failed */ |
5824 | grn_obj_close(ctx, (grn_obj *)res); |
5825 | res = NULL; |
5826 | goto exit; |
5827 | } |
5828 | } |
5829 | } |
5830 | break; |
5831 | case 's' : /* score, sum */ |
5832 | if (len == GRN_COLUMN_NAME_SCORE_LEN && |
5833 | memcmp(name, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN) == 0) { |
5834 | if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, |
5835 | GRN_ACCESSOR_GET_SCORE)) { |
5836 | goto exit; |
5837 | } |
5838 | } else if (len == GRN_COLUMN_NAME_SUM_LEN && |
5839 | memcmp(name, |
5840 | GRN_COLUMN_NAME_SUM, |
5841 | GRN_COLUMN_NAME_SUM_LEN) == 0) { |
5842 | if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, |
5843 | GRN_ACCESSOR_GET_SUM)) { |
5844 | goto exit; |
5845 | } |
5846 | } else { |
5847 | goto exit; |
5848 | } |
5849 | break; |
5850 | case 'n' : /* nsubrecs */ |
5851 | if (len != GRN_COLUMN_NAME_NSUBRECS_LEN || |
5852 | memcmp(name, |
5853 | GRN_COLUMN_NAME_NSUBRECS, |
5854 | GRN_COLUMN_NAME_NSUBRECS_LEN)) { |
5855 | goto exit; |
5856 | } |
5857 | if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, |
5858 | GRN_ACCESSOR_GET_NSUBRECS)) { |
5859 | goto exit; |
5860 | } |
5861 | break; |
5862 | case 'm' : /* max, min */ |
5863 | if (len == GRN_COLUMN_NAME_MAX_LEN && |
5864 | memcmp(name, |
5865 | GRN_COLUMN_NAME_MAX, |
5866 | GRN_COLUMN_NAME_MAX_LEN) == 0) { |
5867 | if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, |
5868 | GRN_ACCESSOR_GET_MAX)) { |
5869 | goto exit; |
5870 | } |
5871 | } else if (len == GRN_COLUMN_NAME_MIN_LEN && |
5872 | memcmp(name, |
5873 | GRN_COLUMN_NAME_MIN, |
5874 | GRN_COLUMN_NAME_MIN_LEN) == 0) { |
5875 | if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, |
5876 | GRN_ACCESSOR_GET_MIN)) { |
5877 | goto exit; |
5878 | } |
5879 | } else { |
5880 | goto exit; |
5881 | } |
5882 | break; |
5883 | case 'a' : /* avg */ |
5884 | if (len == GRN_COLUMN_NAME_AVG_LEN && |
5885 | memcmp(name, |
5886 | GRN_COLUMN_NAME_AVG, |
5887 | GRN_COLUMN_NAME_AVG_LEN) == 0) { |
5888 | if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, |
5889 | GRN_ACCESSOR_GET_AVG)) { |
5890 | goto exit; |
5891 | } |
5892 | } else { |
5893 | goto exit; |
5894 | } |
5895 | break; |
5896 | default : |
5897 | res = NULL; |
5898 | goto exit; |
5899 | } |
5900 | } else { |
5901 | /* if obj->header.type == GRN_TYPE ... lookup table */ |
5902 | for (rp = &res; ; rp = &(*rp)->next) { |
5903 | grn_obj *column = grn_obj_column_(ctx, obj, name, len); |
5904 | if (column) { |
5905 | *rp = accessor_new(ctx); |
5906 | (*rp)->obj = column; |
5907 | /* |
5908 | switch (column->header.type) { |
5909 | case GRN_COLUMN_VAR_SIZE : |
5910 | break; |
5911 | case GRN_COLUMN_FIX_SIZE : |
5912 | break; |
5913 | case GRN_COLUMN_INDEX : |
5914 | break; |
5915 | } |
5916 | */ |
5917 | (*rp)->action = GRN_ACCESSOR_GET_COLUMN_VALUE; |
5918 | break; |
5919 | } else { |
5920 | grn_id next_obj_id; |
5921 | next_obj_id = obj->header.domain; |
5922 | if (!next_obj_id) { |
5923 | // ERR(GRN_INVALID_ARGUMENT, "no such column: <%s>", name); |
5924 | if (!is_chained) { |
5925 | grn_obj_close(ctx, (grn_obj *)res); |
5926 | } |
5927 | res = NULL; |
5928 | goto exit; |
5929 | } |
5930 | *rp = accessor_new(ctx); |
5931 | (*rp)->obj = obj; |
5932 | obj = grn_ctx_at(ctx, next_obj_id); |
5933 | if (!obj) { |
5934 | grn_obj_close(ctx, (grn_obj *)res); |
5935 | res = NULL; |
5936 | goto exit; |
5937 | } |
5938 | switch (obj->header.type) { |
5939 | case GRN_TABLE_PAT_KEY : |
5940 | case GRN_TABLE_DAT_KEY : |
5941 | case GRN_TABLE_HASH_KEY : |
5942 | case GRN_TABLE_NO_KEY : |
5943 | (*rp)->action = GRN_ACCESSOR_GET_KEY; |
5944 | break; |
5945 | default : |
5946 | /* lookup failed */ |
5947 | grn_obj_close(ctx, (grn_obj *)res); |
5948 | res = NULL; |
5949 | goto exit; |
5950 | } |
5951 | } |
5952 | } |
5953 | } |
5954 | if (sp != se) { |
5955 | if (!grn_obj_get_accessor(ctx, (grn_obj *)res, sp, se - sp)) { |
5956 | if (!is_chained) { |
5957 | grn_obj_close(ctx, (grn_obj *)res); |
5958 | res = NULL; |
5959 | goto exit; |
5960 | } |
5961 | } |
5962 | } |
5963 | } |
5964 | if (rp0) { *rp0 = res; } |
5965 | exit : |
5966 | GRN_API_RETURN((grn_obj *)res); |
5967 | } |
5968 | |
5969 | inline static grn_bool |
5970 | grn_column_is_vector(grn_ctx *ctx, grn_obj *column) |
5971 | { |
5972 | grn_obj_flags type; |
5973 | |
5974 | if (column->header.type != GRN_COLUMN_VAR_SIZE) { |
5975 | return GRN_FALSE; |
5976 | } |
5977 | |
5978 | type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK; |
5979 | return type == GRN_OBJ_COLUMN_VECTOR; |
5980 | } |
5981 | |
5982 | inline static grn_bool |
5983 | grn_column_is_index(grn_ctx *ctx, grn_obj *column) |
5984 | { |
5985 | grn_obj_flags type; |
5986 | |
5987 | if (column->header.type == GRN_ACCESSOR) { |
5988 | grn_accessor *a; |
5989 | for (a = (grn_accessor *)column; a; a = a->next) { |
5990 | if (a->next) { |
5991 | continue; |
5992 | } |
5993 | if (a->action != GRN_ACCESSOR_GET_COLUMN_VALUE) { |
5994 | return GRN_FALSE; |
5995 | } |
5996 | |
5997 | column = a->obj; |
5998 | } |
5999 | } |
6000 | |
6001 | if (column->header.type != GRN_COLUMN_INDEX) { |
6002 | return GRN_FALSE; |
6003 | } |
6004 | |
6005 | type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK; |
6006 | return type == GRN_OBJ_COLUMN_INDEX; |
6007 | } |
6008 | |
6009 | inline static void |
6010 | grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj, |
6011 | grn_id *range_id, grn_obj_flags *range_flags) |
6012 | { |
6013 | if (!obj) { |
6014 | *range_id = GRN_ID_NIL; |
6015 | } else if (grn_obj_is_proc(ctx, obj)) { |
6016 | /* TODO */ |
6017 | *range_id = GRN_ID_NIL; |
6018 | } else if (GRN_DB_OBJP(obj)) { |
6019 | *range_id = DB_OBJ(obj)->range; |
6020 | if (grn_column_is_vector(ctx, obj)) { |
6021 | *range_flags = GRN_OBJ_VECTOR; |
6022 | } |
6023 | } else if (obj->header.type == GRN_ACCESSOR) { |
6024 | grn_accessor *a; |
6025 | for (a = (grn_accessor *)obj; a; a = a->next) { |
6026 | switch (a->action) { |
6027 | case GRN_ACCESSOR_GET_ID : |
6028 | *range_id = GRN_DB_UINT32; |
6029 | break; |
6030 | case GRN_ACCESSOR_GET_VALUE : |
6031 | if (GRN_DB_OBJP(a->obj)) { |
6032 | *range_id = DB_OBJ(a->obj)->range; |
6033 | } |
6034 | break; |
6035 | case GRN_ACCESSOR_GET_SCORE : |
6036 | *range_id = GRN_DB_FLOAT; |
6037 | break; |
6038 | case GRN_ACCESSOR_GET_NSUBRECS : |
6039 | *range_id = GRN_DB_INT32; |
6040 | break; |
6041 | case GRN_ACCESSOR_GET_MAX : |
6042 | case GRN_ACCESSOR_GET_MIN : |
6043 | case GRN_ACCESSOR_GET_SUM : |
6044 | *range_id = GRN_DB_INT64; |
6045 | break; |
6046 | case GRN_ACCESSOR_GET_AVG : |
6047 | *range_id = GRN_DB_FLOAT; |
6048 | break; |
6049 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
6050 | grn_obj_get_range_info(ctx, a->obj, range_id, range_flags); |
6051 | break; |
6052 | case GRN_ACCESSOR_GET_KEY : |
6053 | if (GRN_DB_OBJP(a->obj)) { *range_id = DB_OBJ(a->obj)->header.domain; } |
6054 | break; |
6055 | default : |
6056 | if (GRN_DB_OBJP(a->obj)) { *range_id = DB_OBJ(a->obj)->range; } |
6057 | break; |
6058 | } |
6059 | } |
6060 | } |
6061 | } |
6062 | |
6063 | grn_id |
6064 | grn_obj_get_range(grn_ctx *ctx, grn_obj *obj) |
6065 | { |
6066 | grn_id range_id = GRN_ID_NIL; |
6067 | grn_obj_flags range_flags = 0; |
6068 | |
6069 | grn_obj_get_range_info(ctx, obj, &range_id, &range_flags); |
6070 | |
6071 | return range_id; |
6072 | } |
6073 | |
6074 | int |
6075 | grn_obj_is_persistent(grn_ctx *ctx, grn_obj *obj) |
6076 | { |
6077 | int res = 0; |
6078 | if (GRN_DB_OBJP(obj)) { |
6079 | res = IS_TEMP(obj) ? 0 : 1; |
6080 | } else if (obj->header.type == GRN_ACCESSOR) { |
6081 | grn_accessor *a; |
6082 | for (a = (grn_accessor *)obj; a; a = a->next) { |
6083 | switch (a->action) { |
6084 | case GRN_ACCESSOR_GET_SCORE : |
6085 | case GRN_ACCESSOR_GET_NSUBRECS : |
6086 | case GRN_ACCESSOR_GET_MAX : |
6087 | case GRN_ACCESSOR_GET_MIN : |
6088 | case GRN_ACCESSOR_GET_SUM : |
6089 | case GRN_ACCESSOR_GET_AVG : |
6090 | res = 0; |
6091 | break; |
6092 | case GRN_ACCESSOR_GET_ID : |
6093 | case GRN_ACCESSOR_GET_VALUE : |
6094 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
6095 | case GRN_ACCESSOR_GET_KEY : |
6096 | if (GRN_DB_OBJP(a->obj)) { res = IS_TEMP(obj) ? 0 : 1; } |
6097 | break; |
6098 | default : |
6099 | if (GRN_DB_OBJP(a->obj)) { res = IS_TEMP(obj) ? 0 : 1; } |
6100 | break; |
6101 | } |
6102 | } |
6103 | } |
6104 | return res; |
6105 | } |
6106 | |
6107 | #define SRC2RECORD() do {\ |
6108 | grn_obj *table = grn_ctx_at(ctx, dest->header.domain);\ |
6109 | if (GRN_OBJ_TABLEP(table)) {\ |
6110 | grn_obj *p_key = src;\ |
6111 | grn_id id;\ |
6112 | if (table->header.type != GRN_TABLE_NO_KEY) {\ |
6113 | grn_obj key;\ |
6114 | GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);\ |
6115 | if (src->header.domain != table->header.domain) {\ |
6116 | rc = grn_obj_cast(ctx, src, &key, GRN_TRUE);\ |
6117 | p_key = &key;\ |
6118 | }\ |
6119 | if (!rc) {\ |
6120 | if (GRN_BULK_VSIZE(p_key)) {\ |
6121 | if (add_record_if_not_exist) {\ |
6122 | id = grn_table_add_by_key(ctx, table, p_key, NULL);\ |
6123 | } else {\ |
6124 | id = grn_table_get_by_key(ctx, table, p_key);\ |
6125 | }\ |
6126 | if (id) {\ |
6127 | GRN_RECORD_SET(ctx, dest, id);\ |
6128 | } else {\ |
6129 | rc = GRN_INVALID_ARGUMENT;\ |
6130 | }\ |
6131 | } else {\ |
6132 | GRN_RECORD_SET(ctx, dest, GRN_ID_NIL);\ |
6133 | }\ |
6134 | }\ |
6135 | GRN_OBJ_FIN(ctx, &key);\ |
6136 | } else {\ |
6137 | grn_obj record_id;\ |
6138 | GRN_UINT32_INIT(&record_id, 0);\ |
6139 | rc = grn_obj_cast(ctx, src, &record_id, GRN_TRUE);\ |
6140 | if (!rc) {\ |
6141 | id = GRN_UINT32_VALUE(&record_id);\ |
6142 | if (id) {\ |
6143 | GRN_RECORD_SET(ctx, dest, id);\ |
6144 | } else {\ |
6145 | rc = GRN_INVALID_ARGUMENT;\ |
6146 | }\ |
6147 | }\ |
6148 | }\ |
6149 | } else {\ |
6150 | rc = GRN_FUNCTION_NOT_IMPLEMENTED;\ |
6151 | }\ |
6152 | } while (0) |
6153 | |
6154 | inline static grn_rc |
6155 | grn_obj_cast_bool(grn_ctx *ctx, grn_obj *src, grn_obj *dest, |
6156 | grn_bool add_record_if_not_exist) |
6157 | { |
6158 | grn_rc rc = GRN_SUCCESS; |
6159 | |
6160 | switch (dest->header.domain) { |
6161 | case GRN_DB_BOOL : |
6162 | GRN_BOOL_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6163 | break; |
6164 | case GRN_DB_INT8 : |
6165 | GRN_INT8_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6166 | break; |
6167 | case GRN_DB_UINT8 : |
6168 | GRN_UINT8_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6169 | break; |
6170 | case GRN_DB_INT16 : |
6171 | GRN_INT16_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6172 | break; |
6173 | case GRN_DB_UINT16 : |
6174 | GRN_UINT16_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6175 | break; |
6176 | case GRN_DB_INT32 : |
6177 | GRN_INT32_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6178 | break; |
6179 | case GRN_DB_UINT32 : |
6180 | GRN_UINT32_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6181 | break; |
6182 | case GRN_DB_INT64 : |
6183 | GRN_INT64_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6184 | break; |
6185 | case GRN_DB_UINT64 : |
6186 | GRN_UINT64_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6187 | break; |
6188 | case GRN_DB_FLOAT : |
6189 | GRN_FLOAT_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6190 | break; |
6191 | case GRN_DB_TIME : |
6192 | GRN_TIME_SET(ctx, dest, GRN_BOOL_VALUE(src)); |
6193 | break; |
6194 | case GRN_DB_SHORT_TEXT : |
6195 | case GRN_DB_TEXT : |
6196 | case GRN_DB_LONG_TEXT : |
6197 | { |
6198 | const char *bool_text; |
6199 | bool_text = GRN_BOOL_VALUE(src) ? "true" : "false" ; |
6200 | GRN_TEXT_PUTS(ctx, dest, bool_text); |
6201 | } |
6202 | break; |
6203 | case GRN_DB_TOKYO_GEO_POINT : |
6204 | case GRN_DB_WGS84_GEO_POINT : |
6205 | rc = GRN_INVALID_ARGUMENT; |
6206 | break; |
6207 | default : |
6208 | SRC2RECORD(); |
6209 | break; |
6210 | } |
6211 | return rc; |
6212 | } |
6213 | |
6214 | #define NUM2DEST(getvalue,totext,tobool,totime,tofloat)\ |
6215 | switch (dest->header.domain) {\ |
6216 | case GRN_DB_BOOL :\ |
6217 | tobool(ctx, dest, getvalue(src));\ |
6218 | break;\ |
6219 | case GRN_DB_INT8 :\ |
6220 | GRN_INT8_SET(ctx, dest, getvalue(src));\ |
6221 | break;\ |
6222 | case GRN_DB_UINT8 :\ |
6223 | GRN_UINT8_SET(ctx, dest, getvalue(src));\ |
6224 | break;\ |
6225 | case GRN_DB_INT16 :\ |
6226 | GRN_INT16_SET(ctx, dest, getvalue(src));\ |
6227 | break;\ |
6228 | case GRN_DB_UINT16 :\ |
6229 | GRN_UINT16_SET(ctx, dest, getvalue(src));\ |
6230 | break;\ |
6231 | case GRN_DB_INT32 :\ |
6232 | GRN_INT32_SET(ctx, dest, getvalue(src));\ |
6233 | break;\ |
6234 | case GRN_DB_UINT32 :\ |
6235 | GRN_UINT32_SET(ctx, dest, getvalue(src));\ |
6236 | break;\ |
6237 | case GRN_DB_TIME :\ |
6238 | totime(ctx, dest, getvalue(src));\ |
6239 | break;\ |
6240 | case GRN_DB_INT64 :\ |
6241 | GRN_INT64_SET(ctx, dest, getvalue(src));\ |
6242 | break;\ |
6243 | case GRN_DB_UINT64 :\ |
6244 | GRN_UINT64_SET(ctx, dest, getvalue(src));\ |
6245 | break;\ |
6246 | case GRN_DB_FLOAT :\ |
6247 | tofloat(ctx, dest, getvalue(src));\ |
6248 | break;\ |
6249 | case GRN_DB_SHORT_TEXT :\ |
6250 | case GRN_DB_TEXT :\ |
6251 | case GRN_DB_LONG_TEXT :\ |
6252 | totext(ctx, dest, getvalue(src));\ |
6253 | break;\ |
6254 | case GRN_DB_TOKYO_GEO_POINT :\ |
6255 | case GRN_DB_WGS84_GEO_POINT :\ |
6256 | rc = GRN_INVALID_ARGUMENT;\ |
6257 | break;\ |
6258 | default :\ |
6259 | SRC2RECORD();\ |
6260 | break;\ |
6261 | } |
6262 | |
6263 | #define TEXT2DEST(type,tonum,setvalue) do {\ |
6264 | const char *cur, *str = GRN_TEXT_VALUE(src);\ |
6265 | const char *str_end = GRN_BULK_CURR(src);\ |
6266 | type i = tonum(str, str_end, &cur);\ |
6267 | if (cur == str_end) {\ |
6268 | setvalue(ctx, dest, i);\ |
6269 | } else if (cur != str) {\ |
6270 | const char *rest;\ |
6271 | grn_obj buf;\ |
6272 | GRN_VOID_INIT(&buf);\ |
6273 | rc = grn_aton(ctx, str, str_end, &rest, &buf);\ |
6274 | if (!rc) {\ |
6275 | rc = grn_obj_cast(ctx, &buf, dest, add_record_if_not_exist);\ |
6276 | }\ |
6277 | GRN_OBJ_FIN(ctx, &buf);\ |
6278 | } else {\ |
6279 | rc = GRN_INVALID_ARGUMENT;\ |
6280 | }\ |
6281 | } while (0) |
6282 | |
6283 | #define NUM2BOOL(ctx, dest, value) GRN_BOOL_SET(ctx, dest, value != 0) |
6284 | #define FLOAT2BOOL(ctx, dest, value) do {\ |
6285 | double value_ = value;\ |
6286 | GRN_BOOL_SET(ctx, dest, value_ < -DBL_EPSILON || DBL_EPSILON < value_);\ |
6287 | } while (0) |
6288 | |
6289 | #define NUM2TIME(ctx, dest, value)\ |
6290 | GRN_TIME_SET(ctx, dest, (long long int)(value) * GRN_TIME_USEC_PER_SEC); |
6291 | #define TIME2TIME(ctx, dest, value)\ |
6292 | GRN_TIME_SET(ctx, dest, value); |
6293 | #define FLOAT2TIME(ctx, dest, value) do {\ |
6294 | int64_t usec = llround(value * GRN_TIME_USEC_PER_SEC);\ |
6295 | GRN_TIME_SET(ctx, dest, usec);\ |
6296 | } while (0) |
6297 | |
6298 | #define NUM2FLOAT(ctx, dest, value)\ |
6299 | GRN_FLOAT_SET(ctx, dest, value); |
6300 | #define TIME2FLOAT(ctx, dest, value)\ |
6301 | GRN_FLOAT_SET(ctx, dest, (double)(value) / GRN_TIME_USEC_PER_SEC); |
6302 | #define FLOAT2FLOAT(ctx, dest, value)\ |
6303 | GRN_FLOAT_SET(ctx, dest, value); |
6304 | |
6305 | static grn_rc |
6306 | grn_obj_cast_record(grn_ctx *ctx, |
6307 | grn_obj *src, |
6308 | grn_obj *dest, |
6309 | grn_bool add_record_if_not_exist) |
6310 | { |
6311 | grn_obj *src_table; |
6312 | grn_obj *dest_table; |
6313 | const char *key; |
6314 | uint32_t key_size; |
6315 | grn_id dest_id; |
6316 | |
6317 | if (src->header.domain == dest->header.domain) { |
6318 | GRN_RECORD_SET(ctx, dest, GRN_RECORD_VALUE(src)); |
6319 | return GRN_SUCCESS; |
6320 | } |
6321 | |
6322 | src_table = grn_ctx_at(ctx, src->header.domain); |
6323 | if (!src_table) { |
6324 | return GRN_INVALID_ARGUMENT; |
6325 | } |
6326 | if (src_table->header.type == GRN_TABLE_NO_KEY) { |
6327 | return GRN_INVALID_ARGUMENT; |
6328 | } |
6329 | |
6330 | dest_table = grn_ctx_at(ctx, dest->header.domain); |
6331 | if (!dest_table) { |
6332 | return GRN_INVALID_ARGUMENT; |
6333 | } |
6334 | switch (dest_table->header.type) { |
6335 | case GRN_TABLE_HASH_KEY : |
6336 | case GRN_TABLE_PAT_KEY : |
6337 | case GRN_TABLE_DAT_KEY : |
6338 | break; |
6339 | default : |
6340 | return GRN_INVALID_ARGUMENT; |
6341 | } |
6342 | |
6343 | if (GRN_RECORD_VALUE(src) == GRN_ID_NIL) { |
6344 | GRN_RECORD_SET(ctx, dest, GRN_RECORD_VALUE(src)); |
6345 | return GRN_SUCCESS; |
6346 | } |
6347 | |
6348 | key = _grn_table_key(ctx, src_table, GRN_RECORD_VALUE(src), &key_size); |
6349 | if (add_record_if_not_exist) { |
6350 | dest_id = grn_table_add(ctx, dest_table, key, key_size, NULL); |
6351 | } else { |
6352 | dest_id = grn_table_get(ctx, dest_table, key, key_size); |
6353 | } |
6354 | GRN_RECORD_SET(ctx, dest, dest_id); |
6355 | return GRN_SUCCESS; |
6356 | } |
6357 | |
6358 | grn_rc |
6359 | grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, |
6360 | grn_bool add_record_if_not_exist) |
6361 | { |
6362 | grn_rc rc = GRN_SUCCESS; |
6363 | switch (src->header.domain) { |
6364 | case GRN_DB_BOOL : |
6365 | rc = grn_obj_cast_bool(ctx, src, dest, add_record_if_not_exist); |
6366 | break; |
6367 | case GRN_DB_INT8 : |
6368 | NUM2DEST(GRN_INT8_VALUE, grn_text_itoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); |
6369 | break; |
6370 | case GRN_DB_UINT8 : |
6371 | NUM2DEST(GRN_UINT8_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); |
6372 | break; |
6373 | case GRN_DB_INT16 : |
6374 | NUM2DEST(GRN_INT16_VALUE, grn_text_itoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); |
6375 | break; |
6376 | case GRN_DB_UINT16 : |
6377 | NUM2DEST(GRN_UINT16_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); |
6378 | break; |
6379 | case GRN_DB_INT32 : |
6380 | NUM2DEST(GRN_INT32_VALUE, grn_text_itoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); |
6381 | break; |
6382 | case GRN_DB_UINT32 : |
6383 | NUM2DEST(GRN_UINT32_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); |
6384 | break; |
6385 | case GRN_DB_INT64 : |
6386 | NUM2DEST(GRN_INT64_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); |
6387 | break; |
6388 | case GRN_DB_TIME : |
6389 | NUM2DEST(GRN_TIME_VALUE, grn_text_lltoa, NUM2BOOL, TIME2TIME, TIME2FLOAT); |
6390 | break; |
6391 | case GRN_DB_UINT64 : |
6392 | NUM2DEST(GRN_UINT64_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); |
6393 | break; |
6394 | case GRN_DB_FLOAT : |
6395 | NUM2DEST(GRN_FLOAT_VALUE, grn_text_ftoa, FLOAT2BOOL, FLOAT2TIME, |
6396 | FLOAT2FLOAT); |
6397 | break; |
6398 | case GRN_DB_SHORT_TEXT : |
6399 | case GRN_DB_TEXT : |
6400 | case GRN_DB_LONG_TEXT : |
6401 | switch (dest->header.domain) { |
6402 | case GRN_DB_BOOL : |
6403 | GRN_BOOL_SET(ctx, dest, GRN_TEXT_LEN(src) > 0); |
6404 | break; |
6405 | case GRN_DB_INT8 : |
6406 | TEXT2DEST(int8_t, grn_atoi8, GRN_INT8_SET); |
6407 | break; |
6408 | case GRN_DB_UINT8 : |
6409 | TEXT2DEST(uint8_t, grn_atoui8, GRN_UINT8_SET); |
6410 | break; |
6411 | case GRN_DB_INT16 : |
6412 | TEXT2DEST(int16_t, grn_atoi16, GRN_INT16_SET); |
6413 | break; |
6414 | case GRN_DB_UINT16 : |
6415 | TEXT2DEST(uint16_t, grn_atoui16, GRN_UINT16_SET); |
6416 | break; |
6417 | case GRN_DB_INT32 : |
6418 | TEXT2DEST(int32_t, grn_atoi, GRN_INT32_SET); |
6419 | break; |
6420 | case GRN_DB_UINT32 : |
6421 | TEXT2DEST(uint32_t, grn_atoui, GRN_UINT32_SET); |
6422 | break; |
6423 | case GRN_DB_TIME : |
6424 | { |
6425 | grn_timeval v; |
6426 | int len = GRN_TEXT_LEN(src); |
6427 | char *str = GRN_TEXT_VALUE(src); |
6428 | if (grn_str2timeval(str, len, &v)) { |
6429 | double d; |
6430 | char *end; |
6431 | grn_obj buf; |
6432 | GRN_TEXT_INIT(&buf, 0); |
6433 | GRN_TEXT_PUT(ctx, &buf, str, len); |
6434 | GRN_TEXT_PUTC(ctx, &buf, '\0'); |
6435 | errno = 0; |
6436 | d = strtod(GRN_TEXT_VALUE(&buf), &end); |
6437 | if (!errno && end + 1 == GRN_BULK_CURR(&buf)) { |
6438 | v.tv_sec = d; |
6439 | v.tv_nsec = ((d - v.tv_sec) * GRN_TIME_NSEC_PER_SEC); |
6440 | } else { |
6441 | rc = GRN_INVALID_ARGUMENT; |
6442 | } |
6443 | GRN_OBJ_FIN(ctx, &buf); |
6444 | } |
6445 | GRN_TIME_SET(ctx, dest, |
6446 | GRN_TIME_PACK((int64_t)v.tv_sec, |
6447 | GRN_TIME_NSEC_TO_USEC(v.tv_nsec))); |
6448 | } |
6449 | break; |
6450 | case GRN_DB_INT64 : |
6451 | TEXT2DEST(int64_t, grn_atoll, GRN_INT64_SET); |
6452 | break; |
6453 | case GRN_DB_UINT64 : |
6454 | TEXT2DEST(int64_t, grn_atoll, GRN_UINT64_SET); |
6455 | break; |
6456 | case GRN_DB_FLOAT : |
6457 | { |
6458 | double d; |
6459 | char *end; |
6460 | grn_obj buf; |
6461 | GRN_TEXT_INIT(&buf, 0); |
6462 | GRN_TEXT_PUT(ctx, &buf, GRN_TEXT_VALUE(src), GRN_TEXT_LEN(src)); |
6463 | GRN_TEXT_PUTC(ctx, &buf, '\0'); |
6464 | errno = 0; |
6465 | d = strtod(GRN_TEXT_VALUE(&buf), &end); |
6466 | if (!errno && end + 1 == GRN_BULK_CURR(&buf)) { |
6467 | GRN_FLOAT_SET(ctx, dest, d); |
6468 | } else { |
6469 | rc = GRN_INVALID_ARGUMENT; |
6470 | } |
6471 | GRN_OBJ_FIN(ctx, &buf); |
6472 | } |
6473 | break; |
6474 | case GRN_DB_SHORT_TEXT : |
6475 | case GRN_DB_TEXT : |
6476 | case GRN_DB_LONG_TEXT : |
6477 | GRN_TEXT_PUT(ctx, dest, GRN_TEXT_VALUE(src), GRN_TEXT_LEN(src)); |
6478 | break; |
6479 | case GRN_DB_TOKYO_GEO_POINT : |
6480 | case GRN_DB_WGS84_GEO_POINT : |
6481 | { |
6482 | int latitude, longitude; |
6483 | double degree; |
6484 | const char *cur, *str = GRN_TEXT_VALUE(src); |
6485 | const char *str_end = GRN_BULK_CURR(src); |
6486 | if (str == str_end) { |
6487 | GRN_GEO_POINT_SET(ctx, dest, 0, 0); |
6488 | } else { |
6489 | char *end; |
6490 | grn_obj buf, *buf_p = NULL; |
6491 | latitude = grn_atoi(str, str_end, &cur); |
6492 | if (cur < str_end && cur[0] == '.') { |
6493 | GRN_TEXT_INIT(&buf, 0); |
6494 | GRN_TEXT_PUT(ctx, &buf, str, GRN_TEXT_LEN(src)); |
6495 | GRN_TEXT_PUTC(ctx, &buf, '\0'); |
6496 | buf_p = &buf; |
6497 | errno = 0; |
6498 | degree = strtod(GRN_TEXT_VALUE(buf_p), &end); |
6499 | if (errno) { |
6500 | rc = GRN_INVALID_ARGUMENT; |
6501 | } else { |
6502 | latitude = GRN_GEO_DEGREE2MSEC(degree); |
6503 | cur = str + (end - GRN_TEXT_VALUE(buf_p)); |
6504 | } |
6505 | } |
6506 | if (!rc && (cur[0] == 'x' || cur[0] == ',') && cur + 1 < str_end) { |
6507 | const char *c = cur + 1; |
6508 | longitude = grn_atoi(c, str_end, &cur); |
6509 | if (cur < str_end && cur[0] == '.') { |
6510 | if (!buf_p) { |
6511 | GRN_TEXT_INIT(&buf, 0); |
6512 | GRN_TEXT_PUT(ctx, &buf, str, GRN_TEXT_LEN(src)); |
6513 | GRN_TEXT_PUTC(ctx, &buf, '\0'); |
6514 | buf_p = &buf; |
6515 | } |
6516 | errno = 0; |
6517 | degree = strtod(GRN_TEXT_VALUE(buf_p) + (c - str), &end); |
6518 | if (errno) { |
6519 | rc = GRN_INVALID_ARGUMENT; |
6520 | } else { |
6521 | longitude = GRN_GEO_DEGREE2MSEC(degree); |
6522 | cur = str + (end - GRN_TEXT_VALUE(buf_p)); |
6523 | } |
6524 | } |
6525 | if (!rc && cur == str_end) { |
6526 | if ((GRN_GEO_MIN_LATITUDE <= latitude && |
6527 | latitude <= GRN_GEO_MAX_LATITUDE) && |
6528 | (GRN_GEO_MIN_LONGITUDE <= longitude && |
6529 | longitude <= GRN_GEO_MAX_LONGITUDE)) { |
6530 | GRN_GEO_POINT_SET(ctx, dest, latitude, longitude); |
6531 | } else { |
6532 | rc = GRN_INVALID_ARGUMENT; |
6533 | } |
6534 | } else { |
6535 | rc = GRN_INVALID_ARGUMENT; |
6536 | } |
6537 | } else { |
6538 | rc = GRN_INVALID_ARGUMENT; |
6539 | } |
6540 | if (buf_p) { GRN_OBJ_FIN(ctx, buf_p); } |
6541 | } |
6542 | } |
6543 | break; |
6544 | default : |
6545 | SRC2RECORD(); |
6546 | break; |
6547 | } |
6548 | break; |
6549 | case GRN_DB_TOKYO_GEO_POINT : |
6550 | case GRN_DB_WGS84_GEO_POINT : |
6551 | if (src->header.domain == dest->header.domain) { |
6552 | GRN_TEXT_PUT(ctx, dest, GRN_TEXT_VALUE(src), GRN_TEXT_LEN(src)); |
6553 | } else { |
6554 | int latitude, longitude; |
6555 | double latitude_in_degree, longitude_in_degree; |
6556 | GRN_GEO_POINT_VALUE(src, latitude, longitude); |
6557 | latitude_in_degree = GRN_GEO_MSEC2DEGREE(latitude); |
6558 | longitude_in_degree = GRN_GEO_MSEC2DEGREE(longitude); |
6559 | /* TokyoGeoPoint <-> WGS84GeoPoint is based on |
6560 | http://www.jalan.net/jw/jwp0200/jww0203.do |
6561 | |
6562 | jx: longitude in degree in Tokyo Geodetic System. |
6563 | jy: latitude in degree in Tokyo Geodetic System. |
6564 | wx: longitude in degree in WGS 84. |
6565 | wy: latitude in degree in WGS 84. |
6566 | |
6567 | jy = wy * 1.000106961 - wx * 0.000017467 - 0.004602017 |
6568 | jx = wx * 1.000083049 + wy * 0.000046047 - 0.010041046 |
6569 | |
6570 | wy = jy - jy * 0.00010695 + jx * 0.000017464 + 0.0046017 |
6571 | wx = jx - jy * 0.000046038 - jx * 0.000083043 + 0.010040 |
6572 | */ |
6573 | if (dest->header.domain == GRN_DB_TOKYO_GEO_POINT) { |
6574 | double wgs84_latitude_in_degree = latitude_in_degree; |
6575 | double wgs84_longitude_in_degree = longitude_in_degree; |
6576 | int tokyo_latitude, tokyo_longitude; |
6577 | double tokyo_latitude_in_degree, tokyo_longitude_in_degree; |
6578 | tokyo_latitude_in_degree = |
6579 | wgs84_latitude_in_degree * 1.000106961 - |
6580 | wgs84_longitude_in_degree * 0.000017467 - |
6581 | 0.004602017; |
6582 | tokyo_longitude_in_degree = |
6583 | wgs84_longitude_in_degree * 1.000083049 + |
6584 | wgs84_latitude_in_degree * 0.000046047 - |
6585 | 0.010041046; |
6586 | tokyo_latitude = GRN_GEO_DEGREE2MSEC(tokyo_latitude_in_degree); |
6587 | tokyo_longitude = GRN_GEO_DEGREE2MSEC(tokyo_longitude_in_degree); |
6588 | GRN_GEO_POINT_SET(ctx, dest, tokyo_latitude, tokyo_longitude); |
6589 | } else { |
6590 | double tokyo_latitude_in_degree = latitude_in_degree; |
6591 | double tokyo_longitude_in_degree = longitude_in_degree; |
6592 | int wgs84_latitude, wgs84_longitude; |
6593 | double wgs84_latitude_in_degree, wgs84_longitude_in_degree; |
6594 | wgs84_latitude_in_degree = |
6595 | tokyo_latitude_in_degree - |
6596 | tokyo_latitude_in_degree * 0.00010695 + |
6597 | tokyo_longitude_in_degree * 0.000017464 + |
6598 | 0.0046017; |
6599 | wgs84_longitude_in_degree = |
6600 | tokyo_longitude_in_degree - |
6601 | tokyo_latitude_in_degree * 0.000046038 - |
6602 | tokyo_longitude_in_degree * 0.000083043 + |
6603 | 0.010040; |
6604 | wgs84_latitude = GRN_GEO_DEGREE2MSEC(wgs84_latitude_in_degree); |
6605 | wgs84_longitude = GRN_GEO_DEGREE2MSEC(wgs84_longitude_in_degree); |
6606 | GRN_GEO_POINT_SET(ctx, dest, wgs84_latitude, wgs84_longitude); |
6607 | } |
6608 | } |
6609 | break; |
6610 | case GRN_VOID : |
6611 | rc = grn_obj_reinit(ctx, dest, dest->header.domain, dest->header.flags); |
6612 | break; |
6613 | default : |
6614 | if (src->header.domain >= GRN_N_RESERVED_TYPES) { |
6615 | grn_obj *table; |
6616 | table = grn_ctx_at(ctx, src->header.domain); |
6617 | switch (table->header.type) { |
6618 | case GRN_TABLE_HASH_KEY : |
6619 | case GRN_TABLE_PAT_KEY : |
6620 | case GRN_TABLE_DAT_KEY : |
6621 | case GRN_TABLE_NO_KEY : |
6622 | rc = grn_obj_cast_record(ctx, src, dest, add_record_if_not_exist); |
6623 | break; |
6624 | default : |
6625 | rc = GRN_FUNCTION_NOT_IMPLEMENTED; |
6626 | break; |
6627 | } |
6628 | } else { |
6629 | rc = GRN_FUNCTION_NOT_IMPLEMENTED; |
6630 | } |
6631 | break; |
6632 | } |
6633 | return rc; |
6634 | } |
6635 | |
6636 | const char * |
6637 | grn_accessor_get_value_(grn_ctx *ctx, grn_accessor *a, grn_id id, uint32_t *size) |
6638 | { |
6639 | const char *value = NULL; |
6640 | for (;;) { |
6641 | switch (a->action) { |
6642 | case GRN_ACCESSOR_GET_ID : |
6643 | value = (const char *)(uintptr_t)id; |
6644 | *size = GRN_OBJ_GET_VALUE_IMD; |
6645 | break; |
6646 | case GRN_ACCESSOR_GET_KEY : |
6647 | value = _grn_table_key(ctx, a->obj, id, size); |
6648 | break; |
6649 | case GRN_ACCESSOR_GET_VALUE : |
6650 | value = grn_obj_get_value_(ctx, a->obj, id, size); |
6651 | break; |
6652 | case GRN_ACCESSOR_GET_SCORE : |
6653 | if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { |
6654 | value = (const char *)&((grn_rset_recinfo *)value)->score; |
6655 | *size = sizeof(double); |
6656 | } |
6657 | break; |
6658 | case GRN_ACCESSOR_GET_NSUBRECS : |
6659 | if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { |
6660 | value = (const char *)&((grn_rset_recinfo *)value)->n_subrecs; |
6661 | *size = sizeof(int); |
6662 | } |
6663 | break; |
6664 | case GRN_ACCESSOR_GET_MAX : |
6665 | if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { |
6666 | value = |
6667 | (const char *)grn_rset_recinfo_get_max_(ctx, |
6668 | (grn_rset_recinfo *)value, |
6669 | a->obj); |
6670 | *size = GRN_RSET_MAX_SIZE; |
6671 | } |
6672 | break; |
6673 | case GRN_ACCESSOR_GET_MIN : |
6674 | if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { |
6675 | value = |
6676 | (const char *)grn_rset_recinfo_get_min_(ctx, |
6677 | (grn_rset_recinfo *)value, |
6678 | a->obj); |
6679 | *size = GRN_RSET_MIN_SIZE; |
6680 | } |
6681 | break; |
6682 | case GRN_ACCESSOR_GET_SUM : |
6683 | if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { |
6684 | value = |
6685 | (const char *)grn_rset_recinfo_get_sum_(ctx, |
6686 | (grn_rset_recinfo *)value, |
6687 | a->obj); |
6688 | *size = GRN_RSET_SUM_SIZE; |
6689 | } |
6690 | break; |
6691 | case GRN_ACCESSOR_GET_AVG : |
6692 | if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { |
6693 | value = |
6694 | (const char *)grn_rset_recinfo_get_avg_(ctx, |
6695 | (grn_rset_recinfo *)value, |
6696 | a->obj); |
6697 | *size = GRN_RSET_AVG_SIZE; |
6698 | } |
6699 | break; |
6700 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
6701 | /* todo : support vector */ |
6702 | value = grn_obj_get_value_(ctx, a->obj, id, size); |
6703 | break; |
6704 | case GRN_ACCESSOR_GET_DB_OBJ : |
6705 | value = _grn_table_key(ctx, ((grn_db *)ctx->impl->db)->keys, id, size); |
6706 | break; |
6707 | case GRN_ACCESSOR_LOOKUP : |
6708 | /* todo */ |
6709 | break; |
6710 | case GRN_ACCESSOR_FUNCALL : |
6711 | /* todo */ |
6712 | break; |
6713 | } |
6714 | if (value && (a = a->next)) { |
6715 | id = *((grn_id *)value); |
6716 | } else { |
6717 | break; |
6718 | } |
6719 | } |
6720 | return value; |
6721 | } |
6722 | |
6723 | static grn_obj * |
6724 | grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value) |
6725 | { |
6726 | uint32_t vs = 0; |
6727 | uint32_t size0; |
6728 | void *vp = NULL; |
6729 | if (!value) { |
6730 | if (!(value = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; } |
6731 | } else { |
6732 | value->header.type = GRN_BULK; |
6733 | } |
6734 | size0 = GRN_BULK_VSIZE(value); |
6735 | for (;;) { |
6736 | grn_bulk_truncate(ctx, value, size0); |
6737 | switch (a->action) { |
6738 | case GRN_ACCESSOR_GET_ID : |
6739 | GRN_UINT32_PUT(ctx, value, id); |
6740 | value->header.domain = GRN_DB_UINT32; |
6741 | vp = GRN_BULK_HEAD(value) + size0; |
6742 | vs = GRN_BULK_VSIZE(value) - size0; |
6743 | break; |
6744 | case GRN_ACCESSOR_GET_KEY : |
6745 | if (!a->next && GRN_TABLE_IS_MULTI_KEYS_GROUPED(a->obj)) { |
6746 | grn_obj_ensure_vector(ctx, value); |
6747 | if (id) { |
6748 | grn_obj raw_vector; |
6749 | GRN_TEXT_INIT(&raw_vector, 0); |
6750 | grn_table_get_key2(ctx, a->obj, id, &raw_vector); |
6751 | grn_vector_decode(ctx, value, |
6752 | GRN_BULK_HEAD(&raw_vector), |
6753 | GRN_BULK_VSIZE(&raw_vector)); |
6754 | GRN_OBJ_FIN(ctx, &raw_vector); |
6755 | } |
6756 | vp = NULL; |
6757 | vs = 0; |
6758 | } else { |
6759 | if (id) { |
6760 | grn_table_get_key2(ctx, a->obj, id, value); |
6761 | vp = GRN_BULK_HEAD(value) + size0; |
6762 | vs = GRN_BULK_VSIZE(value) - size0; |
6763 | } else { |
6764 | vp = NULL; |
6765 | vs = 0; |
6766 | } |
6767 | value->header.domain = a->obj->header.domain; |
6768 | } |
6769 | break; |
6770 | case GRN_ACCESSOR_GET_VALUE : |
6771 | grn_obj_get_value(ctx, a->obj, id, value); |
6772 | vp = GRN_BULK_HEAD(value) + size0; |
6773 | vs = GRN_BULK_VSIZE(value) - size0; |
6774 | break; |
6775 | case GRN_ACCESSOR_GET_SCORE : |
6776 | if (id) { |
6777 | grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); |
6778 | GRN_FLOAT_PUT(ctx, value, ri->score); |
6779 | } else { |
6780 | GRN_FLOAT_PUT(ctx, value, 0.0); |
6781 | } |
6782 | value->header.domain = GRN_DB_FLOAT; |
6783 | break; |
6784 | case GRN_ACCESSOR_GET_NSUBRECS : |
6785 | if (id) { |
6786 | grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); |
6787 | GRN_INT32_PUT(ctx, value, ri->n_subrecs); |
6788 | } else { |
6789 | GRN_INT32_PUT(ctx, value, 0); |
6790 | } |
6791 | value->header.domain = GRN_DB_INT32; |
6792 | break; |
6793 | case GRN_ACCESSOR_GET_MAX : |
6794 | if (id) { |
6795 | grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); |
6796 | int64_t max; |
6797 | max = grn_rset_recinfo_get_max(ctx, ri, a->obj); |
6798 | GRN_INT64_PUT(ctx, value, max); |
6799 | } else { |
6800 | GRN_INT64_PUT(ctx, value, 0); |
6801 | } |
6802 | value->header.domain = GRN_DB_INT64; |
6803 | break; |
6804 | case GRN_ACCESSOR_GET_MIN : |
6805 | if (id) { |
6806 | grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); |
6807 | int64_t min; |
6808 | min = grn_rset_recinfo_get_min(ctx, ri, a->obj); |
6809 | GRN_INT64_PUT(ctx, value, min); |
6810 | } else { |
6811 | GRN_INT64_PUT(ctx, value, 0); |
6812 | } |
6813 | value->header.domain = GRN_DB_INT64; |
6814 | break; |
6815 | case GRN_ACCESSOR_GET_SUM : |
6816 | if (id) { |
6817 | grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); |
6818 | int64_t sum; |
6819 | sum = grn_rset_recinfo_get_sum(ctx, ri, a->obj); |
6820 | GRN_INT64_PUT(ctx, value, sum); |
6821 | } else { |
6822 | GRN_INT64_PUT(ctx, value, 0); |
6823 | } |
6824 | value->header.domain = GRN_DB_INT64; |
6825 | break; |
6826 | case GRN_ACCESSOR_GET_AVG : |
6827 | if (id) { |
6828 | grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); |
6829 | double avg; |
6830 | avg = grn_rset_recinfo_get_avg(ctx, ri, a->obj); |
6831 | GRN_FLOAT_PUT(ctx, value, avg); |
6832 | } else { |
6833 | GRN_FLOAT_PUT(ctx, value, 0.0); |
6834 | } |
6835 | value->header.domain = GRN_DB_FLOAT; |
6836 | break; |
6837 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
6838 | /* todo : support vector */ |
6839 | grn_obj_get_value(ctx, a->obj, id, value); |
6840 | vp = GRN_BULK_HEAD(value) + size0; |
6841 | vs = GRN_BULK_VSIZE(value) - size0; |
6842 | break; |
6843 | case GRN_ACCESSOR_GET_DB_OBJ : |
6844 | value = grn_ctx_at(ctx, id); |
6845 | grn_obj_close(ctx, value); |
6846 | return value; |
6847 | break; |
6848 | case GRN_ACCESSOR_LOOKUP : |
6849 | /* todo */ |
6850 | break; |
6851 | case GRN_ACCESSOR_FUNCALL : |
6852 | /* todo */ |
6853 | break; |
6854 | } |
6855 | if ((a = a->next)) { |
6856 | if (vs > 0) { |
6857 | id = *((grn_id *)vp); |
6858 | } else { |
6859 | id = GRN_ID_NIL; |
6860 | } |
6861 | } else { |
6862 | break; |
6863 | } |
6864 | } |
6865 | return value; |
6866 | } |
6867 | |
6868 | static grn_rc |
6869 | grn_accessor_set_value(grn_ctx *ctx, grn_accessor *a, grn_id id, |
6870 | grn_obj *value, int flags) |
6871 | { |
6872 | grn_rc rc = GRN_SUCCESS; |
6873 | if (!value) { value = grn_obj_open(ctx, GRN_BULK, 0, 0); } |
6874 | if (value) { |
6875 | grn_obj buf; |
6876 | void *vp = NULL; |
6877 | GRN_TEXT_INIT(&buf, 0); |
6878 | for (;;) { |
6879 | GRN_BULK_REWIND(&buf); |
6880 | switch (a->action) { |
6881 | case GRN_ACCESSOR_GET_KEY : |
6882 | grn_table_get_key2(ctx, a->obj, id, &buf); |
6883 | vp = GRN_BULK_HEAD(&buf); |
6884 | break; |
6885 | case GRN_ACCESSOR_GET_VALUE : |
6886 | if (a->next) { |
6887 | grn_obj_get_value(ctx, a->obj, id, &buf); |
6888 | vp = GRN_BULK_HEAD(&buf); |
6889 | } else { |
6890 | rc = grn_obj_set_value(ctx, a->obj, id, value, flags); |
6891 | } |
6892 | break; |
6893 | case GRN_ACCESSOR_GET_SCORE : |
6894 | { |
6895 | grn_rset_recinfo *ri; |
6896 | if (a->next) { |
6897 | grn_obj_get_value(ctx, a->obj, id, &buf); |
6898 | ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); |
6899 | vp = &ri->score; |
6900 | } else { |
6901 | uint32_t size; |
6902 | if ((ri = (grn_rset_recinfo *) grn_obj_get_value_(ctx, a->obj, id, &size))) { |
6903 | // todo : flags support |
6904 | if (value->header.domain == GRN_DB_FLOAT) { |
6905 | ri->score = GRN_FLOAT_VALUE(value); |
6906 | } else { |
6907 | grn_obj buf; |
6908 | GRN_FLOAT_INIT(&buf, 0); |
6909 | grn_obj_cast(ctx, value, &buf, GRN_FALSE); |
6910 | ri->score = GRN_FLOAT_VALUE(&buf); |
6911 | GRN_OBJ_FIN(ctx, &buf); |
6912 | } |
6913 | } |
6914 | } |
6915 | } |
6916 | break; |
6917 | case GRN_ACCESSOR_GET_NSUBRECS : |
6918 | grn_obj_get_value(ctx, a->obj, id, &buf); |
6919 | { |
6920 | grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); |
6921 | vp = &ri->n_subrecs; |
6922 | } |
6923 | break; |
6924 | case GRN_ACCESSOR_GET_MAX : |
6925 | grn_obj_get_value(ctx, a->obj, id, &buf); |
6926 | { |
6927 | grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); |
6928 | if (value->header.type == GRN_DB_INT64) { |
6929 | grn_rset_recinfo_set_max(ctx, ri, a->obj, GRN_INT64_VALUE(value)); |
6930 | } else { |
6931 | grn_obj value_int64; |
6932 | GRN_INT64_INIT(&value_int64, 0); |
6933 | if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) { |
6934 | grn_rset_recinfo_set_max(ctx, ri, a->obj, |
6935 | GRN_INT64_VALUE(&value_int64)); |
6936 | } |
6937 | GRN_OBJ_FIN(ctx, &value_int64); |
6938 | } |
6939 | } |
6940 | break; |
6941 | case GRN_ACCESSOR_GET_MIN : |
6942 | grn_obj_get_value(ctx, a->obj, id, &buf); |
6943 | { |
6944 | grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); |
6945 | if (value->header.type == GRN_DB_INT64) { |
6946 | grn_rset_recinfo_set_min(ctx, ri, a->obj, GRN_INT64_VALUE(value)); |
6947 | } else { |
6948 | grn_obj value_int64; |
6949 | GRN_INT64_INIT(&value_int64, 0); |
6950 | if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) { |
6951 | grn_rset_recinfo_set_min(ctx, ri, a->obj, |
6952 | GRN_INT64_VALUE(&value_int64)); |
6953 | } |
6954 | GRN_OBJ_FIN(ctx, &value_int64); |
6955 | } |
6956 | } |
6957 | break; |
6958 | case GRN_ACCESSOR_GET_SUM : |
6959 | grn_obj_get_value(ctx, a->obj, id, &buf); |
6960 | { |
6961 | grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); |
6962 | if (value->header.type == GRN_DB_INT64) { |
6963 | grn_rset_recinfo_set_sum(ctx, ri, a->obj, GRN_INT64_VALUE(value)); |
6964 | } else { |
6965 | grn_obj value_int64; |
6966 | GRN_INT64_INIT(&value_int64, 0); |
6967 | if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) { |
6968 | grn_rset_recinfo_set_sum(ctx, ri, a->obj, |
6969 | GRN_INT64_VALUE(&value_int64)); |
6970 | } |
6971 | GRN_OBJ_FIN(ctx, &value_int64); |
6972 | } |
6973 | } |
6974 | break; |
6975 | case GRN_ACCESSOR_GET_AVG : |
6976 | grn_obj_get_value(ctx, a->obj, id, &buf); |
6977 | { |
6978 | grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); |
6979 | if (value->header.type == GRN_DB_FLOAT) { |
6980 | grn_rset_recinfo_set_avg(ctx, ri, a->obj, GRN_FLOAT_VALUE(value)); |
6981 | } else { |
6982 | grn_obj value_float; |
6983 | GRN_FLOAT_INIT(&value_float, 0); |
6984 | if (!grn_obj_cast(ctx, value, &value_float, GRN_FALSE)) { |
6985 | grn_rset_recinfo_set_avg(ctx, ri, a->obj, |
6986 | GRN_FLOAT_VALUE(&value_float)); |
6987 | } |
6988 | GRN_OBJ_FIN(ctx, &value_float); |
6989 | } |
6990 | } |
6991 | break; |
6992 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
6993 | /* todo : support vector */ |
6994 | if (a->next) { |
6995 | grn_obj_get_value(ctx, a->obj, id, &buf); |
6996 | vp = GRN_BULK_HEAD(&buf); |
6997 | } else { |
6998 | rc = grn_obj_set_value(ctx, a->obj, id, value, flags); |
6999 | } |
7000 | break; |
7001 | case GRN_ACCESSOR_LOOKUP : |
7002 | /* todo */ |
7003 | break; |
7004 | case GRN_ACCESSOR_FUNCALL : |
7005 | /* todo */ |
7006 | break; |
7007 | } |
7008 | if ((a = a->next)) { |
7009 | id = *((grn_id *)vp); |
7010 | } else { |
7011 | break; |
7012 | } |
7013 | } |
7014 | grn_obj_close(ctx, &buf); |
7015 | } |
7016 | return rc; |
7017 | } |
7018 | |
7019 | #define INCRDECR(op) \ |
7020 | switch (DB_OBJ(obj)->range) {\ |
7021 | case GRN_DB_INT8 :\ |
7022 | if (s == sizeof(int8_t)) {\ |
7023 | int8_t *vp = (int8_t *)p;\ |
7024 | *vp op *(int8_t *)v;\ |
7025 | rc = GRN_SUCCESS;\ |
7026 | } else {\ |
7027 | rc = GRN_INVALID_ARGUMENT;\ |
7028 | }\ |
7029 | break;\ |
7030 | case GRN_DB_UINT8 :\ |
7031 | if (s == sizeof(uint8_t)) {\ |
7032 | uint8_t *vp = (uint8_t *)p;\ |
7033 | *vp op *(int8_t *)v;\ |
7034 | rc = GRN_SUCCESS;\ |
7035 | } else {\ |
7036 | rc = GRN_INVALID_ARGUMENT;\ |
7037 | }\ |
7038 | break;\ |
7039 | case GRN_DB_INT16 :\ |
7040 | if (s == sizeof(int16_t)) {\ |
7041 | int16_t *vp = (int16_t *)p;\ |
7042 | *vp op *(int16_t *)v;\ |
7043 | rc = GRN_SUCCESS;\ |
7044 | } else {\ |
7045 | rc = GRN_INVALID_ARGUMENT;\ |
7046 | }\ |
7047 | break;\ |
7048 | case GRN_DB_UINT16 :\ |
7049 | if (s == sizeof(uint16_t)) {\ |
7050 | uint16_t *vp = (uint16_t *)p;\ |
7051 | *vp op *(int16_t *)v;\ |
7052 | rc = GRN_SUCCESS;\ |
7053 | } else {\ |
7054 | rc = GRN_INVALID_ARGUMENT;\ |
7055 | }\ |
7056 | break;\ |
7057 | case GRN_DB_INT32 :\ |
7058 | if (s == sizeof(int32_t)) {\ |
7059 | int32_t *vp = (int32_t *)p;\ |
7060 | *vp op *(int32_t *)v;\ |
7061 | rc = GRN_SUCCESS;\ |
7062 | } else {\ |
7063 | rc = GRN_INVALID_ARGUMENT;\ |
7064 | }\ |
7065 | break;\ |
7066 | case GRN_DB_UINT32 :\ |
7067 | if (s == sizeof(uint32_t)) {\ |
7068 | uint32_t *vp = (uint32_t *)p;\ |
7069 | *vp op *(int32_t *)v;\ |
7070 | rc = GRN_SUCCESS;\ |
7071 | } else {\ |
7072 | rc = GRN_INVALID_ARGUMENT;\ |
7073 | }\ |
7074 | break;\ |
7075 | case GRN_DB_INT64 :\ |
7076 | case GRN_DB_TIME :\ |
7077 | if (s == sizeof(int64_t)) {\ |
7078 | int64_t *vp = (int64_t *)p;\ |
7079 | *vp op *(int64_t *)v;\ |
7080 | rc = GRN_SUCCESS;\ |
7081 | } else {\ |
7082 | rc = GRN_INVALID_ARGUMENT;\ |
7083 | }\ |
7084 | break;\ |
7085 | case GRN_DB_FLOAT :\ |
7086 | if (s == sizeof(double)) {\ |
7087 | double *vp = (double *)p;\ |
7088 | *vp op *(double *)v;\ |
7089 | rc = GRN_SUCCESS;\ |
7090 | } else {\ |
7091 | rc = GRN_INVALID_ARGUMENT;\ |
7092 | }\ |
7093 | break;\ |
7094 | default :\ |
7095 | rc = GRN_OPERATION_NOT_SUPPORTED;\ |
7096 | break;\ |
7097 | } |
7098 | |
7099 | uint32_t |
7100 | grn_obj_size(grn_ctx *ctx, grn_obj *obj) |
7101 | { |
7102 | if (!obj) { return 0; } |
7103 | switch (obj->header.type) { |
7104 | case GRN_VOID : |
7105 | case GRN_BULK : |
7106 | case GRN_PTR : |
7107 | case GRN_UVECTOR : |
7108 | case GRN_PVECTOR : |
7109 | case GRN_MSG : |
7110 | return GRN_BULK_VSIZE(obj); |
7111 | case GRN_VECTOR : |
7112 | return obj->u.v.body ? GRN_BULK_VSIZE(obj->u.v.body) : 0; |
7113 | default : |
7114 | return 0; |
7115 | } |
7116 | } |
7117 | |
7118 | inline static int |
7119 | call_hook(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags) |
7120 | { |
7121 | grn_hook *hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET]; |
7122 | void *v = GRN_BULK_HEAD(value); |
7123 | unsigned int s = grn_obj_size(ctx, value); |
7124 | if (hooks || obj->header.type == GRN_COLUMN_VAR_SIZE) { |
7125 | grn_obj oldbuf, *oldvalue; |
7126 | GRN_TEXT_INIT(&oldbuf, 0); |
7127 | oldvalue = grn_obj_get_value(ctx, obj, id, &oldbuf); |
7128 | if (flags & GRN_OBJ_SET) { |
7129 | void *ov; |
7130 | unsigned int os; |
7131 | ov = GRN_BULK_HEAD(oldvalue); |
7132 | os = grn_obj_size(ctx, oldvalue); |
7133 | if ((ov && v && os == s && !memcmp(ov, v, s)) && |
7134 | !(obj->header.type == GRN_COLUMN_FIX_SIZE && |
7135 | grn_bulk_is_zero(ctx, value))) { |
7136 | grn_obj_close(ctx, oldvalue); |
7137 | return 0; |
7138 | } |
7139 | } |
7140 | if (hooks) { |
7141 | // todo : grn_proc_ctx_open() |
7142 | grn_obj id_, flags_; |
7143 | grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4}; |
7144 | GRN_UINT32_INIT(&id_, 0); |
7145 | GRN_UINT32_INIT(&flags_, 0); |
7146 | GRN_UINT32_SET(ctx, &id_, id); |
7147 | GRN_UINT32_SET(ctx, &flags_, flags); |
7148 | while (hooks) { |
7149 | grn_ctx_push(ctx, &id_); |
7150 | grn_ctx_push(ctx, oldvalue); |
7151 | grn_ctx_push(ctx, value); |
7152 | grn_ctx_push(ctx, &flags_); |
7153 | pctx.caller = NULL; |
7154 | pctx.currh = hooks; |
7155 | if (hooks->proc) { |
7156 | hooks->proc->funcs[PROC_INIT](ctx, 1, &obj, &pctx.user_data); |
7157 | } else { |
7158 | grn_obj_default_set_value_hook(ctx, 1, &obj, &pctx.user_data); |
7159 | } |
7160 | if (ctx->rc) { |
7161 | grn_obj_close(ctx, oldvalue); |
7162 | return 1; |
7163 | } |
7164 | hooks = hooks->next; |
7165 | pctx.offset++; |
7166 | } |
7167 | } |
7168 | grn_obj_close(ctx, oldvalue); |
7169 | } |
7170 | return 0; |
7171 | } |
7172 | |
7173 | static grn_rc |
7174 | grn_obj_set_value_table_pat_key(grn_ctx *ctx, grn_obj *obj, grn_id id, |
7175 | grn_obj *value, int flags) |
7176 | { |
7177 | grn_rc rc = GRN_INVALID_ARGUMENT; |
7178 | grn_id range = DB_OBJ(obj)->range; |
7179 | void *v = GRN_BULK_HEAD(value); |
7180 | grn_obj buf; |
7181 | |
7182 | if (call_hook(ctx, obj, id, value, flags)) { |
7183 | if (ctx->rc) { |
7184 | rc = ctx->rc; |
7185 | } |
7186 | return rc; |
7187 | } |
7188 | |
7189 | if (range != value->header.domain) { |
7190 | GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); |
7191 | if (grn_obj_cast(ctx, value, &buf, GRN_TRUE) == GRN_SUCCESS) { |
7192 | v = GRN_BULK_HEAD(&buf); |
7193 | } |
7194 | } |
7195 | rc = grn_pat_set_value(ctx, (grn_pat *)obj, id, v, flags); |
7196 | if (range != value->header.domain) { |
7197 | grn_obj_close(ctx, &buf); |
7198 | } |
7199 | |
7200 | return rc; |
7201 | } |
7202 | |
7203 | static grn_rc |
7204 | grn_obj_set_value_table_hash_key(grn_ctx *ctx, grn_obj *obj, grn_id id, |
7205 | grn_obj *value, int flags) |
7206 | { |
7207 | grn_rc rc = GRN_INVALID_ARGUMENT; |
7208 | grn_id range = DB_OBJ(obj)->range; |
7209 | void *v = GRN_BULK_HEAD(value); |
7210 | grn_obj buf; |
7211 | |
7212 | if (call_hook(ctx, obj, id, value, flags)) { |
7213 | if (ctx->rc) { |
7214 | rc = ctx->rc; |
7215 | } |
7216 | return rc; |
7217 | } |
7218 | |
7219 | if (range != value->header.domain) { |
7220 | GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); |
7221 | if (grn_obj_cast(ctx, value, &buf, GRN_TRUE) == GRN_SUCCESS) { |
7222 | v = GRN_BULK_HEAD(&buf); |
7223 | } |
7224 | } |
7225 | rc = grn_hash_set_value(ctx, (grn_hash *)obj, id, v, flags); |
7226 | if (range != value->header.domain) { |
7227 | grn_obj_close(ctx, &buf); |
7228 | } |
7229 | |
7230 | return rc; |
7231 | } |
7232 | |
7233 | static grn_rc |
7234 | grn_obj_set_value_table_no_key(grn_ctx *ctx, grn_obj *obj, grn_id id, |
7235 | grn_obj *value, int flags) |
7236 | { |
7237 | grn_rc rc = GRN_INVALID_ARGUMENT; |
7238 | grn_id range = DB_OBJ(obj)->range; |
7239 | void *v = GRN_BULK_HEAD(value); |
7240 | grn_obj buf; |
7241 | |
7242 | if (call_hook(ctx, obj, id, value, flags)) { |
7243 | if (ctx->rc) { |
7244 | rc = ctx->rc; |
7245 | } |
7246 | return rc; |
7247 | } |
7248 | |
7249 | if (range != value->header.domain) { |
7250 | GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); |
7251 | if (grn_obj_cast(ctx, value, &buf, GRN_TRUE) == GRN_SUCCESS) { |
7252 | v = GRN_BULK_HEAD(&buf); |
7253 | } |
7254 | } |
7255 | rc = grn_array_set_value(ctx, (grn_array *)obj, id, v, flags); |
7256 | if (range != value->header.domain) { |
7257 | grn_obj_close(ctx, &buf); |
7258 | } |
7259 | |
7260 | return rc; |
7261 | } |
7262 | |
7263 | static grn_rc |
7264 | grn_obj_set_value_column_var_size_scalar(grn_ctx *ctx, grn_obj *obj, grn_id id, |
7265 | grn_obj *value, int flags) |
7266 | { |
7267 | grn_rc rc = GRN_INVALID_ARGUMENT; |
7268 | grn_id range = DB_OBJ(obj)->range; |
7269 | void *v = GRN_BULK_HEAD(value); |
7270 | unsigned int s = grn_obj_size(ctx, value); |
7271 | grn_obj buf; |
7272 | grn_id buf_domain = GRN_DB_VOID; |
7273 | |
7274 | if (call_hook(ctx, obj, id, value, flags)) { |
7275 | if (ctx->rc) { |
7276 | rc = ctx->rc; |
7277 | } |
7278 | return rc; |
7279 | } |
7280 | |
7281 | switch (flags & GRN_OBJ_SET_MASK) { |
7282 | case GRN_OBJ_INCR : |
7283 | case GRN_OBJ_DECR : |
7284 | if (value->header.domain == GRN_DB_INT32 || |
7285 | value->header.domain == GRN_DB_INT64) { |
7286 | /* do nothing */ |
7287 | } else if (GRN_DB_INT8 <= value->header.domain && |
7288 | value->header.domain < GRN_DB_INT32) { |
7289 | buf_domain = GRN_DB_INT32; |
7290 | } else { |
7291 | buf_domain = GRN_DB_INT64; |
7292 | } |
7293 | break; |
7294 | default : |
7295 | if (range != value->header.domain) { |
7296 | buf_domain = range; |
7297 | } |
7298 | break; |
7299 | } |
7300 | |
7301 | if (buf_domain != GRN_DB_VOID) { |
7302 | GRN_OBJ_INIT(&buf, GRN_BULK, 0, buf_domain); |
7303 | if (grn_obj_cast(ctx, value, &buf, GRN_TRUE) == GRN_SUCCESS) { |
7304 | v = GRN_BULK_HEAD(&buf); |
7305 | s = GRN_BULK_VSIZE(&buf); |
7306 | } |
7307 | } |
7308 | |
7309 | rc = grn_ja_put(ctx, (grn_ja *)obj, id, v, s, flags, NULL); |
7310 | |
7311 | if (buf_domain != GRN_DB_VOID) { |
7312 | grn_obj_close(ctx, &buf); |
7313 | } |
7314 | |
7315 | return rc; |
7316 | } |
7317 | |
7318 | static grn_rc |
7319 | grn_obj_set_value_column_var_size_vector_uvector(grn_ctx *ctx, grn_obj *column, |
7320 | grn_id id, grn_obj *value, |
7321 | int flags) |
7322 | { |
7323 | grn_rc rc = GRN_SUCCESS; |
7324 | grn_obj uvector; |
7325 | grn_obj_flags uvector_flags = 0; |
7326 | grn_bool need_convert = GRN_FALSE; |
7327 | grn_bool need_cast = GRN_FALSE; |
7328 | grn_id column_range_id; |
7329 | void *raw_value; |
7330 | unsigned int size; |
7331 | |
7332 | if (column->header.flags & GRN_OBJ_WITH_WEIGHT) { |
7333 | if (!IS_WEIGHT_UVECTOR(value)) { |
7334 | need_convert = GRN_TRUE; |
7335 | } |
7336 | } else { |
7337 | if (IS_WEIGHT_UVECTOR(value)) { |
7338 | need_convert = GRN_TRUE; |
7339 | uvector_flags = GRN_OBJ_WITH_WEIGHT; |
7340 | } |
7341 | } |
7342 | column_range_id = DB_OBJ(column)->range; |
7343 | if (column_range_id != value->header.domain) { |
7344 | need_convert = GRN_TRUE; |
7345 | need_cast = GRN_TRUE; |
7346 | } |
7347 | |
7348 | if (need_convert) { |
7349 | unsigned int i, n; |
7350 | |
7351 | GRN_VALUE_FIX_SIZE_INIT(&uvector, GRN_OBJ_VECTOR, column_range_id); |
7352 | uvector.header.flags |= uvector_flags; |
7353 | n = grn_uvector_size(ctx, value); |
7354 | if (need_cast) { |
7355 | grn_obj value_record; |
7356 | grn_obj casted_record; |
7357 | |
7358 | GRN_VALUE_FIX_SIZE_INIT(&value_record, 0, value->header.domain); |
7359 | GRN_VALUE_FIX_SIZE_INIT(&casted_record, 0, column_range_id); |
7360 | for (i = 0; i < n; i++) { |
7361 | grn_id id; |
7362 | grn_id casted_id; |
7363 | unsigned int weight = 0; |
7364 | |
7365 | GRN_BULK_REWIND(&value_record); |
7366 | GRN_BULK_REWIND(&casted_record); |
7367 | |
7368 | id = grn_uvector_get_element(ctx, value, i, NULL); |
7369 | GRN_RECORD_SET(ctx, &value_record, id); |
7370 | rc = grn_obj_cast(ctx, &value_record, &casted_record, GRN_TRUE); |
7371 | if (rc != GRN_SUCCESS) { |
7372 | char column_name[GRN_TABLE_MAX_KEY_SIZE]; |
7373 | int column_name_size; |
7374 | grn_obj inspected; |
7375 | column_name_size = grn_obj_name(ctx, |
7376 | column, |
7377 | column_name, |
7378 | GRN_TABLE_MAX_KEY_SIZE); |
7379 | GRN_TEXT_INIT(&inspected, 0); |
7380 | grn_inspect(ctx, &inspected, &value_record); |
7381 | ERR(rc, |
7382 | "[column][set-value] failed to cast: <%.*s>: <%.*s>" , |
7383 | column_name_size, |
7384 | column_name, |
7385 | (int)GRN_TEXT_LEN(&inspected), |
7386 | GRN_TEXT_VALUE(&inspected)); |
7387 | GRN_OBJ_FIN(ctx, &inspected); |
7388 | break; |
7389 | } |
7390 | casted_id = GRN_RECORD_VALUE(&casted_record); |
7391 | grn_uvector_add_element(ctx, &uvector, casted_id, weight); |
7392 | } |
7393 | |
7394 | GRN_OBJ_FIN(ctx, &value_record); |
7395 | GRN_OBJ_FIN(ctx, &casted_record); |
7396 | } else { |
7397 | for (i = 0; i < n; i++) { |
7398 | grn_id id; |
7399 | unsigned int weight = 0; |
7400 | id = grn_uvector_get_element(ctx, value, i, NULL); |
7401 | grn_uvector_add_element(ctx, &uvector, id, weight); |
7402 | } |
7403 | } |
7404 | raw_value = GRN_BULK_HEAD(&uvector); |
7405 | size = GRN_BULK_VSIZE(&uvector); |
7406 | } else { |
7407 | raw_value = GRN_BULK_HEAD(value); |
7408 | size = GRN_BULK_VSIZE(value); |
7409 | } |
7410 | |
7411 | if (rc == GRN_SUCCESS) { |
7412 | rc = grn_ja_put(ctx, (grn_ja *)column, id, raw_value, size, flags, NULL); |
7413 | } |
7414 | |
7415 | if (need_convert) { |
7416 | GRN_OBJ_FIN(ctx, &uvector); |
7417 | } |
7418 | |
7419 | return rc; |
7420 | } |
7421 | |
7422 | static grn_rc |
7423 | grn_obj_set_value_column_var_size_vector(grn_ctx *ctx, grn_obj *obj, grn_id id, |
7424 | grn_obj *value, int flags) |
7425 | { |
7426 | grn_rc rc = GRN_INVALID_ARGUMENT; |
7427 | grn_id range = DB_OBJ(obj)->range; |
7428 | void *v = GRN_BULK_HEAD(value); |
7429 | unsigned int s = grn_obj_size(ctx, value); |
7430 | grn_obj *lexicon = grn_ctx_at(ctx, range); |
7431 | |
7432 | if (call_hook(ctx, obj, id, value, flags)) { |
7433 | if (ctx->rc) { |
7434 | rc = ctx->rc; |
7435 | } |
7436 | return rc; |
7437 | } |
7438 | |
7439 | if (value->header.type == GRN_UVECTOR) { |
7440 | rc = grn_obj_set_value_column_var_size_vector_uvector(ctx, obj, |
7441 | id, value, |
7442 | flags); |
7443 | return rc; |
7444 | } |
7445 | |
7446 | if (GRN_OBJ_TABLEP(lexicon)) { |
7447 | grn_obj uvector; |
7448 | GRN_RECORD_INIT(&uvector, GRN_OBJ_VECTOR, range); |
7449 | if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) { |
7450 | uvector.header.flags |= GRN_OBJ_WITH_WEIGHT; |
7451 | } |
7452 | switch (value->header.type) { |
7453 | case GRN_BULK : |
7454 | { |
7455 | unsigned int token_flags = 0; |
7456 | grn_token_cursor *token_cursor; |
7457 | if (v && s && |
7458 | (token_cursor = grn_token_cursor_open(ctx, lexicon, v, s, |
7459 | GRN_TOKEN_ADD, token_flags))) { |
7460 | while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) { |
7461 | grn_id tid = grn_token_cursor_next(ctx, token_cursor); |
7462 | grn_uvector_add_element(ctx, &uvector, tid, 0); |
7463 | } |
7464 | grn_token_cursor_close(ctx, token_cursor); |
7465 | } |
7466 | rc = grn_ja_put(ctx, (grn_ja *)obj, id, |
7467 | GRN_BULK_HEAD(&uvector), GRN_BULK_VSIZE(&uvector), |
7468 | flags, NULL); |
7469 | } |
7470 | break; |
7471 | case GRN_VECTOR : |
7472 | { |
7473 | unsigned int n; |
7474 | n = grn_vector_size(ctx, value); |
7475 | if (n > 0) { |
7476 | unsigned int i; |
7477 | grn_obj value_buf, cast_buf; |
7478 | GRN_OBJ_INIT(&value_buf, GRN_BULK, 0, GRN_DB_VOID); |
7479 | GRN_OBJ_INIT(&cast_buf, GRN_BULK, 0, lexicon->header.domain); |
7480 | for (i = 0; i < n; i++) { |
7481 | grn_id tid; |
7482 | const char *element; |
7483 | unsigned int element_length; |
7484 | unsigned int weight; |
7485 | grn_id element_domain; |
7486 | |
7487 | element_length = grn_vector_get_element(ctx, value, i, |
7488 | &element, &weight, |
7489 | &element_domain); |
7490 | if (element_domain != lexicon->header.domain) { |
7491 | GRN_BULK_REWIND(&cast_buf); |
7492 | GRN_BULK_REWIND(&value_buf); |
7493 | grn_bulk_write(ctx, &value_buf, element, element_length); |
7494 | value_buf.header.domain = element_domain; |
7495 | rc = grn_obj_cast(ctx, &value_buf, &cast_buf, GRN_TRUE); |
7496 | if (rc) { |
7497 | grn_obj *range_obj; |
7498 | range_obj = grn_ctx_at(ctx, range); |
7499 | ERR_CAST(obj, range_obj, &value_buf); |
7500 | grn_obj_unlink(ctx, range_obj); |
7501 | } else { |
7502 | element = GRN_BULK_HEAD(&cast_buf); |
7503 | element_length = GRN_BULK_VSIZE(&cast_buf); |
7504 | } |
7505 | } else { |
7506 | rc = GRN_SUCCESS; |
7507 | } |
7508 | if (rc) { |
7509 | continue; |
7510 | } |
7511 | tid = grn_table_add(ctx, lexicon, element, element_length, NULL); |
7512 | grn_uvector_add_element(ctx, &uvector, tid, weight); |
7513 | } |
7514 | GRN_OBJ_FIN(ctx, &value_buf); |
7515 | GRN_OBJ_FIN(ctx, &cast_buf); |
7516 | } |
7517 | } |
7518 | rc = grn_ja_put(ctx, (grn_ja *)obj, id, |
7519 | GRN_BULK_HEAD(&uvector), GRN_BULK_VSIZE(&uvector), |
7520 | flags, NULL); |
7521 | break; |
7522 | default : |
7523 | ERR(GRN_INVALID_ARGUMENT, "vector, uvector or bulk required" ); |
7524 | break; |
7525 | } |
7526 | grn_obj_close(ctx, &uvector); |
7527 | } else { |
7528 | switch (value->header.type) { |
7529 | case GRN_BULK : |
7530 | if (!GRN_BULK_VSIZE(value)) { |
7531 | rc = grn_ja_put(ctx, (grn_ja *)obj, id, NULL, 0, flags, NULL); |
7532 | } else { |
7533 | grn_obj v; |
7534 | GRN_OBJ_INIT(&v, GRN_VECTOR, GRN_OBJ_DO_SHALLOW_COPY, GRN_DB_TEXT); |
7535 | v.u.v.body = value; |
7536 | grn_vector_delimit(ctx, &v, 0, GRN_ID_NIL); |
7537 | rc = grn_ja_putv(ctx, (grn_ja *)obj, id, &v, 0); |
7538 | grn_obj_close(ctx, &v); |
7539 | } |
7540 | break; |
7541 | case GRN_VECTOR : |
7542 | rc = grn_ja_putv(ctx, (grn_ja *)obj, id, value, 0); |
7543 | break; |
7544 | default : |
7545 | ERR(GRN_INVALID_ARGUMENT, "vector or bulk required" ); |
7546 | break; |
7547 | } |
7548 | } |
7549 | return rc; |
7550 | } |
7551 | |
7552 | static grn_rc |
7553 | grn_obj_set_value_column_fix_size(grn_ctx *ctx, grn_obj *obj, grn_id id, |
7554 | grn_obj *value, int flags) |
7555 | { |
7556 | grn_rc rc = GRN_INVALID_ARGUMENT; |
7557 | grn_id range = DB_OBJ(obj)->range; |
7558 | void *v = GRN_BULK_HEAD(value); |
7559 | unsigned int s = grn_obj_size(ctx, value); |
7560 | grn_obj buf, *value_ = value; |
7561 | uint32_t element_size = ((grn_ra *)obj)->header->element_size; |
7562 | GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); |
7563 | if (range != value->header.domain) { |
7564 | rc = grn_obj_cast(ctx, value, &buf, GRN_TRUE); |
7565 | if (rc) { |
7566 | grn_obj *range_obj; |
7567 | range_obj = grn_ctx_at(ctx, range); |
7568 | ERR_CAST(obj, range_obj, value); |
7569 | grn_obj_unlink(ctx, range_obj); |
7570 | } else { |
7571 | value_ = &buf; |
7572 | v = GRN_BULK_HEAD(&buf); |
7573 | s = GRN_BULK_VSIZE(&buf); |
7574 | } |
7575 | } else { |
7576 | rc = GRN_SUCCESS; |
7577 | } |
7578 | if (rc) { |
7579 | /* do nothing because it already has error. */ |
7580 | } else if (element_size < s) { |
7581 | ERR(GRN_INVALID_ARGUMENT, "too long value (%d)" , s); |
7582 | } else { |
7583 | void *p = grn_ra_ref(ctx, (grn_ra *)obj, id); |
7584 | if (!p) { |
7585 | ERR(GRN_NO_MEMORY_AVAILABLE, "ra get failed" ); |
7586 | rc = GRN_NO_MEMORY_AVAILABLE; |
7587 | return rc; |
7588 | } |
7589 | switch (flags & GRN_OBJ_SET_MASK) { |
7590 | case GRN_OBJ_SET : |
7591 | if (call_hook(ctx, obj, id, value_, flags)) { |
7592 | if (ctx->rc) { |
7593 | rc = ctx->rc; |
7594 | } |
7595 | GRN_OBJ_FIN(ctx, &buf); |
7596 | grn_ra_unref(ctx, (grn_ra *)obj, id); |
7597 | return rc; |
7598 | } |
7599 | if (element_size != s) { |
7600 | if (!s) { |
7601 | memset(p, 0, element_size); |
7602 | } else { |
7603 | void *b; |
7604 | if ((b = GRN_CALLOC(element_size))) { |
7605 | grn_memcpy(b, v, s); |
7606 | grn_memcpy(p, b, element_size); |
7607 | GRN_FREE(b); |
7608 | } |
7609 | } |
7610 | } else { |
7611 | grn_memcpy(p, v, s); |
7612 | } |
7613 | rc = GRN_SUCCESS; |
7614 | break; |
7615 | case GRN_OBJ_INCR : |
7616 | /* todo : support hook */ |
7617 | INCRDECR(+=); |
7618 | break; |
7619 | case GRN_OBJ_DECR : |
7620 | /* todo : support hook */ |
7621 | INCRDECR(-=); |
7622 | break; |
7623 | default : |
7624 | rc = GRN_OPERATION_NOT_SUPPORTED; |
7625 | break; |
7626 | } |
7627 | grn_ra_unref(ctx, (grn_ra *)obj, id); |
7628 | } |
7629 | GRN_OBJ_FIN(ctx, &buf); |
7630 | return rc; |
7631 | } |
7632 | |
7633 | static grn_rc |
7634 | grn_obj_set_value_column_index(grn_ctx *ctx, grn_obj *obj, grn_id id, |
7635 | grn_obj *value, int flags) |
7636 | { |
7637 | char column_name[GRN_TABLE_MAX_KEY_SIZE]; |
7638 | int column_name_size; |
7639 | column_name_size = grn_obj_name(ctx, obj, column_name, |
7640 | GRN_TABLE_MAX_KEY_SIZE); |
7641 | ERR(GRN_INVALID_ARGUMENT, |
7642 | "can't set value to index column directly: <%.*s>" , |
7643 | column_name_size, column_name); |
7644 | return ctx->rc; |
7645 | } |
7646 | |
7647 | grn_rc |
7648 | grn_obj_set_value(grn_ctx *ctx, grn_obj *obj, grn_id id, |
7649 | grn_obj *value, int flags) |
7650 | { |
7651 | grn_rc rc = GRN_INVALID_ARGUMENT; |
7652 | GRN_API_ENTER; |
7653 | if (!GRN_DB_OBJP(obj)) { |
7654 | if (obj->header.type == GRN_ACCESSOR) { |
7655 | rc = grn_accessor_set_value(ctx, (grn_accessor *)obj, id, value, flags); |
7656 | } else { |
7657 | ERR(GRN_INVALID_ARGUMENT, "not db_obj" ); |
7658 | } |
7659 | } else { |
7660 | switch (obj->header.type) { |
7661 | case GRN_TABLE_PAT_KEY : |
7662 | rc = grn_obj_set_value_table_pat_key(ctx, obj, id, value, flags); |
7663 | break; |
7664 | case GRN_TABLE_DAT_KEY : |
7665 | rc = GRN_OPERATION_NOT_SUPPORTED; |
7666 | break; |
7667 | case GRN_TABLE_HASH_KEY : |
7668 | rc = grn_obj_set_value_table_hash_key(ctx, obj, id, value, flags); |
7669 | break; |
7670 | case GRN_TABLE_NO_KEY : |
7671 | rc = grn_obj_set_value_table_no_key(ctx, obj, id, value, flags); |
7672 | break; |
7673 | case GRN_COLUMN_VAR_SIZE : |
7674 | switch (obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { |
7675 | case GRN_OBJ_COLUMN_SCALAR : |
7676 | rc = grn_obj_set_value_column_var_size_scalar(ctx, obj, id, value, |
7677 | flags); |
7678 | break; |
7679 | case GRN_OBJ_COLUMN_VECTOR : |
7680 | rc = grn_obj_set_value_column_var_size_vector(ctx, obj, id, value, |
7681 | flags); |
7682 | break; |
7683 | default : |
7684 | ERR(GRN_FILE_CORRUPT, "invalid GRN_OBJ_COLUMN_TYPE" ); |
7685 | break; |
7686 | } |
7687 | break; |
7688 | case GRN_COLUMN_FIX_SIZE : |
7689 | rc = grn_obj_set_value_column_fix_size(ctx, obj, id, value, flags); |
7690 | break; |
7691 | case GRN_COLUMN_INDEX : |
7692 | rc = grn_obj_set_value_column_index(ctx, obj, id, value, flags); |
7693 | break; |
7694 | } |
7695 | } |
7696 | GRN_API_RETURN(rc); |
7697 | } |
7698 | |
7699 | const char * |
7700 | grn_obj_get_value_(grn_ctx *ctx, grn_obj *obj, grn_id id, uint32_t *size) |
7701 | { |
7702 | const char *value = NULL; |
7703 | *size = 0; |
7704 | switch (obj->header.type) { |
7705 | case GRN_ACCESSOR : |
7706 | value = grn_accessor_get_value_(ctx, (grn_accessor *)obj, id, size); |
7707 | break; |
7708 | case GRN_TABLE_PAT_KEY : |
7709 | value = grn_pat_get_value_(ctx, (grn_pat *)obj, id, size); |
7710 | break; |
7711 | case GRN_TABLE_DAT_KEY : |
7712 | ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "GRN_TABLE_DAT_KEY not supported" ); |
7713 | break; |
7714 | case GRN_TABLE_HASH_KEY : |
7715 | value = grn_hash_get_value_(ctx, (grn_hash *)obj, id, size); |
7716 | break; |
7717 | case GRN_TABLE_NO_KEY : |
7718 | if ((value = _grn_array_get_value(ctx, (grn_array *)obj, id))) { |
7719 | *size = ((grn_array *)obj)->value_size; |
7720 | } |
7721 | break; |
7722 | case GRN_COLUMN_VAR_SIZE : |
7723 | { |
7724 | grn_io_win jw; |
7725 | if ((value = grn_ja_ref(ctx, (grn_ja *)obj, id, &jw, size))) { |
7726 | grn_ja_unref(ctx, &jw); |
7727 | } |
7728 | } |
7729 | break; |
7730 | case GRN_COLUMN_FIX_SIZE : |
7731 | if ((value = grn_ra_ref(ctx, (grn_ra *)obj, id))) { |
7732 | grn_ra_unref(ctx, (grn_ra *)obj, id); |
7733 | *size = ((grn_ra *)obj)->header->element_size; |
7734 | } |
7735 | break; |
7736 | case GRN_COLUMN_INDEX : |
7737 | ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "todo: GRN_COLUMN_INDEX" ); |
7738 | break; |
7739 | } |
7740 | return value; |
7741 | } |
7742 | |
7743 | static void |
7744 | grn_obj_get_value_expr(grn_ctx *ctx, grn_obj *expr, grn_id id, grn_obj *value) |
7745 | { |
7746 | grn_expr *e = (grn_expr *)expr; |
7747 | grn_expr_code *code; |
7748 | |
7749 | if (e->codes_curr != 1) { |
7750 | return; |
7751 | } |
7752 | |
7753 | code = e->codes; |
7754 | if (code->op != GRN_OP_GET_VALUE) { |
7755 | return; |
7756 | } |
7757 | |
7758 | if (!code->value) { |
7759 | return; |
7760 | } |
7761 | |
7762 | switch (code->value->header.type) { |
7763 | case GRN_COLUMN_VAR_SIZE : |
7764 | case GRN_COLUMN_FIX_SIZE : |
7765 | grn_obj_get_value(ctx, code->value, id, value); |
7766 | break; |
7767 | default : |
7768 | break; |
7769 | } |
7770 | } |
7771 | |
7772 | static void |
7773 | grn_obj_get_value_column_index(grn_ctx *ctx, grn_obj *index_column, |
7774 | grn_id id, grn_obj *value) |
7775 | { |
7776 | grn_ii *ii = (grn_ii *)index_column; |
7777 | grn_obj_ensure_bulk(ctx, value); |
7778 | if (id) { |
7779 | GRN_UINT32_SET(ctx, value, grn_ii_estimate_size(ctx, ii, id)); |
7780 | } else { |
7781 | GRN_UINT32_SET(ctx, value, 0); |
7782 | } |
7783 | value->header.domain = GRN_DB_UINT32; |
7784 | } |
7785 | |
7786 | static grn_obj * |
7787 | grn_obj_get_value_column_vector(grn_ctx *ctx, grn_obj *obj, |
7788 | grn_id id, grn_obj *value) |
7789 | { |
7790 | grn_obj *lexicon; |
7791 | |
7792 | lexicon = grn_ctx_at(ctx, DB_OBJ(obj)->range); |
7793 | if (lexicon && !GRN_OBJ_TABLEP(lexicon) && |
7794 | (lexicon->header.flags & GRN_OBJ_KEY_VAR_SIZE)) { |
7795 | grn_obj_ensure_vector(ctx, value); |
7796 | if (id) { |
7797 | grn_obj v_; |
7798 | GRN_TEXT_INIT(&v_, 0); |
7799 | grn_ja_get_value(ctx, (grn_ja *)obj, id, &v_); |
7800 | grn_vector_decode(ctx, value, GRN_TEXT_VALUE(&v_), GRN_TEXT_LEN(&v_)); |
7801 | GRN_OBJ_FIN(ctx, &v_); |
7802 | } |
7803 | } else { |
7804 | grn_obj_ensure_bulk(ctx, value); |
7805 | if (id) { |
7806 | grn_ja_get_value(ctx, (grn_ja *)obj, id, value); |
7807 | } |
7808 | value->header.type = GRN_UVECTOR; |
7809 | if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) { |
7810 | value->header.flags |= GRN_OBJ_WITH_WEIGHT; |
7811 | } else { |
7812 | value->header.flags &= ~GRN_OBJ_WITH_WEIGHT; |
7813 | } |
7814 | } |
7815 | |
7816 | return value; |
7817 | } |
7818 | |
7819 | grn_obj * |
7820 | grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) |
7821 | { |
7822 | GRN_API_ENTER; |
7823 | if (!obj) { |
7824 | ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed" ); |
7825 | goto exit; |
7826 | } |
7827 | if (!value) { |
7828 | if (!(value = grn_obj_open(ctx, GRN_BULK, 0, 0))) { |
7829 | ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed" ); |
7830 | goto exit; |
7831 | } |
7832 | } |
7833 | switch (value->header.type) { |
7834 | case GRN_VOID : |
7835 | grn_obj_reinit(ctx, value, GRN_DB_TEXT, 0); |
7836 | break; |
7837 | case GRN_BULK : |
7838 | case GRN_VECTOR : |
7839 | case GRN_UVECTOR : |
7840 | case GRN_MSG : |
7841 | break; |
7842 | default : |
7843 | ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed" ); |
7844 | goto exit; |
7845 | } |
7846 | switch (obj->header.type) { |
7847 | case GRN_ACCESSOR : |
7848 | grn_obj_ensure_bulk(ctx, value); |
7849 | value = grn_accessor_get_value(ctx, (grn_accessor *)obj, id, value); |
7850 | break; |
7851 | case GRN_EXPR : |
7852 | grn_obj_get_value_expr(ctx, obj, id, value); |
7853 | break; |
7854 | case GRN_TABLE_PAT_KEY : |
7855 | { |
7856 | grn_pat *pat = (grn_pat *)obj; |
7857 | uint32_t size = pat->value_size; |
7858 | grn_obj_ensure_bulk(ctx, value); |
7859 | if (id) { |
7860 | if (grn_bulk_space(ctx, value, size)) { |
7861 | MERR("grn_bulk_space failed" ); |
7862 | goto exit; |
7863 | } |
7864 | { |
7865 | char *curr = GRN_BULK_CURR(value); |
7866 | grn_pat_get_value(ctx, pat, id, curr - size); |
7867 | } |
7868 | } |
7869 | value->header.type = GRN_BULK; |
7870 | value->header.domain = grn_obj_get_range(ctx, obj); |
7871 | } |
7872 | break; |
7873 | case GRN_TABLE_DAT_KEY : |
7874 | ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "GRN_TABLE_DAT_KEY not supported" ); |
7875 | break; |
7876 | case GRN_TABLE_HASH_KEY : |
7877 | { |
7878 | grn_bool processed = GRN_FALSE; |
7879 | grn_obj_ensure_bulk(ctx, value); |
7880 | value->header.domain = grn_obj_get_range(ctx, obj); |
7881 | if (id) { |
7882 | if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(obj)) { |
7883 | grn_obj *domain; |
7884 | domain = grn_ctx_at(ctx, value->header.domain); |
7885 | if (GRN_OBJ_TABLEP(domain)) { |
7886 | grn_id subrec_id; |
7887 | if (grn_table_get_subrecs(ctx, obj, id, &subrec_id, NULL, 1) == 1) { |
7888 | GRN_RECORD_SET(ctx, value, subrec_id); |
7889 | processed = GRN_TRUE; |
7890 | } |
7891 | } |
7892 | } |
7893 | if (!processed) { |
7894 | grn_hash *hash = (grn_hash *)obj; |
7895 | uint32_t size = hash->value_size; |
7896 | if (grn_bulk_space(ctx, value, size)) { |
7897 | MERR("grn_bulk_space failed" ); |
7898 | goto exit; |
7899 | } |
7900 | { |
7901 | char *curr = GRN_BULK_CURR(value); |
7902 | grn_hash_get_value(ctx, hash, id, curr - size); |
7903 | } |
7904 | } |
7905 | } |
7906 | } |
7907 | break; |
7908 | case GRN_TABLE_NO_KEY : |
7909 | { |
7910 | grn_array *array = (grn_array *)obj; |
7911 | uint32_t size = array->value_size; |
7912 | grn_obj_ensure_bulk(ctx, value); |
7913 | if (id) { |
7914 | if (grn_bulk_space(ctx, value, size)) { |
7915 | MERR("grn_bulk_space failed" ); |
7916 | goto exit; |
7917 | } |
7918 | { |
7919 | char *curr = GRN_BULK_CURR(value); |
7920 | grn_array_get_value(ctx, array, id, curr - size); |
7921 | } |
7922 | } |
7923 | value->header.type = GRN_BULK; |
7924 | value->header.domain = grn_obj_get_range(ctx, obj); |
7925 | } |
7926 | break; |
7927 | case GRN_COLUMN_VAR_SIZE : |
7928 | switch (obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { |
7929 | case GRN_OBJ_COLUMN_VECTOR : |
7930 | grn_obj_get_value_column_vector(ctx, obj, id, value); |
7931 | break; |
7932 | case GRN_OBJ_COLUMN_SCALAR : |
7933 | grn_obj_ensure_bulk(ctx, value); |
7934 | if (id) { |
7935 | grn_ja_get_value(ctx, (grn_ja *)obj, id, value); |
7936 | } |
7937 | value->header.type = GRN_BULK; |
7938 | break; |
7939 | default : |
7940 | ERR(GRN_FILE_CORRUPT, "invalid GRN_OBJ_COLUMN_TYPE" ); |
7941 | break; |
7942 | } |
7943 | value->header.domain = grn_obj_get_range(ctx, obj); |
7944 | break; |
7945 | case GRN_COLUMN_FIX_SIZE : |
7946 | grn_obj_ensure_bulk(ctx, value); |
7947 | value->header.type = GRN_BULK; |
7948 | value->header.domain = grn_obj_get_range(ctx, obj); |
7949 | if (id) { |
7950 | unsigned int element_size; |
7951 | void *v = grn_ra_ref(ctx, (grn_ra *)obj, id); |
7952 | if (v) { |
7953 | element_size = ((grn_ra *)obj)->header->element_size; |
7954 | grn_bulk_write(ctx, value, v, element_size); |
7955 | grn_ra_unref(ctx, (grn_ra *)obj, id); |
7956 | } |
7957 | } |
7958 | break; |
7959 | case GRN_COLUMN_INDEX : |
7960 | grn_obj_get_value_column_index(ctx, obj, id, value); |
7961 | break; |
7962 | } |
7963 | exit : |
7964 | GRN_API_RETURN(value); |
7965 | } |
7966 | |
7967 | int |
7968 | grn_obj_get_values(grn_ctx *ctx, grn_obj *obj, grn_id offset, void **values) |
7969 | { |
7970 | int nrecords = -1; |
7971 | GRN_API_ENTER; |
7972 | if (obj->header.type == GRN_COLUMN_FIX_SIZE) { |
7973 | grn_obj *domain = grn_column_table(ctx, obj); |
7974 | if (domain) { |
7975 | int table_size = (int)grn_table_size(ctx, domain); |
7976 | if (0 < offset && offset <= table_size) { |
7977 | grn_ra *ra = (grn_ra *)obj; |
7978 | void *p = grn_ra_ref(ctx, ra, offset); |
7979 | if (p) { |
7980 | if ((offset >> ra->element_width) == (table_size >> ra->element_width)) { |
7981 | nrecords = (table_size & ra->element_mask) + 1 - (offset & ra->element_mask); |
7982 | } else { |
7983 | nrecords = ra->element_mask + 1 - (offset & ra->element_mask); |
7984 | } |
7985 | if (values) { *values = p; } |
7986 | grn_ra_unref(ctx, ra, offset); |
7987 | } else { |
7988 | ERR(GRN_NO_MEMORY_AVAILABLE, "ra get failed" ); |
7989 | } |
7990 | } else { |
7991 | nrecords = 0; |
7992 | } |
7993 | } else { |
7994 | ERR(GRN_INVALID_ARGUMENT, "no domain found" ); |
7995 | } |
7996 | } else { |
7997 | ERR(GRN_INVALID_ARGUMENT, "obj is not a fix sized column" ); |
7998 | } |
7999 | GRN_API_RETURN(nrecords); |
8000 | } |
8001 | |
8002 | grn_rc |
8003 | grn_column_index_update(grn_ctx *ctx, grn_obj *column, |
8004 | grn_id id, unsigned int section, |
8005 | grn_obj *oldvalue, grn_obj *newvalue) |
8006 | { |
8007 | grn_rc rc = GRN_INVALID_ARGUMENT; |
8008 | GRN_API_ENTER; |
8009 | if (column->header.type != GRN_COLUMN_INDEX) { |
8010 | ERR(GRN_INVALID_ARGUMENT, "invalid column assigned" ); |
8011 | } else { |
8012 | rc = grn_ii_column_update(ctx, (grn_ii *)column, id, section, oldvalue, newvalue, NULL); |
8013 | } |
8014 | GRN_API_RETURN(rc); |
8015 | } |
8016 | |
8017 | grn_obj * |
8018 | grn_column_table(grn_ctx *ctx, grn_obj *column) |
8019 | { |
8020 | grn_obj *obj = NULL; |
8021 | grn_db_obj *col = DB_OBJ(column); |
8022 | GRN_API_ENTER; |
8023 | if (col) { |
8024 | obj = grn_ctx_at(ctx, col->header.domain); |
8025 | } |
8026 | GRN_API_RETURN(obj); |
8027 | } |
8028 | |
8029 | grn_obj * |
8030 | grn_obj_get_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *valuebuf) |
8031 | { |
8032 | GRN_API_ENTER; |
8033 | switch (type) { |
8034 | case GRN_INFO_SUPPORT_ZLIB : |
8035 | if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) { |
8036 | ERR(GRN_INVALID_ARGUMENT, |
8037 | "failed to open value buffer for GRN_INFO_ZLIB_SUPPORT" ); |
8038 | goto exit; |
8039 | } |
8040 | #ifdef GRN_WITH_ZLIB |
8041 | GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE); |
8042 | #else |
8043 | GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); |
8044 | #endif |
8045 | break; |
8046 | case GRN_INFO_SUPPORT_LZ4 : |
8047 | if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) { |
8048 | ERR(GRN_INVALID_ARGUMENT, |
8049 | "failed to open value buffer for GRN_INFO_LZ4_SUPPORT" ); |
8050 | goto exit; |
8051 | } |
8052 | #ifdef GRN_WITH_LZ4 |
8053 | GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE); |
8054 | #else /* GRN_WITH_LZ4 */ |
8055 | GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); |
8056 | #endif /* GRN_WITH_LZ4 */ |
8057 | break; |
8058 | case GRN_INFO_SUPPORT_ZSTD : |
8059 | if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) { |
8060 | ERR(GRN_INVALID_ARGUMENT, |
8061 | "failed to open value buffer for GRN_INFO_ZSTD_SUPPORT" ); |
8062 | goto exit; |
8063 | } |
8064 | #ifdef GRN_WITH_ZSTD |
8065 | GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE); |
8066 | #else /* GRN_WITH_ZSTD */ |
8067 | GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); |
8068 | #endif /* GRN_WITH_ZSTD */ |
8069 | break; |
8070 | case GRN_INFO_SUPPORT_ARROW : |
8071 | if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) { |
8072 | ERR(GRN_INVALID_ARGUMENT, |
8073 | "failed to open value buffer for GRN_INFO_ARROW_SUPPORT" ); |
8074 | goto exit; |
8075 | } |
8076 | #ifdef GRN_WITH_ARROW |
8077 | GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE); |
8078 | #else /* GRN_WITH_ARROW */ |
8079 | GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); |
8080 | #endif /* GRN_WITH_ARROW */ |
8081 | break; |
8082 | default : |
8083 | if (!obj) { |
8084 | ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_info failed" ); |
8085 | goto exit; |
8086 | } |
8087 | switch (type) { |
8088 | case GRN_INFO_ENCODING : |
8089 | if (!valuebuf) { |
8090 | if (!(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, 0))) { |
8091 | ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_info failed" ); |
8092 | goto exit; |
8093 | } |
8094 | } |
8095 | { |
8096 | grn_encoding enc; |
8097 | if (obj->header.type == GRN_DB) { obj = ((grn_db *)obj)->keys; } |
8098 | switch (obj->header.type) { |
8099 | case GRN_TABLE_PAT_KEY : |
8100 | enc = ((grn_pat *)obj)->encoding; |
8101 | grn_bulk_write(ctx, valuebuf, (const char *)&enc, sizeof(grn_encoding)); |
8102 | break; |
8103 | case GRN_TABLE_DAT_KEY : |
8104 | enc = ((grn_dat *)obj)->encoding; |
8105 | grn_bulk_write(ctx, valuebuf, (const char *)&enc, sizeof(grn_encoding)); |
8106 | break; |
8107 | case GRN_TABLE_HASH_KEY : |
8108 | enc = ((grn_hash *)obj)->encoding; |
8109 | grn_bulk_write(ctx, valuebuf, (const char *)&enc, sizeof(grn_encoding)); |
8110 | break; |
8111 | default : |
8112 | ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_info failed" ); |
8113 | } |
8114 | } |
8115 | break; |
8116 | case GRN_INFO_SOURCE : |
8117 | if (!valuebuf) { |
8118 | if (!(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, 0))) { |
8119 | ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_info failed" ); |
8120 | goto exit; |
8121 | } |
8122 | } |
8123 | if (!GRN_DB_OBJP(obj)) { |
8124 | ERR(GRN_INVALID_ARGUMENT, "only db_obj can accept GRN_INFO_SOURCE" ); |
8125 | goto exit; |
8126 | } |
8127 | grn_bulk_write(ctx, valuebuf, DB_OBJ(obj)->source, DB_OBJ(obj)->source_size); |
8128 | break; |
8129 | case GRN_INFO_DEFAULT_TOKENIZER : |
8130 | switch (DB_OBJ(obj)->header.type) { |
8131 | case GRN_TABLE_HASH_KEY : |
8132 | valuebuf = ((grn_hash *)obj)->tokenizer; |
8133 | break; |
8134 | case GRN_TABLE_PAT_KEY : |
8135 | valuebuf = ((grn_pat *)obj)->tokenizer; |
8136 | break; |
8137 | case GRN_TABLE_DAT_KEY : |
8138 | valuebuf = ((grn_dat *)obj)->tokenizer; |
8139 | break; |
8140 | } |
8141 | break; |
8142 | case GRN_INFO_NORMALIZER : |
8143 | switch (DB_OBJ(obj)->header.type) { |
8144 | case GRN_TABLE_HASH_KEY : |
8145 | valuebuf = ((grn_hash *)obj)->normalizer; |
8146 | break; |
8147 | case GRN_TABLE_PAT_KEY : |
8148 | valuebuf = ((grn_pat *)obj)->normalizer; |
8149 | break; |
8150 | case GRN_TABLE_DAT_KEY : |
8151 | valuebuf = ((grn_dat *)obj)->normalizer; |
8152 | break; |
8153 | } |
8154 | break; |
8155 | case GRN_INFO_TOKEN_FILTERS : |
8156 | if (!valuebuf) { |
8157 | if (!(valuebuf = grn_obj_open(ctx, GRN_PVECTOR, 0, 0))) { |
8158 | ERR(GRN_NO_MEMORY_AVAILABLE, |
8159 | "grn_obj_get_info: failed to allocate value buffer" ); |
8160 | goto exit; |
8161 | } |
8162 | } |
8163 | { |
8164 | grn_obj *token_filters = NULL; |
8165 | switch (obj->header.type) { |
8166 | case GRN_TABLE_HASH_KEY : |
8167 | token_filters = &(((grn_hash *)obj)->token_filters); |
8168 | break; |
8169 | case GRN_TABLE_PAT_KEY : |
8170 | token_filters = &(((grn_pat *)obj)->token_filters); |
8171 | break; |
8172 | case GRN_TABLE_DAT_KEY : |
8173 | token_filters = &(((grn_dat *)obj)->token_filters); |
8174 | break; |
8175 | default : |
8176 | ERR(GRN_INVALID_ARGUMENT, |
8177 | /* TODO: Show type name instead of type ID */ |
8178 | "[info][get][token-filters] target object must be one of " |
8179 | "GRN_TABLE_HASH_KEY, GRN_TABLE_PAT_KEY and GRN_TABLE_DAT_KEY: %d" , |
8180 | obj->header.type); |
8181 | break; |
8182 | } |
8183 | if (token_filters) { |
8184 | grn_bulk_write(ctx, |
8185 | valuebuf, |
8186 | GRN_BULK_HEAD(token_filters), |
8187 | GRN_BULK_VSIZE(token_filters)); |
8188 | } |
8189 | } |
8190 | break; |
8191 | default : |
8192 | /* todo */ |
8193 | break; |
8194 | } |
8195 | } |
8196 | exit : |
8197 | GRN_API_RETURN(valuebuf); |
8198 | } |
8199 | |
8200 | static void |
8201 | update_source_hook(grn_ctx *ctx, grn_obj *obj) |
8202 | { |
8203 | grn_id *s = DB_OBJ(obj)->source; |
8204 | int i, n = DB_OBJ(obj)->source_size / sizeof(grn_id); |
8205 | grn_obj_default_set_value_hook_data hook_data = { DB_OBJ(obj)->id, 0 }; |
8206 | grn_obj *source, data; |
8207 | GRN_TEXT_INIT(&data, GRN_OBJ_DO_SHALLOW_COPY); |
8208 | GRN_TEXT_SET_REF(&data, &hook_data, sizeof(hook_data)); |
8209 | for (i = 1; i <= n; i++, s++) { |
8210 | hook_data.section = i; |
8211 | if ((source = grn_ctx_at(ctx, *s))) { |
8212 | switch (source->header.type) { |
8213 | case GRN_TABLE_HASH_KEY : |
8214 | case GRN_TABLE_PAT_KEY : |
8215 | case GRN_TABLE_DAT_KEY : |
8216 | grn_obj_add_hook(ctx, source, GRN_HOOK_INSERT, 0, NULL, &data); |
8217 | grn_obj_add_hook(ctx, source, GRN_HOOK_DELETE, 0, NULL, &data); |
8218 | break; |
8219 | case GRN_COLUMN_FIX_SIZE : |
8220 | case GRN_COLUMN_VAR_SIZE : |
8221 | case GRN_COLUMN_INDEX : |
8222 | grn_obj_add_hook(ctx, source, GRN_HOOK_SET, 0, NULL, &data); |
8223 | break; |
8224 | default : |
8225 | /* invalid target */ |
8226 | break; |
8227 | } |
8228 | } |
8229 | } |
8230 | grn_obj_close(ctx, &data); |
8231 | } |
8232 | |
8233 | static void |
8234 | del_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, grn_obj *hld) |
8235 | { |
8236 | int i; |
8237 | void *hld_value = NULL; |
8238 | uint32_t hld_size = 0; |
8239 | grn_hook **last; |
8240 | hld_value = GRN_BULK_HEAD(hld); |
8241 | hld_size = GRN_BULK_VSIZE(hld); |
8242 | if (!hld_size) { return; } |
8243 | for (i = 0, last = &DB_OBJ(obj)->hooks[entry]; *last; i++, last = &(*last)->next) { |
8244 | if (!memcmp(GRN_NEXT_ADDR(*last), hld_value, hld_size)) { |
8245 | grn_obj_delete_hook(ctx, obj, entry, i); |
8246 | return; |
8247 | } |
8248 | } |
8249 | } |
8250 | |
8251 | static void |
8252 | delete_source_hook(grn_ctx *ctx, grn_obj *obj) |
8253 | { |
8254 | grn_id *s = DB_OBJ(obj)->source; |
8255 | int i, n = DB_OBJ(obj)->source_size / sizeof(grn_id); |
8256 | grn_obj_default_set_value_hook_data hook_data = { DB_OBJ(obj)->id, 0 }; |
8257 | grn_obj *source, data; |
8258 | GRN_TEXT_INIT(&data, GRN_OBJ_DO_SHALLOW_COPY); |
8259 | GRN_TEXT_SET_REF(&data, &hook_data, sizeof(hook_data)); |
8260 | for (i = 1; i <= n; i++, s++) { |
8261 | hook_data.section = i; |
8262 | |
8263 | source = grn_ctx_at(ctx, *s); |
8264 | if (!source) { |
8265 | ERRCLR(ctx); |
8266 | continue; |
8267 | } |
8268 | |
8269 | switch (source->header.type) { |
8270 | case GRN_TABLE_HASH_KEY : |
8271 | case GRN_TABLE_PAT_KEY : |
8272 | case GRN_TABLE_DAT_KEY : |
8273 | del_hook(ctx, source, GRN_HOOK_INSERT, &data); |
8274 | del_hook(ctx, source, GRN_HOOK_DELETE, &data); |
8275 | break; |
8276 | case GRN_COLUMN_FIX_SIZE : |
8277 | case GRN_COLUMN_VAR_SIZE : |
8278 | del_hook(ctx, source, GRN_HOOK_SET, &data); |
8279 | break; |
8280 | default : |
8281 | /* invalid target */ |
8282 | break; |
8283 | } |
8284 | } |
8285 | grn_obj_close(ctx, &data); |
8286 | } |
8287 | |
8288 | #define N_HOOK_ENTRIES 5 |
8289 | |
8290 | grn_rc |
8291 | grn_hook_pack(grn_ctx *ctx, grn_db_obj *obj, grn_obj *buf) |
8292 | { |
8293 | grn_rc rc; |
8294 | grn_hook_entry e; |
8295 | for (e = 0; e < N_HOOK_ENTRIES; e++) { |
8296 | grn_hook *hooks; |
8297 | for (hooks = obj->hooks[e]; hooks; hooks = hooks->next) { |
8298 | grn_id id = hooks->proc ? hooks->proc->obj.id : 0; |
8299 | if ((rc = grn_text_benc(ctx, buf, id + 1))) { goto exit; } |
8300 | if ((rc = grn_text_benc(ctx, buf, hooks->hld_size))) { goto exit; } |
8301 | if ((rc = grn_bulk_write(ctx, buf, (char *)GRN_NEXT_ADDR(hooks), hooks->hld_size))) { goto exit; } |
8302 | } |
8303 | if ((rc = grn_text_benc(ctx, buf, 0))) { goto exit; } |
8304 | } |
8305 | exit : |
8306 | return rc; |
8307 | } |
8308 | |
8309 | static grn_rc |
8310 | grn_hook_unpack(grn_ctx *ctx, grn_db_obj *obj, const char *buf, uint32_t buf_size) |
8311 | { |
8312 | grn_hook_entry e; |
8313 | const uint8_t *p = (uint8_t *)buf, *pe = p + buf_size; |
8314 | for (e = 0; e < N_HOOK_ENTRIES; e++) { |
8315 | grn_hook *new, **last = &obj->hooks[e]; |
8316 | for (;;) { |
8317 | grn_id id; |
8318 | uint32_t hld_size; |
8319 | GRN_B_DEC(id, p); |
8320 | if (!id--) { break; } |
8321 | if (p >= pe) { return GRN_FILE_CORRUPT; } |
8322 | GRN_B_DEC(hld_size, p); |
8323 | if (p >= pe) { return GRN_FILE_CORRUPT; } |
8324 | if (!(new = GRN_MALLOC(sizeof(grn_hook) + hld_size))) { |
8325 | return GRN_NO_MEMORY_AVAILABLE; |
8326 | } |
8327 | if (id) { |
8328 | new->proc = (grn_proc *)grn_ctx_at(ctx, id); |
8329 | if (!new->proc) { |
8330 | GRN_FREE(new); |
8331 | return ctx->rc; |
8332 | } |
8333 | } else { |
8334 | new->proc = NULL; |
8335 | } |
8336 | if ((new->hld_size = hld_size)) { |
8337 | grn_memcpy(GRN_NEXT_ADDR(new), p, hld_size); |
8338 | p += hld_size; |
8339 | } |
8340 | *last = new; |
8341 | last = &new->next; |
8342 | if (p >= pe) { return GRN_FILE_CORRUPT; } |
8343 | } |
8344 | *last = NULL; |
8345 | } |
8346 | return GRN_SUCCESS; |
8347 | } |
8348 | |
8349 | static void |
8350 | grn_token_filters_pack(grn_ctx *ctx, |
8351 | grn_obj *token_filters, |
8352 | grn_obj *buffer) |
8353 | { |
8354 | unsigned int i, n_token_filters; |
8355 | |
8356 | n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); |
8357 | for (i = 0; i < n_token_filters; i++) { |
8358 | grn_obj *token_filter = GRN_PTR_VALUE_AT(token_filters, i); |
8359 | grn_id token_filter_id; |
8360 | |
8361 | token_filter_id = grn_obj_id(ctx, token_filter); |
8362 | GRN_RECORD_PUT(ctx, buffer, token_filter_id); |
8363 | } |
8364 | } |
8365 | |
8366 | static grn_bool |
8367 | grn_obj_encoded_spec_equal(grn_ctx *ctx, |
8368 | grn_obj *encoded_spec1, |
8369 | grn_obj *encoded_spec2) |
8370 | { |
8371 | unsigned int i, n_elements; |
8372 | |
8373 | if (encoded_spec1->header.type != GRN_VECTOR) { |
8374 | return GRN_FALSE; |
8375 | } |
8376 | |
8377 | if (encoded_spec1->header.type != encoded_spec2->header.type) { |
8378 | return GRN_FALSE; |
8379 | } |
8380 | |
8381 | n_elements = grn_vector_size(ctx, encoded_spec1); |
8382 | if (grn_vector_size(ctx, encoded_spec2) != n_elements) { |
8383 | return GRN_FALSE; |
8384 | } |
8385 | |
8386 | for (i = 0; i < n_elements; i++) { |
8387 | const char *content1; |
8388 | const char *content2; |
8389 | unsigned int content_size1; |
8390 | unsigned int content_size2; |
8391 | unsigned int weight1; |
8392 | unsigned int weight2; |
8393 | grn_id domain1; |
8394 | grn_id domain2; |
8395 | |
8396 | content_size1 = grn_vector_get_element(ctx, |
8397 | encoded_spec1, |
8398 | i, |
8399 | &content1, |
8400 | &weight1, |
8401 | &domain1); |
8402 | content_size2 = grn_vector_get_element(ctx, |
8403 | encoded_spec2, |
8404 | i, |
8405 | &content2, |
8406 | &weight2, |
8407 | &domain2); |
8408 | if (content_size1 != content_size2) { |
8409 | return GRN_FALSE; |
8410 | } |
8411 | if (memcmp(content1, content2, content_size1) != 0) { |
8412 | return GRN_FALSE; |
8413 | } |
8414 | if (weight1 != weight2) { |
8415 | return GRN_FALSE; |
8416 | } |
8417 | if (domain1 != domain2) { |
8418 | return GRN_FALSE; |
8419 | } |
8420 | } |
8421 | |
8422 | return GRN_TRUE; |
8423 | } |
8424 | |
8425 | void |
8426 | grn_obj_spec_save(grn_ctx *ctx, grn_db_obj *obj) |
8427 | { |
8428 | grn_db *s; |
8429 | grn_obj v, *b; |
8430 | grn_obj_spec spec; |
8431 | grn_bool need_update = GRN_TRUE; |
8432 | |
8433 | if (obj->id & GRN_OBJ_TMP_OBJECT) { return; } |
8434 | if (!ctx->impl || !GRN_DB_OBJP(obj)) { return; } |
8435 | if (!(s = (grn_db *)ctx->impl->db) || !s->specs) { return; } |
8436 | if (obj->header.type == GRN_PROC && obj->range == GRN_ID_NIL) { |
8437 | return; |
8438 | } |
8439 | GRN_OBJ_INIT(&v, GRN_VECTOR, 0, GRN_DB_TEXT); |
8440 | if (!(b = grn_vector_body(ctx, &v))) { return; } |
8441 | spec.header = obj->header; |
8442 | spec.range = obj->range; |
8443 | grn_bulk_write(ctx, b, (void *)&spec, sizeof(grn_obj_spec)); |
8444 | grn_vector_delimit(ctx, &v, 0, 0); |
8445 | if (obj->header.flags & GRN_OBJ_CUSTOM_NAME) { |
8446 | GRN_TEXT_PUTS(ctx, b, grn_obj_path(ctx, (grn_obj *)obj)); |
8447 | } |
8448 | grn_vector_delimit(ctx, &v, 0, 0); |
8449 | grn_bulk_write(ctx, b, obj->source, obj->source_size); |
8450 | grn_vector_delimit(ctx, &v, 0, 0); |
8451 | grn_hook_pack(ctx, obj, b); |
8452 | grn_vector_delimit(ctx, &v, 0, 0); |
8453 | switch (obj->header.type) { |
8454 | case GRN_TABLE_HASH_KEY : |
8455 | grn_token_filters_pack(ctx, &(((grn_hash *)obj)->token_filters), b); |
8456 | grn_vector_delimit(ctx, &v, 0, 0); |
8457 | break; |
8458 | case GRN_TABLE_PAT_KEY : |
8459 | grn_token_filters_pack(ctx, &(((grn_pat *)obj)->token_filters), b); |
8460 | grn_vector_delimit(ctx, &v, 0, 0); |
8461 | break; |
8462 | case GRN_TABLE_DAT_KEY : |
8463 | grn_token_filters_pack(ctx, &(((grn_dat *)obj)->token_filters), b); |
8464 | grn_vector_delimit(ctx, &v, 0, 0); |
8465 | break; |
8466 | case GRN_EXPR : |
8467 | grn_expr_pack(ctx, b, (grn_obj *)obj); |
8468 | grn_vector_delimit(ctx, &v, 0, 0); |
8469 | break; |
8470 | } |
8471 | |
8472 | { |
8473 | grn_io_win jw; |
8474 | uint32_t current_spec_raw_len; |
8475 | char *current_spec_raw; |
8476 | |
8477 | current_spec_raw = grn_ja_ref(ctx, |
8478 | s->specs, |
8479 | obj->id, |
8480 | &jw, |
8481 | ¤t_spec_raw_len); |
8482 | if (current_spec_raw) { |
8483 | grn_rc rc; |
8484 | grn_obj current_spec; |
8485 | |
8486 | GRN_OBJ_INIT(¤t_spec, GRN_VECTOR, 0, GRN_DB_TEXT); |
8487 | rc = grn_vector_decode(ctx, |
8488 | ¤t_spec, |
8489 | current_spec_raw, |
8490 | current_spec_raw_len); |
8491 | if (rc == GRN_SUCCESS) { |
8492 | need_update = !grn_obj_encoded_spec_equal(ctx, &v, ¤t_spec); |
8493 | } |
8494 | GRN_OBJ_FIN(ctx, ¤t_spec); |
8495 | grn_ja_unref(ctx, &jw); |
8496 | } |
8497 | } |
8498 | |
8499 | if (!need_update) { |
8500 | grn_obj_close(ctx, &v); |
8501 | return; |
8502 | } |
8503 | |
8504 | { |
8505 | const char *name; |
8506 | uint32_t name_size = 0; |
8507 | const char *range_name = NULL; |
8508 | uint32_t range_name_size = 0; |
8509 | |
8510 | name = _grn_table_key(ctx, s->keys, obj->id, &name_size); |
8511 | switch (obj->header.type) { |
8512 | case GRN_TABLE_HASH_KEY : |
8513 | case GRN_TABLE_PAT_KEY : |
8514 | case GRN_TABLE_DAT_KEY : |
8515 | case GRN_TABLE_NO_KEY : |
8516 | case GRN_COLUMN_FIX_SIZE : |
8517 | case GRN_COLUMN_VAR_SIZE : |
8518 | case GRN_COLUMN_INDEX : |
8519 | if (obj->range != GRN_ID_NIL) { |
8520 | range_name = _grn_table_key(ctx, s->keys, obj->range, &range_name_size); |
8521 | } |
8522 | break; |
8523 | default : |
8524 | break; |
8525 | } |
8526 | /* TODO: reduce log level. */ |
8527 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
8528 | "spec:%u:update:%.*s:%u(%s):%u%s%.*s%s" , |
8529 | obj->id, |
8530 | name_size, name, |
8531 | obj->header.type, |
8532 | grn_obj_type_to_string(obj->header.type), |
8533 | obj->range, |
8534 | range_name_size == 0 ? "" : "(" , |
8535 | range_name_size, range_name, |
8536 | range_name_size == 0 ? "" : ")" ); |
8537 | } |
8538 | grn_ja_putv(ctx, s->specs, obj->id, &v, 0); |
8539 | grn_obj_close(ctx, &v); |
8540 | } |
8541 | |
8542 | inline static void |
8543 | grn_obj_set_info_source_invalid_lexicon_error(grn_ctx *ctx, |
8544 | const char *message, |
8545 | grn_obj *actual_type, |
8546 | grn_obj *expected_type, |
8547 | grn_obj *index_column, |
8548 | grn_obj *source) |
8549 | { |
8550 | char actual_type_name[GRN_TABLE_MAX_KEY_SIZE]; |
8551 | int actual_type_name_size; |
8552 | char expected_type_name[GRN_TABLE_MAX_KEY_SIZE]; |
8553 | int expected_type_name_size; |
8554 | char index_column_name[GRN_TABLE_MAX_KEY_SIZE]; |
8555 | int index_column_name_size; |
8556 | char source_name[GRN_TABLE_MAX_KEY_SIZE]; |
8557 | int source_name_size; |
8558 | |
8559 | actual_type_name_size = grn_obj_name(ctx, actual_type, |
8560 | actual_type_name, |
8561 | GRN_TABLE_MAX_KEY_SIZE); |
8562 | expected_type_name_size = grn_obj_name(ctx, expected_type, |
8563 | expected_type_name, |
8564 | GRN_TABLE_MAX_KEY_SIZE); |
8565 | index_column_name_size = grn_obj_name(ctx, index_column, |
8566 | index_column_name, |
8567 | GRN_TABLE_MAX_KEY_SIZE); |
8568 | |
8569 | source_name_size = grn_obj_name(ctx, source, |
8570 | source_name, GRN_TABLE_MAX_KEY_SIZE); |
8571 | if (grn_obj_is_table(ctx, source)) { |
8572 | source_name[source_name_size] = '\0'; |
8573 | grn_strncat(source_name, |
8574 | GRN_TABLE_MAX_KEY_SIZE, |
8575 | "._key" , |
8576 | GRN_TABLE_MAX_KEY_SIZE - source_name_size - 1); |
8577 | source_name_size = strlen(source_name); |
8578 | } |
8579 | |
8580 | ERR(GRN_INVALID_ARGUMENT, |
8581 | "[column][index][source] %s: " |
8582 | "<%.*s> -> <%.*s>: " |
8583 | "index-column:<%.*s> " |
8584 | "source:<%.*s>" , |
8585 | message, |
8586 | actual_type_name_size, actual_type_name, |
8587 | expected_type_name_size, expected_type_name, |
8588 | index_column_name_size, index_column_name, |
8589 | source_name_size, source_name); |
8590 | } |
8591 | |
8592 | inline static grn_rc |
8593 | grn_obj_set_info_source_validate(grn_ctx *ctx, grn_obj *obj, grn_obj *value) |
8594 | { |
8595 | grn_id lexicon_id; |
8596 | grn_obj *lexicon = NULL; |
8597 | grn_id lexicon_domain_id; |
8598 | grn_obj *lexicon_domain = NULL; |
8599 | grn_bool lexicon_domain_is_table; |
8600 | grn_bool lexicon_have_tokenizer; |
8601 | grn_id *source_ids; |
8602 | int i, n_source_ids; |
8603 | |
8604 | lexicon_id = obj->header.domain; |
8605 | lexicon = grn_ctx_at(ctx, lexicon_id); |
8606 | if (!lexicon) { |
8607 | goto exit; |
8608 | } |
8609 | |
8610 | lexicon_domain_id = lexicon->header.domain; |
8611 | lexicon_domain = grn_ctx_at(ctx, lexicon_domain_id); |
8612 | if (!lexicon_domain) { |
8613 | goto exit; |
8614 | } |
8615 | |
8616 | source_ids = (grn_id *)GRN_BULK_HEAD(value); |
8617 | n_source_ids = GRN_BULK_VSIZE(value) / sizeof(grn_id); |
8618 | if (n_source_ids > 1 && !(obj->header.flags & GRN_OBJ_WITH_SECTION)) { |
8619 | char index_name[GRN_TABLE_MAX_KEY_SIZE]; |
8620 | int index_name_size; |
8621 | index_name_size = grn_obj_name(ctx, obj, |
8622 | index_name, GRN_TABLE_MAX_KEY_SIZE); |
8623 | ERR(GRN_INVALID_ARGUMENT, |
8624 | "grn_obj_set_info(): GRN_INFO_SOURCE: " |
8625 | "multi column index must be created with WITH_SECTION flag: <%.*s>" , |
8626 | index_name_size, index_name); |
8627 | goto exit; |
8628 | } |
8629 | |
8630 | lexicon_domain_is_table = grn_obj_is_table(ctx, lexicon_domain); |
8631 | { |
8632 | grn_obj *tokenizer; |
8633 | grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL); |
8634 | lexicon_have_tokenizer = (tokenizer != NULL); |
8635 | } |
8636 | |
8637 | for (i = 0; i < n_source_ids; i++) { |
8638 | grn_id source_id = source_ids[i]; |
8639 | grn_obj *source; |
8640 | grn_id source_type_id; |
8641 | grn_obj *source_type; |
8642 | |
8643 | source = grn_ctx_at(ctx, source_id); |
8644 | if (!source) { |
8645 | continue; |
8646 | } |
8647 | if (grn_obj_is_table(ctx, source)) { |
8648 | source_type_id = source->header.domain; |
8649 | } else { |
8650 | source_type_id = DB_OBJ(source)->range; |
8651 | } |
8652 | source_type = grn_ctx_at(ctx, source_type_id); |
8653 | if (!lexicon_have_tokenizer) { |
8654 | if (grn_obj_is_table(ctx, source_type)) { |
8655 | if (lexicon_id != source_type_id) { |
8656 | grn_obj_set_info_source_invalid_lexicon_error( |
8657 | ctx, |
8658 | "index table must equal to source type" , |
8659 | lexicon, |
8660 | source_type, |
8661 | obj, |
8662 | source); |
8663 | } |
8664 | } else { |
8665 | if (!(lexicon_domain_id == source_type_id || |
8666 | (grn_type_id_is_text_family(ctx, lexicon_domain_id) && |
8667 | grn_type_id_is_text_family(ctx, source_type_id)))) { |
8668 | grn_obj_set_info_source_invalid_lexicon_error( |
8669 | ctx, |
8670 | "index table's key must equal source type" , |
8671 | lexicon_domain, |
8672 | source_type, |
8673 | obj, |
8674 | source); |
8675 | } |
8676 | } |
8677 | } |
8678 | grn_obj_unlink(ctx, source); |
8679 | if (ctx->rc != GRN_SUCCESS) { |
8680 | goto exit; |
8681 | } |
8682 | } |
8683 | |
8684 | exit: |
8685 | if (lexicon) { |
8686 | grn_obj_unlink(ctx, lexicon); |
8687 | } |
8688 | if (lexicon_domain) { |
8689 | grn_obj_unlink(ctx, lexicon_domain); |
8690 | } |
8691 | return ctx->rc; |
8692 | } |
8693 | |
8694 | inline static void |
8695 | grn_obj_set_info_source_log(grn_ctx *ctx, grn_obj *obj, grn_obj *value) |
8696 | { |
8697 | grn_obj buf; |
8698 | grn_id *vp = (grn_id *)GRN_BULK_HEAD(value); |
8699 | uint32_t vs = GRN_BULK_VSIZE(value), s = 0; |
8700 | grn_id id; |
8701 | const char *n; |
8702 | |
8703 | id = DB_OBJ(obj)->id; |
8704 | n = _grn_table_key(ctx, ctx->impl->db, id, &s); |
8705 | GRN_TEXT_INIT(&buf, 0); |
8706 | GRN_TEXT_PUT(ctx, &buf, n, s); |
8707 | GRN_TEXT_PUTC(ctx, &buf, ' '); |
8708 | while (vs) { |
8709 | n = _grn_table_key(ctx, ctx->impl->db, *vp++, &s); |
8710 | GRN_TEXT_PUT(ctx, &buf, n, s); |
8711 | vs -= sizeof(grn_id); |
8712 | if (vs) { GRN_TEXT_PUTC(ctx, &buf, ','); } |
8713 | } |
8714 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
8715 | "DDL:%u:set_source %.*s" , |
8716 | id, |
8717 | (int)GRN_BULK_VSIZE(&buf), GRN_BULK_HEAD(&buf)); |
8718 | GRN_OBJ_FIN(ctx, &buf); |
8719 | } |
8720 | |
8721 | inline static grn_rc |
8722 | grn_obj_set_info_source_update(grn_ctx *ctx, grn_obj *obj, grn_obj *value) |
8723 | { |
8724 | void *v = GRN_BULK_HEAD(value); |
8725 | uint32_t s = GRN_BULK_VSIZE(value); |
8726 | if (s) { |
8727 | void *v2 = GRN_MALLOC(s); |
8728 | if (!v2) { |
8729 | return ctx->rc; |
8730 | } |
8731 | grn_memcpy(v2, v, s); |
8732 | if (DB_OBJ(obj)->source) { GRN_FREE(DB_OBJ(obj)->source); } |
8733 | DB_OBJ(obj)->source = v2; |
8734 | DB_OBJ(obj)->source_size = s; |
8735 | |
8736 | if (obj->header.type == GRN_COLUMN_INDEX) { |
8737 | update_source_hook(ctx, obj); |
8738 | grn_index_column_build(ctx, obj); |
8739 | } |
8740 | } else { |
8741 | DB_OBJ(obj)->source = NULL; |
8742 | DB_OBJ(obj)->source_size = 0; |
8743 | } |
8744 | |
8745 | return GRN_SUCCESS; |
8746 | } |
8747 | |
8748 | inline static grn_rc |
8749 | grn_obj_set_info_source(grn_ctx *ctx, grn_obj *obj, grn_obj *value) |
8750 | { |
8751 | grn_rc rc; |
8752 | |
8753 | rc = grn_obj_set_info_source_validate(ctx, obj, value); |
8754 | if (rc != GRN_SUCCESS) { |
8755 | return rc; |
8756 | } |
8757 | grn_obj_set_info_source_log(ctx, obj, value); |
8758 | rc = grn_obj_set_info_source_update(ctx, obj, value); |
8759 | if (rc != GRN_SUCCESS) { |
8760 | return rc; |
8761 | } |
8762 | grn_obj_spec_save(ctx, DB_OBJ(obj)); |
8763 | |
8764 | return rc; |
8765 | } |
8766 | |
8767 | static grn_rc |
8768 | grn_obj_set_info_token_filters(grn_ctx *ctx, |
8769 | grn_obj *table, |
8770 | grn_obj *token_filters) |
8771 | { |
8772 | grn_obj *current_token_filters; |
8773 | unsigned int i, n_current_token_filters, n_token_filters; |
8774 | grn_obj token_filter_names; |
8775 | |
8776 | switch (table->header.type) { |
8777 | case GRN_TABLE_HASH_KEY : |
8778 | current_token_filters = &(((grn_hash *)table)->token_filters); |
8779 | break; |
8780 | case GRN_TABLE_PAT_KEY : |
8781 | current_token_filters = &(((grn_pat *)table)->token_filters); |
8782 | break; |
8783 | case GRN_TABLE_DAT_KEY : |
8784 | current_token_filters = &(((grn_dat *)table)->token_filters); |
8785 | break; |
8786 | default : |
8787 | /* TODO: Show type name instead of type ID */ |
8788 | ERR(GRN_INVALID_ARGUMENT, |
8789 | "[info][set][token-filters] target object must be one of " |
8790 | "GRN_TABLE_HASH_KEY, GRN_TABLE_PAT_KEY and GRN_TABLE_DAT_KEY: %d" , |
8791 | table->header.type); |
8792 | return ctx->rc; |
8793 | } |
8794 | |
8795 | n_current_token_filters = |
8796 | GRN_BULK_VSIZE(current_token_filters) / sizeof(grn_obj *); |
8797 | n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); |
8798 | |
8799 | GRN_TEXT_INIT(&token_filter_names, 0); |
8800 | GRN_BULK_REWIND(current_token_filters); |
8801 | for (i = 0; i < n_token_filters; i++) { |
8802 | grn_obj *token_filter = GRN_PTR_VALUE_AT(token_filters, i); |
8803 | char token_filter_name[GRN_TABLE_MAX_KEY_SIZE]; |
8804 | unsigned int token_filter_name_size; |
8805 | |
8806 | GRN_PTR_PUT(ctx, current_token_filters, token_filter); |
8807 | |
8808 | if (i > 0) { |
8809 | GRN_TEXT_PUTC(ctx, &token_filter_names, ','); |
8810 | } |
8811 | token_filter_name_size = grn_obj_name(ctx, |
8812 | token_filter, |
8813 | token_filter_name, |
8814 | GRN_TABLE_MAX_KEY_SIZE); |
8815 | GRN_TEXT_PUT(ctx, |
8816 | &token_filter_names, |
8817 | token_filter_name, |
8818 | token_filter_name_size); |
8819 | } |
8820 | if (n_token_filters > 0 || n_token_filters != n_current_token_filters) { |
8821 | GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:%u:set_token_filters %.*s" , |
8822 | DB_OBJ(table)->id, |
8823 | (int)GRN_BULK_VSIZE(&token_filter_names), |
8824 | GRN_BULK_HEAD(&token_filter_names)); |
8825 | } |
8826 | GRN_OBJ_FIN(ctx, &token_filter_names); |
8827 | grn_obj_spec_save(ctx, DB_OBJ(table)); |
8828 | |
8829 | return GRN_SUCCESS; |
8830 | } |
8831 | |
8832 | grn_rc |
8833 | grn_obj_set_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *value) |
8834 | { |
8835 | grn_rc rc = GRN_INVALID_ARGUMENT; |
8836 | GRN_API_ENTER; |
8837 | if (!obj) { |
8838 | ERR(GRN_INVALID_ARGUMENT, "grn_obj_set_info failed" ); |
8839 | goto exit; |
8840 | } |
8841 | switch (type) { |
8842 | case GRN_INFO_SOURCE : |
8843 | if (!GRN_DB_OBJP(obj)) { |
8844 | ERR(GRN_INVALID_ARGUMENT, "only db_obj can accept GRN_INFO_SOURCE" ); |
8845 | goto exit; |
8846 | } |
8847 | rc = grn_obj_set_info_source(ctx, obj, value); |
8848 | break; |
8849 | case GRN_INFO_DEFAULT_TOKENIZER : |
8850 | if (!value || DB_OBJ(value)->header.type == GRN_PROC) { |
8851 | switch (DB_OBJ(obj)->header.type) { |
8852 | case GRN_TABLE_HASH_KEY : |
8853 | ((grn_hash *)obj)->tokenizer = value; |
8854 | ((grn_hash *)obj)->header.common->tokenizer = grn_obj_id(ctx, value); |
8855 | rc = GRN_SUCCESS; |
8856 | break; |
8857 | case GRN_TABLE_PAT_KEY : |
8858 | ((grn_pat *)obj)->tokenizer = value; |
8859 | ((grn_pat *)obj)->header->tokenizer = grn_obj_id(ctx, value); |
8860 | rc = GRN_SUCCESS; |
8861 | break; |
8862 | case GRN_TABLE_DAT_KEY : |
8863 | ((grn_dat *)obj)->tokenizer = value; |
8864 | ((grn_dat *)obj)->header->tokenizer = grn_obj_id(ctx, value); |
8865 | rc = GRN_SUCCESS; |
8866 | break; |
8867 | } |
8868 | } |
8869 | break; |
8870 | case GRN_INFO_NORMALIZER : |
8871 | if (!value || DB_OBJ(value)->header.type == GRN_PROC) { |
8872 | switch (DB_OBJ(obj)->header.type) { |
8873 | case GRN_TABLE_HASH_KEY : |
8874 | ((grn_hash *)obj)->normalizer = value; |
8875 | ((grn_hash *)obj)->header.common->normalizer = grn_obj_id(ctx, value); |
8876 | rc = GRN_SUCCESS; |
8877 | break; |
8878 | case GRN_TABLE_PAT_KEY : |
8879 | ((grn_pat *)obj)->normalizer = value; |
8880 | ((grn_pat *)obj)->header->normalizer = grn_obj_id(ctx, value); |
8881 | rc = GRN_SUCCESS; |
8882 | break; |
8883 | case GRN_TABLE_DAT_KEY : |
8884 | ((grn_dat *)obj)->normalizer = value; |
8885 | ((grn_dat *)obj)->header->normalizer = grn_obj_id(ctx, value); |
8886 | rc = GRN_SUCCESS; |
8887 | break; |
8888 | } |
8889 | } |
8890 | break; |
8891 | case GRN_INFO_TOKEN_FILTERS : |
8892 | rc = grn_obj_set_info_token_filters(ctx, obj, value); |
8893 | break; |
8894 | default : |
8895 | /* todo */ |
8896 | break; |
8897 | } |
8898 | exit : |
8899 | GRN_API_RETURN(rc); |
8900 | } |
8901 | |
8902 | grn_obj * |
8903 | grn_obj_get_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id, |
8904 | grn_info_type type, grn_obj *valuebuf) |
8905 | { |
8906 | GRN_API_ENTER; |
8907 | GRN_API_RETURN(valuebuf); |
8908 | } |
8909 | |
8910 | grn_rc |
8911 | grn_obj_set_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id, |
8912 | grn_info_type type, grn_obj *value) |
8913 | { |
8914 | GRN_API_ENTER; |
8915 | GRN_API_RETURN(GRN_SUCCESS); |
8916 | } |
8917 | |
8918 | static void |
8919 | grn_hook_free(grn_ctx *ctx, grn_hook *h) |
8920 | { |
8921 | grn_hook *curr, *next; |
8922 | for (curr = h; curr; curr = next) { |
8923 | next = curr->next; |
8924 | GRN_FREE(curr); |
8925 | } |
8926 | } |
8927 | |
8928 | grn_rc |
8929 | grn_obj_add_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, |
8930 | int offset, grn_obj *proc, grn_obj *hld) |
8931 | { |
8932 | grn_rc rc = GRN_SUCCESS; |
8933 | GRN_API_ENTER; |
8934 | if (!GRN_DB_OBJP(obj)) { |
8935 | rc = GRN_INVALID_ARGUMENT; |
8936 | } else { |
8937 | int i; |
8938 | void *hld_value = NULL; |
8939 | uint32_t hld_size = 0; |
8940 | grn_hook *new, **last = &DB_OBJ(obj)->hooks[entry]; |
8941 | if (hld) { |
8942 | hld_value = GRN_BULK_HEAD(hld); |
8943 | hld_size = GRN_BULK_VSIZE(hld); |
8944 | } |
8945 | if (!(new = GRN_MALLOC(sizeof(grn_hook) + hld_size))) { |
8946 | rc = GRN_NO_MEMORY_AVAILABLE; |
8947 | goto exit; |
8948 | } |
8949 | new->proc = (grn_proc *)proc; |
8950 | new->hld_size = hld_size; |
8951 | if (hld_size) { |
8952 | grn_memcpy(GRN_NEXT_ADDR(new), hld_value, hld_size); |
8953 | } |
8954 | for (i = 0; i != offset && *last; i++) { last = &(*last)->next; } |
8955 | new->next = *last; |
8956 | *last = new; |
8957 | grn_obj_spec_save(ctx, DB_OBJ(obj)); |
8958 | } |
8959 | exit : |
8960 | GRN_API_RETURN(rc); |
8961 | } |
8962 | |
8963 | int |
8964 | grn_obj_get_nhooks(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry) |
8965 | { |
8966 | int res = 0; |
8967 | GRN_API_ENTER; |
8968 | { |
8969 | grn_hook *hook = DB_OBJ(obj)->hooks[entry]; |
8970 | while (hook) { |
8971 | res++; |
8972 | hook = hook->next; |
8973 | } |
8974 | } |
8975 | GRN_API_RETURN(res); |
8976 | } |
8977 | |
8978 | grn_obj * |
8979 | grn_obj_get_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, |
8980 | int offset, grn_obj *hldbuf) |
8981 | { |
8982 | grn_obj *res = NULL; |
8983 | GRN_API_ENTER; |
8984 | { |
8985 | int i; |
8986 | grn_hook *hook = DB_OBJ(obj)->hooks[entry]; |
8987 | for (i = 0; i < offset; i++) { |
8988 | hook = hook->next; |
8989 | if (!hook) { return NULL; } |
8990 | } |
8991 | res = (grn_obj *)hook->proc; |
8992 | grn_bulk_write(ctx, hldbuf, (char *)GRN_NEXT_ADDR(hook), hook->hld_size); |
8993 | } |
8994 | GRN_API_RETURN(res); |
8995 | } |
8996 | |
8997 | grn_rc |
8998 | grn_obj_delete_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, int offset) |
8999 | { |
9000 | GRN_API_ENTER; |
9001 | { |
9002 | int i = 0; |
9003 | grn_hook *h, **last = &DB_OBJ(obj)->hooks[entry]; |
9004 | for (;;) { |
9005 | if (!(h = *last)) { return GRN_INVALID_ARGUMENT; } |
9006 | if (++i > offset) { break; } |
9007 | last = &h->next; |
9008 | } |
9009 | *last = h->next; |
9010 | GRN_FREE(h); |
9011 | } |
9012 | grn_obj_spec_save(ctx, DB_OBJ(obj)); |
9013 | GRN_API_RETURN(GRN_SUCCESS); |
9014 | } |
9015 | |
9016 | static grn_rc |
9017 | remove_index(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry) |
9018 | { |
9019 | grn_rc rc = GRN_SUCCESS; |
9020 | grn_hook *h0, *hooks = DB_OBJ(obj)->hooks[entry]; |
9021 | DB_OBJ(obj)->hooks[entry] = NULL; /* avoid mutual recursive call */ |
9022 | while (hooks) { |
9023 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
9024 | grn_obj *target = grn_ctx_at(ctx, data->target); |
9025 | if (!target) { |
9026 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
9027 | int length; |
9028 | char hook_name[GRN_TABLE_MAX_KEY_SIZE]; |
9029 | int hook_name_length; |
9030 | |
9031 | length = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE); |
9032 | hook_name_length = grn_table_get_key(ctx, |
9033 | ctx->impl->db, |
9034 | data->target, |
9035 | hook_name, |
9036 | GRN_TABLE_MAX_KEY_SIZE); |
9037 | ERR(GRN_OBJECT_CORRUPT, |
9038 | "[column][remove][index] " |
9039 | "hook has a dangling reference: <%.*s> -> <%.*s>" , |
9040 | length, name, |
9041 | hook_name_length, hook_name); |
9042 | rc = ctx->rc; |
9043 | } else if (target->header.type == GRN_COLUMN_INDEX) { |
9044 | //TODO: multicolumn MULTI_COLUMN_INDEXP |
9045 | rc = _grn_obj_remove(ctx, target, GRN_FALSE); |
9046 | } else { |
9047 | //TODO: err |
9048 | char fn[GRN_TABLE_MAX_KEY_SIZE]; |
9049 | int flen; |
9050 | flen = grn_obj_name(ctx, target, fn, GRN_TABLE_MAX_KEY_SIZE); |
9051 | fn[flen] = '\0'; |
9052 | ERR(GRN_UNKNOWN_ERROR, "column has unsupported hooks, col=%s" ,fn); |
9053 | rc = ctx->rc; |
9054 | } |
9055 | if (rc != GRN_SUCCESS) { |
9056 | DB_OBJ(obj)->hooks[entry] = hooks; |
9057 | break; |
9058 | } |
9059 | h0 = hooks; |
9060 | hooks = hooks->next; |
9061 | GRN_FREE(h0); |
9062 | } |
9063 | return rc; |
9064 | } |
9065 | |
9066 | static grn_rc |
9067 | remove_columns(grn_ctx *ctx, grn_obj *obj) |
9068 | { |
9069 | grn_rc rc = GRN_SUCCESS; |
9070 | grn_hash *cols; |
9071 | if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
9072 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { |
9073 | if (grn_table_columns(ctx, obj, "" , 0, (grn_obj *)cols)) { |
9074 | GRN_HASH_EACH_BEGIN(ctx, cols, cursor, id) { |
9075 | grn_id *key; |
9076 | grn_obj *col; |
9077 | |
9078 | grn_hash_cursor_get_key(ctx, cursor, (void **)&key); |
9079 | col = grn_ctx_at(ctx, *key); |
9080 | |
9081 | if (!col) { |
9082 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
9083 | int name_size; |
9084 | name_size = grn_table_get_key(ctx, ctx->impl->db, *key, |
9085 | name, GRN_TABLE_MAX_KEY_SIZE); |
9086 | if (ctx->rc == GRN_SUCCESS) { |
9087 | ERR(GRN_INVALID_ARGUMENT, |
9088 | "[object][remove] column is broken: <%.*s>" , |
9089 | name_size, name); |
9090 | } else { |
9091 | ERR(ctx->rc, |
9092 | "[object][remove] column is broken: <%.*s>: %s" , |
9093 | name_size, name, |
9094 | ctx->errbuf); |
9095 | } |
9096 | rc = ctx->rc; |
9097 | break; |
9098 | } |
9099 | |
9100 | rc = _grn_obj_remove(ctx, col, GRN_FALSE); |
9101 | if (rc != GRN_SUCCESS) { |
9102 | grn_obj_unlink(ctx, col); |
9103 | break; |
9104 | } |
9105 | } GRN_HASH_EACH_END(ctx, cursor); |
9106 | } |
9107 | grn_hash_close(ctx, cols); |
9108 | } |
9109 | return rc; |
9110 | } |
9111 | |
9112 | static grn_rc |
9113 | _grn_obj_remove_db_index_columns(grn_ctx *ctx, grn_obj *db) |
9114 | { |
9115 | grn_rc rc = GRN_SUCCESS; |
9116 | grn_table_cursor *cur; |
9117 | if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) { |
9118 | grn_id id; |
9119 | while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { |
9120 | grn_obj *obj = grn_ctx_at(ctx, id); |
9121 | if (obj && obj->header.type == GRN_COLUMN_INDEX) { |
9122 | rc = _grn_obj_remove(ctx, obj, GRN_FALSE); |
9123 | if (rc != GRN_SUCCESS) { |
9124 | grn_obj_unlink(ctx, obj); |
9125 | break; |
9126 | } |
9127 | } |
9128 | } |
9129 | grn_table_cursor_close(ctx, cur); |
9130 | } |
9131 | return rc; |
9132 | } |
9133 | |
9134 | static grn_rc |
9135 | _grn_obj_remove_db_reference_columns(grn_ctx *ctx, grn_obj *db) |
9136 | { |
9137 | grn_rc rc = GRN_SUCCESS; |
9138 | grn_table_cursor *cur; |
9139 | if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) { |
9140 | grn_id id; |
9141 | while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { |
9142 | grn_obj *obj = grn_ctx_at(ctx, id); |
9143 | grn_obj *range = NULL; |
9144 | |
9145 | if (!obj) { |
9146 | continue; |
9147 | } |
9148 | |
9149 | switch (obj->header.type) { |
9150 | case GRN_COLUMN_FIX_SIZE : |
9151 | case GRN_COLUMN_VAR_SIZE : |
9152 | if (!DB_OBJ(obj)->range) { |
9153 | break; |
9154 | } |
9155 | |
9156 | range = grn_ctx_at(ctx, DB_OBJ(obj)->range); |
9157 | if (!range) { |
9158 | break; |
9159 | } |
9160 | |
9161 | switch (range->header.type) { |
9162 | case GRN_TABLE_NO_KEY : |
9163 | case GRN_TABLE_HASH_KEY : |
9164 | case GRN_TABLE_PAT_KEY : |
9165 | case GRN_TABLE_DAT_KEY : |
9166 | rc = _grn_obj_remove(ctx, obj, GRN_FALSE); |
9167 | break; |
9168 | } |
9169 | break; |
9170 | } |
9171 | |
9172 | if (rc != GRN_SUCCESS) { |
9173 | break; |
9174 | } |
9175 | } |
9176 | grn_table_cursor_close(ctx, cur); |
9177 | } |
9178 | return rc; |
9179 | } |
9180 | |
9181 | static grn_rc |
9182 | _grn_obj_remove_db_reference_tables(grn_ctx *ctx, grn_obj *db) |
9183 | { |
9184 | grn_rc rc = GRN_SUCCESS; |
9185 | grn_table_cursor *cur; |
9186 | if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) { |
9187 | grn_id id; |
9188 | while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { |
9189 | grn_obj *obj = grn_ctx_at(ctx, id); |
9190 | grn_obj *domain = NULL; |
9191 | |
9192 | if (!obj) { |
9193 | continue; |
9194 | } |
9195 | |
9196 | switch (obj->header.type) { |
9197 | case GRN_TABLE_HASH_KEY : |
9198 | case GRN_TABLE_PAT_KEY : |
9199 | case GRN_TABLE_DAT_KEY : |
9200 | if (!obj->header.domain) { |
9201 | break; |
9202 | } |
9203 | |
9204 | domain = grn_ctx_at(ctx, obj->header.domain); |
9205 | if (!domain) { |
9206 | break; |
9207 | } |
9208 | |
9209 | switch (domain->header.type) { |
9210 | case GRN_TABLE_NO_KEY : |
9211 | case GRN_TABLE_HASH_KEY : |
9212 | case GRN_TABLE_PAT_KEY : |
9213 | case GRN_TABLE_DAT_KEY : |
9214 | rc = _grn_obj_remove(ctx, obj, GRN_FALSE); |
9215 | break; |
9216 | } |
9217 | break; |
9218 | } |
9219 | |
9220 | if (rc != GRN_SUCCESS) { |
9221 | break; |
9222 | } |
9223 | } |
9224 | grn_table_cursor_close(ctx, cur); |
9225 | } |
9226 | return rc; |
9227 | } |
9228 | |
9229 | static grn_rc |
9230 | _grn_obj_remove_db_all_tables(grn_ctx *ctx, grn_obj *db) |
9231 | { |
9232 | grn_rc rc = GRN_SUCCESS; |
9233 | grn_table_cursor *cur; |
9234 | if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) { |
9235 | grn_id id; |
9236 | while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { |
9237 | grn_obj *obj = grn_ctx_at(ctx, id); |
9238 | |
9239 | if (!obj) { |
9240 | continue; |
9241 | } |
9242 | |
9243 | switch (obj->header.type) { |
9244 | case GRN_TABLE_NO_KEY : |
9245 | case GRN_TABLE_HASH_KEY : |
9246 | case GRN_TABLE_PAT_KEY : |
9247 | case GRN_TABLE_DAT_KEY : |
9248 | rc = _grn_obj_remove(ctx, obj, GRN_FALSE); |
9249 | break; |
9250 | } |
9251 | |
9252 | if (rc != GRN_SUCCESS) { |
9253 | break; |
9254 | } |
9255 | } |
9256 | grn_table_cursor_close(ctx, cur); |
9257 | } |
9258 | return rc; |
9259 | } |
9260 | |
9261 | static grn_rc |
9262 | _grn_obj_remove_db(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9263 | const char *path) |
9264 | { |
9265 | grn_rc rc = GRN_SUCCESS; |
9266 | const char *io_spath; |
9267 | char *spath; |
9268 | grn_db *s = (grn_db *)db; |
9269 | unsigned char key_type; |
9270 | |
9271 | rc = _grn_obj_remove_db_index_columns(ctx, db); |
9272 | if (rc != GRN_SUCCESS) { return rc; } |
9273 | rc = _grn_obj_remove_db_reference_columns(ctx, db); |
9274 | if (rc != GRN_SUCCESS) { return rc; } |
9275 | rc = _grn_obj_remove_db_reference_tables(ctx, db); |
9276 | if (rc != GRN_SUCCESS) { return rc; } |
9277 | rc = _grn_obj_remove_db_all_tables(ctx, db); |
9278 | if (rc != GRN_SUCCESS) { return rc; } |
9279 | |
9280 | if (s->specs && |
9281 | (io_spath = grn_obj_path(ctx, (grn_obj *)s->specs)) && *io_spath != '\0') { |
9282 | if (!(spath = GRN_STRDUP(io_spath))) { |
9283 | ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>" , io_spath); |
9284 | return ctx->rc; |
9285 | } |
9286 | } else { |
9287 | spath = NULL; |
9288 | } |
9289 | |
9290 | key_type = s->keys->header.type; |
9291 | |
9292 | rc = grn_obj_close(ctx, obj); |
9293 | if (rc != GRN_SUCCESS) { |
9294 | if (spath) { |
9295 | GRN_FREE(spath); |
9296 | } |
9297 | return rc; |
9298 | } |
9299 | |
9300 | if (spath) { |
9301 | rc = grn_ja_remove(ctx, spath); |
9302 | GRN_FREE(spath); |
9303 | if (rc != GRN_SUCCESS) { return rc; } |
9304 | } |
9305 | |
9306 | if (path) { |
9307 | switch (key_type) { |
9308 | case GRN_TABLE_PAT_KEY : |
9309 | rc = grn_pat_remove(ctx, path); |
9310 | break; |
9311 | case GRN_TABLE_DAT_KEY : |
9312 | rc = grn_dat_remove(ctx, path); |
9313 | break; |
9314 | } |
9315 | if (rc == GRN_SUCCESS) { |
9316 | rc = grn_db_config_remove(ctx, path); |
9317 | } else { |
9318 | grn_db_config_remove(ctx, path); |
9319 | } |
9320 | } |
9321 | |
9322 | return rc; |
9323 | } |
9324 | |
9325 | static grn_rc |
9326 | remove_reference_tables(grn_ctx *ctx, grn_obj *table, grn_obj *db) |
9327 | { |
9328 | grn_rc rc = GRN_SUCCESS; |
9329 | grn_bool is_close_opened_object_mode = GRN_FALSE; |
9330 | grn_id table_id; |
9331 | char table_name[GRN_TABLE_MAX_KEY_SIZE]; |
9332 | int table_name_size; |
9333 | grn_table_cursor *cursor; |
9334 | |
9335 | if (grn_thread_get_limit() == 1) { |
9336 | is_close_opened_object_mode = GRN_TRUE; |
9337 | } |
9338 | |
9339 | table_id = DB_OBJ(table)->id; |
9340 | table_name_size = grn_obj_name(ctx, table, table_name, GRN_TABLE_MAX_KEY_SIZE); |
9341 | if ((cursor = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, |
9342 | GRN_CURSOR_BY_ID))) { |
9343 | grn_id id; |
9344 | while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { |
9345 | grn_obj *object; |
9346 | grn_bool is_removed = GRN_FALSE; |
9347 | |
9348 | if (is_close_opened_object_mode) { |
9349 | grn_ctx_push_temporary_open_space(ctx); |
9350 | } |
9351 | |
9352 | object = grn_ctx_at(ctx, id); |
9353 | if (!object) { |
9354 | ERRCLR(ctx); |
9355 | if (is_close_opened_object_mode) { |
9356 | grn_ctx_pop_temporary_open_space(ctx); |
9357 | } |
9358 | continue; |
9359 | } |
9360 | |
9361 | switch (object->header.type) { |
9362 | case GRN_TABLE_HASH_KEY : |
9363 | case GRN_TABLE_PAT_KEY : |
9364 | case GRN_TABLE_DAT_KEY : |
9365 | if (DB_OBJ(object)->id == table_id) { |
9366 | break; |
9367 | } |
9368 | |
9369 | if (object->header.domain == table_id) { |
9370 | rc = _grn_obj_remove(ctx, object, GRN_TRUE); |
9371 | is_removed = (grn_table_at(ctx, db, id) == GRN_ID_NIL); |
9372 | } |
9373 | break; |
9374 | case GRN_TABLE_NO_KEY : |
9375 | break; |
9376 | case GRN_COLUMN_VAR_SIZE : |
9377 | case GRN_COLUMN_FIX_SIZE : |
9378 | if (object->header.domain == table_id) { |
9379 | break; |
9380 | } |
9381 | if (DB_OBJ(object)->range == table_id) { |
9382 | rc = _grn_obj_remove(ctx, object, GRN_FALSE); |
9383 | is_removed = (grn_table_at(ctx, db, id) == GRN_ID_NIL); |
9384 | } |
9385 | break; |
9386 | case GRN_COLUMN_INDEX : |
9387 | break; |
9388 | default: |
9389 | break; |
9390 | } |
9391 | |
9392 | if (!is_removed) { |
9393 | grn_obj_unlink(ctx, object); |
9394 | } |
9395 | |
9396 | if (is_close_opened_object_mode) { |
9397 | grn_ctx_pop_temporary_open_space(ctx); |
9398 | } |
9399 | |
9400 | if (rc != GRN_SUCCESS) { |
9401 | break; |
9402 | } |
9403 | } |
9404 | grn_table_cursor_close(ctx, cursor); |
9405 | } |
9406 | |
9407 | return rc; |
9408 | } |
9409 | |
9410 | static grn_bool |
9411 | is_removable_table(grn_ctx *ctx, grn_obj *table, grn_obj *db) |
9412 | { |
9413 | grn_id table_id; |
9414 | grn_id reference_object_id; |
9415 | |
9416 | table_id = DB_OBJ(table)->id; |
9417 | if (table_id & GRN_OBJ_TMP_OBJECT) { |
9418 | return GRN_TRUE; |
9419 | } |
9420 | |
9421 | reference_object_id = grn_table_find_reference_object(ctx, table); |
9422 | if (reference_object_id == GRN_ID_NIL) { |
9423 | return GRN_TRUE; |
9424 | } |
9425 | |
9426 | { |
9427 | grn_obj *db; |
9428 | const char *table_name; |
9429 | int table_name_size; |
9430 | grn_obj *reference_object; |
9431 | const char *reference_object_name; |
9432 | int reference_object_name_size; |
9433 | |
9434 | db = grn_ctx_db(ctx); |
9435 | |
9436 | table_name = _grn_table_key(ctx, db, table_id,&table_name_size); |
9437 | |
9438 | reference_object = grn_ctx_at(ctx, reference_object_id); |
9439 | reference_object_name = _grn_table_key(ctx, |
9440 | db, |
9441 | reference_object_id, |
9442 | &reference_object_name_size); |
9443 | if (reference_object) { |
9444 | if (grn_obj_is_table(ctx, reference_object)) { |
9445 | ERR(GRN_OPERATION_NOT_PERMITTED, |
9446 | "[table][remove] a table that references the table exists: " |
9447 | "<%.*s._key> -> <%.*s>" , |
9448 | reference_object_name_size, reference_object_name, |
9449 | table_name_size, table_name); |
9450 | } else { |
9451 | ERR(GRN_OPERATION_NOT_PERMITTED, |
9452 | "[table][remove] a column that references the table exists: " |
9453 | "<%.*s> -> <%.*s>" , |
9454 | reference_object_name_size, reference_object_name, |
9455 | table_name_size, table_name); |
9456 | } |
9457 | } else { |
9458 | ERR(GRN_OPERATION_NOT_PERMITTED, |
9459 | "[table][remove] a dangling object that references the table exists: " |
9460 | "<%.*s(%u)> -> <%.*s>" , |
9461 | reference_object_name_size, |
9462 | reference_object_name, |
9463 | reference_object_id, |
9464 | table_name_size, table_name); |
9465 | } |
9466 | } |
9467 | |
9468 | return GRN_FALSE; |
9469 | } |
9470 | |
9471 | static inline grn_rc |
9472 | _grn_obj_remove_spec(grn_ctx *ctx, grn_obj *db, grn_id id, uint8_t type) |
9473 | { |
9474 | const char *name; |
9475 | uint32_t name_size = 0; |
9476 | |
9477 | name = _grn_table_key(ctx, db, id, &name_size); |
9478 | /* TODO: reduce log level. */ |
9479 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
9480 | "spec:%u:remove:%.*s:%u(%s)" , |
9481 | id, |
9482 | name_size, name, |
9483 | type, |
9484 | grn_obj_type_to_string(type)); |
9485 | |
9486 | return grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL); |
9487 | } |
9488 | |
9489 | static grn_rc |
9490 | _grn_obj_remove_pat(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9491 | const char *path, grn_bool dependent) |
9492 | { |
9493 | grn_rc rc = GRN_SUCCESS; |
9494 | uint8_t type; |
9495 | |
9496 | type = obj->header.type; |
9497 | |
9498 | if (dependent) { |
9499 | rc = remove_reference_tables(ctx, obj, db); |
9500 | if (rc != GRN_SUCCESS) { |
9501 | return rc; |
9502 | } |
9503 | } else { |
9504 | if (!is_removable_table(ctx, obj, db)) { |
9505 | return ctx->rc; |
9506 | } |
9507 | } |
9508 | |
9509 | rc = remove_index(ctx, obj, GRN_HOOK_INSERT); |
9510 | if (rc != GRN_SUCCESS) { return rc; } |
9511 | rc = remove_columns(ctx, obj); |
9512 | if (rc != GRN_SUCCESS) { return rc; } |
9513 | |
9514 | rc = grn_obj_close(ctx, obj); |
9515 | if (rc != GRN_SUCCESS) { return rc; } |
9516 | |
9517 | if (path) { |
9518 | rc = grn_pat_remove(ctx, path); |
9519 | if (rc != GRN_SUCCESS) { return rc; } |
9520 | rc = _grn_obj_remove_spec(ctx, db, id, type); |
9521 | if (rc != GRN_SUCCESS) { return rc; } |
9522 | rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
9523 | if (rc != GRN_SUCCESS) { return rc; } |
9524 | } |
9525 | |
9526 | grn_obj_touch(ctx, db, NULL); |
9527 | |
9528 | return rc; |
9529 | } |
9530 | |
9531 | static grn_rc |
9532 | _grn_obj_remove_dat(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9533 | const char *path, grn_bool dependent) |
9534 | { |
9535 | grn_rc rc = GRN_SUCCESS; |
9536 | uint8_t type; |
9537 | |
9538 | type = obj->header.type; |
9539 | |
9540 | if (dependent) { |
9541 | rc = remove_reference_tables(ctx, obj, db); |
9542 | if (rc != GRN_SUCCESS) { |
9543 | return rc; |
9544 | } |
9545 | } else { |
9546 | if (!is_removable_table(ctx, obj, db)) { |
9547 | return ctx->rc; |
9548 | } |
9549 | } |
9550 | |
9551 | rc = remove_index(ctx, obj, GRN_HOOK_INSERT); |
9552 | if (rc != GRN_SUCCESS) { return rc; } |
9553 | rc = remove_columns(ctx, obj); |
9554 | if (rc != GRN_SUCCESS) { return rc; } |
9555 | |
9556 | rc = grn_obj_close(ctx, obj); |
9557 | if (rc != GRN_SUCCESS) { return rc; } |
9558 | |
9559 | if (path) { |
9560 | rc = grn_dat_remove(ctx, path); |
9561 | if (rc != GRN_SUCCESS) { return rc; } |
9562 | rc = _grn_obj_remove_spec(ctx, db, id, type); |
9563 | if (rc != GRN_SUCCESS) { return rc; } |
9564 | rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
9565 | if (rc != GRN_SUCCESS) { return rc; } |
9566 | } |
9567 | |
9568 | grn_obj_touch(ctx, db, NULL); |
9569 | |
9570 | return rc; |
9571 | } |
9572 | |
9573 | static grn_rc |
9574 | _grn_obj_remove_hash(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9575 | const char *path, grn_bool dependent) |
9576 | { |
9577 | grn_rc rc = GRN_SUCCESS; |
9578 | uint8_t type; |
9579 | |
9580 | type = obj->header.type; |
9581 | |
9582 | if (dependent) { |
9583 | rc = remove_reference_tables(ctx, obj, db); |
9584 | if (rc != GRN_SUCCESS) { |
9585 | return rc; |
9586 | } |
9587 | } else { |
9588 | if (!is_removable_table(ctx, obj, db)) { |
9589 | return ctx->rc; |
9590 | } |
9591 | } |
9592 | |
9593 | rc = remove_index(ctx, obj, GRN_HOOK_INSERT); |
9594 | if (rc != GRN_SUCCESS) { return rc; } |
9595 | rc = remove_columns(ctx, obj); |
9596 | if (rc != GRN_SUCCESS) { return rc; } |
9597 | |
9598 | rc = grn_obj_close(ctx, obj); |
9599 | if (rc != GRN_SUCCESS) { return rc; } |
9600 | |
9601 | if (path) { |
9602 | rc = grn_hash_remove(ctx, path); |
9603 | if (rc != GRN_SUCCESS) { return rc; } |
9604 | rc = _grn_obj_remove_spec(ctx, db, id, type); |
9605 | if (rc != GRN_SUCCESS) { return rc; } |
9606 | rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
9607 | if (rc != GRN_SUCCESS) { return rc; } |
9608 | } |
9609 | |
9610 | grn_obj_touch(ctx, db, NULL); |
9611 | |
9612 | return rc; |
9613 | } |
9614 | |
9615 | static grn_rc |
9616 | _grn_obj_remove_array(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9617 | const char *path, grn_bool dependent) |
9618 | { |
9619 | grn_rc rc = GRN_SUCCESS; |
9620 | uint8_t type; |
9621 | |
9622 | type = obj->header.type; |
9623 | |
9624 | if (dependent) { |
9625 | rc = remove_reference_tables(ctx, obj, db); |
9626 | if (rc != GRN_SUCCESS) { |
9627 | return rc; |
9628 | } |
9629 | } else { |
9630 | if (!is_removable_table(ctx, obj, db)) { |
9631 | return ctx->rc; |
9632 | } |
9633 | } |
9634 | |
9635 | rc = remove_columns(ctx, obj); |
9636 | if (rc != GRN_SUCCESS) { return rc; } |
9637 | |
9638 | rc = grn_obj_close(ctx, obj); |
9639 | if (rc != GRN_SUCCESS) { return rc; } |
9640 | |
9641 | if (path) { |
9642 | rc = grn_array_remove(ctx, path); |
9643 | if (rc != GRN_SUCCESS) { return rc; } |
9644 | rc = _grn_obj_remove_spec(ctx, db, id, type); |
9645 | if (rc != GRN_SUCCESS) { return rc; } |
9646 | rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
9647 | if (rc != GRN_SUCCESS) { return rc; } |
9648 | } |
9649 | |
9650 | grn_obj_touch(ctx, db, NULL); |
9651 | |
9652 | return rc; |
9653 | } |
9654 | |
9655 | static grn_rc |
9656 | _grn_obj_remove_ja(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9657 | const char *path) |
9658 | { |
9659 | grn_rc rc = GRN_SUCCESS; |
9660 | uint8_t type; |
9661 | |
9662 | type = obj->header.type; |
9663 | |
9664 | rc = remove_index(ctx, obj, GRN_HOOK_SET); |
9665 | if (rc != GRN_SUCCESS) { return rc; } |
9666 | rc = grn_obj_close(ctx, obj); |
9667 | if (rc != GRN_SUCCESS) { return rc; } |
9668 | |
9669 | if (path) { |
9670 | rc = grn_ja_remove(ctx, path); |
9671 | if (rc != GRN_SUCCESS) { return rc; } |
9672 | rc = _grn_obj_remove_spec(ctx, db, id, type); |
9673 | if (rc != GRN_SUCCESS) { return rc; } |
9674 | rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
9675 | if (rc != GRN_SUCCESS) { return rc; } |
9676 | } |
9677 | |
9678 | grn_obj_touch(ctx, db, NULL); |
9679 | |
9680 | return rc; |
9681 | } |
9682 | |
9683 | static grn_rc |
9684 | _grn_obj_remove_ra(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9685 | const char *path) |
9686 | { |
9687 | grn_rc rc = GRN_SUCCESS; |
9688 | uint8_t type; |
9689 | |
9690 | type = obj->header.type; |
9691 | |
9692 | rc = remove_index(ctx, obj, GRN_HOOK_SET); |
9693 | if (rc != GRN_SUCCESS) { return rc; } |
9694 | rc = grn_obj_close(ctx, obj); |
9695 | if (rc != GRN_SUCCESS) { return rc; } |
9696 | |
9697 | if (path) { |
9698 | rc = grn_ra_remove(ctx, path); |
9699 | if (rc != GRN_SUCCESS) { return rc; } |
9700 | rc = _grn_obj_remove_spec(ctx, db, id, type); |
9701 | if (rc != GRN_SUCCESS) { return rc; } |
9702 | rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
9703 | if (rc != GRN_SUCCESS) { return rc; } |
9704 | } |
9705 | grn_obj_touch(ctx, db, NULL); |
9706 | |
9707 | return rc; |
9708 | } |
9709 | |
9710 | static grn_rc |
9711 | _grn_obj_remove_index(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9712 | const char *path) |
9713 | { |
9714 | grn_rc rc = GRN_SUCCESS; |
9715 | uint8_t type; |
9716 | |
9717 | type = obj->header.type; |
9718 | |
9719 | delete_source_hook(ctx, obj); |
9720 | rc = grn_obj_close(ctx, obj); |
9721 | if (rc != GRN_SUCCESS) { return rc; } |
9722 | |
9723 | if (path) { |
9724 | rc = grn_ii_remove(ctx, path); |
9725 | if (rc != GRN_SUCCESS) { return rc; } |
9726 | rc = _grn_obj_remove_spec(ctx, db, id, type); |
9727 | if (rc != GRN_SUCCESS) { return rc; } |
9728 | rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
9729 | if (rc != GRN_SUCCESS) { return rc; } |
9730 | } |
9731 | |
9732 | grn_obj_touch(ctx, db, NULL); |
9733 | |
9734 | return rc; |
9735 | } |
9736 | |
9737 | static grn_rc |
9738 | _grn_obj_remove_db_obj(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9739 | const char *path) |
9740 | { |
9741 | grn_rc rc = GRN_SUCCESS; |
9742 | uint8_t type; |
9743 | |
9744 | type = obj->header.type; |
9745 | |
9746 | rc = grn_obj_close(ctx, obj); |
9747 | if (rc != GRN_SUCCESS) { return rc; } |
9748 | |
9749 | if (path) { |
9750 | rc = grn_io_remove(ctx, path); |
9751 | if (rc != GRN_SUCCESS) { return rc; } |
9752 | } |
9753 | |
9754 | if (!(id & GRN_OBJ_TMP_OBJECT)) { |
9755 | rc = _grn_obj_remove_spec(ctx, db, id, type); |
9756 | if (rc != GRN_SUCCESS) { return rc; } |
9757 | rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
9758 | if (rc != GRN_SUCCESS) { return rc; } |
9759 | } |
9760 | |
9761 | grn_obj_touch(ctx, db, NULL); |
9762 | |
9763 | return rc; |
9764 | } |
9765 | |
9766 | static grn_rc |
9767 | _grn_obj_remove_other(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, |
9768 | const char *path) |
9769 | { |
9770 | return grn_obj_close(ctx, obj); |
9771 | } |
9772 | |
9773 | static grn_rc |
9774 | _grn_obj_remove(grn_ctx *ctx, grn_obj *obj, grn_bool dependent) |
9775 | { |
9776 | grn_rc rc = GRN_SUCCESS; |
9777 | grn_id id = GRN_ID_NIL; |
9778 | grn_obj *db = NULL; |
9779 | const char *io_path; |
9780 | char *path; |
9781 | grn_bool is_temporary_open_target = GRN_FALSE; |
9782 | |
9783 | if (ctx->impl && ctx->impl->db) { |
9784 | grn_id id; |
9785 | uint32_t s = 0; |
9786 | const char *n; |
9787 | |
9788 | id = DB_OBJ(obj)->id; |
9789 | n = _grn_table_key(ctx, ctx->impl->db, id, &s); |
9790 | if (s > 0) { |
9791 | GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:%u:obj_remove %.*s" , id, s, n); |
9792 | } |
9793 | } |
9794 | if (obj->header.type != GRN_PROC && |
9795 | (io_path = grn_obj_path(ctx, obj)) && *io_path != '\0') { |
9796 | if (!(path = GRN_STRDUP(io_path))) { |
9797 | ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>" , io_path); |
9798 | return ctx->rc; |
9799 | } |
9800 | } else { |
9801 | path = NULL; |
9802 | } |
9803 | if (GRN_DB_OBJP(obj)) { |
9804 | id = DB_OBJ(obj)->id; |
9805 | db = DB_OBJ(obj)->db; |
9806 | } |
9807 | switch (obj->header.type) { |
9808 | case GRN_DB : |
9809 | rc = _grn_obj_remove_db(ctx, obj, db, id, path); |
9810 | break; |
9811 | case GRN_TABLE_PAT_KEY : |
9812 | rc = _grn_obj_remove_pat(ctx, obj, db, id, path, dependent); |
9813 | is_temporary_open_target = GRN_TRUE; |
9814 | break; |
9815 | case GRN_TABLE_DAT_KEY : |
9816 | rc = _grn_obj_remove_dat(ctx, obj, db, id, path, dependent); |
9817 | is_temporary_open_target = GRN_TRUE; |
9818 | break; |
9819 | case GRN_TABLE_HASH_KEY : |
9820 | rc = _grn_obj_remove_hash(ctx, obj, db, id, path, dependent); |
9821 | is_temporary_open_target = GRN_TRUE; |
9822 | break; |
9823 | case GRN_TABLE_NO_KEY : |
9824 | rc = _grn_obj_remove_array(ctx, obj, db, id, path, dependent); |
9825 | is_temporary_open_target = GRN_TRUE; |
9826 | break; |
9827 | case GRN_COLUMN_VAR_SIZE : |
9828 | rc = _grn_obj_remove_ja(ctx, obj, db, id, path); |
9829 | is_temporary_open_target = GRN_TRUE; |
9830 | break; |
9831 | case GRN_COLUMN_FIX_SIZE : |
9832 | rc = _grn_obj_remove_ra(ctx, obj, db, id, path); |
9833 | is_temporary_open_target = GRN_TRUE; |
9834 | break; |
9835 | case GRN_COLUMN_INDEX : |
9836 | rc = _grn_obj_remove_index(ctx, obj, db, id, path); |
9837 | is_temporary_open_target = GRN_TRUE; |
9838 | break; |
9839 | default : |
9840 | if (GRN_DB_OBJP(obj)) { |
9841 | rc = _grn_obj_remove_db_obj(ctx, obj, db, id, path); |
9842 | } else { |
9843 | rc = _grn_obj_remove_other(ctx, obj, db, id, path); |
9844 | } |
9845 | } |
9846 | if (path) { |
9847 | GRN_FREE(path); |
9848 | } else { |
9849 | is_temporary_open_target = GRN_FALSE; |
9850 | } |
9851 | |
9852 | if (is_temporary_open_target && rc == GRN_SUCCESS) { |
9853 | grn_obj *space; |
9854 | space = ctx->impl->temporary_open_spaces.current; |
9855 | if (space) { |
9856 | unsigned int i, n_elements; |
9857 | n_elements = GRN_BULK_VSIZE(space) / sizeof(grn_obj *); |
9858 | for (i = 0; i < n_elements; i++) { |
9859 | if (GRN_PTR_VALUE_AT(space, i) == obj) { |
9860 | GRN_PTR_SET_AT(ctx, space, i, NULL); |
9861 | } |
9862 | } |
9863 | } |
9864 | } |
9865 | |
9866 | return rc; |
9867 | } |
9868 | |
9869 | grn_rc |
9870 | grn_obj_remove(grn_ctx *ctx, grn_obj *obj) |
9871 | { |
9872 | grn_rc rc = GRN_SUCCESS; |
9873 | GRN_API_ENTER; |
9874 | if (ctx->impl && ctx->impl->db && ctx->impl->db != obj) { |
9875 | grn_io *io = grn_obj_get_io(ctx, ctx->impl->db); |
9876 | rc = grn_io_lock(ctx, io, grn_lock_timeout); |
9877 | if (rc == GRN_SUCCESS) { |
9878 | rc = _grn_obj_remove(ctx, obj, GRN_FALSE); |
9879 | grn_io_unlock(io); |
9880 | } |
9881 | } else { |
9882 | rc = _grn_obj_remove(ctx, obj, GRN_FALSE); |
9883 | } |
9884 | GRN_API_RETURN(rc); |
9885 | } |
9886 | |
9887 | grn_rc |
9888 | grn_obj_remove_dependent(grn_ctx *ctx, grn_obj *obj) |
9889 | { |
9890 | grn_rc rc = GRN_SUCCESS; |
9891 | GRN_API_ENTER; |
9892 | if (ctx->impl && ctx->impl->db && ctx->impl->db != obj) { |
9893 | grn_io *io = grn_obj_get_io(ctx, ctx->impl->db); |
9894 | rc = grn_io_lock(ctx, io, grn_lock_timeout); |
9895 | if (rc == GRN_SUCCESS) { |
9896 | rc = _grn_obj_remove(ctx, obj, GRN_TRUE); |
9897 | grn_io_unlock(io); |
9898 | } |
9899 | } else { |
9900 | rc = _grn_obj_remove(ctx, obj, GRN_TRUE); |
9901 | } |
9902 | GRN_API_RETURN(rc); |
9903 | } |
9904 | |
9905 | grn_rc |
9906 | grn_obj_remove_force(grn_ctx *ctx, const char *name, int name_size) |
9907 | { |
9908 | grn_rc rc = GRN_SUCCESS; |
9909 | grn_obj *db; |
9910 | grn_id obj_id; |
9911 | char path[PATH_MAX]; |
9912 | |
9913 | GRN_API_ENTER; |
9914 | |
9915 | if (!(ctx->impl && ctx->impl->db)) { |
9916 | ERR(GRN_INVALID_ARGUMENT, |
9917 | "[object][remove][force] database isn't initialized" ); |
9918 | rc = ctx->rc; |
9919 | goto exit; |
9920 | } |
9921 | |
9922 | db = ctx->impl->db; |
9923 | if (name_size == -1) { |
9924 | name_size = strlen(name); |
9925 | } |
9926 | obj_id = grn_table_get(ctx, db, name, name_size); |
9927 | if (obj_id == GRN_ID_NIL) { |
9928 | ERR(GRN_INVALID_ARGUMENT, |
9929 | "[object][remove][force] nonexistent object: <%.*s>" , |
9930 | name_size, name); |
9931 | rc = ctx->rc; |
9932 | goto exit; |
9933 | } |
9934 | |
9935 | grn_obj_delete_by_id(ctx, db, obj_id, GRN_TRUE); |
9936 | grn_obj_path_by_id(ctx, db, obj_id, path); |
9937 | grn_io_remove_if_exist(ctx, path); |
9938 | grn_strcat(path, PATH_MAX, ".c" ); |
9939 | grn_io_remove_if_exist(ctx, path); |
9940 | |
9941 | exit : |
9942 | GRN_API_RETURN(rc); |
9943 | } |
9944 | |
9945 | grn_rc |
9946 | grn_table_update_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, |
9947 | const void *dest_key, unsigned int dest_key_size) |
9948 | { |
9949 | grn_rc rc = GRN_OPERATION_NOT_SUPPORTED; |
9950 | GRN_API_ENTER; |
9951 | if (table->header.type == GRN_TABLE_DAT_KEY) { |
9952 | grn_dat *dat = (grn_dat *)table; |
9953 | if (dat->io && !(dat->io->flags & GRN_IO_TEMPORARY)) { |
9954 | if (grn_io_lock(ctx, dat->io, grn_lock_timeout)) { |
9955 | rc = ctx->rc; |
9956 | } else { |
9957 | rc = grn_dat_update_by_id(ctx, dat, id, dest_key, dest_key_size); |
9958 | grn_io_unlock(dat->io); |
9959 | } |
9960 | } else { |
9961 | rc = grn_dat_update_by_id(ctx, dat, id, dest_key, dest_key_size); |
9962 | } |
9963 | } |
9964 | GRN_API_RETURN(rc); |
9965 | } |
9966 | |
9967 | grn_rc |
9968 | grn_table_update(grn_ctx *ctx, grn_obj *table, |
9969 | const void *src_key, unsigned int src_key_size, |
9970 | const void *dest_key, unsigned int dest_key_size) |
9971 | { |
9972 | grn_rc rc = GRN_OPERATION_NOT_SUPPORTED; |
9973 | GRN_API_ENTER; |
9974 | if (table->header.type == GRN_TABLE_DAT_KEY) { |
9975 | rc = grn_dat_update(ctx, (grn_dat *)table, |
9976 | src_key, src_key_size, |
9977 | dest_key, dest_key_size); |
9978 | } |
9979 | GRN_API_RETURN(rc); |
9980 | } |
9981 | |
9982 | grn_rc |
9983 | grn_obj_rename(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int name_size) |
9984 | { |
9985 | grn_rc rc = GRN_INVALID_ARGUMENT; |
9986 | GRN_API_ENTER; |
9987 | if (ctx && ctx->impl && GRN_DB_P(ctx->impl->db) && GRN_DB_OBJP(obj) && !IS_TEMP(obj)) { |
9988 | grn_db *s = (grn_db *)ctx->impl->db; |
9989 | grn_obj *keys = (grn_obj *)s->keys; |
9990 | rc = grn_table_update_by_id(ctx, keys, DB_OBJ(obj)->id, name, name_size); |
9991 | } |
9992 | GRN_API_RETURN(rc); |
9993 | } |
9994 | |
9995 | grn_rc |
9996 | grn_table_rename(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size) |
9997 | { |
9998 | grn_rc rc = GRN_INVALID_ARGUMENT; |
9999 | grn_hash *cols; |
10000 | |
10001 | GRN_API_ENTER; |
10002 | |
10003 | if (!GRN_OBJ_TABLEP(table)) { |
10004 | char table_name[GRN_TABLE_MAX_KEY_SIZE]; |
10005 | int table_name_size; |
10006 | table_name_size = grn_obj_name(ctx, table, table_name, |
10007 | GRN_TABLE_MAX_KEY_SIZE); |
10008 | rc = GRN_INVALID_ARGUMENT; |
10009 | ERR(rc, |
10010 | "[table][rename] isn't table: <%.*s> -> <%.*s>" , |
10011 | table_name_size, table_name, |
10012 | name_size, name); |
10013 | goto exit; |
10014 | } |
10015 | if (IS_TEMP(table)) { |
10016 | rc = GRN_INVALID_ARGUMENT; |
10017 | ERR(rc, |
10018 | "[table][rename] temporary table doesn't have name: " |
10019 | "(anonymous) -> <%.*s>" , |
10020 | name_size, name); |
10021 | goto exit; |
10022 | } |
10023 | |
10024 | if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
10025 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { |
10026 | grn_table_columns(ctx, table, "" , 0, (grn_obj *)cols); |
10027 | if (!(rc = grn_obj_rename(ctx, table, name, name_size))) { |
10028 | grn_id *key; |
10029 | char fullname[GRN_TABLE_MAX_KEY_SIZE]; |
10030 | grn_memcpy(fullname, name, name_size); |
10031 | fullname[name_size] = GRN_DB_DELIMITER; |
10032 | GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { |
10033 | grn_obj *col = grn_ctx_at(ctx, *key); |
10034 | if (col) { |
10035 | int colname_len = grn_column_name(ctx, col, fullname + name_size + 1, |
10036 | GRN_TABLE_MAX_KEY_SIZE - name_size - 1); |
10037 | if (colname_len) { |
10038 | if ((rc = grn_obj_rename(ctx, col, fullname, |
10039 | name_size + 1 + colname_len))) { |
10040 | break; |
10041 | } |
10042 | } |
10043 | } |
10044 | }); |
10045 | } |
10046 | grn_hash_close(ctx, cols); |
10047 | } |
10048 | exit: |
10049 | GRN_API_RETURN(rc); |
10050 | } |
10051 | |
10052 | grn_rc |
10053 | grn_column_rename(grn_ctx *ctx, grn_obj *column, const char *name, unsigned int name_size) |
10054 | { |
10055 | grn_rc rc = GRN_INVALID_ARGUMENT; |
10056 | GRN_API_ENTER; |
10057 | if (GRN_DB_OBJP(column)) { |
10058 | char fullname[GRN_TABLE_MAX_KEY_SIZE]; |
10059 | grn_db *s = (grn_db *)DB_OBJ(column)->db; |
10060 | int len = grn_table_get_key(ctx, s->keys, DB_OBJ(column)->header.domain, |
10061 | fullname, GRN_TABLE_MAX_KEY_SIZE); |
10062 | if (name_size + 1 + len > GRN_TABLE_MAX_KEY_SIZE) { |
10063 | ERR(GRN_INVALID_ARGUMENT, |
10064 | "[column][rename] too long column name: required name_size(%d) < %d" |
10065 | ": <%.*s>.<%.*s>" , |
10066 | name_size, GRN_TABLE_MAX_KEY_SIZE - 1 - len, |
10067 | len, fullname, name_size, name); |
10068 | goto exit; |
10069 | } |
10070 | fullname[len] = GRN_DB_DELIMITER; |
10071 | grn_memcpy(fullname + len + 1, name, name_size); |
10072 | name_size += len + 1; |
10073 | rc = grn_obj_rename(ctx, column, fullname, name_size); |
10074 | if (rc == GRN_SUCCESS) { |
10075 | grn_obj_touch(ctx, column, NULL); |
10076 | } |
10077 | } |
10078 | exit : |
10079 | GRN_API_RETURN(rc); |
10080 | } |
10081 | |
10082 | grn_rc |
10083 | grn_obj_path_rename(grn_ctx *ctx, const char *old_path, const char *new_path) |
10084 | { |
10085 | GRN_API_ENTER; |
10086 | GRN_API_RETURN(GRN_SUCCESS); |
10087 | } |
10088 | |
10089 | /* db must be validated by caller */ |
10090 | grn_id |
10091 | grn_obj_register(grn_ctx *ctx, grn_obj *db, const char *name, unsigned int name_size) |
10092 | { |
10093 | grn_id id = GRN_ID_NIL; |
10094 | if (name && name_size) { |
10095 | grn_db *s = (grn_db *)db; |
10096 | int added; |
10097 | if (!(id = grn_table_add(ctx, s->keys, name, name_size, &added))) { |
10098 | grn_rc rc; |
10099 | rc = ctx->rc; |
10100 | if (rc == GRN_SUCCESS) { |
10101 | rc = GRN_NO_MEMORY_AVAILABLE; |
10102 | } |
10103 | ERR(rc, |
10104 | "[object][register] failed to register a name: <%.*s>%s%s%s" , |
10105 | name_size, name, |
10106 | ctx->rc == GRN_SUCCESS ? "" : ": <" , |
10107 | ctx->rc == GRN_SUCCESS ? "" : ctx->errbuf, |
10108 | ctx->rc == GRN_SUCCESS ? "" : ">" ); |
10109 | } else if (!added) { |
10110 | ERR(GRN_INVALID_ARGUMENT, |
10111 | "[object][register] already used name was assigned: <%.*s>" , |
10112 | name_size, name); |
10113 | id = GRN_ID_NIL; |
10114 | } |
10115 | } else if (ctx->impl && ctx->impl->values) { |
10116 | id = grn_array_add(ctx, ctx->impl->values, NULL) | GRN_OBJ_TMP_OBJECT; |
10117 | } |
10118 | return id; |
10119 | } |
10120 | |
10121 | grn_rc |
10122 | grn_obj_delete_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, grn_bool removep) |
10123 | { |
10124 | grn_rc rc = GRN_INVALID_ARGUMENT; |
10125 | GRN_API_ENTER; |
10126 | if (id) { |
10127 | if (id & GRN_OBJ_TMP_OBJECT) { |
10128 | if (ctx->impl) { |
10129 | if (id & GRN_OBJ_TMP_COLUMN) { |
10130 | if (ctx->impl->temporary_columns) { |
10131 | rc = grn_pat_delete_by_id(ctx, ctx->impl->temporary_columns, |
10132 | id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT), |
10133 | NULL); |
10134 | } |
10135 | } else { |
10136 | if (ctx->impl->values) { |
10137 | rc = grn_array_delete_by_id(ctx, ctx->impl->values, |
10138 | id & ~GRN_OBJ_TMP_OBJECT, NULL); |
10139 | } |
10140 | } |
10141 | } |
10142 | } else { |
10143 | db_value *vp; |
10144 | grn_db *s = (grn_db *)db; |
10145 | if ((vp = grn_tiny_array_at(&s->values, id))) { |
10146 | GRN_ASSERT(!vp->lock); |
10147 | vp->lock = 0; |
10148 | vp->ptr = NULL; |
10149 | vp->done = 0; |
10150 | } |
10151 | if (removep) { |
10152 | switch (s->keys->header.type) { |
10153 | case GRN_TABLE_PAT_KEY : |
10154 | rc = grn_pat_delete_by_id(ctx, (grn_pat *)s->keys, id, NULL); |
10155 | break; |
10156 | case GRN_TABLE_DAT_KEY : |
10157 | rc = grn_dat_delete_by_id(ctx, (grn_dat *)s->keys, id, NULL); |
10158 | break; |
10159 | } |
10160 | } else { |
10161 | rc = GRN_SUCCESS; |
10162 | } |
10163 | } |
10164 | } |
10165 | GRN_API_RETURN(rc); |
10166 | } |
10167 | |
10168 | |
10169 | grn_rc |
10170 | grn_obj_path_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer) |
10171 | { |
10172 | grn_rc rc = GRN_SUCCESS; |
10173 | GRN_API_ENTER; |
10174 | if (!GRN_DB_P(db) || !buffer) { |
10175 | rc = GRN_INVALID_ARGUMENT; |
10176 | } else { |
10177 | grn_db_generate_pathname(ctx, db, id, buffer); |
10178 | } |
10179 | GRN_API_RETURN(rc); |
10180 | } |
10181 | |
10182 | /* db must be validated by caller */ |
10183 | grn_rc |
10184 | grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj) |
10185 | { |
10186 | grn_rc rc = GRN_SUCCESS; |
10187 | if (id) { |
10188 | if (id & GRN_OBJ_TMP_OBJECT) { |
10189 | if (id & GRN_OBJ_TMP_COLUMN) { |
10190 | if (ctx->impl && ctx->impl->temporary_columns) { |
10191 | grn_id real_id = id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT); |
10192 | rc = grn_pat_set_value(ctx, ctx->impl->temporary_columns, |
10193 | real_id, &obj, GRN_OBJ_SET); |
10194 | } |
10195 | } else { |
10196 | if (ctx->impl && ctx->impl->values) { |
10197 | rc = grn_array_set_value(ctx, ctx->impl->values, |
10198 | id & ~GRN_OBJ_TMP_OBJECT, &obj, GRN_OBJ_SET); |
10199 | } |
10200 | } |
10201 | } else { |
10202 | db_value *vp; |
10203 | vp = grn_tiny_array_at(&((grn_db *)db)->values, id); |
10204 | if (!vp) { |
10205 | rc = GRN_NO_MEMORY_AVAILABLE; |
10206 | ERR(rc, "grn_tiny_array_at failed (%d)" , id); |
10207 | return rc; |
10208 | } |
10209 | vp->lock = 1; |
10210 | vp->ptr = (grn_obj *)obj; |
10211 | } |
10212 | } |
10213 | obj->id = id; |
10214 | obj->db = db; |
10215 | obj->source = NULL; |
10216 | obj->source_size = 0; |
10217 | { |
10218 | grn_hook_entry entry; |
10219 | for (entry = 0; entry < N_HOOK_ENTRIES; entry++) { |
10220 | obj->hooks[entry] = NULL; |
10221 | } |
10222 | } |
10223 | grn_obj_spec_save(ctx, obj); |
10224 | return rc; |
10225 | } |
10226 | |
10227 | #define GET_PATH(spec,decoded_spec,buffer,s,id) do {\ |
10228 | if (spec->header.flags & GRN_OBJ_CUSTOM_NAME) {\ |
10229 | const char *path;\ |
10230 | unsigned int size = grn_vector_get_element(ctx,\ |
10231 | decoded_spec,\ |
10232 | GRN_SERIALIZED_SPEC_INDEX_PATH,\ |
10233 | &path,\ |
10234 | NULL,\ |
10235 | NULL);\ |
10236 | if (size > PATH_MAX) { ERR(GRN_FILENAME_TOO_LONG, "too long path"); }\ |
10237 | grn_memcpy(buffer, path, size);\ |
10238 | buffer[size] = '\0';\ |
10239 | } else {\ |
10240 | grn_db_generate_pathname(ctx, (grn_obj *)s, id, buffer);\ |
10241 | }\ |
10242 | } while (0) |
10243 | |
10244 | #define UNPACK_INFO(spec,decoded_spec) do {\ |
10245 | if (vp->ptr) {\ |
10246 | const char *p;\ |
10247 | uint32_t size;\ |
10248 | grn_db_obj *r = DB_OBJ(vp->ptr);\ |
10249 | r->header = spec->header;\ |
10250 | r->id = id;\ |
10251 | r->range = spec->range;\ |
10252 | r->db = (grn_obj *)s;\ |
10253 | size = grn_vector_get_element(ctx,\ |
10254 | decoded_spec,\ |
10255 | GRN_SERIALIZED_SPEC_INDEX_SOURCE,\ |
10256 | &p,\ |
10257 | NULL,\ |
10258 | NULL);\ |
10259 | if (size) {\ |
10260 | if ((r->source = GRN_MALLOC(size))) {\ |
10261 | grn_memcpy(r->source, p, size);\ |
10262 | r->source_size = size;\ |
10263 | }\ |
10264 | }\ |
10265 | size = grn_vector_get_element(ctx,\ |
10266 | decoded_spec,\ |
10267 | GRN_SERIALIZED_SPEC_INDEX_HOOK,\ |
10268 | &p,\ |
10269 | NULL,\ |
10270 | NULL);\ |
10271 | grn_hook_unpack(ctx, r, p, size);\ |
10272 | }\ |
10273 | } while (0) |
10274 | |
10275 | static void |
10276 | grn_token_filters_unpack(grn_ctx *ctx, |
10277 | grn_obj *token_filters, |
10278 | grn_obj *spec_vector) |
10279 | { |
10280 | grn_id *token_filter_ids; |
10281 | unsigned int element_size; |
10282 | unsigned int i, n_token_filter_ids; |
10283 | |
10284 | if (grn_vector_size(ctx, spec_vector) <= GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS) { |
10285 | return; |
10286 | } |
10287 | |
10288 | element_size = grn_vector_get_element(ctx, |
10289 | spec_vector, |
10290 | GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS, |
10291 | (const char **)(&token_filter_ids), |
10292 | NULL, |
10293 | NULL); |
10294 | n_token_filter_ids = element_size / sizeof(grn_id); |
10295 | for (i = 0; i < n_token_filter_ids; i++) { |
10296 | grn_id token_filter_id = token_filter_ids[i]; |
10297 | grn_obj *token_filter; |
10298 | |
10299 | token_filter = grn_ctx_at(ctx, token_filter_id); |
10300 | if (!token_filter) { |
10301 | ERR(GRN_INVALID_ARGUMENT, |
10302 | "nonexistent token filter ID: %d" , token_filter_id); |
10303 | return; |
10304 | } |
10305 | GRN_PTR_PUT(ctx, token_filters, token_filter); |
10306 | } |
10307 | } |
10308 | |
10309 | grn_bool |
10310 | grn_db_spec_unpack(grn_ctx *ctx, |
10311 | grn_id id, |
10312 | void *encoded_spec, |
10313 | uint32_t encoded_spec_size, |
10314 | grn_obj_spec **spec, |
10315 | grn_obj *decoded_spec, |
10316 | const char *error_message_tag) |
10317 | { |
10318 | grn_obj *db; |
10319 | grn_db *db_raw; |
10320 | grn_rc rc; |
10321 | uint32_t spec_size; |
10322 | |
10323 | db = ctx->impl->db; |
10324 | db_raw = (grn_db *)db; |
10325 | |
10326 | rc = grn_vector_decode(ctx, |
10327 | decoded_spec, |
10328 | encoded_spec, |
10329 | encoded_spec_size); |
10330 | if (rc != GRN_SUCCESS) { |
10331 | const char *name; |
10332 | uint32_t name_size; |
10333 | name = _grn_table_key(ctx, db, id, &name_size); |
10334 | GRN_LOG((ctx), GRN_LOG_ERROR, |
10335 | "%s: failed to decode spec: <%u>(<%.*s>):<%u>: %s" , |
10336 | error_message_tag, |
10337 | id, |
10338 | name_size, name, |
10339 | encoded_spec_size, |
10340 | grn_rc_to_string(rc)); |
10341 | return GRN_FALSE; |
10342 | } |
10343 | |
10344 | spec_size = grn_vector_get_element(ctx, |
10345 | decoded_spec, |
10346 | GRN_SERIALIZED_SPEC_INDEX_SPEC, |
10347 | (const char **)spec, |
10348 | NULL, |
10349 | NULL); |
10350 | if (spec_size == 0) { |
10351 | const char *name; |
10352 | uint32_t name_size; |
10353 | name = _grn_table_key(ctx, db, id, &name_size); |
10354 | GRN_LOG(ctx, GRN_LOG_ERROR, |
10355 | "%s: spec value is empty: <%u>(<%.*s>)" , |
10356 | error_message_tag, |
10357 | id, |
10358 | name_size, name); |
10359 | return GRN_FALSE; |
10360 | } |
10361 | |
10362 | return GRN_TRUE; |
10363 | } |
10364 | |
10365 | grn_obj * |
10366 | grn_ctx_at(grn_ctx *ctx, grn_id id) |
10367 | { |
10368 | grn_obj *res = NULL; |
10369 | if (!ctx || !ctx->impl || !id) { return res; } |
10370 | GRN_API_ENTER; |
10371 | if (id & GRN_OBJ_TMP_OBJECT) { |
10372 | if (id & GRN_OBJ_TMP_COLUMN) { |
10373 | if (ctx->impl->temporary_columns) { |
10374 | grn_id real_id = id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT); |
10375 | grn_obj **tmp_obj; |
10376 | uint32_t size; |
10377 | tmp_obj = (grn_obj **)grn_pat_get_value_(ctx, |
10378 | ctx->impl->temporary_columns, |
10379 | real_id, |
10380 | &size); |
10381 | if (tmp_obj) { |
10382 | res = *tmp_obj; |
10383 | } |
10384 | } |
10385 | } else { |
10386 | if (ctx->impl->values) { |
10387 | grn_obj **tmp_obj; |
10388 | tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, |
10389 | id & ~GRN_OBJ_TMP_OBJECT); |
10390 | if (tmp_obj) { |
10391 | res = *tmp_obj; |
10392 | } |
10393 | } |
10394 | } |
10395 | } else { |
10396 | grn_db *s = (grn_db *)ctx->impl->db; |
10397 | if (s) { |
10398 | db_value *vp; |
10399 | uint32_t l, *pl, ntrial; |
10400 | if (!(vp = grn_tiny_array_at(&s->values, id))) { goto exit; } |
10401 | #ifdef USE_NREF |
10402 | pl = &vp->lock; |
10403 | for (ntrial = 0;; ntrial++) { |
10404 | GRN_ATOMIC_ADD_EX(pl, 1, l); |
10405 | if (l < GRN_IO_MAX_REF) { break; } |
10406 | if (ntrial >= 10) { |
10407 | GRN_LOG(ctx, GRN_LOG_NOTICE, "max trial in ctx_at(%p,%d)" , vp->ptr, vp->lock); |
10408 | break; |
10409 | } |
10410 | GRN_ATOMIC_ADD_EX(pl, -1, l); |
10411 | GRN_FUTEX_WAIT(pl); |
10412 | } |
10413 | #endif /* USE_NREF */ |
10414 | if (s->specs && !vp->ptr /* && !vp->done */) { |
10415 | #ifndef USE_NREF |
10416 | pl = &vp->lock; |
10417 | for (ntrial = 0;; ntrial++) { |
10418 | GRN_ATOMIC_ADD_EX(pl, 1, l); |
10419 | if (l < GRN_IO_MAX_REF) { break; } |
10420 | if (ntrial >= 10) { |
10421 | GRN_LOG(ctx, GRN_LOG_NOTICE, "max trial in ctx_at(%p,%d)" , vp->ptr, vp->lock); |
10422 | break; |
10423 | } |
10424 | GRN_ATOMIC_ADD_EX(pl, -1, l); |
10425 | GRN_FUTEX_WAIT(pl); |
10426 | } |
10427 | #endif /* USE_NREF */ |
10428 | if (!l) { |
10429 | grn_io_win iw; |
10430 | uint32_t encoded_spec_size; |
10431 | void *encoded_spec; |
10432 | |
10433 | encoded_spec = grn_ja_ref(ctx, s->specs, id, &iw, &encoded_spec_size); |
10434 | if (encoded_spec) { |
10435 | grn_bool success; |
10436 | grn_obj_spec *spec; |
10437 | grn_obj decoded_spec; |
10438 | |
10439 | GRN_OBJ_INIT(&decoded_spec, GRN_VECTOR, 0, GRN_DB_TEXT); |
10440 | success = grn_db_spec_unpack(ctx, |
10441 | id, |
10442 | encoded_spec, |
10443 | encoded_spec_size, |
10444 | &spec, |
10445 | &decoded_spec, |
10446 | "grn_ctx_at" ); |
10447 | if (success) { |
10448 | char buffer[PATH_MAX]; |
10449 | switch (spec->header.type) { |
10450 | case GRN_TYPE : |
10451 | vp->ptr = (grn_obj *)grn_type_open(ctx, spec); |
10452 | UNPACK_INFO(spec, &decoded_spec); |
10453 | break; |
10454 | case GRN_TABLE_HASH_KEY : |
10455 | GET_PATH(spec, &decoded_spec, buffer, s, id); |
10456 | vp->ptr = (grn_obj *)grn_hash_open(ctx, buffer); |
10457 | if (vp->ptr) { |
10458 | grn_hash *hash = (grn_hash *)(vp->ptr); |
10459 | grn_obj_flags flags = vp->ptr->header.flags; |
10460 | UNPACK_INFO(spec, &decoded_spec); |
10461 | vp->ptr->header.flags = flags; |
10462 | grn_token_filters_unpack(ctx, |
10463 | &(hash->token_filters), |
10464 | &decoded_spec); |
10465 | } |
10466 | break; |
10467 | case GRN_TABLE_PAT_KEY : |
10468 | GET_PATH(spec, &decoded_spec, buffer, s, id); |
10469 | vp->ptr = (grn_obj *)grn_pat_open(ctx, buffer); |
10470 | if (vp->ptr) { |
10471 | grn_pat *pat = (grn_pat *)(vp->ptr); |
10472 | grn_obj_flags flags = vp->ptr->header.flags; |
10473 | UNPACK_INFO(spec, &decoded_spec); |
10474 | vp->ptr->header.flags = flags; |
10475 | grn_token_filters_unpack(ctx, |
10476 | &(pat->token_filters), |
10477 | &decoded_spec); |
10478 | } |
10479 | break; |
10480 | case GRN_TABLE_DAT_KEY : |
10481 | GET_PATH(spec, &decoded_spec, buffer, s, id); |
10482 | vp->ptr = (grn_obj *)grn_dat_open(ctx, buffer); |
10483 | if (vp->ptr) { |
10484 | grn_dat *dat = (grn_dat *)(vp->ptr); |
10485 | grn_obj_flags flags = vp->ptr->header.flags; |
10486 | UNPACK_INFO(spec, &decoded_spec); |
10487 | vp->ptr->header.flags = flags; |
10488 | grn_token_filters_unpack(ctx, |
10489 | &(dat->token_filters), |
10490 | &decoded_spec); |
10491 | } |
10492 | break; |
10493 | case GRN_TABLE_NO_KEY : |
10494 | GET_PATH(spec, &decoded_spec, buffer, s, id); |
10495 | vp->ptr = (grn_obj *)grn_array_open(ctx, buffer); |
10496 | UNPACK_INFO(spec, &decoded_spec); |
10497 | break; |
10498 | case GRN_COLUMN_VAR_SIZE : |
10499 | GET_PATH(spec, &decoded_spec, buffer, s, id); |
10500 | vp->ptr = (grn_obj *)grn_ja_open(ctx, buffer); |
10501 | UNPACK_INFO(spec, &decoded_spec); |
10502 | break; |
10503 | case GRN_COLUMN_FIX_SIZE : |
10504 | GET_PATH(spec, &decoded_spec, buffer, s, id); |
10505 | vp->ptr = (grn_obj *)grn_ra_open(ctx, buffer); |
10506 | UNPACK_INFO(spec, &decoded_spec); |
10507 | break; |
10508 | case GRN_COLUMN_INDEX : |
10509 | GET_PATH(spec, &decoded_spec, buffer, s, id); |
10510 | { |
10511 | grn_obj *table = grn_ctx_at(ctx, spec->header.domain); |
10512 | vp->ptr = (grn_obj *)grn_ii_open(ctx, buffer, table); |
10513 | } |
10514 | UNPACK_INFO(spec, &decoded_spec); |
10515 | break; |
10516 | case GRN_PROC : |
10517 | GET_PATH(spec, &decoded_spec, buffer, s, id); |
10518 | grn_plugin_register(ctx, buffer); |
10519 | break; |
10520 | case GRN_EXPR : |
10521 | { |
10522 | const char *p; |
10523 | uint32_t size; |
10524 | uint8_t *u; |
10525 | size = grn_vector_get_element(ctx, |
10526 | &decoded_spec, |
10527 | GRN_SERIALIZED_SPEC_INDEX_EXPR, |
10528 | &p, |
10529 | NULL, |
10530 | NULL); |
10531 | u = (uint8_t *)p; |
10532 | vp->ptr = grn_expr_open(ctx, spec, u, u + size); |
10533 | } |
10534 | break; |
10535 | } |
10536 | if (!vp->ptr) { |
10537 | const char *name; |
10538 | uint32_t name_size = 0; |
10539 | name = _grn_table_key(ctx, (grn_obj *)s, id, &name_size); |
10540 | GRN_LOG(ctx, GRN_LOG_ERROR, |
10541 | "grn_ctx_at: failed to open object: " |
10542 | "<%u>(<%.*s>):<%u>(<%s>)" , |
10543 | id, |
10544 | name_size, name, |
10545 | spec->header.type, |
10546 | grn_obj_type_to_string(spec->header.type)); |
10547 | } |
10548 | } |
10549 | GRN_OBJ_FIN(ctx, &decoded_spec); |
10550 | grn_ja_unref(ctx, &iw); |
10551 | } |
10552 | #ifndef USE_NREF |
10553 | GRN_ATOMIC_ADD_EX(pl, -1, l); |
10554 | #endif /* USE_NREF */ |
10555 | vp->done = 1; |
10556 | GRN_FUTEX_WAKE(&vp->ptr); |
10557 | } else { |
10558 | for (ntrial = 0; !vp->ptr; ntrial++) { |
10559 | if (ntrial >= 1000) { |
10560 | GRN_LOG(ctx, GRN_LOG_NOTICE, "max trial in ctx_at(%d,%p,%d)!" , id, vp->ptr, vp->lock); |
10561 | break; |
10562 | } |
10563 | GRN_FUTEX_WAIT(&vp->ptr); |
10564 | } |
10565 | } |
10566 | if (vp->ptr) { |
10567 | switch (vp->ptr->header.type) { |
10568 | case GRN_TABLE_HASH_KEY : |
10569 | case GRN_TABLE_PAT_KEY : |
10570 | case GRN_TABLE_DAT_KEY : |
10571 | case GRN_TABLE_NO_KEY : |
10572 | case GRN_COLUMN_FIX_SIZE : |
10573 | case GRN_COLUMN_VAR_SIZE : |
10574 | case GRN_COLUMN_INDEX : |
10575 | { |
10576 | grn_obj *space; |
10577 | space = ctx->impl->temporary_open_spaces.current; |
10578 | if (space) { |
10579 | GRN_PTR_PUT(ctx, space, vp->ptr); |
10580 | } |
10581 | } |
10582 | break; |
10583 | } |
10584 | } |
10585 | } |
10586 | res = vp->ptr; |
10587 | if (res && res->header.type == GRN_PROC) { |
10588 | grn_plugin_ensure_registered(ctx, res); |
10589 | } |
10590 | } |
10591 | } |
10592 | exit : |
10593 | GRN_API_RETURN(res); |
10594 | } |
10595 | |
10596 | grn_bool |
10597 | grn_ctx_is_opened(grn_ctx *ctx, grn_id id) |
10598 | { |
10599 | grn_bool is_opened = GRN_FALSE; |
10600 | |
10601 | if (!ctx || !ctx->impl || !id) { |
10602 | return GRN_FALSE; |
10603 | } |
10604 | |
10605 | GRN_API_ENTER; |
10606 | if (id & GRN_OBJ_TMP_OBJECT) { |
10607 | if (ctx->impl->values) { |
10608 | grn_obj **tmp_obj; |
10609 | tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, |
10610 | id & ~GRN_OBJ_TMP_OBJECT); |
10611 | if (tmp_obj) { |
10612 | is_opened = GRN_TRUE; |
10613 | } |
10614 | } |
10615 | } else { |
10616 | grn_db *s = (grn_db *)ctx->impl->db; |
10617 | if (s) { |
10618 | db_value *vp; |
10619 | vp = grn_tiny_array_at(&s->values, id); |
10620 | if (vp && vp->ptr) { |
10621 | is_opened = GRN_TRUE; |
10622 | } |
10623 | } |
10624 | } |
10625 | GRN_API_RETURN(is_opened); |
10626 | } |
10627 | |
10628 | grn_obj * |
10629 | grn_obj_open(grn_ctx *ctx, unsigned char type, grn_obj_flags flags, grn_id domain) |
10630 | { |
10631 | grn_obj *obj = GRN_MALLOCN(grn_obj, 1); |
10632 | if (obj) { |
10633 | GRN_OBJ_INIT(obj, type, flags, domain); |
10634 | obj->header.impl_flags |= GRN_OBJ_ALLOCATED; |
10635 | } |
10636 | return obj; |
10637 | } |
10638 | |
10639 | grn_obj * |
10640 | grn_obj_graft(grn_ctx *ctx, grn_obj *obj) |
10641 | { |
10642 | grn_obj *new = grn_obj_open(ctx, obj->header.type, obj->header.impl_flags, obj->header.domain); |
10643 | if (new) { |
10644 | /* todo : deep copy if (obj->header.impl_flags & GRN_OBJ_DO_SHALLOW_COPY) */ |
10645 | new->u.b.head = obj->u.b.head; |
10646 | new->u.b.curr = obj->u.b.curr; |
10647 | new->u.b.tail = obj->u.b.tail; |
10648 | obj->u.b.head = NULL; |
10649 | obj->u.b.curr = NULL; |
10650 | obj->u.b.tail = NULL; |
10651 | } |
10652 | return new; |
10653 | } |
10654 | |
10655 | grn_rc |
10656 | grn_pvector_fin(grn_ctx *ctx, grn_obj *obj) |
10657 | { |
10658 | grn_rc rc; |
10659 | if (obj->header.impl_flags & GRN_OBJ_OWN) { |
10660 | /* |
10661 | * Note that GRN_OBJ_OWN should not be used outside the DB API function |
10662 | * because grn_obj_close is a DB API function. |
10663 | */ |
10664 | unsigned int i, n_elements; |
10665 | n_elements = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *); |
10666 | for (i = 0; i < n_elements; i++) { |
10667 | grn_obj *element = GRN_PTR_VALUE_AT(obj, n_elements - i - 1); |
10668 | if (element) { |
10669 | grn_obj_close(ctx, element); |
10670 | } |
10671 | } |
10672 | } |
10673 | obj->header.type = GRN_VOID; |
10674 | rc = grn_bulk_fin(ctx, obj); |
10675 | if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { |
10676 | GRN_FREE(obj); |
10677 | } |
10678 | return rc; |
10679 | } |
10680 | |
10681 | static void |
10682 | grn_table_close_columns(grn_ctx *ctx, grn_obj *table) |
10683 | { |
10684 | grn_hash *columns; |
10685 | int n_columns; |
10686 | |
10687 | columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
10688 | GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); |
10689 | if (!columns) { |
10690 | return; |
10691 | } |
10692 | |
10693 | n_columns = grn_table_columns(ctx, table, "" , 0, (grn_obj *)columns); |
10694 | if (n_columns > 0) { |
10695 | grn_hash_cursor *cursor; |
10696 | cursor = grn_hash_cursor_open(ctx, columns, NULL, 0, NULL, 0, 0, -1, 0); |
10697 | if (cursor) { |
10698 | while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { |
10699 | grn_id *id; |
10700 | grn_obj *column; |
10701 | |
10702 | grn_hash_cursor_get_key(ctx, cursor, (void **)&id); |
10703 | column = grn_ctx_at(ctx, *id); |
10704 | if (column) { |
10705 | grn_obj_close(ctx, column); |
10706 | } |
10707 | } |
10708 | grn_hash_cursor_close(ctx, cursor); |
10709 | } |
10710 | } |
10711 | |
10712 | grn_hash_close(ctx, columns); |
10713 | } |
10714 | |
10715 | grn_rc |
10716 | grn_obj_close(grn_ctx *ctx, grn_obj *obj) |
10717 | { |
10718 | grn_rc rc = GRN_INVALID_ARGUMENT; |
10719 | GRN_API_ENTER; |
10720 | if (obj) { |
10721 | if (grn_obj_is_table(ctx, obj) && |
10722 | (DB_OBJ(obj)->id & GRN_OBJ_TMP_OBJECT)) { |
10723 | grn_table_close_columns(ctx, obj); |
10724 | } |
10725 | if (GRN_DB_OBJP(obj)) { |
10726 | grn_hook_entry entry; |
10727 | if (DB_OBJ(obj)->finalizer) { |
10728 | DB_OBJ(obj)->finalizer(ctx, 1, &obj, &DB_OBJ(obj)->user_data); |
10729 | } |
10730 | if (DB_OBJ(obj)->source) { |
10731 | GRN_FREE(DB_OBJ(obj)->source); |
10732 | } |
10733 | for (entry = 0; entry < N_HOOK_ENTRIES; entry++) { |
10734 | grn_hook_free(ctx, DB_OBJ(obj)->hooks[entry]); |
10735 | } |
10736 | grn_obj_delete_by_id(ctx, DB_OBJ(obj)->db, DB_OBJ(obj)->id, GRN_FALSE); |
10737 | } |
10738 | switch (obj->header.type) { |
10739 | case GRN_VECTOR : |
10740 | if (obj->u.v.body && !(obj->header.impl_flags & GRN_OBJ_REFER)) { |
10741 | grn_obj_close(ctx, obj->u.v.body); |
10742 | } |
10743 | if (obj->u.v.sections) { GRN_FREE(obj->u.v.sections); } |
10744 | if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { GRN_FREE(obj); } |
10745 | rc = GRN_SUCCESS; |
10746 | break; |
10747 | case GRN_VOID : |
10748 | case GRN_BULK : |
10749 | case GRN_UVECTOR : |
10750 | case GRN_MSG : |
10751 | obj->header.type = GRN_VOID; |
10752 | rc = grn_bulk_fin(ctx, obj); |
10753 | if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { GRN_FREE(obj); } |
10754 | break; |
10755 | case GRN_PTR : |
10756 | if (obj->header.impl_flags & GRN_OBJ_OWN) { |
10757 | if (GRN_BULK_VSIZE(obj) == sizeof(grn_obj *)) { |
10758 | grn_obj_close(ctx, GRN_PTR_VALUE(obj)); |
10759 | } |
10760 | } |
10761 | obj->header.type = GRN_VOID; |
10762 | rc = grn_bulk_fin(ctx, obj); |
10763 | if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { GRN_FREE(obj); } |
10764 | break; |
10765 | case GRN_PVECTOR : |
10766 | rc = grn_pvector_fin(ctx, obj); |
10767 | break; |
10768 | case GRN_ACCESSOR : |
10769 | { |
10770 | grn_accessor *p, *n; |
10771 | for (p = (grn_accessor *)obj; p; p = n) { |
10772 | n = p->next; |
10773 | GRN_FREE(p); |
10774 | } |
10775 | } |
10776 | rc = GRN_SUCCESS; |
10777 | break; |
10778 | case GRN_SNIP : |
10779 | rc = grn_snip_close(ctx, (grn_snip *)obj); |
10780 | break; |
10781 | case GRN_STRING : |
10782 | rc = grn_string_close(ctx, obj); |
10783 | break; |
10784 | case GRN_CURSOR_TABLE_PAT_KEY : |
10785 | grn_pat_cursor_close(ctx, (grn_pat_cursor *)obj); |
10786 | break; |
10787 | case GRN_CURSOR_TABLE_DAT_KEY : |
10788 | grn_dat_cursor_close(ctx, (grn_dat_cursor *)obj); |
10789 | break; |
10790 | case GRN_CURSOR_TABLE_HASH_KEY : |
10791 | grn_hash_cursor_close(ctx, (grn_hash_cursor *)obj); |
10792 | break; |
10793 | case GRN_CURSOR_TABLE_NO_KEY : |
10794 | grn_array_cursor_close(ctx, (grn_array_cursor *)obj); |
10795 | break; |
10796 | case GRN_CURSOR_COLUMN_INDEX : |
10797 | { |
10798 | grn_index_cursor *ic = (grn_index_cursor *)obj; |
10799 | if (ic->iic) { grn_ii_cursor_close(ctx, ic->iic); } |
10800 | GRN_FREE(ic); |
10801 | } |
10802 | break; |
10803 | case GRN_CURSOR_COLUMN_GEO_INDEX : |
10804 | grn_geo_cursor_close(ctx, obj); |
10805 | break; |
10806 | case GRN_CURSOR_CONFIG : |
10807 | grn_config_cursor_close(ctx, (grn_config_cursor *)obj); |
10808 | break; |
10809 | case GRN_TYPE : |
10810 | GRN_FREE(obj); |
10811 | rc = GRN_SUCCESS; |
10812 | break; |
10813 | case GRN_DB : |
10814 | rc = grn_db_close(ctx, obj); |
10815 | break; |
10816 | case GRN_TABLE_PAT_KEY : |
10817 | rc = grn_pat_close(ctx, (grn_pat *)obj); |
10818 | break; |
10819 | case GRN_TABLE_DAT_KEY : |
10820 | rc = grn_dat_close(ctx, (grn_dat *)obj); |
10821 | break; |
10822 | case GRN_TABLE_HASH_KEY : |
10823 | rc = grn_hash_close(ctx, (grn_hash *)obj); |
10824 | break; |
10825 | case GRN_TABLE_NO_KEY : |
10826 | rc = grn_array_close(ctx, (grn_array *)obj); |
10827 | break; |
10828 | case GRN_COLUMN_VAR_SIZE : |
10829 | rc = grn_ja_close(ctx, (grn_ja *)obj); |
10830 | break; |
10831 | case GRN_COLUMN_FIX_SIZE : |
10832 | rc = grn_ra_close(ctx, (grn_ra *)obj); |
10833 | break; |
10834 | case GRN_COLUMN_INDEX : |
10835 | rc = grn_ii_close(ctx, (grn_ii *)obj); |
10836 | break; |
10837 | case GRN_PROC : |
10838 | { |
10839 | uint32_t i; |
10840 | grn_proc *p = (grn_proc *)obj; |
10841 | /* |
10842 | if (obj->header.domain) { |
10843 | grn_hash_delete(ctx, ctx->impl->qe, &obj->header.domain, sizeof(grn_id), NULL); |
10844 | } |
10845 | */ |
10846 | for (i = 0; i < p->nvars; i++) { |
10847 | grn_obj_close(ctx, &p->vars[i].value); |
10848 | } |
10849 | GRN_REALLOC(p->vars, 0); |
10850 | grn_obj_close(ctx, &p->name_buf); |
10851 | if (p->obj.range != GRN_ID_NIL) { |
10852 | grn_plugin_close(ctx, p->obj.range); |
10853 | } |
10854 | GRN_FREE(obj); |
10855 | rc = GRN_SUCCESS; |
10856 | } |
10857 | break; |
10858 | case GRN_EXPR : |
10859 | rc = grn_expr_close(ctx, obj); |
10860 | break; |
10861 | } |
10862 | } |
10863 | GRN_API_RETURN(rc); |
10864 | } |
10865 | |
10866 | void |
10867 | grn_obj_unlink(grn_ctx *ctx, grn_obj *obj) |
10868 | { |
10869 | if (obj && |
10870 | (!GRN_DB_OBJP(obj) || |
10871 | (((grn_db_obj *)obj)->id & GRN_OBJ_TMP_OBJECT) || |
10872 | (((grn_db_obj *)obj)->id == GRN_ID_NIL) || |
10873 | obj->header.type == GRN_DB)) { |
10874 | grn_obj_close(ctx, obj); |
10875 | } else if (GRN_DB_OBJP(obj)) { |
10876 | #ifdef USE_NREF |
10877 | grn_db_obj *dob = DB_OBJ(obj); |
10878 | grn_db *s = (grn_db *)dob->db; |
10879 | db_value *vp = grn_tiny_array_at(&s->values, dob->id); |
10880 | if (vp) { |
10881 | uint32_t l, *pl = &vp->lock; |
10882 | if (!vp->lock) { |
10883 | GRN_LOG(ctx, GRN_LOG_ERROR, "invalid unlink(%p,%d)" , obj, vp->lock); |
10884 | return; |
10885 | } |
10886 | GRN_ATOMIC_ADD_EX(pl, -1, l); |
10887 | if (l == 1) { |
10888 | GRN_ATOMIC_ADD_EX(pl, GRN_IO_MAX_REF, l); |
10889 | if (l == GRN_IO_MAX_REF) { |
10890 | #ifdef CALL_FINALIZER |
10891 | grn_obj_close(ctx, obj); |
10892 | vp->done = 0; |
10893 | if (dob->finalizer) { |
10894 | dob->finalizer(ctx, 1, &obj, &dob->user_data); |
10895 | dob->finalizer = NULL; |
10896 | dob->user_data.ptr = NULL; |
10897 | } |
10898 | #endif /* CALL_FINALIZER */ |
10899 | } |
10900 | GRN_ATOMIC_ADD_EX(pl, -GRN_IO_MAX_REF, l); |
10901 | GRN_FUTEX_WAKE(pl); |
10902 | } |
10903 | } |
10904 | #endif /* USE_NREF */ |
10905 | } |
10906 | } |
10907 | |
10908 | #define VECTOR_CLEAR(ctx,obj) do {\ |
10909 | if ((obj)->u.v.body && !((obj)->header.impl_flags & GRN_OBJ_REFER)) {\ |
10910 | grn_obj_close((ctx), (obj)->u.v.body);\ |
10911 | }\ |
10912 | if ((obj)->u.v.sections) { GRN_FREE((obj)->u.v.sections); }\ |
10913 | (obj)->header.impl_flags &= ~GRN_OBJ_DO_SHALLOW_COPY;\ |
10914 | (obj)->u.b.head = NULL;\ |
10915 | (obj)->u.b.curr = NULL;\ |
10916 | (obj)->u.b.tail = NULL;\ |
10917 | } while (0) |
10918 | |
10919 | static void |
10920 | grn_obj_ensure_vector(grn_ctx *ctx, grn_obj *obj) |
10921 | { |
10922 | if (obj->header.type != GRN_VECTOR) { grn_bulk_fin(ctx, obj); } |
10923 | obj->header.type = GRN_VECTOR; |
10924 | obj->header.flags &= ~GRN_OBJ_WITH_WEIGHT; |
10925 | } |
10926 | |
10927 | static void |
10928 | grn_obj_ensure_bulk(grn_ctx *ctx, grn_obj *obj) |
10929 | { |
10930 | if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } |
10931 | obj->header.type = GRN_BULK; |
10932 | obj->header.flags &= ~GRN_OBJ_WITH_WEIGHT; |
10933 | } |
10934 | |
10935 | grn_rc |
10936 | grn_obj_reinit(grn_ctx *ctx, grn_obj *obj, grn_id domain, unsigned char flags) |
10937 | { |
10938 | if (!GRN_OBJ_MUTABLE(obj)) { |
10939 | ERR(GRN_INVALID_ARGUMENT, "invalid obj assigned" ); |
10940 | } else { |
10941 | switch (obj->header.type) { |
10942 | case GRN_PTR : |
10943 | if (obj->header.impl_flags & GRN_OBJ_OWN) { |
10944 | if (GRN_BULK_VSIZE(obj) == sizeof(grn_obj *)) { |
10945 | grn_obj_close(ctx, GRN_PTR_VALUE(obj)); |
10946 | } |
10947 | obj->header.impl_flags &= ~GRN_OBJ_OWN; |
10948 | } |
10949 | break; |
10950 | case GRN_PVECTOR : |
10951 | if (obj->header.impl_flags & GRN_OBJ_OWN) { |
10952 | unsigned int i, n_elements; |
10953 | n_elements = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *); |
10954 | for (i = 0; i < n_elements; i++) { |
10955 | grn_obj *element = GRN_PTR_VALUE_AT(obj, i); |
10956 | grn_obj_close(ctx, element); |
10957 | } |
10958 | obj->header.impl_flags &= ~GRN_OBJ_OWN; |
10959 | } |
10960 | break; |
10961 | default : |
10962 | break; |
10963 | } |
10964 | |
10965 | switch (domain) { |
10966 | case GRN_DB_VOID : |
10967 | if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } |
10968 | obj->header.type = GRN_VOID; |
10969 | obj->header.domain = domain; |
10970 | GRN_BULK_REWIND(obj); |
10971 | break; |
10972 | case GRN_DB_OBJECT : |
10973 | case GRN_DB_BOOL : |
10974 | case GRN_DB_INT8 : |
10975 | case GRN_DB_UINT8 : |
10976 | case GRN_DB_INT16 : |
10977 | case GRN_DB_UINT16 : |
10978 | case GRN_DB_INT32 : |
10979 | case GRN_DB_UINT32 : |
10980 | case GRN_DB_INT64 : |
10981 | case GRN_DB_UINT64 : |
10982 | case GRN_DB_FLOAT : |
10983 | case GRN_DB_TIME : |
10984 | case GRN_DB_TOKYO_GEO_POINT : |
10985 | case GRN_DB_WGS84_GEO_POINT : |
10986 | if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } |
10987 | obj->header.type = (flags & GRN_OBJ_VECTOR) ? GRN_UVECTOR : GRN_BULK; |
10988 | obj->header.domain = domain; |
10989 | GRN_BULK_REWIND(obj); |
10990 | break; |
10991 | case GRN_DB_SHORT_TEXT : |
10992 | case GRN_DB_TEXT : |
10993 | case GRN_DB_LONG_TEXT : |
10994 | if (flags & GRN_OBJ_VECTOR) { |
10995 | if (obj->header.type != GRN_VECTOR) { grn_bulk_fin(ctx, obj); } |
10996 | obj->header.type = GRN_VECTOR; |
10997 | if (obj->u.v.body) { |
10998 | grn_obj_reinit(ctx, obj->u.v.body, domain, 0); |
10999 | } |
11000 | obj->u.v.n_sections = 0; |
11001 | } else { |
11002 | if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } |
11003 | obj->header.type = GRN_BULK; |
11004 | } |
11005 | obj->header.domain = domain; |
11006 | GRN_BULK_REWIND(obj); |
11007 | break; |
11008 | default : |
11009 | { |
11010 | grn_obj *d = grn_ctx_at(ctx, domain); |
11011 | if (!d) { |
11012 | ERR(GRN_INVALID_ARGUMENT, "invalid domain assigned" ); |
11013 | } else { |
11014 | if (d->header.type == GRN_TYPE && (d->header.flags & GRN_OBJ_KEY_VAR_SIZE)) { |
11015 | if (flags & GRN_OBJ_VECTOR) { |
11016 | if (obj->header.type != GRN_VECTOR) { grn_bulk_fin(ctx, obj); } |
11017 | obj->header.type = GRN_VECTOR; |
11018 | } else { |
11019 | if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } |
11020 | obj->header.type = GRN_BULK; |
11021 | } |
11022 | } else { |
11023 | if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } |
11024 | obj->header.type = (flags & GRN_OBJ_VECTOR) ? GRN_UVECTOR : GRN_BULK; |
11025 | } |
11026 | obj->header.domain = domain; |
11027 | GRN_BULK_REWIND(obj); |
11028 | } |
11029 | } |
11030 | break; |
11031 | } |
11032 | } |
11033 | return ctx->rc; |
11034 | } |
11035 | |
11036 | grn_rc |
11037 | grn_obj_reinit_for(grn_ctx *ctx, grn_obj *obj, grn_obj *domain_obj) |
11038 | { |
11039 | grn_id domain = GRN_ID_NIL; |
11040 | grn_obj_flags flags = 0; |
11041 | |
11042 | if (!GRN_DB_OBJP(domain_obj) && domain_obj->header.type != GRN_ACCESSOR) { |
11043 | grn_obj inspected; |
11044 | GRN_TEXT_INIT(&inspected, 0); |
11045 | grn_inspect_limited(ctx, &inspected, domain_obj); |
11046 | ERR(GRN_INVALID_ARGUMENT, |
11047 | "[reinit] invalid domain object: <%.*s>" , |
11048 | (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); |
11049 | GRN_OBJ_FIN(ctx, &inspected); |
11050 | return ctx->rc; |
11051 | } |
11052 | |
11053 | if (grn_column_is_index(ctx, domain_obj)) { |
11054 | domain = GRN_DB_UINT32; |
11055 | } else { |
11056 | grn_obj_get_range_info(ctx, domain_obj, &domain, &flags); |
11057 | if (GRN_OBJ_TABLEP(domain_obj) && |
11058 | domain_obj->header.type != GRN_TABLE_NO_KEY) { |
11059 | domain = domain_obj->header.domain; |
11060 | } |
11061 | } |
11062 | return grn_obj_reinit(ctx, obj, domain, flags); |
11063 | } |
11064 | |
11065 | const char * |
11066 | grn_obj_path(grn_ctx *ctx, grn_obj *obj) |
11067 | { |
11068 | grn_io *io; |
11069 | const char *path = NULL; |
11070 | GRN_API_ENTER; |
11071 | if (obj->header.type == GRN_PROC) { |
11072 | path = grn_plugin_path(ctx, DB_OBJ(obj)->range); |
11073 | GRN_API_RETURN(path); |
11074 | } |
11075 | io = grn_obj_get_io(ctx, obj); |
11076 | if (io && !(io->flags & GRN_IO_TEMPORARY)) { path = io->path; } |
11077 | GRN_API_RETURN(path); |
11078 | } |
11079 | |
11080 | int |
11081 | grn_obj_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size) |
11082 | { |
11083 | int len = 0; |
11084 | GRN_API_ENTER; |
11085 | if (GRN_DB_OBJP(obj)) { |
11086 | if (DB_OBJ(obj)->id) { |
11087 | grn_db *s = (grn_db *)DB_OBJ(obj)->db; |
11088 | grn_id id = DB_OBJ(obj)->id; |
11089 | if (id & GRN_OBJ_TMP_OBJECT) { |
11090 | if (id & GRN_OBJ_TMP_COLUMN) { |
11091 | grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN); |
11092 | len = grn_pat_get_key(ctx, ctx->impl->temporary_columns, |
11093 | real_id, namebuf, buf_size); |
11094 | } |
11095 | } else { |
11096 | len = grn_table_get_key(ctx, s->keys, id, namebuf, buf_size); |
11097 | } |
11098 | } |
11099 | } |
11100 | GRN_API_RETURN(len); |
11101 | } |
11102 | |
11103 | int |
11104 | grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size) |
11105 | { |
11106 | int len = 0; |
11107 | char buf[GRN_TABLE_MAX_KEY_SIZE]; |
11108 | if (!obj) { return len; } |
11109 | GRN_API_ENTER; |
11110 | if (GRN_DB_OBJP(obj)) { |
11111 | grn_id id = DB_OBJ(obj)->id; |
11112 | if (id & GRN_OBJ_TMP_OBJECT) { |
11113 | if (id & GRN_OBJ_TMP_COLUMN) { |
11114 | grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN); |
11115 | len = grn_pat_get_key(ctx, ctx->impl->temporary_columns, |
11116 | real_id, buf, GRN_TABLE_MAX_KEY_SIZE); |
11117 | } |
11118 | } else if (id && id < GRN_ID_MAX) { |
11119 | grn_db *s = (grn_db *)DB_OBJ(obj)->db; |
11120 | len = grn_table_get_key(ctx, s->keys, id, buf, GRN_TABLE_MAX_KEY_SIZE); |
11121 | } |
11122 | if (len) { |
11123 | int cl; |
11124 | char *p = buf, *p0 = p, *pe = p + len; |
11125 | for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) { |
11126 | if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; } |
11127 | } |
11128 | len = pe - p0; |
11129 | if (len && len <= buf_size) { |
11130 | grn_memcpy(namebuf, p0, len); |
11131 | } |
11132 | } |
11133 | } else if (obj->header.type == GRN_ACCESSOR) { |
11134 | grn_obj name; |
11135 | grn_accessor *a; |
11136 | |
11137 | GRN_TEXT_INIT(&name, 0); |
11138 | |
11139 | #define ADD_DELMITER() do { \ |
11140 | if (GRN_TEXT_LEN(&name) > 0) { \ |
11141 | GRN_TEXT_PUTC(ctx, &name, GRN_DB_DELIMITER); \ |
11142 | } \ |
11143 | } while (GRN_FALSE) |
11144 | |
11145 | for (a = (grn_accessor *)obj; a; a = a->next) { |
11146 | switch (a->action) { |
11147 | case GRN_ACCESSOR_GET_ID : |
11148 | ADD_DELMITER(); |
11149 | GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_ID); |
11150 | break; |
11151 | case GRN_ACCESSOR_GET_KEY : |
11152 | if (!a->next) { |
11153 | ADD_DELMITER(); |
11154 | GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_KEY); |
11155 | } |
11156 | break; |
11157 | case GRN_ACCESSOR_GET_VALUE : |
11158 | if (!a->next) { |
11159 | ADD_DELMITER(); |
11160 | GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_VALUE); |
11161 | } |
11162 | break; |
11163 | case GRN_ACCESSOR_GET_SCORE : |
11164 | ADD_DELMITER(); |
11165 | GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_SCORE); |
11166 | break; |
11167 | case GRN_ACCESSOR_GET_NSUBRECS : |
11168 | ADD_DELMITER(); |
11169 | GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_NSUBRECS); |
11170 | break; |
11171 | case GRN_ACCESSOR_GET_MAX : |
11172 | ADD_DELMITER(); |
11173 | GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_MAX); |
11174 | break; |
11175 | case GRN_ACCESSOR_GET_MIN : |
11176 | ADD_DELMITER(); |
11177 | GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_MIN); |
11178 | break; |
11179 | case GRN_ACCESSOR_GET_SUM : |
11180 | ADD_DELMITER(); |
11181 | GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_SUM); |
11182 | break; |
11183 | case GRN_ACCESSOR_GET_AVG : |
11184 | ADD_DELMITER(); |
11185 | GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_AVG); |
11186 | break; |
11187 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
11188 | ADD_DELMITER(); |
11189 | { |
11190 | char column_name[GRN_TABLE_MAX_KEY_SIZE]; |
11191 | int column_name_size; |
11192 | column_name_size = grn_column_name(ctx, a->obj, |
11193 | column_name, |
11194 | GRN_TABLE_MAX_KEY_SIZE); |
11195 | GRN_TEXT_PUT(ctx, &name, column_name, column_name_size); |
11196 | } |
11197 | break; |
11198 | case GRN_ACCESSOR_GET_DB_OBJ : |
11199 | case GRN_ACCESSOR_LOOKUP : |
11200 | case GRN_ACCESSOR_FUNCALL : |
11201 | break; |
11202 | } |
11203 | } |
11204 | #undef ADD_DELIMITER |
11205 | |
11206 | len = GRN_TEXT_LEN(&name); |
11207 | if (len > 0 && len <= buf_size) { |
11208 | grn_memcpy(namebuf, GRN_TEXT_VALUE(&name), len); |
11209 | } |
11210 | |
11211 | GRN_OBJ_FIN(ctx, &name); |
11212 | } |
11213 | GRN_API_RETURN(len); |
11214 | } |
11215 | |
11216 | grn_rc |
11217 | grn_column_name_(grn_ctx *ctx, grn_obj *obj, grn_obj *buf) |
11218 | { |
11219 | if (GRN_DB_OBJP(obj)) { |
11220 | uint32_t len = 0; |
11221 | const char *p = NULL; |
11222 | grn_id id = DB_OBJ(obj)->id; |
11223 | if (id & GRN_OBJ_TMP_OBJECT) { |
11224 | if (id & GRN_OBJ_TMP_COLUMN) { |
11225 | grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN); |
11226 | p = _grn_pat_key(ctx, ctx->impl->temporary_columns, real_id, &len); |
11227 | } |
11228 | } else if (id && id < GRN_ID_MAX) { |
11229 | grn_db *s = (grn_db *)DB_OBJ(obj)->db; |
11230 | p = _grn_table_key(ctx, s->keys, id, &len); |
11231 | } |
11232 | if (len) { |
11233 | int cl; |
11234 | const char *p0 = p, *pe = p + len; |
11235 | for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) { |
11236 | if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; } |
11237 | } |
11238 | GRN_TEXT_PUT(ctx, buf, p0, pe - p0); |
11239 | } |
11240 | } else if (obj->header.type == GRN_ACCESSOR) { |
11241 | grn_accessor *a; |
11242 | for (a = (grn_accessor *)obj; a; a = a->next) { |
11243 | switch (a->action) { |
11244 | case GRN_ACCESSOR_GET_ID : |
11245 | GRN_TEXT_PUT(ctx, buf, GRN_COLUMN_NAME_ID, GRN_COLUMN_NAME_ID_LEN); |
11246 | break; |
11247 | case GRN_ACCESSOR_GET_KEY : |
11248 | if (!a->next) { |
11249 | GRN_TEXT_PUT(ctx, buf, GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_KEY_LEN); |
11250 | } |
11251 | break; |
11252 | case GRN_ACCESSOR_GET_VALUE : |
11253 | if (!a->next) { |
11254 | GRN_TEXT_PUT(ctx, buf, |
11255 | GRN_COLUMN_NAME_VALUE, |
11256 | GRN_COLUMN_NAME_VALUE_LEN); |
11257 | } |
11258 | break; |
11259 | case GRN_ACCESSOR_GET_SCORE : |
11260 | GRN_TEXT_PUT(ctx, buf, |
11261 | GRN_COLUMN_NAME_SCORE, |
11262 | GRN_COLUMN_NAME_SCORE_LEN); |
11263 | break; |
11264 | case GRN_ACCESSOR_GET_NSUBRECS : |
11265 | GRN_TEXT_PUT(ctx, buf, |
11266 | GRN_COLUMN_NAME_NSUBRECS, |
11267 | GRN_COLUMN_NAME_NSUBRECS_LEN); |
11268 | break; |
11269 | case GRN_ACCESSOR_GET_MAX : |
11270 | GRN_TEXT_PUT(ctx, buf, |
11271 | GRN_COLUMN_NAME_MAX, |
11272 | GRN_COLUMN_NAME_MAX_LEN); |
11273 | break; |
11274 | case GRN_ACCESSOR_GET_MIN : |
11275 | GRN_TEXT_PUT(ctx, buf, |
11276 | GRN_COLUMN_NAME_MIN, |
11277 | GRN_COLUMN_NAME_MIN_LEN); |
11278 | break; |
11279 | case GRN_ACCESSOR_GET_SUM : |
11280 | GRN_TEXT_PUT(ctx, buf, |
11281 | GRN_COLUMN_NAME_SUM, |
11282 | GRN_COLUMN_NAME_SUM_LEN); |
11283 | break; |
11284 | case GRN_ACCESSOR_GET_AVG : |
11285 | GRN_TEXT_PUT(ctx, buf, |
11286 | GRN_COLUMN_NAME_AVG, |
11287 | GRN_COLUMN_NAME_AVG_LEN); |
11288 | break; |
11289 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
11290 | grn_column_name_(ctx, a->obj, buf); |
11291 | if (a->next) { GRN_TEXT_PUTC(ctx, buf, '.'); } |
11292 | break; |
11293 | case GRN_ACCESSOR_GET_DB_OBJ : |
11294 | case GRN_ACCESSOR_LOOKUP : |
11295 | case GRN_ACCESSOR_FUNCALL : |
11296 | break; |
11297 | } |
11298 | } |
11299 | } |
11300 | return ctx->rc; |
11301 | } |
11302 | |
11303 | int |
11304 | grn_obj_expire(grn_ctx *ctx, grn_obj *obj, int threshold) |
11305 | { |
11306 | GRN_API_ENTER; |
11307 | GRN_API_RETURN(0); |
11308 | } |
11309 | |
11310 | int |
11311 | grn_obj_check(grn_ctx *ctx, grn_obj *obj) |
11312 | { |
11313 | GRN_API_ENTER; |
11314 | GRN_API_RETURN(0); |
11315 | } |
11316 | |
11317 | grn_rc |
11318 | grn_obj_lock(grn_ctx *ctx, grn_obj *obj, grn_id id, int timeout) |
11319 | { |
11320 | grn_rc rc = GRN_SUCCESS; |
11321 | GRN_API_ENTER; |
11322 | rc = grn_io_lock(ctx, grn_obj_get_io(ctx, obj), timeout); |
11323 | if (rc == GRN_SUCCESS && obj && obj->header.type == GRN_COLUMN_INDEX) { |
11324 | rc = grn_io_lock(ctx, ((grn_ii *)obj)->chunk, timeout); |
11325 | } |
11326 | GRN_API_RETURN(rc); |
11327 | } |
11328 | |
11329 | grn_rc |
11330 | grn_obj_unlock(grn_ctx *ctx, grn_obj *obj, grn_id id) |
11331 | { |
11332 | GRN_API_ENTER; |
11333 | if (obj && obj->header.type == GRN_COLUMN_INDEX) { |
11334 | grn_io_unlock(((grn_ii *)obj)->chunk); |
11335 | } |
11336 | grn_io_unlock(grn_obj_get_io(ctx, obj)); |
11337 | GRN_API_RETURN(GRN_SUCCESS); |
11338 | } |
11339 | |
11340 | grn_user_data * |
11341 | grn_obj_user_data(grn_ctx *ctx, grn_obj *obj) |
11342 | { |
11343 | if (!GRN_DB_OBJP(obj)) { return NULL; } |
11344 | return &DB_OBJ(obj)->user_data; |
11345 | } |
11346 | |
11347 | grn_rc |
11348 | grn_obj_set_finalizer(grn_ctx *ctx, grn_obj *obj, grn_proc_func *func) |
11349 | { |
11350 | if (!GRN_DB_OBJP(obj)) { return GRN_INVALID_ARGUMENT; } |
11351 | DB_OBJ(obj)->finalizer = func; |
11352 | return GRN_SUCCESS; |
11353 | } |
11354 | |
11355 | grn_rc |
11356 | grn_obj_clear_lock(grn_ctx *ctx, grn_obj *obj) |
11357 | { |
11358 | GRN_API_ENTER; |
11359 | switch (obj->header.type) { |
11360 | case GRN_DB: |
11361 | { |
11362 | grn_table_cursor *cur; |
11363 | if ((cur = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, 0, -1, 0))) { |
11364 | grn_id id; |
11365 | while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { |
11366 | grn_obj *tbl = grn_ctx_at(ctx, id); |
11367 | if (tbl) { |
11368 | switch (tbl->header.type) { |
11369 | case GRN_TABLE_HASH_KEY : |
11370 | case GRN_TABLE_PAT_KEY: |
11371 | case GRN_TABLE_DAT_KEY: |
11372 | case GRN_TABLE_NO_KEY: |
11373 | grn_obj_clear_lock(ctx, tbl); |
11374 | break; |
11375 | } |
11376 | } else { |
11377 | if (ctx->rc != GRN_SUCCESS) { |
11378 | ERRCLR(ctx); |
11379 | } |
11380 | } |
11381 | } |
11382 | grn_table_cursor_close(ctx, cur); |
11383 | } |
11384 | } |
11385 | grn_io_clear_lock(grn_obj_get_io(ctx, obj)); |
11386 | { |
11387 | grn_db *db = (grn_db *)obj; |
11388 | if (db->specs) { |
11389 | grn_obj_clear_lock(ctx, (grn_obj *)(db->specs)); |
11390 | } |
11391 | } |
11392 | break; |
11393 | case GRN_TABLE_NO_KEY : |
11394 | grn_array_queue_lock_clear(ctx, (grn_array *)obj); |
11395 | /* fallthru */ |
11396 | case GRN_TABLE_HASH_KEY : |
11397 | case GRN_TABLE_PAT_KEY : |
11398 | case GRN_TABLE_DAT_KEY : |
11399 | { |
11400 | grn_hash *cols; |
11401 | if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
11402 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { |
11403 | if (grn_table_columns(ctx, obj, "" , 0, (grn_obj *)cols)) { |
11404 | grn_id *key; |
11405 | GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { |
11406 | grn_obj *col = grn_ctx_at(ctx, *key); |
11407 | if (col) { grn_obj_clear_lock(ctx, col); } |
11408 | }); |
11409 | } |
11410 | grn_hash_close(ctx, cols); |
11411 | } |
11412 | grn_io_clear_lock(grn_obj_get_io(ctx, obj)); |
11413 | } |
11414 | break; |
11415 | case GRN_COLUMN_FIX_SIZE: |
11416 | case GRN_COLUMN_VAR_SIZE: |
11417 | grn_io_clear_lock(grn_obj_get_io(ctx, obj)); |
11418 | break; |
11419 | case GRN_COLUMN_INDEX: |
11420 | grn_io_clear_lock(grn_obj_get_io(ctx, obj)); |
11421 | if (obj) { |
11422 | grn_io_clear_lock(((grn_ii *)obj)->chunk); |
11423 | } |
11424 | break; |
11425 | } |
11426 | GRN_API_RETURN(GRN_SUCCESS); |
11427 | } |
11428 | |
11429 | unsigned int |
11430 | grn_obj_is_locked(grn_ctx *ctx, grn_obj *obj) |
11431 | { |
11432 | unsigned int res = 0; |
11433 | GRN_API_ENTER; |
11434 | res = grn_io_is_locked(grn_obj_get_io(ctx, obj)); |
11435 | if (obj && obj->header.type == GRN_COLUMN_INDEX) { |
11436 | res += grn_io_is_locked(((grn_ii *)obj)->chunk); |
11437 | } |
11438 | GRN_API_RETURN(res); |
11439 | } |
11440 | |
11441 | grn_rc |
11442 | grn_obj_flush(grn_ctx *ctx, grn_obj *obj) |
11443 | { |
11444 | grn_rc rc = GRN_SUCCESS; |
11445 | |
11446 | GRN_API_ENTER; |
11447 | |
11448 | switch (obj->header.type) { |
11449 | case GRN_DB : |
11450 | { |
11451 | grn_db *db = (grn_db *)obj; |
11452 | rc = grn_obj_flush(ctx, db->keys); |
11453 | if (rc == GRN_SUCCESS && db->specs) { |
11454 | rc = grn_obj_flush(ctx, (grn_obj *)(db->specs)); |
11455 | } |
11456 | if (rc == GRN_SUCCESS) { |
11457 | rc = grn_obj_flush(ctx, (grn_obj *)(db->config)); |
11458 | } |
11459 | } |
11460 | break; |
11461 | case GRN_TABLE_DAT_KEY : |
11462 | rc = grn_dat_flush(ctx, (grn_dat *)obj); |
11463 | break; |
11464 | case GRN_COLUMN_INDEX : |
11465 | rc = grn_ii_flush(ctx, (grn_ii *)obj); |
11466 | break; |
11467 | default : |
11468 | { |
11469 | grn_io *io; |
11470 | io = grn_obj_get_io(ctx, obj); |
11471 | if (io) { |
11472 | rc = grn_io_flush(ctx, io); |
11473 | } |
11474 | } |
11475 | break; |
11476 | } |
11477 | |
11478 | if (rc == GRN_SUCCESS && |
11479 | GRN_DB_OBJP(obj) && |
11480 | DB_OBJ(obj)->id != GRN_ID_NIL && |
11481 | !IS_TEMP(obj)) { |
11482 | rc = grn_db_clean(ctx, DB_OBJ(obj)->db); |
11483 | } |
11484 | |
11485 | GRN_API_RETURN(rc); |
11486 | } |
11487 | |
11488 | grn_rc |
11489 | grn_obj_flush_recursive(grn_ctx *ctx, grn_obj *obj) |
11490 | { |
11491 | grn_rc rc = GRN_SUCCESS; |
11492 | |
11493 | GRN_API_ENTER; |
11494 | switch (obj->header.type) { |
11495 | case GRN_DB : |
11496 | { |
11497 | grn_table_cursor *cursor; |
11498 | grn_id id; |
11499 | |
11500 | cursor = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, 0, -1, 0); |
11501 | if (!cursor) { |
11502 | GRN_API_RETURN(ctx->rc); |
11503 | } |
11504 | |
11505 | while ((id = grn_table_cursor_next_inline(ctx, cursor)) != GRN_ID_NIL) { |
11506 | grn_obj *table = grn_ctx_at(ctx, id); |
11507 | rc = GRN_SUCCESS; |
11508 | if (table) { |
11509 | switch (table->header.type) { |
11510 | case GRN_TABLE_HASH_KEY : |
11511 | case GRN_TABLE_PAT_KEY: |
11512 | case GRN_TABLE_DAT_KEY: |
11513 | case GRN_TABLE_NO_KEY: |
11514 | rc = grn_obj_flush_recursive(ctx, table); |
11515 | break; |
11516 | } |
11517 | } else { |
11518 | if (ctx->rc != GRN_SUCCESS) { |
11519 | ERRCLR(ctx); |
11520 | } |
11521 | } |
11522 | if (rc != GRN_SUCCESS) { |
11523 | break; |
11524 | } |
11525 | } |
11526 | grn_table_cursor_close(ctx, cursor); |
11527 | } |
11528 | if (rc == GRN_SUCCESS) { |
11529 | rc = grn_obj_flush(ctx, obj); |
11530 | } |
11531 | break; |
11532 | case GRN_TABLE_NO_KEY : |
11533 | case GRN_TABLE_HASH_KEY : |
11534 | case GRN_TABLE_PAT_KEY : |
11535 | case GRN_TABLE_DAT_KEY : |
11536 | { |
11537 | grn_hash *columns; |
11538 | columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
11539 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); |
11540 | if (!columns) { |
11541 | GRN_API_RETURN(ctx->rc); |
11542 | } |
11543 | |
11544 | if (grn_table_columns(ctx, obj, "" , 0, (grn_obj *)columns) > 0) { |
11545 | grn_id *key; |
11546 | GRN_HASH_EACH(ctx, columns, id, &key, NULL, NULL, { |
11547 | grn_obj *column = grn_ctx_at(ctx, *key); |
11548 | if (column) { |
11549 | rc = grn_obj_flush(ctx, column); |
11550 | if (rc != GRN_SUCCESS) { |
11551 | break; |
11552 | } |
11553 | } |
11554 | }); |
11555 | } |
11556 | grn_hash_close(ctx, columns); |
11557 | } |
11558 | |
11559 | if (rc == GRN_SUCCESS) { |
11560 | rc = grn_obj_flush(ctx, obj); |
11561 | } |
11562 | break; |
11563 | case GRN_COLUMN_FIX_SIZE : |
11564 | case GRN_COLUMN_VAR_SIZE : |
11565 | case GRN_COLUMN_INDEX : |
11566 | rc = grn_obj_flush(ctx, obj); |
11567 | break; |
11568 | default : |
11569 | { |
11570 | grn_obj inspected; |
11571 | GRN_TEXT_INIT(&inspected, 0); |
11572 | grn_inspect(ctx, &inspected, obj); |
11573 | ERR(GRN_INVALID_ARGUMENT, |
11574 | "[flush] object must be DB, table or column: <%.*s>" , |
11575 | (int)GRN_TEXT_LEN(&inspected), |
11576 | GRN_TEXT_VALUE(&inspected)); |
11577 | rc = ctx->rc; |
11578 | GRN_OBJ_FIN(ctx, &inspected); |
11579 | } |
11580 | break; |
11581 | } |
11582 | |
11583 | GRN_API_RETURN(rc); |
11584 | } |
11585 | |
11586 | grn_obj * |
11587 | grn_obj_db(grn_ctx *ctx, grn_obj *obj) |
11588 | { |
11589 | grn_obj *db = NULL; |
11590 | GRN_API_ENTER; |
11591 | if (GRN_DB_OBJP(obj)) { db = DB_OBJ(obj)->db; } |
11592 | GRN_API_RETURN(db); |
11593 | } |
11594 | |
11595 | grn_id |
11596 | grn_obj_id(grn_ctx *ctx, grn_obj *obj) |
11597 | { |
11598 | grn_id id = GRN_ID_NIL; |
11599 | GRN_API_ENTER; |
11600 | if (GRN_DB_OBJP(obj)) { |
11601 | id = DB_OBJ(obj)->id; |
11602 | } |
11603 | GRN_API_RETURN(id); |
11604 | } |
11605 | |
11606 | int |
11607 | grn_obj_defrag(grn_ctx *ctx, grn_obj *obj, int threshold) |
11608 | { |
11609 | int r = 0; |
11610 | GRN_API_ENTER; |
11611 | switch (obj->header.type) { |
11612 | case GRN_DB: |
11613 | { |
11614 | grn_table_cursor *cur; |
11615 | if ((cur = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, 0, -1, 0))) { |
11616 | grn_id id; |
11617 | while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { |
11618 | grn_obj *ja = grn_ctx_at(ctx, id); |
11619 | if (ja && ja->header.type == GRN_COLUMN_VAR_SIZE) { |
11620 | r += grn_ja_defrag(ctx, (grn_ja *)ja, threshold); |
11621 | } |
11622 | } |
11623 | grn_table_cursor_close(ctx, cur); |
11624 | } |
11625 | } |
11626 | break; |
11627 | case GRN_TABLE_HASH_KEY : |
11628 | case GRN_TABLE_PAT_KEY : |
11629 | case GRN_TABLE_DAT_KEY : |
11630 | case GRN_TABLE_NO_KEY : |
11631 | { |
11632 | grn_hash *cols; |
11633 | if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
11634 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { |
11635 | if (grn_table_columns(ctx, obj, "" , 0, (grn_obj *)cols)) { |
11636 | grn_id *key; |
11637 | GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { |
11638 | grn_obj *col = grn_ctx_at(ctx, *key); |
11639 | if (col) { |
11640 | r += grn_obj_defrag(ctx, col, threshold); |
11641 | grn_obj_unlink(ctx, col); |
11642 | } |
11643 | }); |
11644 | } |
11645 | grn_hash_close(ctx, cols); |
11646 | } |
11647 | } |
11648 | break; |
11649 | case GRN_COLUMN_VAR_SIZE: |
11650 | r = grn_ja_defrag(ctx, (grn_ja *)obj, threshold); |
11651 | break; |
11652 | } |
11653 | GRN_API_RETURN(r); |
11654 | } |
11655 | |
11656 | /**** sort ****/ |
11657 | |
11658 | typedef struct { |
11659 | grn_id id; |
11660 | uint32_t size; |
11661 | const void *value; |
11662 | } sort_reference_entry; |
11663 | |
11664 | enum { |
11665 | KEY_ID = 0, |
11666 | KEY_BULK, |
11667 | KEY_INT8, |
11668 | KEY_INT16, |
11669 | KEY_INT32, |
11670 | KEY_INT64, |
11671 | KEY_UINT8, |
11672 | KEY_UINT16, |
11673 | KEY_UINT32, |
11674 | KEY_UINT64, |
11675 | KEY_FLOAT32, |
11676 | KEY_FLOAT64, |
11677 | }; |
11678 | |
11679 | #define CMPNUM(type) do {\ |
11680 | if (as) {\ |
11681 | if (bs) {\ |
11682 | type va = *((type *)(ap));\ |
11683 | type vb = *((type *)(bp));\ |
11684 | if (va != vb) { return va > vb; }\ |
11685 | } else {\ |
11686 | return 1;\ |
11687 | }\ |
11688 | } else {\ |
11689 | if (bs) { return 0; }\ |
11690 | }\ |
11691 | } while (0) |
11692 | |
11693 | inline static int |
11694 | compare_reference(grn_ctx *ctx, |
11695 | sort_reference_entry *a, sort_reference_entry *b, |
11696 | grn_table_sort_key *keys, int n_keys) |
11697 | { |
11698 | int i; |
11699 | uint8_t type; |
11700 | uint32_t as, bs; |
11701 | const unsigned char *ap, *bp; |
11702 | for (i = 0; i < n_keys; i++, keys++) { |
11703 | if (i) { |
11704 | const char *ap_raw, *bp_raw; |
11705 | if (keys->flags & GRN_TABLE_SORT_DESC) { |
11706 | ap_raw = grn_obj_get_value_(ctx, keys->key, b->id, &as); |
11707 | bp_raw = grn_obj_get_value_(ctx, keys->key, a->id, &bs); |
11708 | } else { |
11709 | ap_raw = grn_obj_get_value_(ctx, keys->key, a->id, &as); |
11710 | bp_raw = grn_obj_get_value_(ctx, keys->key, b->id, &bs); |
11711 | } |
11712 | ap = (const unsigned char *)ap_raw; |
11713 | bp = (const unsigned char *)bp_raw; |
11714 | } else { |
11715 | if (keys->flags & GRN_TABLE_SORT_DESC) { |
11716 | ap = b->value; as = b->size; |
11717 | bp = a->value; bs = a->size; |
11718 | } else { |
11719 | ap = a->value; as = a->size; |
11720 | bp = b->value; bs = b->size; |
11721 | } |
11722 | } |
11723 | type = keys->offset; |
11724 | switch (type) { |
11725 | case KEY_ID : |
11726 | if (ap != bp) { return ap > bp; } |
11727 | break; |
11728 | case KEY_BULK : |
11729 | for (;; ap++, bp++, as--, bs--) { |
11730 | if (!as) { if (bs) { return 0; } else { break; } } |
11731 | if (!bs) { return 1; } |
11732 | if (*ap < *bp) { return 0; } |
11733 | if (*ap > *bp) { return 1; } |
11734 | } |
11735 | break; |
11736 | case KEY_INT8 : |
11737 | CMPNUM(int8_t); |
11738 | break; |
11739 | case KEY_INT16 : |
11740 | CMPNUM(int16_t); |
11741 | break; |
11742 | case KEY_INT32 : |
11743 | CMPNUM(int32_t); |
11744 | break; |
11745 | case KEY_INT64 : |
11746 | CMPNUM(int64_t); |
11747 | break; |
11748 | case KEY_UINT8 : |
11749 | CMPNUM(uint8_t); |
11750 | break; |
11751 | case KEY_UINT16 : |
11752 | CMPNUM(uint16_t); |
11753 | break; |
11754 | case KEY_UINT32 : |
11755 | CMPNUM(uint32_t); |
11756 | break; |
11757 | case KEY_UINT64 : |
11758 | CMPNUM(uint64_t); |
11759 | break; |
11760 | case KEY_FLOAT32 : |
11761 | if (as) { |
11762 | if (bs) { |
11763 | float va = *((float *)(ap)); |
11764 | float vb = *((float *)(bp)); |
11765 | if (va < vb || va > vb) { return va > vb; } |
11766 | } else { |
11767 | return 1; |
11768 | } |
11769 | } else { |
11770 | if (bs) { return 0; } |
11771 | } |
11772 | break; |
11773 | case KEY_FLOAT64 : |
11774 | if (as) { |
11775 | if (bs) { |
11776 | double va = *((double *)(ap)); |
11777 | double vb = *((double *)(bp)); |
11778 | if (va < vb || va > vb) { return va > vb; } |
11779 | } else { |
11780 | return 1; |
11781 | } |
11782 | } else { |
11783 | if (bs) { return 0; } |
11784 | } |
11785 | break; |
11786 | } |
11787 | } |
11788 | return 0; |
11789 | } |
11790 | |
11791 | inline static void |
11792 | swap_reference(sort_reference_entry *a, sort_reference_entry *b) |
11793 | { |
11794 | sort_reference_entry c_ = *a; |
11795 | *a = *b; |
11796 | *b = c_; |
11797 | } |
11798 | |
11799 | inline static sort_reference_entry * |
11800 | part_reference(grn_ctx *ctx, |
11801 | sort_reference_entry *b, sort_reference_entry *e, |
11802 | grn_table_sort_key *keys, int n_keys) |
11803 | { |
11804 | sort_reference_entry *c; |
11805 | intptr_t d = e - b; |
11806 | if (compare_reference(ctx, b, e, keys, n_keys)) { |
11807 | swap_reference(b, e); |
11808 | } |
11809 | if (d < 2) { return NULL; } |
11810 | c = b + (d >> 1); |
11811 | if (compare_reference(ctx, b, c, keys, n_keys)) { |
11812 | swap_reference(b, c); |
11813 | } else { |
11814 | if (compare_reference(ctx, c, e, keys, n_keys)) { |
11815 | swap_reference(c, e); |
11816 | } |
11817 | } |
11818 | if (d < 3) { return NULL; } |
11819 | b++; |
11820 | swap_reference(b, c); |
11821 | c = b; |
11822 | for (;;) { |
11823 | do { |
11824 | b++; |
11825 | } while (compare_reference(ctx, c, b, keys, n_keys)); |
11826 | do { |
11827 | e--; |
11828 | } while (compare_reference(ctx, e, c, keys, n_keys)); |
11829 | if (b >= e) { break; } |
11830 | swap_reference(b, e); |
11831 | } |
11832 | swap_reference(c, e); |
11833 | return e; |
11834 | } |
11835 | |
11836 | static void |
11837 | sort_reference(grn_ctx *ctx, |
11838 | sort_reference_entry *head, sort_reference_entry *tail, |
11839 | int from, int to, |
11840 | grn_table_sort_key *keys, int n_keys) |
11841 | { |
11842 | sort_reference_entry *c; |
11843 | if (head < tail && (c = part_reference(ctx, head, tail, keys, n_keys))) { |
11844 | intptr_t m = c - head + 1; |
11845 | if (from < m - 1) { |
11846 | sort_reference(ctx, head, c - 1, from, to, keys, n_keys); |
11847 | } |
11848 | if (m < to) { |
11849 | sort_reference(ctx, c + 1, tail, from - m, to - m, keys, n_keys); |
11850 | } |
11851 | } |
11852 | } |
11853 | |
11854 | static sort_reference_entry * |
11855 | pack_reference(grn_ctx *ctx, grn_obj *table, |
11856 | sort_reference_entry *head, sort_reference_entry *tail, |
11857 | grn_table_sort_key *keys, int n_keys) |
11858 | { |
11859 | int i = 0; |
11860 | sort_reference_entry e, c; |
11861 | grn_table_cursor *tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); |
11862 | if (!tc) { return NULL; } |
11863 | if ((c.id = grn_table_cursor_next_inline(ctx, tc))) { |
11864 | c.value = grn_obj_get_value_(ctx, keys->key, c.id, &c.size); |
11865 | while ((e.id = grn_table_cursor_next_inline(ctx, tc))) { |
11866 | e.value = grn_obj_get_value_(ctx, keys->key, e.id, &e.size); |
11867 | if (compare_reference(ctx, &c, &e, keys, n_keys)) { |
11868 | *head++ = e; |
11869 | } else { |
11870 | *tail-- = e; |
11871 | } |
11872 | i++; |
11873 | } |
11874 | *head = c; |
11875 | i++; |
11876 | } |
11877 | grn_table_cursor_close(ctx, tc); |
11878 | return i > 2 ? head : NULL; |
11879 | } |
11880 | |
11881 | static int |
11882 | grn_table_sort_reference(grn_ctx *ctx, grn_obj *table, |
11883 | int offset, int limit, |
11884 | grn_obj *result, |
11885 | grn_table_sort_key *keys, int n_keys) |
11886 | { |
11887 | int e, n; |
11888 | sort_reference_entry *array, *ep; |
11889 | e = offset + limit; |
11890 | n = grn_table_size(ctx, table); |
11891 | if (!(array = GRN_MALLOC(sizeof(sort_reference_entry) * n))) { |
11892 | return 0; |
11893 | } |
11894 | if ((ep = pack_reference(ctx, table, array, array + n - 1, keys, n_keys))) { |
11895 | intptr_t m = ep - array + 1; |
11896 | if (offset < m - 1) { |
11897 | sort_reference(ctx, array, ep - 1, offset, e, keys, n_keys); |
11898 | } |
11899 | if (m < e) { |
11900 | sort_reference(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys); |
11901 | } |
11902 | } |
11903 | { |
11904 | int i; |
11905 | grn_id *v; |
11906 | for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) { |
11907 | if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } |
11908 | *v = ep->id; |
11909 | } |
11910 | GRN_FREE(array); |
11911 | return i; |
11912 | } |
11913 | } |
11914 | |
11915 | |
11916 | typedef struct { |
11917 | grn_id id; |
11918 | grn_obj value; |
11919 | } sort_value_entry; |
11920 | |
11921 | inline static int |
11922 | compare_value(grn_ctx *ctx, |
11923 | sort_value_entry *a, sort_value_entry *b, |
11924 | grn_table_sort_key *keys, int n_keys, |
11925 | grn_obj *a_buffer, grn_obj *b_buffer) |
11926 | { |
11927 | int i; |
11928 | uint8_t type; |
11929 | uint32_t as, bs; |
11930 | const unsigned char *ap, *bp; |
11931 | for (i = 0; i < n_keys; i++, keys++) { |
11932 | if (i) { |
11933 | GRN_BULK_REWIND(a_buffer); |
11934 | GRN_BULK_REWIND(b_buffer); |
11935 | if (keys->flags & GRN_TABLE_SORT_DESC) { |
11936 | grn_obj_get_value(ctx, keys->key, b->id, a_buffer); |
11937 | grn_obj_get_value(ctx, keys->key, a->id, b_buffer); |
11938 | } else { |
11939 | grn_obj_get_value(ctx, keys->key, a->id, a_buffer); |
11940 | grn_obj_get_value(ctx, keys->key, b->id, b_buffer); |
11941 | } |
11942 | ap = (const unsigned char *)GRN_BULK_HEAD(a_buffer); |
11943 | as = GRN_BULK_VSIZE(a_buffer); |
11944 | bp = (const unsigned char *)GRN_BULK_HEAD(b_buffer); |
11945 | bs = GRN_BULK_VSIZE(b_buffer); |
11946 | } else { |
11947 | if (keys->flags & GRN_TABLE_SORT_DESC) { |
11948 | ap = (const unsigned char *)GRN_BULK_HEAD(&b->value); |
11949 | as = GRN_BULK_VSIZE(&b->value); |
11950 | bp = (const unsigned char *)GRN_BULK_HEAD(&a->value); |
11951 | bs = GRN_BULK_VSIZE(&a->value); |
11952 | } else { |
11953 | ap = (const unsigned char *)GRN_BULK_HEAD(&a->value); |
11954 | as = GRN_BULK_VSIZE(&a->value); |
11955 | bp = (const unsigned char *)GRN_BULK_HEAD(&b->value); |
11956 | bs = GRN_BULK_VSIZE(&b->value); |
11957 | } |
11958 | } |
11959 | type = keys->offset; |
11960 | switch (type) { |
11961 | case KEY_ID : |
11962 | if (ap != bp) { return ap > bp; } |
11963 | break; |
11964 | case KEY_BULK : |
11965 | for (;; ap++, bp++, as--, bs--) { |
11966 | if (!as) { if (bs) { return 0; } else { break; } } |
11967 | if (!bs) { return 1; } |
11968 | if (*ap < *bp) { return 0; } |
11969 | if (*ap > *bp) { return 1; } |
11970 | } |
11971 | break; |
11972 | case KEY_INT8 : |
11973 | CMPNUM(int8_t); |
11974 | break; |
11975 | case KEY_INT16 : |
11976 | CMPNUM(int16_t); |
11977 | break; |
11978 | case KEY_INT32 : |
11979 | CMPNUM(int32_t); |
11980 | break; |
11981 | case KEY_INT64 : |
11982 | CMPNUM(int64_t); |
11983 | break; |
11984 | case KEY_UINT8 : |
11985 | CMPNUM(uint8_t); |
11986 | break; |
11987 | case KEY_UINT16 : |
11988 | CMPNUM(uint16_t); |
11989 | break; |
11990 | case KEY_UINT32 : |
11991 | CMPNUM(uint32_t); |
11992 | break; |
11993 | case KEY_UINT64 : |
11994 | CMPNUM(uint64_t); |
11995 | break; |
11996 | case KEY_FLOAT32 : |
11997 | if (as) { |
11998 | if (bs) { |
11999 | float va = *((float *)(ap)); |
12000 | float vb = *((float *)(bp)); |
12001 | if (va < vb || va > vb) { return va > vb; } |
12002 | } else { |
12003 | return 1; |
12004 | } |
12005 | } else { |
12006 | if (bs) { return 0; } |
12007 | } |
12008 | break; |
12009 | case KEY_FLOAT64 : |
12010 | if (as) { |
12011 | if (bs) { |
12012 | double va = *((double *)(ap)); |
12013 | double vb = *((double *)(bp)); |
12014 | if (va < vb || va > vb) { return va > vb; } |
12015 | } else { |
12016 | return 1; |
12017 | } |
12018 | } else { |
12019 | if (bs) { return 0; } |
12020 | } |
12021 | break; |
12022 | } |
12023 | } |
12024 | return 0; |
12025 | } |
12026 | |
12027 | inline static void |
12028 | swap_value(sort_value_entry *a, sort_value_entry *b) |
12029 | { |
12030 | sort_value_entry c_ = *a; |
12031 | *a = *b; |
12032 | *b = c_; |
12033 | } |
12034 | |
12035 | inline static sort_value_entry * |
12036 | part_value(grn_ctx *ctx, |
12037 | sort_value_entry *b, sort_value_entry *e, |
12038 | grn_table_sort_key *keys, int n_keys, |
12039 | grn_obj *a_buffer, grn_obj *b_buffer) |
12040 | { |
12041 | sort_value_entry *c; |
12042 | intptr_t d = e - b; |
12043 | if (compare_value(ctx, b, e, keys, n_keys, a_buffer, b_buffer)) { |
12044 | swap_value(b, e); |
12045 | } |
12046 | if (d < 2) { return NULL; } |
12047 | c = b + (d >> 1); |
12048 | if (compare_value(ctx, b, c, keys, n_keys, a_buffer, b_buffer)) { |
12049 | swap_value(b, c); |
12050 | } else { |
12051 | if (compare_value(ctx, c, e, keys, n_keys, a_buffer, b_buffer)) { |
12052 | swap_value(c, e); |
12053 | } |
12054 | } |
12055 | if (d < 3) { return NULL; } |
12056 | b++; |
12057 | swap_value(b, c); |
12058 | c = b; |
12059 | for (;;) { |
12060 | do { |
12061 | b++; |
12062 | } while (compare_value(ctx, c, b, keys, n_keys, a_buffer, b_buffer)); |
12063 | do { |
12064 | e--; |
12065 | } while (compare_value(ctx, e, c, keys, n_keys, a_buffer, b_buffer)); |
12066 | if (b >= e) { break; } |
12067 | swap_value(b, e); |
12068 | } |
12069 | swap_value(c, e); |
12070 | return e; |
12071 | } |
12072 | |
12073 | static void |
12074 | sort_value(grn_ctx *ctx, |
12075 | sort_value_entry *head, sort_value_entry *tail, |
12076 | int from, int to, |
12077 | grn_table_sort_key *keys, int n_keys, |
12078 | grn_obj *a_buffer, grn_obj *b_buffer) |
12079 | { |
12080 | sort_value_entry *c; |
12081 | if (head < tail && (c = part_value(ctx, head, tail, keys, n_keys, |
12082 | a_buffer, b_buffer))) { |
12083 | intptr_t m = c - head + 1; |
12084 | if (from < m - 1) { |
12085 | sort_value(ctx, head, c - 1, from, to, keys, n_keys, a_buffer, b_buffer); |
12086 | } |
12087 | if (m < to) { |
12088 | sort_value(ctx, c + 1, tail, from - m, to - m, keys, n_keys, |
12089 | a_buffer, b_buffer); |
12090 | } |
12091 | } |
12092 | } |
12093 | |
12094 | static sort_value_entry * |
12095 | pack_value(grn_ctx *ctx, grn_obj *table, |
12096 | sort_value_entry *head, sort_value_entry *tail, |
12097 | grn_table_sort_key *keys, int n_keys, |
12098 | grn_obj *a_buffer, grn_obj *b_buffer) |
12099 | { |
12100 | int i = 0; |
12101 | sort_value_entry e, c; |
12102 | grn_table_cursor *tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); |
12103 | if (!tc) { return NULL; } |
12104 | if ((c.id = grn_table_cursor_next_inline(ctx, tc))) { |
12105 | GRN_TEXT_INIT(&c.value, 0); |
12106 | grn_obj_get_value(ctx, keys->key, c.id, &c.value); |
12107 | while ((e.id = grn_table_cursor_next_inline(ctx, tc))) { |
12108 | GRN_TEXT_INIT(&e.value, 0); |
12109 | grn_obj_get_value(ctx, keys->key, e.id, &e.value); |
12110 | if (compare_value(ctx, &c, &e, keys, n_keys, a_buffer, b_buffer)) { |
12111 | *head++ = e; |
12112 | } else { |
12113 | *tail-- = e; |
12114 | } |
12115 | i++; |
12116 | } |
12117 | *head = c; |
12118 | i++; |
12119 | } |
12120 | grn_table_cursor_close(ctx, tc); |
12121 | return i > 2 ? head : NULL; |
12122 | } |
12123 | |
12124 | static int |
12125 | grn_table_sort_value(grn_ctx *ctx, grn_obj *table, |
12126 | int offset, int limit, |
12127 | grn_obj *result, |
12128 | grn_table_sort_key *keys, int n_keys) |
12129 | { |
12130 | int e, n; |
12131 | sort_value_entry *array, *ep; |
12132 | e = offset + limit; |
12133 | n = grn_table_size(ctx, table); |
12134 | if (!(array = GRN_MALLOC(sizeof(sort_value_entry) * n))) { |
12135 | return 0; |
12136 | } |
12137 | { |
12138 | grn_obj a_buffer; |
12139 | grn_obj b_buffer; |
12140 | GRN_TEXT_INIT(&a_buffer, 0); |
12141 | GRN_TEXT_INIT(&b_buffer, 0); |
12142 | if ((ep = pack_value(ctx, table, array, array + n - 1, keys, n_keys, |
12143 | &a_buffer, &b_buffer))) { |
12144 | intptr_t m = ep - array + 1; |
12145 | if (offset < m - 1) { |
12146 | sort_value(ctx, array, ep - 1, offset, e, keys, n_keys, |
12147 | &a_buffer, &b_buffer); |
12148 | } |
12149 | if (m < e) { |
12150 | sort_value(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys, |
12151 | &a_buffer, &b_buffer); |
12152 | } |
12153 | } |
12154 | GRN_OBJ_FIN(ctx, &a_buffer); |
12155 | GRN_OBJ_FIN(ctx, &b_buffer); |
12156 | } |
12157 | { |
12158 | int i; |
12159 | grn_id *v; |
12160 | for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) { |
12161 | if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } |
12162 | *v = ep->id; |
12163 | } |
12164 | GRN_FREE(array); |
12165 | return i; |
12166 | } |
12167 | } |
12168 | |
12169 | static grn_bool |
12170 | is_compressed_column(grn_ctx *ctx, grn_obj *obj) |
12171 | { |
12172 | grn_obj *target_obj; |
12173 | |
12174 | if (!obj) { |
12175 | return GRN_FALSE; |
12176 | } |
12177 | |
12178 | if (obj->header.type == GRN_ACCESSOR) { |
12179 | grn_accessor *a = (grn_accessor *)obj; |
12180 | while (a->next) { |
12181 | a = a->next; |
12182 | } |
12183 | target_obj = a->obj; |
12184 | } else { |
12185 | target_obj = obj; |
12186 | } |
12187 | |
12188 | if (target_obj->header.type != GRN_COLUMN_VAR_SIZE) { |
12189 | return GRN_FALSE; |
12190 | } |
12191 | |
12192 | switch (target_obj->header.flags & GRN_OBJ_COMPRESS_MASK) { |
12193 | case GRN_OBJ_COMPRESS_ZLIB : |
12194 | case GRN_OBJ_COMPRESS_LZ4 : |
12195 | case GRN_OBJ_COMPRESS_ZSTD : |
12196 | return GRN_TRUE; |
12197 | default : |
12198 | return GRN_FALSE; |
12199 | } |
12200 | } |
12201 | |
12202 | static grn_bool |
12203 | is_sub_record_accessor(grn_ctx *ctx, grn_obj *obj) |
12204 | { |
12205 | grn_accessor *accessor; |
12206 | |
12207 | if (!obj) { |
12208 | return GRN_FALSE; |
12209 | } |
12210 | |
12211 | if (obj->header.type != GRN_ACCESSOR) { |
12212 | return GRN_FALSE; |
12213 | } |
12214 | |
12215 | for (accessor = (grn_accessor *)obj; accessor; accessor = accessor->next) { |
12216 | switch (accessor->action) { |
12217 | case GRN_ACCESSOR_GET_VALUE : |
12218 | if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(accessor->obj)) { |
12219 | return GRN_TRUE; |
12220 | } |
12221 | break; |
12222 | default : |
12223 | break; |
12224 | } |
12225 | } |
12226 | |
12227 | return GRN_FALSE; |
12228 | } |
12229 | |
12230 | static grn_bool |
12231 | is_encoded_pat_key_accessor(grn_ctx *ctx, grn_obj *obj) |
12232 | { |
12233 | grn_accessor *accessor; |
12234 | |
12235 | if (!grn_obj_is_accessor(ctx, obj)) { |
12236 | return GRN_FALSE; |
12237 | } |
12238 | |
12239 | accessor = (grn_accessor *)obj; |
12240 | while (accessor->next) { |
12241 | accessor = accessor->next; |
12242 | } |
12243 | |
12244 | if (accessor->action != GRN_ACCESSOR_GET_KEY) { |
12245 | return GRN_FALSE; |
12246 | } |
12247 | |
12248 | if (accessor->obj->header.type != GRN_TABLE_PAT_KEY) { |
12249 | return GRN_FALSE; |
12250 | } |
12251 | |
12252 | return grn_pat_is_key_encoded(ctx, (grn_pat *)(accessor->obj)); |
12253 | } |
12254 | |
12255 | static int |
12256 | range_is_idp(grn_obj *obj) |
12257 | { |
12258 | if (obj && obj->header.type == GRN_ACCESSOR) { |
12259 | grn_accessor *a; |
12260 | for (a = (grn_accessor *)obj; a; a = a->next) { |
12261 | if (a->action == GRN_ACCESSOR_GET_ID) { return 1; } |
12262 | } |
12263 | } |
12264 | return 0; |
12265 | } |
12266 | |
12267 | int |
12268 | grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit, |
12269 | grn_obj *result, grn_table_sort_key *keys, int n_keys) |
12270 | { |
12271 | grn_rc rc; |
12272 | grn_obj *index; |
12273 | int n, e, i = 0; |
12274 | GRN_API_ENTER; |
12275 | if (!n_keys || !keys) { |
12276 | WARN(GRN_INVALID_ARGUMENT, "keys is null" ); |
12277 | goto exit; |
12278 | } |
12279 | if (!table) { |
12280 | WARN(GRN_INVALID_ARGUMENT, "table is null" ); |
12281 | goto exit; |
12282 | } |
12283 | if (!(result && result->header.type == GRN_TABLE_NO_KEY)) { |
12284 | WARN(GRN_INVALID_ARGUMENT, "result is not a array" ); |
12285 | goto exit; |
12286 | } |
12287 | n = grn_table_size(ctx, table); |
12288 | if ((rc = grn_normalize_offset_and_limit(ctx, n, &offset, &limit))) { |
12289 | ERR(rc, "grn_normalize_offset_and_limit failed" ); |
12290 | goto exit; |
12291 | } else { |
12292 | e = offset + limit; |
12293 | } |
12294 | if (keys->flags & GRN_TABLE_SORT_GEO) { |
12295 | if (n_keys == 2) { |
12296 | i = grn_geo_table_sort(ctx, table, offset, limit, result, |
12297 | keys[0].key, keys[1].key); |
12298 | } else { |
12299 | i = 0; |
12300 | } |
12301 | goto exit; |
12302 | } |
12303 | if (n_keys == 1 && !GRN_ACCESSORP(keys->key) && |
12304 | grn_column_index(ctx, keys->key, GRN_OP_LESS, &index, 1, NULL)) { |
12305 | grn_id tid; |
12306 | grn_pat *lexicon = (grn_pat *)grn_ctx_at(ctx, index->header.domain); |
12307 | grn_pat_cursor *pc = grn_pat_cursor_open(ctx, lexicon, NULL, 0, NULL, 0, |
12308 | 0 /* offset : can be used in unique index */, |
12309 | -1 /* limit : can be used in unique index */, |
12310 | (keys->flags & GRN_TABLE_SORT_DESC) |
12311 | ? GRN_CURSOR_DESCENDING |
12312 | : GRN_CURSOR_ASCENDING); |
12313 | if (pc) { |
12314 | while (i < e && (tid = grn_pat_cursor_next(ctx, pc))) { |
12315 | grn_ii_cursor *ic = grn_ii_cursor_open(ctx, (grn_ii *)index, tid, 0, 0, 1, 0); |
12316 | if (ic) { |
12317 | grn_posting *posting; |
12318 | while (i < e && (posting = grn_ii_cursor_next(ctx, ic))) { |
12319 | if (offset <= i) { |
12320 | grn_id *v; |
12321 | if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } |
12322 | *v = posting->rid; |
12323 | } |
12324 | i++; |
12325 | } |
12326 | grn_ii_cursor_close(ctx, ic); |
12327 | } |
12328 | } |
12329 | grn_pat_cursor_close(ctx, pc); |
12330 | } |
12331 | } else { |
12332 | int j; |
12333 | grn_bool have_compressed_column = GRN_FALSE; |
12334 | grn_bool have_sub_record_accessor = GRN_FALSE; |
12335 | grn_bool have_encoded_pat_key_accessor = GRN_FALSE; |
12336 | grn_bool have_index_value_get = GRN_FALSE; |
12337 | grn_table_sort_key *kp; |
12338 | for (kp = keys, j = n_keys; j; kp++, j--) { |
12339 | if (is_compressed_column(ctx, kp->key)) { |
12340 | have_compressed_column = GRN_TRUE; |
12341 | } |
12342 | if (is_sub_record_accessor(ctx, kp->key)) { |
12343 | have_sub_record_accessor = GRN_TRUE; |
12344 | } |
12345 | if (is_encoded_pat_key_accessor(ctx, kp->key)) { |
12346 | have_encoded_pat_key_accessor = GRN_TRUE; |
12347 | } |
12348 | if (range_is_idp(kp->key)) { |
12349 | kp->offset = KEY_ID; |
12350 | } else { |
12351 | grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, kp->key)); |
12352 | if (range->header.type == GRN_TYPE) { |
12353 | if (range->header.flags & GRN_OBJ_KEY_VAR_SIZE) { |
12354 | kp->offset = KEY_BULK; |
12355 | } else { |
12356 | uint8_t key_type = range->header.flags & GRN_OBJ_KEY_MASK; |
12357 | switch (key_type) { |
12358 | case GRN_OBJ_KEY_UINT : |
12359 | case GRN_OBJ_KEY_GEO_POINT : |
12360 | switch (GRN_TYPE_SIZE(DB_OBJ(range))) { |
12361 | case 1 : |
12362 | kp->offset = KEY_UINT8; |
12363 | break; |
12364 | case 2 : |
12365 | kp->offset = KEY_UINT16; |
12366 | break; |
12367 | case 4 : |
12368 | kp->offset = KEY_UINT32; |
12369 | break; |
12370 | case 8 : |
12371 | kp->offset = KEY_UINT64; |
12372 | break; |
12373 | default : |
12374 | ERR(GRN_INVALID_ARGUMENT, "unsupported uint value" ); |
12375 | goto exit; |
12376 | } |
12377 | break; |
12378 | case GRN_OBJ_KEY_INT : |
12379 | switch (GRN_TYPE_SIZE(DB_OBJ(range))) { |
12380 | case 1 : |
12381 | kp->offset = KEY_INT8; |
12382 | break; |
12383 | case 2 : |
12384 | kp->offset = KEY_INT16; |
12385 | break; |
12386 | case 4 : |
12387 | kp->offset = KEY_INT32; |
12388 | break; |
12389 | case 8 : |
12390 | kp->offset = KEY_INT64; |
12391 | break; |
12392 | default : |
12393 | ERR(GRN_INVALID_ARGUMENT, "unsupported int value" ); |
12394 | goto exit; |
12395 | } |
12396 | break; |
12397 | case GRN_OBJ_KEY_FLOAT : |
12398 | switch (GRN_TYPE_SIZE(DB_OBJ(range))) { |
12399 | case 4 : |
12400 | kp->offset = KEY_FLOAT32; |
12401 | break; |
12402 | case 8 : |
12403 | kp->offset = KEY_FLOAT64; |
12404 | break; |
12405 | default : |
12406 | ERR(GRN_INVALID_ARGUMENT, "unsupported float value" ); |
12407 | goto exit; |
12408 | } |
12409 | break; |
12410 | } |
12411 | } |
12412 | } else { |
12413 | if (kp->key->header.type == GRN_COLUMN_INDEX) { |
12414 | have_index_value_get = GRN_TRUE; |
12415 | } |
12416 | kp->offset = KEY_UINT32; |
12417 | } |
12418 | } |
12419 | } |
12420 | if (have_compressed_column || |
12421 | have_sub_record_accessor || |
12422 | have_encoded_pat_key_accessor || |
12423 | have_index_value_get) { |
12424 | i = grn_table_sort_value(ctx, table, offset, limit, result, |
12425 | keys, n_keys); |
12426 | } else { |
12427 | i = grn_table_sort_reference(ctx, table, offset, limit, result, |
12428 | keys, n_keys); |
12429 | } |
12430 | } |
12431 | exit : |
12432 | GRN_API_RETURN(i); |
12433 | } |
12434 | |
12435 | static grn_obj * |
12436 | deftype(grn_ctx *ctx, const char *name, |
12437 | grn_obj_flags flags, unsigned int size) |
12438 | { |
12439 | grn_obj *o = grn_ctx_get(ctx, name, strlen(name)); |
12440 | if (!o) { o = grn_type_create(ctx, name, strlen(name), flags, size); } |
12441 | return o; |
12442 | } |
12443 | |
12444 | grn_rc |
12445 | grn_db_init_builtin_types(grn_ctx *ctx) |
12446 | { |
12447 | grn_id id; |
12448 | grn_obj *obj, *db = ctx->impl->db; |
12449 | char buf[] = "Sys00" ; |
12450 | grn_obj_register(ctx, db, buf, 5); |
12451 | obj = deftype(ctx, "Object" , |
12452 | GRN_OBJ_KEY_UINT, sizeof(uint64_t)); |
12453 | if (!obj || DB_OBJ(obj)->id != GRN_DB_OBJECT) { return GRN_FILE_CORRUPT; } |
12454 | obj = deftype(ctx, "Bool" , |
12455 | GRN_OBJ_KEY_UINT, sizeof(uint8_t)); |
12456 | if (!obj || DB_OBJ(obj)->id != GRN_DB_BOOL) { return GRN_FILE_CORRUPT; } |
12457 | obj = deftype(ctx, "Int8" , |
12458 | GRN_OBJ_KEY_INT, sizeof(int8_t)); |
12459 | if (!obj || DB_OBJ(obj)->id != GRN_DB_INT8) { return GRN_FILE_CORRUPT; } |
12460 | obj = deftype(ctx, "UInt8" , |
12461 | GRN_OBJ_KEY_UINT, sizeof(uint8_t)); |
12462 | if (!obj || DB_OBJ(obj)->id != GRN_DB_UINT8) { return GRN_FILE_CORRUPT; } |
12463 | obj = deftype(ctx, "Int16" , |
12464 | GRN_OBJ_KEY_INT, sizeof(int16_t)); |
12465 | if (!obj || DB_OBJ(obj)->id != GRN_DB_INT16) { return GRN_FILE_CORRUPT; } |
12466 | obj = deftype(ctx, "UInt16" , |
12467 | GRN_OBJ_KEY_UINT, sizeof(uint16_t)); |
12468 | if (!obj || DB_OBJ(obj)->id != GRN_DB_UINT16) { return GRN_FILE_CORRUPT; } |
12469 | obj = deftype(ctx, "Int32" , |
12470 | GRN_OBJ_KEY_INT, sizeof(int32_t)); |
12471 | if (!obj || DB_OBJ(obj)->id != GRN_DB_INT32) { return GRN_FILE_CORRUPT; } |
12472 | obj = deftype(ctx, "UInt32" , |
12473 | GRN_OBJ_KEY_UINT, sizeof(uint32_t)); |
12474 | if (!obj || DB_OBJ(obj)->id != GRN_DB_UINT32) { return GRN_FILE_CORRUPT; } |
12475 | obj = deftype(ctx, "Int64" , |
12476 | GRN_OBJ_KEY_INT, sizeof(int64_t)); |
12477 | if (!obj || DB_OBJ(obj)->id != GRN_DB_INT64) { return GRN_FILE_CORRUPT; } |
12478 | obj = deftype(ctx, "UInt64" , |
12479 | GRN_OBJ_KEY_UINT, sizeof(uint64_t)); |
12480 | if (!obj || DB_OBJ(obj)->id != GRN_DB_UINT64) { return GRN_FILE_CORRUPT; } |
12481 | obj = deftype(ctx, "Float" , |
12482 | GRN_OBJ_KEY_FLOAT, sizeof(double)); |
12483 | if (!obj || DB_OBJ(obj)->id != GRN_DB_FLOAT) { return GRN_FILE_CORRUPT; } |
12484 | obj = deftype(ctx, "Time" , |
12485 | GRN_OBJ_KEY_INT, sizeof(int64_t)); |
12486 | if (!obj || DB_OBJ(obj)->id != GRN_DB_TIME) { return GRN_FILE_CORRUPT; } |
12487 | obj = deftype(ctx, "ShortText" , |
12488 | GRN_OBJ_KEY_VAR_SIZE, GRN_TABLE_MAX_KEY_SIZE); |
12489 | if (!obj || DB_OBJ(obj)->id != GRN_DB_SHORT_TEXT) { return GRN_FILE_CORRUPT; } |
12490 | obj = deftype(ctx, "Text" , |
12491 | GRN_OBJ_KEY_VAR_SIZE, 1 << 16); |
12492 | if (!obj || DB_OBJ(obj)->id != GRN_DB_TEXT) { return GRN_FILE_CORRUPT; } |
12493 | obj = deftype(ctx, "LongText" , |
12494 | GRN_OBJ_KEY_VAR_SIZE, 1 << 31); |
12495 | if (!obj || DB_OBJ(obj)->id != GRN_DB_LONG_TEXT) { return GRN_FILE_CORRUPT; } |
12496 | obj = deftype(ctx, "TokyoGeoPoint" , |
12497 | GRN_OBJ_KEY_GEO_POINT, sizeof(grn_geo_point)); |
12498 | if (!obj || DB_OBJ(obj)->id != GRN_DB_TOKYO_GEO_POINT) { return GRN_FILE_CORRUPT; } |
12499 | obj = deftype(ctx, "WGS84GeoPoint" , |
12500 | GRN_OBJ_KEY_GEO_POINT, sizeof(grn_geo_point)); |
12501 | if (!obj || DB_OBJ(obj)->id != GRN_DB_WGS84_GEO_POINT) { return GRN_FILE_CORRUPT; } |
12502 | for (id = grn_db_curr_id(ctx, db) + 1; id < GRN_DB_MECAB; id++) { |
12503 | grn_itoh(id, buf + 3, 2); |
12504 | grn_obj_register(ctx, db, buf, 5); |
12505 | } |
12506 | #ifdef GRN_WITH_MECAB |
12507 | if (grn_db_init_mecab_tokenizer(ctx)) { |
12508 | ERRCLR(ctx); |
12509 | #endif |
12510 | grn_obj_register(ctx, db, "TokenMecab" , 10); |
12511 | #ifdef GRN_WITH_MECAB |
12512 | } |
12513 | #endif |
12514 | grn_db_init_builtin_tokenizers(ctx); |
12515 | grn_db_init_builtin_normalizers(ctx); |
12516 | grn_db_init_builtin_scorers(ctx); |
12517 | for (id = grn_db_curr_id(ctx, db) + 1; id < 128; id++) { |
12518 | grn_itoh(id, buf + 3, 2); |
12519 | grn_obj_register(ctx, db, buf, 5); |
12520 | } |
12521 | grn_db_init_builtin_commands(ctx); |
12522 | grn_db_init_builtin_window_functions(ctx); |
12523 | for (id = grn_db_curr_id(ctx, db) + 1; id < GRN_N_RESERVED_TYPES; id++) { |
12524 | grn_itoh(id, buf + 3, 2); |
12525 | grn_obj_register(ctx, db, buf, 5); |
12526 | } |
12527 | return ctx->rc; |
12528 | } |
12529 | |
12530 | #define MULTI_COLUMN_INDEXP(i) (DB_OBJ(i)->source_size > sizeof(grn_id)) |
12531 | |
12532 | static grn_obj * |
12533 | grn_index_column_get_tokenizer(grn_ctx *ctx, grn_obj *index_column) |
12534 | { |
12535 | grn_obj *tokenizer; |
12536 | grn_obj *lexicon; |
12537 | |
12538 | lexicon = grn_ctx_at(ctx, index_column->header.domain); |
12539 | if (!lexicon) { |
12540 | return NULL; |
12541 | } |
12542 | |
12543 | grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL); |
12544 | return tokenizer; |
12545 | } |
12546 | |
12547 | static grn_bool |
12548 | is_full_text_searchable_index(grn_ctx *ctx, grn_obj *index_column) |
12549 | { |
12550 | grn_obj *tokenizer; |
12551 | |
12552 | tokenizer = grn_index_column_get_tokenizer(ctx, index_column); |
12553 | return tokenizer != NULL; |
12554 | } |
12555 | |
12556 | static int |
12557 | grn_column_find_index_data_column_equal(grn_ctx *ctx, grn_obj *obj, |
12558 | grn_operator op, |
12559 | grn_index_datum *index_data, |
12560 | unsigned int n_index_data, |
12561 | grn_obj **index_buf, int buf_size, |
12562 | int *section_buf) |
12563 | { |
12564 | int n = 0; |
12565 | grn_obj **ip = index_buf; |
12566 | grn_hook *hooks; |
12567 | |
12568 | for (hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) { |
12569 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
12570 | grn_obj *target = grn_ctx_at(ctx, data->target); |
12571 | int section; |
12572 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
12573 | if (obj->header.type != GRN_COLUMN_FIX_SIZE) { |
12574 | if (is_full_text_searchable_index(ctx, target)) { continue; } |
12575 | } |
12576 | section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; |
12577 | if (section_buf) { *section_buf = section; } |
12578 | if (n < buf_size) { |
12579 | *ip++ = target; |
12580 | } |
12581 | if (n < n_index_data) { |
12582 | index_data[n].index = target; |
12583 | index_data[n].section = section; |
12584 | } |
12585 | n++; |
12586 | } |
12587 | |
12588 | return n; |
12589 | } |
12590 | |
12591 | static grn_bool |
12592 | is_valid_regexp_index(grn_ctx *ctx, grn_obj *index_column) |
12593 | { |
12594 | grn_obj *tokenizer; |
12595 | |
12596 | tokenizer = grn_index_column_get_tokenizer(ctx, index_column); |
12597 | /* TODO: Restrict to TokenRegexp? */ |
12598 | return tokenizer != NULL; |
12599 | } |
12600 | |
12601 | static int |
12602 | grn_column_find_index_data_column_match(grn_ctx *ctx, grn_obj *obj, |
12603 | grn_operator op, |
12604 | grn_index_datum *index_data, |
12605 | unsigned int n_index_data, |
12606 | grn_obj **index_buf, int buf_size, |
12607 | int *section_buf) |
12608 | { |
12609 | int n = 0; |
12610 | grn_obj **ip = index_buf; |
12611 | grn_hook_entry hook_entry; |
12612 | grn_hook *hooks; |
12613 | grn_bool prefer_full_text_search_index = GRN_FALSE; |
12614 | |
12615 | switch (obj->header.type) { |
12616 | case GRN_TABLE_HASH_KEY : |
12617 | case GRN_TABLE_PAT_KEY : |
12618 | case GRN_TABLE_DAT_KEY : |
12619 | case GRN_TABLE_NO_KEY : |
12620 | hook_entry = GRN_HOOK_INSERT; |
12621 | break; |
12622 | default : |
12623 | hook_entry = GRN_HOOK_SET; |
12624 | break; |
12625 | } |
12626 | |
12627 | if (op != GRN_OP_REGEXP && !grn_column_is_vector(ctx, obj)) { |
12628 | prefer_full_text_search_index = GRN_TRUE; |
12629 | } |
12630 | |
12631 | if (prefer_full_text_search_index) { |
12632 | for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) { |
12633 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
12634 | grn_obj *target = grn_ctx_at(ctx, data->target); |
12635 | int section; |
12636 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
12637 | if (!is_full_text_searchable_index(ctx, target)) { continue; } |
12638 | section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; |
12639 | if (section_buf) { *section_buf = section; } |
12640 | if (n < buf_size) { |
12641 | *ip++ = target; |
12642 | } |
12643 | if (n < n_index_data) { |
12644 | index_data[n].index = target; |
12645 | index_data[n].section = section; |
12646 | } |
12647 | n++; |
12648 | } |
12649 | } |
12650 | |
12651 | for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) { |
12652 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
12653 | grn_obj *target = grn_ctx_at(ctx, data->target); |
12654 | int section; |
12655 | |
12656 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
12657 | if (op == GRN_OP_REGEXP && !is_valid_regexp_index(ctx, target)) { |
12658 | continue; |
12659 | } |
12660 | |
12661 | if (prefer_full_text_search_index) { |
12662 | if (is_full_text_searchable_index(ctx, target)) { continue; } |
12663 | } |
12664 | |
12665 | section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; |
12666 | if (section_buf) { *section_buf = section; } |
12667 | if (n < buf_size) { |
12668 | *ip++ = target; |
12669 | } |
12670 | if (n < n_index_data) { |
12671 | index_data[n].index = target; |
12672 | index_data[n].section = section; |
12673 | } |
12674 | n++; |
12675 | } |
12676 | |
12677 | return n; |
12678 | } |
12679 | |
12680 | static int |
12681 | grn_column_find_index_data_column_range(grn_ctx *ctx, grn_obj *obj, |
12682 | grn_operator op, |
12683 | grn_index_datum *index_data, |
12684 | unsigned int n_index_data, |
12685 | grn_obj **index_buf, int buf_size, |
12686 | int *section_buf) |
12687 | { |
12688 | int n = 0; |
12689 | grn_obj **ip = index_buf; |
12690 | grn_hook_entry hook_entry; |
12691 | grn_hook *hooks; |
12692 | |
12693 | switch (obj->header.type) { |
12694 | case GRN_TABLE_HASH_KEY : |
12695 | case GRN_TABLE_PAT_KEY : |
12696 | case GRN_TABLE_DAT_KEY : |
12697 | case GRN_TABLE_NO_KEY : |
12698 | hook_entry = GRN_HOOK_INSERT; |
12699 | break; |
12700 | default : |
12701 | hook_entry = GRN_HOOK_SET; |
12702 | break; |
12703 | } |
12704 | |
12705 | for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) { |
12706 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
12707 | grn_obj *target = grn_ctx_at(ctx, data->target); |
12708 | int section; |
12709 | if (!target) { continue; } |
12710 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
12711 | section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; |
12712 | if (section_buf) { *section_buf = section; } |
12713 | { |
12714 | grn_obj *tokenizer, *lexicon = grn_ctx_at(ctx, target->header.domain); |
12715 | if (!lexicon) { continue; } |
12716 | if (lexicon->header.type != GRN_TABLE_PAT_KEY) { continue; } |
12717 | /* FIXME: GRN_TABLE_DAT_KEY should be supported */ |
12718 | grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL); |
12719 | if (tokenizer) { continue; } |
12720 | } |
12721 | if (n < buf_size) { |
12722 | *ip++ = target; |
12723 | } |
12724 | if (n < n_index_data) { |
12725 | index_data[n].index = target; |
12726 | index_data[n].section = section; |
12727 | } |
12728 | n++; |
12729 | } |
12730 | |
12731 | return n; |
12732 | } |
12733 | |
12734 | static grn_bool |
12735 | is_valid_match_index(grn_ctx *ctx, grn_obj *index_column) |
12736 | { |
12737 | return GRN_TRUE; |
12738 | } |
12739 | |
12740 | static grn_bool |
12741 | is_valid_range_index(grn_ctx *ctx, grn_obj *index_column) |
12742 | { |
12743 | grn_obj *tokenizer; |
12744 | grn_obj *lexicon; |
12745 | |
12746 | lexicon = grn_ctx_at(ctx, index_column->header.domain); |
12747 | if (!lexicon) { return GRN_FALSE; } |
12748 | /* FIXME: GRN_TABLE_DAT_KEY should be supported */ |
12749 | if (lexicon->header.type != GRN_TABLE_PAT_KEY) { |
12750 | grn_obj_unlink(ctx, lexicon); |
12751 | return GRN_FALSE; |
12752 | } |
12753 | |
12754 | grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL); |
12755 | grn_obj_unlink(ctx, lexicon); |
12756 | if (tokenizer) { return GRN_FALSE; } |
12757 | |
12758 | return GRN_TRUE; |
12759 | } |
12760 | |
12761 | static grn_bool |
12762 | is_valid_index(grn_ctx *ctx, grn_obj *index_column, grn_operator op) |
12763 | { |
12764 | switch (op) { |
12765 | case GRN_OP_MATCH : |
12766 | case GRN_OP_NEAR : |
12767 | case GRN_OP_NEAR2 : |
12768 | case GRN_OP_SIMILAR : |
12769 | return is_valid_match_index(ctx, index_column); |
12770 | break; |
12771 | case GRN_OP_LESS : |
12772 | case GRN_OP_GREATER : |
12773 | case GRN_OP_LESS_EQUAL : |
12774 | case GRN_OP_GREATER_EQUAL : |
12775 | case GRN_OP_CALL : |
12776 | return is_valid_range_index(ctx, index_column); |
12777 | break; |
12778 | case GRN_OP_REGEXP : |
12779 | return is_valid_regexp_index(ctx, index_column); |
12780 | break; |
12781 | default : |
12782 | return GRN_FALSE; |
12783 | break; |
12784 | } |
12785 | } |
12786 | |
12787 | static int |
12788 | find_section(grn_ctx *ctx, grn_obj *index_column, grn_obj *indexed_column) |
12789 | { |
12790 | int section = 0; |
12791 | grn_id indexed_column_id; |
12792 | grn_id *source_ids; |
12793 | int i, n_source_ids; |
12794 | |
12795 | indexed_column_id = DB_OBJ(indexed_column)->id; |
12796 | |
12797 | source_ids = DB_OBJ(index_column)->source; |
12798 | n_source_ids = DB_OBJ(index_column)->source_size / sizeof(grn_id); |
12799 | for (i = 0; i < n_source_ids; i++) { |
12800 | grn_id source_id = source_ids[i]; |
12801 | if (source_id == indexed_column_id) { |
12802 | section = i + 1; |
12803 | break; |
12804 | } |
12805 | } |
12806 | |
12807 | return section; |
12808 | } |
12809 | |
12810 | static int |
12811 | grn_column_find_index_data_accessor_index_column(grn_ctx *ctx, grn_accessor *a, |
12812 | grn_operator op, |
12813 | grn_index_datum *index_data, |
12814 | unsigned int n_index_data, |
12815 | grn_obj **index_buf, |
12816 | int buf_size, |
12817 | int *section_buf) |
12818 | { |
12819 | grn_obj *index_column = a->obj; |
12820 | int section = 0; |
12821 | |
12822 | if (!is_valid_index(ctx, index_column, op)) { |
12823 | return 0; |
12824 | } |
12825 | |
12826 | if (a->next) { |
12827 | int specified_section; |
12828 | grn_bool is_invalid_section; |
12829 | if (a->next->next) { |
12830 | return 0; |
12831 | } |
12832 | specified_section = find_section(ctx, index_column, a->next->obj); |
12833 | is_invalid_section = (specified_section == 0); |
12834 | if (is_invalid_section) { |
12835 | return 0; |
12836 | } |
12837 | section = specified_section; |
12838 | if (section_buf) { |
12839 | *section_buf = section; |
12840 | } |
12841 | } |
12842 | if (buf_size > 0) { |
12843 | *index_buf = index_column; |
12844 | } |
12845 | if (n_index_data > 0) { |
12846 | index_data[0].index = index_column; |
12847 | index_data[0].section = section; |
12848 | } |
12849 | |
12850 | return 1; |
12851 | } |
12852 | |
12853 | static grn_bool |
12854 | grn_column_find_index_data_accessor_is_key_search(grn_ctx *ctx, |
12855 | grn_accessor *accessor, |
12856 | grn_operator op) |
12857 | { |
12858 | if (accessor->next) { |
12859 | return GRN_FALSE; |
12860 | } |
12861 | |
12862 | if (accessor->action != GRN_ACCESSOR_GET_KEY) { |
12863 | return GRN_FALSE; |
12864 | } |
12865 | |
12866 | if (!grn_obj_is_table(ctx, accessor->obj)) { |
12867 | return GRN_FALSE; |
12868 | } |
12869 | |
12870 | switch (op) { |
12871 | case GRN_OP_LESS : |
12872 | case GRN_OP_GREATER : |
12873 | case GRN_OP_LESS_EQUAL : |
12874 | case GRN_OP_GREATER_EQUAL : |
12875 | switch (accessor->obj->header.type) { |
12876 | case GRN_TABLE_PAT_KEY : |
12877 | case GRN_TABLE_DAT_KEY : |
12878 | return GRN_TRUE; |
12879 | default : |
12880 | return GRN_FALSE; |
12881 | } |
12882 | case GRN_OP_EQUAL : |
12883 | switch (accessor->obj->header.type) { |
12884 | case GRN_TABLE_HASH_KEY : |
12885 | case GRN_TABLE_PAT_KEY : |
12886 | case GRN_TABLE_DAT_KEY : |
12887 | return GRN_TRUE; |
12888 | default : |
12889 | return GRN_FALSE; |
12890 | } |
12891 | default : |
12892 | return GRN_FALSE; |
12893 | } |
12894 | } |
12895 | |
12896 | static int |
12897 | grn_column_find_index_data_accessor_match(grn_ctx *ctx, grn_obj *obj, |
12898 | grn_operator op, |
12899 | grn_index_datum *index_data, |
12900 | unsigned n_index_data, |
12901 | grn_obj **index_buf, int buf_size, |
12902 | int *section_buf) |
12903 | { |
12904 | int n = 0; |
12905 | grn_obj **ip = index_buf; |
12906 | grn_accessor *a = (grn_accessor *)obj; |
12907 | |
12908 | while (a) { |
12909 | grn_hook *hooks; |
12910 | grn_bool found = GRN_FALSE; |
12911 | grn_hook_entry entry = (grn_hook_entry)-1; |
12912 | |
12913 | if (a->action == GRN_ACCESSOR_GET_COLUMN_VALUE && |
12914 | GRN_OBJ_INDEX_COLUMNP(a->obj)) { |
12915 | return grn_column_find_index_data_accessor_index_column(ctx, a, op, |
12916 | index_data, |
12917 | n_index_data, |
12918 | index_buf, |
12919 | buf_size, |
12920 | section_buf); |
12921 | } |
12922 | |
12923 | switch (a->action) { |
12924 | case GRN_ACCESSOR_GET_KEY : |
12925 | entry = GRN_HOOK_INSERT; |
12926 | break; |
12927 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
12928 | entry = GRN_HOOK_SET; |
12929 | break; |
12930 | default : |
12931 | break; |
12932 | } |
12933 | |
12934 | if (entry == (grn_hook_entry)-1) { |
12935 | break; |
12936 | } |
12937 | |
12938 | for (hooks = DB_OBJ(a->obj)->hooks[entry]; hooks; hooks = hooks->next) { |
12939 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
12940 | grn_obj *target = grn_ctx_at(ctx, data->target); |
12941 | |
12942 | if (target->header.type != GRN_COLUMN_INDEX) { continue; } |
12943 | |
12944 | found = GRN_TRUE; |
12945 | if (!a->next) { |
12946 | int section; |
12947 | |
12948 | if (!is_valid_index(ctx, target, op)) { |
12949 | continue; |
12950 | } |
12951 | |
12952 | section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; |
12953 | if (section_buf) { |
12954 | *section_buf = section; |
12955 | } |
12956 | if (n < buf_size) { |
12957 | *ip++ = target; |
12958 | } |
12959 | if (n < n_index_data) { |
12960 | index_data[n].index = target; |
12961 | index_data[n].section = section; |
12962 | } |
12963 | n++; |
12964 | } |
12965 | } |
12966 | |
12967 | if (!found && |
12968 | grn_column_find_index_data_accessor_is_key_search(ctx, a, op)) { |
12969 | grn_obj *index; |
12970 | int section = 0; |
12971 | |
12972 | if ((grn_obj *)a == obj) { |
12973 | index = a->obj; |
12974 | } else { |
12975 | index = (grn_obj *)a; |
12976 | } |
12977 | |
12978 | found = GRN_TRUE; |
12979 | if (section_buf) { |
12980 | *section_buf = section; |
12981 | } |
12982 | if (n < buf_size) { |
12983 | *ip++ = index; |
12984 | } |
12985 | if (n < n_index_data) { |
12986 | index_data[n].index = index; |
12987 | index_data[n].section = section; |
12988 | } |
12989 | n++; |
12990 | } |
12991 | |
12992 | if (!found && |
12993 | a->next && |
12994 | grn_obj_is_table(ctx, a->obj) && |
12995 | a->obj->header.domain == a->next->obj->header.domain) { |
12996 | grn_obj *index = (grn_obj *)a; |
12997 | int section = 0; |
12998 | |
12999 | found = GRN_TRUE; |
13000 | if (section_buf) { |
13001 | *section_buf = section; |
13002 | } |
13003 | if (n < buf_size) { |
13004 | *ip++ = index; |
13005 | } |
13006 | if (n < n_index_data) { |
13007 | index_data[n].index = index; |
13008 | index_data[n].section = section; |
13009 | } |
13010 | n++; |
13011 | } |
13012 | |
13013 | if (!found) { |
13014 | break; |
13015 | } |
13016 | a = a->next; |
13017 | } |
13018 | |
13019 | return n; |
13020 | } |
13021 | |
13022 | static int |
13023 | grn_column_find_index_data_accessor(grn_ctx *ctx, grn_obj *obj, |
13024 | grn_operator op, |
13025 | grn_index_datum *index_data, |
13026 | unsigned n_index_data, |
13027 | grn_obj **index_buf, int buf_size, |
13028 | int *section_buf) |
13029 | { |
13030 | int n = 0; |
13031 | |
13032 | if (section_buf) { |
13033 | *section_buf = 0; |
13034 | } |
13035 | switch (op) { |
13036 | case GRN_OP_EQUAL : |
13037 | case GRN_OP_NOT_EQUAL : |
13038 | case GRN_OP_TERM_EXTRACT : |
13039 | if (buf_size > 0) { |
13040 | index_buf[n] = obj; |
13041 | } |
13042 | if (n_index_data > 0) { |
13043 | index_data[n].index = obj; |
13044 | index_data[n].section = 0; |
13045 | } |
13046 | n++; |
13047 | break; |
13048 | case GRN_OP_PREFIX : |
13049 | { |
13050 | grn_accessor *a = (grn_accessor *)obj; |
13051 | if (a->action == GRN_ACCESSOR_GET_KEY) { |
13052 | if (a->obj->header.type == GRN_TABLE_PAT_KEY) { |
13053 | if (buf_size > 0) { |
13054 | index_buf[n] = obj; |
13055 | } |
13056 | if (n_index_data > 0) { |
13057 | index_data[n].index = obj; |
13058 | index_data[n].section = 0; |
13059 | } |
13060 | n++; |
13061 | } |
13062 | /* FIXME: GRN_TABLE_DAT_KEY should be supported */ |
13063 | } |
13064 | } |
13065 | break; |
13066 | case GRN_OP_SUFFIX : |
13067 | { |
13068 | grn_accessor *a = (grn_accessor *)obj; |
13069 | if (a->action == GRN_ACCESSOR_GET_KEY) { |
13070 | if (a->obj->header.type == GRN_TABLE_PAT_KEY && |
13071 | a->obj->header.flags & GRN_OBJ_KEY_WITH_SIS) { |
13072 | if (buf_size > 0) { |
13073 | index_buf[n] = obj; |
13074 | } |
13075 | if (n_index_data > 0) { |
13076 | index_data[n].index = obj; |
13077 | index_data[n].section = 0; |
13078 | } |
13079 | n++; |
13080 | } |
13081 | } |
13082 | } |
13083 | break; |
13084 | case GRN_OP_MATCH : |
13085 | case GRN_OP_NEAR : |
13086 | case GRN_OP_NEAR2 : |
13087 | case GRN_OP_SIMILAR : |
13088 | case GRN_OP_LESS : |
13089 | case GRN_OP_GREATER : |
13090 | case GRN_OP_LESS_EQUAL : |
13091 | case GRN_OP_GREATER_EQUAL : |
13092 | case GRN_OP_CALL : |
13093 | case GRN_OP_REGEXP : |
13094 | case GRN_OP_FUZZY : |
13095 | n = grn_column_find_index_data_accessor_match(ctx, obj, op, |
13096 | index_data, n_index_data, |
13097 | index_buf, buf_size, |
13098 | section_buf); |
13099 | break; |
13100 | default : |
13101 | break; |
13102 | } |
13103 | |
13104 | return n; |
13105 | } |
13106 | |
13107 | int |
13108 | grn_column_index(grn_ctx *ctx, grn_obj *obj, grn_operator op, |
13109 | grn_obj **index_buf, int buf_size, int *section_buf) |
13110 | { |
13111 | int n = 0; |
13112 | GRN_API_ENTER; |
13113 | if (GRN_DB_OBJP(obj)) { |
13114 | switch (op) { |
13115 | case GRN_OP_EQUAL : |
13116 | case GRN_OP_NOT_EQUAL : |
13117 | n = grn_column_find_index_data_column_equal(ctx, obj, op, |
13118 | NULL, 0, |
13119 | index_buf, buf_size, |
13120 | section_buf); |
13121 | break; |
13122 | case GRN_OP_PREFIX : |
13123 | case GRN_OP_SUFFIX : |
13124 | case GRN_OP_MATCH : |
13125 | case GRN_OP_NEAR : |
13126 | case GRN_OP_NEAR2 : |
13127 | case GRN_OP_SIMILAR : |
13128 | case GRN_OP_REGEXP : |
13129 | case GRN_OP_FUZZY : |
13130 | n = grn_column_find_index_data_column_match(ctx, obj, op, |
13131 | NULL, 0, |
13132 | index_buf, buf_size, |
13133 | section_buf); |
13134 | break; |
13135 | case GRN_OP_LESS : |
13136 | case GRN_OP_GREATER : |
13137 | case GRN_OP_LESS_EQUAL : |
13138 | case GRN_OP_GREATER_EQUAL : |
13139 | case GRN_OP_CALL : |
13140 | n = grn_column_find_index_data_column_range(ctx, obj, op, |
13141 | NULL, 0, |
13142 | index_buf, buf_size, |
13143 | section_buf); |
13144 | break; |
13145 | default : |
13146 | break; |
13147 | } |
13148 | } else if (GRN_ACCESSORP(obj)) { |
13149 | n = grn_column_find_index_data_accessor(ctx, obj, op, |
13150 | NULL, 0, |
13151 | index_buf, buf_size, |
13152 | section_buf); |
13153 | } |
13154 | GRN_API_RETURN(n); |
13155 | } |
13156 | |
13157 | unsigned int |
13158 | grn_column_find_index_data(grn_ctx *ctx, grn_obj *obj, grn_operator op, |
13159 | grn_index_datum *index_data, |
13160 | unsigned int n_index_data) |
13161 | { |
13162 | unsigned int n = 0; |
13163 | GRN_API_ENTER; |
13164 | if (GRN_DB_OBJP(obj)) { |
13165 | switch (op) { |
13166 | case GRN_OP_EQUAL : |
13167 | case GRN_OP_NOT_EQUAL : |
13168 | n = grn_column_find_index_data_column_equal(ctx, obj, op, |
13169 | index_data, n_index_data, |
13170 | NULL, 0, NULL); |
13171 | break; |
13172 | case GRN_OP_PREFIX : |
13173 | case GRN_OP_SUFFIX : |
13174 | case GRN_OP_MATCH : |
13175 | case GRN_OP_NEAR : |
13176 | case GRN_OP_NEAR2 : |
13177 | case GRN_OP_SIMILAR : |
13178 | case GRN_OP_REGEXP : |
13179 | case GRN_OP_FUZZY : |
13180 | n = grn_column_find_index_data_column_match(ctx, obj, op, |
13181 | index_data, n_index_data, |
13182 | NULL, 0, NULL); |
13183 | break; |
13184 | case GRN_OP_LESS : |
13185 | case GRN_OP_GREATER : |
13186 | case GRN_OP_LESS_EQUAL : |
13187 | case GRN_OP_GREATER_EQUAL : |
13188 | case GRN_OP_CALL : |
13189 | n = grn_column_find_index_data_column_range(ctx, obj, op, |
13190 | index_data, n_index_data, |
13191 | NULL, 0, NULL); |
13192 | break; |
13193 | default : |
13194 | break; |
13195 | } |
13196 | } else if (GRN_ACCESSORP(obj)) { |
13197 | n = grn_column_find_index_data_accessor(ctx, obj, op, |
13198 | index_data, n_index_data, |
13199 | NULL, 0, NULL); |
13200 | } |
13201 | GRN_API_RETURN(n); |
13202 | } |
13203 | |
13204 | static uint32_t |
13205 | grn_column_get_all_index_data_column(grn_ctx *ctx, |
13206 | grn_obj *obj, |
13207 | grn_index_datum *index_data, |
13208 | uint32_t n_index_data) |
13209 | { |
13210 | uint32_t n = 0; |
13211 | grn_hook_entry hook_entry; |
13212 | grn_hook *hooks; |
13213 | |
13214 | switch (obj->header.type) { |
13215 | case GRN_TABLE_HASH_KEY : |
13216 | case GRN_TABLE_PAT_KEY : |
13217 | case GRN_TABLE_DAT_KEY : |
13218 | case GRN_TABLE_NO_KEY : |
13219 | hook_entry = GRN_HOOK_INSERT; |
13220 | break; |
13221 | default : |
13222 | hook_entry = GRN_HOOK_SET; |
13223 | break; |
13224 | } |
13225 | |
13226 | for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) { |
13227 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
13228 | grn_obj *target = grn_ctx_at(ctx, data->target); |
13229 | int section = 0; |
13230 | if (!target) { |
13231 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
13232 | int length; |
13233 | char hook_name[GRN_TABLE_MAX_KEY_SIZE]; |
13234 | int hook_name_length; |
13235 | |
13236 | length = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE); |
13237 | hook_name_length = grn_table_get_key(ctx, |
13238 | ctx->impl->db, |
13239 | data->target, |
13240 | hook_name, |
13241 | GRN_TABLE_MAX_KEY_SIZE); |
13242 | ERR(GRN_OBJECT_CORRUPT, |
13243 | "[column][indexes][all] " |
13244 | "hook has a dangling reference: <%.*s> -> <%.*s>" , |
13245 | length, name, |
13246 | hook_name_length, hook_name); |
13247 | continue; |
13248 | } |
13249 | if (target->header.type != GRN_COLUMN_INDEX) { |
13250 | continue; |
13251 | } |
13252 | if (MULTI_COLUMN_INDEXP(target)) { |
13253 | section = data->section; |
13254 | } |
13255 | if (n < n_index_data) { |
13256 | index_data[n].index = target; |
13257 | index_data[n].section = section; |
13258 | } |
13259 | n++; |
13260 | } |
13261 | |
13262 | return n; |
13263 | } |
13264 | |
13265 | static uint32_t |
13266 | grn_column_get_all_index_data_accessor_index_column(grn_ctx *ctx, |
13267 | grn_accessor *a, |
13268 | grn_index_datum *index_data, |
13269 | uint32_t n_index_data) |
13270 | { |
13271 | grn_obj *index_column = a->obj; |
13272 | int section = 0; |
13273 | |
13274 | if (a->next) { |
13275 | int specified_section; |
13276 | grn_bool is_invalid_section; |
13277 | if (a->next->next) { |
13278 | return 0; |
13279 | } |
13280 | specified_section = find_section(ctx, index_column, a->next->obj); |
13281 | is_invalid_section = (specified_section == 0); |
13282 | if (is_invalid_section) { |
13283 | return 0; |
13284 | } |
13285 | section = specified_section; |
13286 | } |
13287 | if (n_index_data > 0) { |
13288 | index_data[0].index = index_column; |
13289 | index_data[0].section = section; |
13290 | } |
13291 | |
13292 | return 1; |
13293 | } |
13294 | |
13295 | static uint32_t |
13296 | grn_column_get_all_index_data_accessor(grn_ctx *ctx, |
13297 | grn_obj *obj, |
13298 | grn_index_datum *index_data, |
13299 | uint32_t n_index_data) |
13300 | { |
13301 | uint32_t n = 0; |
13302 | grn_accessor *a = (grn_accessor *)obj; |
13303 | |
13304 | while (a) { |
13305 | grn_hook *hooks; |
13306 | grn_bool found = GRN_FALSE; |
13307 | grn_hook_entry entry = (grn_hook_entry)-1; |
13308 | |
13309 | if (a->action == GRN_ACCESSOR_GET_COLUMN_VALUE && |
13310 | GRN_OBJ_INDEX_COLUMNP(a->obj)) { |
13311 | return grn_column_get_all_index_data_accessor_index_column(ctx, |
13312 | a, |
13313 | index_data, |
13314 | n_index_data); |
13315 | } |
13316 | |
13317 | switch (a->action) { |
13318 | case GRN_ACCESSOR_GET_KEY : |
13319 | entry = GRN_HOOK_INSERT; |
13320 | break; |
13321 | case GRN_ACCESSOR_GET_COLUMN_VALUE : |
13322 | entry = GRN_HOOK_SET; |
13323 | break; |
13324 | default : |
13325 | break; |
13326 | } |
13327 | |
13328 | if (entry == (grn_hook_entry)-1) { |
13329 | break; |
13330 | } |
13331 | |
13332 | for (hooks = DB_OBJ(a->obj)->hooks[entry]; hooks; hooks = hooks->next) { |
13333 | grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); |
13334 | grn_obj *target = grn_ctx_at(ctx, data->target); |
13335 | |
13336 | if (target->header.type != GRN_COLUMN_INDEX) { |
13337 | continue; |
13338 | } |
13339 | |
13340 | found = GRN_TRUE; |
13341 | if (!a->next) { |
13342 | int section = 0; |
13343 | |
13344 | if (MULTI_COLUMN_INDEXP(target)) { |
13345 | section = data->section; |
13346 | } |
13347 | if (n < n_index_data) { |
13348 | index_data[n].index = target; |
13349 | index_data[n].section = section; |
13350 | } |
13351 | n++; |
13352 | } |
13353 | } |
13354 | |
13355 | if (!found) { |
13356 | break; |
13357 | } |
13358 | a = a->next; |
13359 | } |
13360 | |
13361 | return n; |
13362 | } |
13363 | |
13364 | uint32_t |
13365 | grn_column_get_all_index_data(grn_ctx *ctx, |
13366 | grn_obj *obj, |
13367 | grn_index_datum *index_data, |
13368 | uint32_t n_index_data) |
13369 | { |
13370 | uint32_t n = 0; |
13371 | GRN_API_ENTER; |
13372 | if (GRN_DB_OBJP(obj)) { |
13373 | n = grn_column_get_all_index_data_column(ctx, obj, |
13374 | index_data, n_index_data); |
13375 | } else if (GRN_ACCESSORP(obj)) { |
13376 | n = grn_column_get_all_index_data_accessor(ctx, obj, |
13377 | index_data, n_index_data); |
13378 | } |
13379 | GRN_API_RETURN(n); |
13380 | } |
13381 | |
13382 | grn_rc |
13383 | grn_obj_columns(grn_ctx *ctx, grn_obj *table, |
13384 | const char *str, unsigned int str_size, grn_obj *res) |
13385 | { |
13386 | grn_obj *col; |
13387 | const char *p = (char *)str, *q, *r, *pe = p + str_size, *tokbuf[256]; |
13388 | while (p < pe) { |
13389 | int i, n = grn_tokenize(p, pe - p, tokbuf, 256, &q); |
13390 | for (i = 0; i < n; i++) { |
13391 | r = tokbuf[i]; |
13392 | while (p < r && (' ' == *p || ',' == *p)) { p++; } |
13393 | if (p < r) { |
13394 | if (r[-1] == '*') { |
13395 | grn_hash *cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
13396 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); |
13397 | if (cols) { |
13398 | grn_id *key; |
13399 | grn_table_columns(ctx, table, p, r - p - 1, (grn_obj *)cols); |
13400 | GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { |
13401 | if ((col = grn_ctx_at(ctx, *key))) { GRN_PTR_PUT(ctx, res, col); } |
13402 | }); |
13403 | grn_hash_close(ctx, cols); |
13404 | } |
13405 | { |
13406 | grn_obj *type = grn_ctx_at(ctx, table->header.domain); |
13407 | if (GRN_OBJ_TABLEP(type)) { |
13408 | grn_obj *ai = grn_obj_column(ctx, table, |
13409 | GRN_COLUMN_NAME_ID, |
13410 | GRN_COLUMN_NAME_ID_LEN); |
13411 | if (ai) { |
13412 | if (ai->header.type == GRN_ACCESSOR) { |
13413 | grn_id *key; |
13414 | grn_accessor *id_accessor; |
13415 | for (id_accessor = ((grn_accessor *)ai)->next; |
13416 | id_accessor; |
13417 | id_accessor = id_accessor->next) { |
13418 | grn_obj *target_table = id_accessor->obj; |
13419 | |
13420 | cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
13421 | GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); |
13422 | if (!cols) { |
13423 | continue; |
13424 | } |
13425 | grn_table_columns(ctx, target_table, |
13426 | p, r - p - 1, (grn_obj *)cols); |
13427 | GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { |
13428 | if ((col = grn_ctx_at(ctx, *key))) { |
13429 | grn_accessor *a; |
13430 | grn_accessor *ac; |
13431 | ac = accessor_new(ctx); |
13432 | GRN_PTR_PUT(ctx, res, (grn_obj *)ac); |
13433 | for (a = (grn_accessor *)ai; a; a = a->next) { |
13434 | if (a->action != GRN_ACCESSOR_GET_ID) { |
13435 | ac->action = a->action; |
13436 | ac->obj = a->obj; |
13437 | ac->next = accessor_new(ctx); |
13438 | if (!(ac = ac->next)) { break; } |
13439 | } else { |
13440 | ac->action = GRN_ACCESSOR_GET_COLUMN_VALUE; |
13441 | ac->obj = col; |
13442 | ac->next = NULL; |
13443 | break; |
13444 | } |
13445 | } |
13446 | } |
13447 | }); |
13448 | grn_hash_close(ctx, cols); |
13449 | } |
13450 | } |
13451 | grn_obj_unlink(ctx, ai); |
13452 | } |
13453 | } |
13454 | } |
13455 | } else if ((col = grn_obj_column(ctx, table, p, r - p))) { |
13456 | GRN_PTR_PUT(ctx, res, col); |
13457 | } |
13458 | } |
13459 | p = r; |
13460 | } |
13461 | p = q; |
13462 | } |
13463 | return ctx->rc; |
13464 | } |
13465 | |
13466 | static grn_table_sort_key * |
13467 | grn_table_sort_key_from_str_geo(grn_ctx *ctx, const char *str, unsigned int str_size, |
13468 | grn_obj *table, unsigned int *nkeys) |
13469 | { |
13470 | const char **tokbuf; |
13471 | const char *p = str, *pe = str + str_size; |
13472 | grn_table_sort_key *keys = NULL, *k = NULL; |
13473 | while ((*p++ != '(')) { if (p == pe) { return NULL; } } |
13474 | str = p; |
13475 | while ((*p != ')')) { if (++p == pe) { return NULL; } } |
13476 | str_size = p - str; |
13477 | p = str; |
13478 | if ((tokbuf = GRN_MALLOCN(const char *, str_size))) { |
13479 | grn_id domain = GRN_ID_NIL; |
13480 | int i, n = grn_tokenize(str, str_size, tokbuf, str_size, NULL); |
13481 | if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) { |
13482 | k = keys; |
13483 | for (i = 0; i < n; i++) { |
13484 | const char *r = tokbuf[i]; |
13485 | while (p < r && (' ' == *p || ',' == *p)) { p++; } |
13486 | if (p < r) { |
13487 | k->flags = GRN_TABLE_SORT_ASC; |
13488 | k->offset = 0; |
13489 | if (*p == '+') { |
13490 | p++; |
13491 | } else if (*p == '-') { |
13492 | k->flags = GRN_TABLE_SORT_DESC; |
13493 | p++; |
13494 | } |
13495 | if (k == keys) { |
13496 | if (!(k->key = grn_obj_column(ctx, table, p, r - p))) { |
13497 | WARN(GRN_INVALID_ARGUMENT, "invalid sort key: <%.*s>(<%.*s>)" , |
13498 | (int)(tokbuf[i] - p), p, str_size, str); |
13499 | break; |
13500 | } |
13501 | domain = grn_obj_get_range(ctx, k->key); |
13502 | } else { |
13503 | grn_obj buf; |
13504 | GRN_TEXT_INIT(&buf, GRN_OBJ_DO_SHALLOW_COPY); |
13505 | GRN_TEXT_SET(ctx, &buf, p + 1, r - p - 2); /* should be quoted */ |
13506 | k->key = grn_obj_open(ctx, GRN_BULK, 0, domain); |
13507 | grn_obj_cast(ctx, &buf, k->key, GRN_FALSE); |
13508 | GRN_OBJ_FIN(ctx, &buf); |
13509 | } |
13510 | k->flags |= GRN_TABLE_SORT_GEO; |
13511 | k++; |
13512 | } |
13513 | p = r; |
13514 | } |
13515 | } |
13516 | GRN_FREE(tokbuf); |
13517 | } |
13518 | if (!ctx->rc && k - keys > 0) { |
13519 | *nkeys = k - keys; |
13520 | } else { |
13521 | grn_table_sort_key_close(ctx, keys, k - keys); |
13522 | *nkeys = 0; |
13523 | keys = NULL; |
13524 | } |
13525 | return keys; |
13526 | } |
13527 | |
13528 | grn_table_sort_key * |
13529 | grn_table_sort_key_from_str(grn_ctx *ctx, const char *str, unsigned int str_size, |
13530 | grn_obj *table, unsigned int *nkeys) |
13531 | { |
13532 | const char *p = str; |
13533 | const char **tokbuf; |
13534 | grn_table_sort_key *keys = NULL, *k = NULL; |
13535 | |
13536 | if (str_size == 0) { |
13537 | return NULL; |
13538 | } |
13539 | |
13540 | if ((keys = grn_table_sort_key_from_str_geo(ctx, str, str_size, table, nkeys))) { |
13541 | return keys; |
13542 | } |
13543 | if ((tokbuf = GRN_MALLOCN(const char *, str_size))) { |
13544 | int i, n = grn_tokenize(str, str_size, tokbuf, str_size, NULL); |
13545 | if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) { |
13546 | k = keys; |
13547 | for (i = 0; i < n; i++) { |
13548 | const char *r = tokbuf[i]; |
13549 | while (p < r && (' ' == *p || ',' == *p)) { p++; } |
13550 | if (p < r) { |
13551 | k->flags = GRN_TABLE_SORT_ASC; |
13552 | k->offset = 0; |
13553 | if (*p == '+') { |
13554 | p++; |
13555 | } else if (*p == '-') { |
13556 | k->flags = GRN_TABLE_SORT_DESC; |
13557 | p++; |
13558 | } |
13559 | if ((k->key = grn_obj_column(ctx, table, p, r - p))) { |
13560 | k++; |
13561 | } else { |
13562 | if (r - p == GRN_COLUMN_NAME_SCORE_LEN && |
13563 | memcmp(p, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN) == 0) { |
13564 | char table_name[GRN_TABLE_MAX_KEY_SIZE]; |
13565 | int table_name_size; |
13566 | table_name_size = grn_obj_name(ctx, table, |
13567 | table_name, |
13568 | GRN_TABLE_MAX_KEY_SIZE); |
13569 | if (table_name_size == 0) { |
13570 | grn_strcpy(table_name, GRN_TABLE_MAX_KEY_SIZE, "(anonymous)" ); |
13571 | table_name_size = strlen(table_name); |
13572 | } |
13573 | GRN_LOG(ctx, GRN_WARN, |
13574 | "ignore invalid sort key: <%.*s>: " |
13575 | "table:<%*.s> keys:<%.*s>" , |
13576 | (int)(r - p), p, |
13577 | table_name_size, table_name, |
13578 | str_size, str); |
13579 | } else { |
13580 | char table_name[GRN_TABLE_MAX_KEY_SIZE]; |
13581 | int table_name_size; |
13582 | table_name_size = grn_obj_name(ctx, table, |
13583 | table_name, |
13584 | GRN_TABLE_MAX_KEY_SIZE); |
13585 | if (table_name_size == 0) { |
13586 | grn_strcpy(table_name, GRN_TABLE_MAX_KEY_SIZE, "(anonymous)" ); |
13587 | table_name_size = strlen(table_name); |
13588 | } |
13589 | WARN(GRN_INVALID_ARGUMENT, |
13590 | "invalid sort key: <%.*s>: " |
13591 | "table:<%.*s> keys:<%.*s>" , |
13592 | (int)(r - p), p, |
13593 | table_name_size, table_name, |
13594 | str_size, str); |
13595 | break; |
13596 | } |
13597 | } |
13598 | } |
13599 | p = r; |
13600 | } |
13601 | } |
13602 | GRN_FREE(tokbuf); |
13603 | } |
13604 | if (!ctx->rc && k - keys > 0) { |
13605 | *nkeys = k - keys; |
13606 | } else { |
13607 | grn_table_sort_key_close(ctx, keys, k - keys); |
13608 | *nkeys = 0; |
13609 | keys = NULL; |
13610 | } |
13611 | return keys; |
13612 | } |
13613 | |
13614 | grn_rc |
13615 | grn_table_sort_key_close(grn_ctx *ctx, grn_table_sort_key *keys, unsigned int nkeys) |
13616 | { |
13617 | int i; |
13618 | if (keys) { |
13619 | for (i = 0; i < nkeys; i++) { |
13620 | grn_obj *key = keys[i].key; |
13621 | if (!grn_obj_is_column(ctx, key)) { |
13622 | grn_obj_unlink(ctx, key); |
13623 | } |
13624 | } |
13625 | GRN_FREE(keys); |
13626 | } |
13627 | return ctx->rc; |
13628 | } |
13629 | |
13630 | grn_bool |
13631 | grn_table_is_grouped(grn_ctx *ctx, grn_obj *table) |
13632 | { |
13633 | if (GRN_OBJ_TABLEP(table) && GRN_TABLE_IS_GROUPED(table)) { |
13634 | return GRN_TRUE; |
13635 | } |
13636 | return GRN_FALSE; |
13637 | } |
13638 | |
13639 | unsigned int |
13640 | grn_table_max_n_subrecs(grn_ctx *ctx, grn_obj *table) |
13641 | { |
13642 | if (GRN_OBJ_TABLEP(table)) { |
13643 | return DB_OBJ(table)->max_n_subrecs; |
13644 | } |
13645 | return 0; |
13646 | } |
13647 | |
13648 | grn_obj * |
13649 | grn_table_tokenize(grn_ctx *ctx, grn_obj *table, |
13650 | const char *str, unsigned int str_len, |
13651 | grn_obj *buf, grn_bool addp) |
13652 | { |
13653 | grn_token_cursor *token_cursor = NULL; |
13654 | grn_tokenize_mode mode = addp ? GRN_TOKENIZE_ADD : GRN_TOKENIZE_GET; |
13655 | GRN_API_ENTER; |
13656 | if (!(token_cursor = grn_token_cursor_open(ctx, table, str, str_len, mode, 0))) { |
13657 | goto exit; |
13658 | } |
13659 | if (buf) { |
13660 | GRN_BULK_REWIND(buf); |
13661 | } else { |
13662 | if (!(buf = grn_obj_open(ctx, GRN_UVECTOR, 0, DB_OBJ(table)->id))) { |
13663 | goto exit; |
13664 | } |
13665 | } |
13666 | while (token_cursor->status != GRN_TOKEN_CURSOR_DONE && token_cursor->status != GRN_TOKEN_CURSOR_DONE_SKIP) { |
13667 | grn_id tid; |
13668 | if ((tid = grn_token_cursor_next(ctx, token_cursor))) { |
13669 | GRN_RECORD_PUT(ctx, buf, tid); |
13670 | } |
13671 | } |
13672 | exit : |
13673 | if (token_cursor) { |
13674 | grn_token_cursor_close(ctx, token_cursor); |
13675 | } |
13676 | GRN_API_RETURN(buf); |
13677 | } |
13678 | |
13679 | static void |
13680 | grn_db_recover_database_remove_orphan_inspect(grn_ctx *ctx, grn_obj *db) |
13681 | { |
13682 | GRN_TABLE_EACH_BEGIN_FLAGS(ctx, db, cursor, id, GRN_CURSOR_BY_ID) { |
13683 | void *key; |
13684 | int key_size; |
13685 | |
13686 | key_size = grn_table_cursor_get_key(ctx, cursor, &key); |
13687 | #define INSPECT "inspect" |
13688 | #define INSPECT_LEN (sizeof(INSPECT) - 1) |
13689 | if (key_size == INSPECT_LEN && memcmp(key, INSPECT, INSPECT_LEN) == 0) { |
13690 | if (!grn_ctx_at(ctx, id)) { |
13691 | ERRCLR(ctx); |
13692 | grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
13693 | } |
13694 | break; |
13695 | } |
13696 | #undef INSPECT |
13697 | #undef INSPECT_LEN |
13698 | } GRN_TABLE_EACH_END(ctx, cursor); |
13699 | } |
13700 | |
13701 | static void |
13702 | grn_db_recover_database(grn_ctx *ctx, grn_obj *db) |
13703 | { |
13704 | if (grn_obj_is_locked(ctx, db)) { |
13705 | ERR(GRN_OBJECT_CORRUPT, |
13706 | "[db][recover] database may be broken. Please re-create the database" ); |
13707 | return; |
13708 | } |
13709 | |
13710 | grn_db_clear_dirty(ctx, db); |
13711 | grn_db_recover_database_remove_orphan_inspect(ctx, db); |
13712 | } |
13713 | |
13714 | static void |
13715 | grn_db_recover_table(grn_ctx *ctx, grn_obj *table) |
13716 | { |
13717 | if (!grn_obj_is_locked(ctx, table)) { |
13718 | return; |
13719 | } |
13720 | |
13721 | { |
13722 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
13723 | unsigned int name_size; |
13724 | name_size = grn_obj_name(ctx, table, name, GRN_TABLE_MAX_KEY_SIZE); |
13725 | ERR(GRN_OBJECT_CORRUPT, |
13726 | "[db][recover] table may be broken: <%.*s>: " |
13727 | "please truncate the table (or clear lock of the table) " |
13728 | "and load data again" , |
13729 | (int)name_size, name); |
13730 | } |
13731 | } |
13732 | |
13733 | static void |
13734 | grn_db_recover_data_column(grn_ctx *ctx, grn_obj *data_column) |
13735 | { |
13736 | if (!grn_obj_is_locked(ctx, data_column)) { |
13737 | return; |
13738 | } |
13739 | |
13740 | { |
13741 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
13742 | unsigned int name_size; |
13743 | name_size = grn_obj_name(ctx, data_column, name, GRN_TABLE_MAX_KEY_SIZE); |
13744 | ERR(GRN_OBJECT_CORRUPT, |
13745 | "[db][recover] column may be broken: <%.*s>: " |
13746 | "please truncate the column (or clear lock of the column) " |
13747 | "and load data again" , |
13748 | (int)name_size, name); |
13749 | } |
13750 | } |
13751 | |
13752 | static void |
13753 | grn_db_recover_index_column(grn_ctx *ctx, grn_obj *index_column) |
13754 | { |
13755 | if (!grn_obj_is_locked(ctx, index_column)) { |
13756 | return; |
13757 | } |
13758 | |
13759 | grn_index_column_rebuild(ctx, index_column); |
13760 | } |
13761 | |
13762 | static grn_bool |
13763 | grn_db_recover_is_builtin(grn_ctx *ctx, grn_id id, grn_table_cursor *cursor) |
13764 | { |
13765 | void *key; |
13766 | const char *name; |
13767 | int name_size; |
13768 | |
13769 | if (id < GRN_N_RESERVED_TYPES) { |
13770 | return GRN_TRUE; |
13771 | } |
13772 | |
13773 | name_size = grn_table_cursor_get_key(ctx, cursor, &key); |
13774 | name = key; |
13775 | |
13776 | #define NAME_EQUAL(value) \ |
13777 | (name_size == strlen(value) && memcmp(name, value, strlen(value)) == 0) |
13778 | |
13779 | if (NAME_EQUAL("inspect" )) { |
13780 | /* Just for compatibility. It's needed for users who used |
13781 | Groonga master at between 2016-02-03 and 2016-02-26. */ |
13782 | return GRN_TRUE; |
13783 | } |
13784 | |
13785 | #undef NAME_EQUAL |
13786 | |
13787 | return GRN_FALSE; |
13788 | } |
13789 | |
13790 | grn_rc |
13791 | grn_db_recover(grn_ctx *ctx, grn_obj *db) |
13792 | { |
13793 | grn_table_cursor *cursor; |
13794 | grn_id id; |
13795 | grn_bool is_close_opened_object_mode; |
13796 | |
13797 | GRN_API_ENTER; |
13798 | |
13799 | is_close_opened_object_mode = (grn_thread_get_limit() == 1); |
13800 | |
13801 | grn_db_recover_database(ctx, db); |
13802 | if (ctx->rc != GRN_SUCCESS) { |
13803 | GRN_API_RETURN(ctx->rc); |
13804 | } |
13805 | |
13806 | cursor = grn_table_cursor_open(ctx, db, |
13807 | NULL, 0, NULL, 0, |
13808 | 0, -1, |
13809 | GRN_CURSOR_BY_ID); |
13810 | if (!cursor) { |
13811 | GRN_API_RETURN(ctx->rc); |
13812 | } |
13813 | |
13814 | while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { |
13815 | grn_obj *object; |
13816 | |
13817 | if (is_close_opened_object_mode) { |
13818 | grn_ctx_push_temporary_open_space(ctx); |
13819 | } |
13820 | |
13821 | if ((object = grn_ctx_at(ctx, id))) { |
13822 | switch (object->header.type) { |
13823 | case GRN_TABLE_NO_KEY : |
13824 | case GRN_TABLE_HASH_KEY : |
13825 | case GRN_TABLE_PAT_KEY : |
13826 | case GRN_TABLE_DAT_KEY : |
13827 | grn_db_recover_table(ctx, object); |
13828 | break; |
13829 | case GRN_COLUMN_FIX_SIZE : |
13830 | case GRN_COLUMN_VAR_SIZE : |
13831 | grn_db_recover_data_column(ctx, object); |
13832 | break; |
13833 | case GRN_COLUMN_INDEX : |
13834 | grn_db_recover_index_column(ctx, object); |
13835 | break; |
13836 | default: |
13837 | break; |
13838 | } |
13839 | grn_obj_unlink(ctx, object); |
13840 | } else { |
13841 | if (grn_db_recover_is_builtin(ctx, id, cursor)) { |
13842 | ERRCLR(ctx); |
13843 | } |
13844 | } |
13845 | |
13846 | if (is_close_opened_object_mode) { |
13847 | grn_ctx_pop_temporary_open_space(ctx); |
13848 | } |
13849 | |
13850 | if (ctx->rc != GRN_SUCCESS) { |
13851 | break; |
13852 | } |
13853 | } |
13854 | grn_table_cursor_close(ctx, cursor); |
13855 | |
13856 | GRN_API_RETURN(ctx->rc); |
13857 | } |
13858 | |
13859 | grn_rc |
13860 | grn_db_unmap(grn_ctx *ctx, grn_obj *db) |
13861 | { |
13862 | grn_id id; |
13863 | db_value *vp; |
13864 | grn_db *s = (grn_db *)db; |
13865 | |
13866 | GRN_API_ENTER; |
13867 | |
13868 | GRN_TINY_ARRAY_EACH(&s->values, 1, grn_db_curr_id(ctx, db), id, vp, { |
13869 | grn_obj *obj = vp->ptr; |
13870 | |
13871 | if (obj) { |
13872 | switch (obj->header.type) { |
13873 | case GRN_TABLE_HASH_KEY : |
13874 | case GRN_TABLE_PAT_KEY : |
13875 | case GRN_TABLE_DAT_KEY : |
13876 | case GRN_TABLE_NO_KEY : |
13877 | case GRN_COLUMN_FIX_SIZE : |
13878 | case GRN_COLUMN_VAR_SIZE : |
13879 | case GRN_COLUMN_INDEX : |
13880 | grn_obj_close(ctx, obj); |
13881 | break; |
13882 | } |
13883 | } |
13884 | }); |
13885 | |
13886 | GRN_API_RETURN(ctx->rc); |
13887 | } |
13888 | |
13889 | static grn_rc |
13890 | grn_ctx_get_all_objects(grn_ctx *ctx, grn_obj *objects_buffer, |
13891 | grn_bool (*predicate)(grn_ctx *ctx, grn_obj *object)) |
13892 | { |
13893 | grn_obj *db; |
13894 | grn_table_cursor *cursor; |
13895 | grn_id id; |
13896 | |
13897 | GRN_API_ENTER; |
13898 | |
13899 | db = ctx->impl->db; |
13900 | if (!db) { |
13901 | ERR(GRN_INVALID_ARGUMENT, "DB isn't associated" ); |
13902 | GRN_API_RETURN(ctx->rc); |
13903 | } |
13904 | |
13905 | cursor = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0); |
13906 | if (!cursor) { |
13907 | GRN_API_RETURN(ctx->rc); |
13908 | } |
13909 | |
13910 | while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { |
13911 | grn_obj *object; |
13912 | |
13913 | if ((object = grn_ctx_at(ctx, id))) { |
13914 | if (predicate(ctx, object)) { |
13915 | GRN_PTR_PUT(ctx, objects_buffer, object); |
13916 | } else { |
13917 | grn_obj_unlink(ctx, object); |
13918 | } |
13919 | } else { |
13920 | if (ctx->rc != GRN_SUCCESS) { |
13921 | ERRCLR(ctx); |
13922 | } |
13923 | } |
13924 | } |
13925 | grn_table_cursor_close(ctx, cursor); |
13926 | |
13927 | GRN_API_RETURN(ctx->rc); |
13928 | } |
13929 | |
13930 | grn_rc |
13931 | grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer) |
13932 | { |
13933 | return grn_ctx_get_all_objects(ctx, tables_buffer, grn_obj_is_table); |
13934 | } |
13935 | |
13936 | grn_rc |
13937 | grn_ctx_get_all_types(grn_ctx *ctx, grn_obj *types_buffer) |
13938 | { |
13939 | return grn_ctx_get_all_objects(ctx, types_buffer, grn_obj_is_type); |
13940 | } |
13941 | |
13942 | grn_rc |
13943 | grn_ctx_get_all_tokenizers(grn_ctx *ctx, grn_obj *tokenizers_buffer) |
13944 | { |
13945 | return grn_ctx_get_all_objects(ctx, tokenizers_buffer, |
13946 | grn_obj_is_tokenizer_proc); |
13947 | } |
13948 | |
13949 | grn_rc |
13950 | grn_ctx_get_all_normalizers(grn_ctx *ctx, grn_obj *normalizers_buffer) |
13951 | { |
13952 | return grn_ctx_get_all_objects(ctx, normalizers_buffer, |
13953 | grn_obj_is_normalizer_proc); |
13954 | } |
13955 | |
13956 | grn_rc |
13957 | grn_ctx_get_all_token_filters(grn_ctx *ctx, grn_obj *token_filters_buffer) |
13958 | { |
13959 | return grn_ctx_get_all_objects(ctx, token_filters_buffer, |
13960 | grn_obj_is_token_filter_proc); |
13961 | } |
13962 | |
13963 | grn_rc |
13964 | grn_ctx_push_temporary_open_space(grn_ctx *ctx) |
13965 | { |
13966 | grn_obj *stack; |
13967 | grn_obj *space; |
13968 | grn_obj buffer; |
13969 | |
13970 | GRN_API_ENTER; |
13971 | |
13972 | stack = &(ctx->impl->temporary_open_spaces.stack); |
13973 | GRN_VOID_INIT(&buffer); |
13974 | grn_bulk_write(ctx, stack, (const char *)&buffer, sizeof(grn_obj)); |
13975 | space = ((grn_obj *)GRN_BULK_CURR(stack)) - 1; |
13976 | GRN_PTR_INIT(space, GRN_OBJ_VECTOR | GRN_OBJ_OWN, GRN_ID_NIL); |
13977 | |
13978 | ctx->impl->temporary_open_spaces.current = space; |
13979 | |
13980 | GRN_API_RETURN(ctx->rc); |
13981 | } |
13982 | |
13983 | grn_rc |
13984 | grn_ctx_pop_temporary_open_space(grn_ctx *ctx) |
13985 | { |
13986 | grn_obj *stack; |
13987 | grn_obj *space; |
13988 | |
13989 | GRN_API_ENTER; |
13990 | |
13991 | stack = &(ctx->impl->temporary_open_spaces.stack); |
13992 | if (GRN_BULK_EMPTYP(stack)) { |
13993 | ERR(GRN_INVALID_ARGUMENT, |
13994 | "[ctx][temporary-open-spaces][pop] too much pop" ); |
13995 | GRN_API_RETURN(ctx->rc); |
13996 | } |
13997 | |
13998 | space = ctx->impl->temporary_open_spaces.current; |
13999 | GRN_OBJ_FIN(ctx, space); |
14000 | grn_bulk_truncate(ctx, stack, GRN_BULK_VSIZE(stack) - sizeof(grn_obj)); |
14001 | |
14002 | if (GRN_BULK_EMPTYP(stack)) { |
14003 | space = NULL; |
14004 | } else { |
14005 | space = ((grn_obj *)GRN_BULK_CURR(stack)) - 1; |
14006 | } |
14007 | ctx->impl->temporary_open_spaces.current = space; |
14008 | |
14009 | GRN_API_RETURN(ctx->rc); |
14010 | } |
14011 | |
14012 | grn_rc |
14013 | grn_ctx_merge_temporary_open_space(grn_ctx *ctx) |
14014 | { |
14015 | grn_obj *stack; |
14016 | grn_obj *space; |
14017 | grn_obj *next_space; |
14018 | |
14019 | GRN_API_ENTER; |
14020 | |
14021 | stack = &(ctx->impl->temporary_open_spaces.stack); |
14022 | if (GRN_BULK_VSIZE(stack) < sizeof(grn_obj) * 2) { |
14023 | ERR(GRN_INVALID_ARGUMENT, |
14024 | "[ctx][temporary-open-spaces][merge] " |
14025 | "merge requires at least two spaces" ); |
14026 | GRN_API_RETURN(ctx->rc); |
14027 | } |
14028 | |
14029 | space = ctx->impl->temporary_open_spaces.current; |
14030 | next_space = ctx->impl->temporary_open_spaces.current - 1; |
14031 | { |
14032 | unsigned int i, n_elements; |
14033 | n_elements = GRN_BULK_VSIZE(space) / sizeof(grn_obj *); |
14034 | for (i = 0; i < n_elements; i++) { |
14035 | grn_obj *element = GRN_PTR_VALUE_AT(space, i); |
14036 | GRN_PTR_PUT(ctx, next_space, element); |
14037 | } |
14038 | } |
14039 | GRN_BULK_REWIND(space); |
14040 | GRN_OBJ_FIN(ctx, space); |
14041 | grn_bulk_truncate(ctx, stack, GRN_BULK_VSIZE(stack) - sizeof(grn_obj)); |
14042 | |
14043 | if (GRN_BULK_EMPTYP(stack)) { |
14044 | space = NULL; |
14045 | } else { |
14046 | space = ((grn_obj *)GRN_BULK_CURR(stack)) - 1; |
14047 | } |
14048 | ctx->impl->temporary_open_spaces.current = space; |
14049 | |
14050 | GRN_API_RETURN(ctx->rc); |
14051 | } |
14052 | |