1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2015-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
19#include "grn.h"
20#include "grn_index_column.h"
21#include "grn_pat.h"
22#include "grn_dat.h"
23#include "grn_ii.h"
24
25grn_bool
26grn_obj_is_true(grn_ctx *ctx, grn_obj *obj)
27{
28 if (!obj) {
29 return GRN_FALSE;
30 }
31
32 switch (obj->header.type) {
33 case GRN_BULK :
34 switch (obj->header.domain) {
35 case GRN_DB_BOOL :
36 return GRN_BOOL_VALUE(obj);
37 break;
38 case GRN_DB_INT32 :
39 return GRN_INT32_VALUE(obj) != 0;
40 break;
41 case GRN_DB_UINT32 :
42 return GRN_UINT32_VALUE(obj) != 0;
43 break;
44 case GRN_DB_FLOAT : {
45 double float_value;
46 float_value = GRN_FLOAT_VALUE(obj);
47 return (float_value < -DBL_EPSILON ||
48 DBL_EPSILON < float_value);
49 break;
50 }
51 case GRN_DB_SHORT_TEXT :
52 case GRN_DB_TEXT :
53 case GRN_DB_LONG_TEXT :
54 return GRN_TEXT_LEN(obj) != 0;
55 break;
56 default :
57 return GRN_FALSE;
58 break;
59 }
60 break;
61 case GRN_VECTOR :
62 return GRN_TRUE;
63 break;
64 default :
65 return GRN_FALSE;
66 break;
67 }
68}
69
70grn_bool
71grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj)
72{
73 grn_id id;
74
75 if (!obj) { return GRN_FALSE; }
76
77 id = grn_obj_id(ctx, obj);
78 return grn_id_is_builtin(ctx, id);
79}
80
81grn_bool
82grn_obj_is_bulk(grn_ctx *ctx, grn_obj *obj)
83{
84 if (!obj) {
85 return GRN_FALSE;
86 }
87
88 return obj->header.type == GRN_BULK;
89}
90
91grn_bool
92grn_obj_is_text_family_bulk(grn_ctx *ctx, grn_obj *obj)
93{
94 if (!grn_obj_is_bulk(ctx, obj)) {
95 return GRN_FALSE;
96 }
97
98 return GRN_TYPE_IS_TEXT_FAMILY(obj->header.domain);
99}
100
101grn_bool
102grn_obj_is_table(grn_ctx *ctx, grn_obj *obj)
103{
104 grn_bool is_table = GRN_FALSE;
105
106 if (!obj) {
107 return GRN_FALSE;
108 }
109
110 switch (obj->header.type) {
111 case GRN_TABLE_NO_KEY :
112 case GRN_TABLE_HASH_KEY :
113 case GRN_TABLE_PAT_KEY :
114 case GRN_TABLE_DAT_KEY :
115 is_table = GRN_TRUE;
116 default :
117 break;
118 }
119
120 return is_table;
121}
122
123grn_bool
124grn_obj_is_column(grn_ctx *ctx, grn_obj *obj)
125{
126 grn_bool is_column = GRN_FALSE;
127
128 if (!obj) {
129 return GRN_FALSE;
130 }
131
132 switch (obj->header.type) {
133 case GRN_COLUMN_FIX_SIZE :
134 case GRN_COLUMN_VAR_SIZE :
135 case GRN_COLUMN_INDEX :
136 is_column = GRN_TRUE;
137 default :
138 break;
139 }
140
141 return is_column;
142}
143
144grn_bool
145grn_obj_is_scalar_column(grn_ctx *ctx, grn_obj *obj)
146{
147 if (!grn_obj_is_column(ctx, obj)) {
148 return GRN_FALSE;
149 }
150
151 return (obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_SCALAR;
152}
153
154grn_bool
155grn_obj_is_vector_column(grn_ctx *ctx, grn_obj *obj)
156{
157 if (!grn_obj_is_column(ctx, obj)) {
158 return GRN_FALSE;
159 }
160
161 return ((obj->header.type == GRN_COLUMN_VAR_SIZE) &&
162 ((obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) ==
163 GRN_OBJ_COLUMN_VECTOR));
164}
165
166grn_bool
167grn_obj_is_weight_vector_column(grn_ctx *ctx, grn_obj *obj)
168{
169 if (!grn_obj_is_vector_column(ctx, obj)) {
170 return GRN_FALSE;
171 }
172
173 return (obj->header.flags & GRN_OBJ_WITH_WEIGHT) == GRN_OBJ_WITH_WEIGHT;
174}
175
176grn_bool
177grn_obj_is_reference_column(grn_ctx *ctx, grn_obj *obj)
178{
179 grn_obj *range;
180
181 if (!grn_obj_is_column(ctx, obj)) {
182 return GRN_FALSE;
183 }
184
185 range = grn_ctx_at(ctx, grn_obj_get_range(ctx, obj));
186 if (!range) {
187 return GRN_FALSE;
188 }
189
190 switch (range->header.type) {
191 case GRN_TABLE_HASH_KEY:
192 case GRN_TABLE_PAT_KEY:
193 case GRN_TABLE_DAT_KEY:
194 case GRN_TABLE_NO_KEY:
195 return GRN_TRUE;
196 default:
197 return GRN_FALSE;
198 }
199}
200
201grn_bool
202grn_obj_is_data_column(grn_ctx *ctx, grn_obj *obj)
203{
204 if (!grn_obj_is_column(ctx, obj)) {
205 return GRN_FALSE;
206 }
207
208 return obj->header.type == GRN_COLUMN_FIX_SIZE ||
209 obj->header.type == GRN_COLUMN_VAR_SIZE;
210}
211
212grn_bool
213grn_obj_is_index_column(grn_ctx *ctx, grn_obj *obj)
214{
215 if (!grn_obj_is_column(ctx, obj)) {
216 return GRN_FALSE;
217 }
218
219 return obj->header.type == GRN_COLUMN_INDEX;
220}
221
222grn_bool
223grn_obj_is_accessor(grn_ctx *ctx, grn_obj *obj)
224{
225 if (!obj) {
226 return GRN_FALSE;
227 }
228
229 return obj->header.type == GRN_ACCESSOR;
230}
231
232grn_bool
233grn_obj_is_key_accessor(grn_ctx *ctx, grn_obj *obj)
234{
235 grn_accessor *accessor;
236
237 if (!grn_obj_is_accessor(ctx, obj)) {
238 return GRN_FALSE;
239 }
240
241 accessor = (grn_accessor *)obj;
242 if (accessor->next) {
243 return GRN_FALSE;
244 }
245
246 return accessor->action == GRN_ACCESSOR_GET_KEY;
247}
248
249grn_bool
250grn_obj_is_type(grn_ctx *ctx, grn_obj *obj)
251{
252 if (!obj) {
253 return GRN_FALSE;
254 }
255
256 return obj->header.type == GRN_TYPE;
257}
258
259grn_bool
260grn_obj_is_text_family_type(grn_ctx *ctx, grn_obj *obj)
261{
262 if (!grn_obj_is_type(ctx, obj)) {
263 return GRN_FALSE;
264 }
265
266 return GRN_TYPE_IS_TEXT_FAMILY(grn_obj_id(ctx, obj));
267}
268
269grn_bool
270grn_obj_is_proc(grn_ctx *ctx, grn_obj *obj)
271{
272 if (!obj) {
273 return GRN_FALSE;
274 }
275
276 return obj->header.type == GRN_PROC;
277}
278
279grn_bool
280grn_obj_is_tokenizer_proc(grn_ctx *ctx, grn_obj *obj)
281{
282 grn_proc *proc;
283
284 if (!grn_obj_is_proc(ctx, obj)) {
285 return GRN_FALSE;
286 }
287
288 proc = (grn_proc *)obj;
289 return proc->type == GRN_PROC_TOKENIZER;
290}
291
292grn_bool
293grn_obj_is_function_proc(grn_ctx *ctx, grn_obj *obj)
294{
295 grn_proc *proc;
296
297 if (!grn_obj_is_proc(ctx, obj)) {
298 return GRN_FALSE;
299 }
300
301 proc = (grn_proc *)obj;
302 return proc->type == GRN_PROC_FUNCTION;
303}
304
305grn_bool
306grn_obj_is_selector_proc(grn_ctx *ctx, grn_obj *obj)
307{
308 grn_proc *proc;
309
310 if (!grn_obj_is_function_proc(ctx, obj)) {
311 return GRN_FALSE;
312 }
313
314 proc = (grn_proc *)obj;
315 return proc->callbacks.function.selector != NULL;
316}
317
318grn_bool
319grn_obj_is_selector_only_proc(grn_ctx *ctx, grn_obj *obj)
320{
321 grn_proc *proc;
322
323 if (!grn_obj_is_selector_proc(ctx, obj)) {
324 return GRN_FALSE;
325 }
326
327 proc = (grn_proc *)obj;
328 return proc->funcs[PROC_INIT] == NULL;
329}
330
331grn_bool
332grn_obj_is_normalizer_proc(grn_ctx *ctx, grn_obj *obj)
333{
334 grn_proc *proc;
335
336 if (!grn_obj_is_proc(ctx, obj)) {
337 return GRN_FALSE;
338 }
339
340 proc = (grn_proc *)obj;
341 return proc->type == GRN_PROC_NORMALIZER;
342}
343
344grn_bool
345grn_obj_is_token_filter_proc(grn_ctx *ctx, grn_obj *obj)
346{
347 grn_proc *proc;
348
349 if (!grn_obj_is_proc(ctx, obj)) {
350 return GRN_FALSE;
351 }
352
353 proc = (grn_proc *)obj;
354 return proc->type == GRN_PROC_TOKEN_FILTER;
355}
356
357grn_bool
358grn_obj_is_scorer_proc(grn_ctx *ctx, grn_obj *obj)
359{
360 grn_proc *proc;
361
362 if (!grn_obj_is_proc(ctx, obj)) {
363 return GRN_FALSE;
364 }
365
366 proc = (grn_proc *)obj;
367 return proc->type == GRN_PROC_SCORER;
368}
369
370grn_bool
371grn_obj_is_window_function_proc(grn_ctx *ctx, grn_obj *obj)
372{
373 grn_proc *proc;
374
375 if (!grn_obj_is_proc(ctx, obj)) {
376 return GRN_FALSE;
377 }
378
379 proc = (grn_proc *)obj;
380 return proc->type == GRN_PROC_WINDOW_FUNCTION;
381}
382
383grn_bool
384grn_obj_is_expr(grn_ctx *ctx, grn_obj *obj)
385{
386 if (!obj) {
387 return GRN_FALSE;
388 }
389
390 return obj->header.type == GRN_EXPR;
391}
392
393static void
394grn_db_reindex(grn_ctx *ctx, grn_obj *db)
395{
396 grn_table_cursor *cursor;
397 grn_id id;
398
399 cursor = grn_table_cursor_open(ctx, db,
400 NULL, 0, NULL, 0,
401 0, -1,
402 GRN_CURSOR_BY_ID);
403 if (!cursor) {
404 return;
405 }
406
407 while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
408 grn_obj *object;
409
410 object = grn_ctx_at(ctx, id);
411 if (!object) {
412 ERRCLR(ctx);
413 continue;
414 }
415
416 switch (object->header.type) {
417 case GRN_TABLE_HASH_KEY :
418 case GRN_TABLE_PAT_KEY :
419 case GRN_TABLE_DAT_KEY :
420 grn_obj_reindex(ctx, object);
421 break;
422 default:
423 break;
424 }
425
426 grn_obj_unlink(ctx, object);
427
428 if (ctx->rc != GRN_SUCCESS) {
429 break;
430 }
431 }
432 grn_table_cursor_close(ctx, cursor);
433}
434
435static void
436grn_table_reindex(grn_ctx *ctx, grn_obj *table)
437{
438 grn_hash *columns;
439
440 columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
441 GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY);
442 if (!columns) {
443 ERR(GRN_NO_MEMORY_AVAILABLE,
444 "[table][reindex] failed to create a table to store columns");
445 return;
446 }
447
448 if (grn_table_columns(ctx, table, "", 0, (grn_obj *)columns) > 0) {
449 grn_id *key;
450 GRN_HASH_EACH(ctx, columns, id, &key, NULL, NULL, {
451 grn_obj *column = grn_ctx_at(ctx, *key);
452 if (column && column->header.type == GRN_COLUMN_INDEX) {
453 grn_obj_reindex(ctx, column);
454 }
455 });
456 }
457 grn_hash_close(ctx, columns);
458}
459
460static void
461grn_data_column_reindex(grn_ctx *ctx, grn_obj *data_column)
462{
463 grn_hook *hooks;
464
465 for (hooks = DB_OBJ(data_column)->hooks[GRN_HOOK_SET];
466 hooks;
467 hooks = hooks->next) {
468 grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
469 grn_obj *target = grn_ctx_at(ctx, data->target);
470 if (target->header.type != GRN_COLUMN_INDEX) {
471 continue;
472 }
473 grn_obj_reindex(ctx, target);
474 if (ctx->rc != GRN_SUCCESS) {
475 break;
476 }
477 }
478}
479
480grn_rc
481grn_obj_reindex(grn_ctx *ctx, grn_obj *obj)
482{
483 GRN_API_ENTER;
484
485 if (!obj) {
486 ERR(GRN_INVALID_ARGUMENT, "[object][reindex] object must not be NULL");
487 GRN_API_RETURN(ctx->rc);
488 }
489
490 switch (obj->header.type) {
491 case GRN_DB :
492 grn_db_reindex(ctx, obj);
493 break;
494 case GRN_TABLE_HASH_KEY :
495 case GRN_TABLE_PAT_KEY :
496 case GRN_TABLE_DAT_KEY :
497 grn_table_reindex(ctx, obj);
498 break;
499 case GRN_COLUMN_FIX_SIZE :
500 case GRN_COLUMN_VAR_SIZE :
501 grn_data_column_reindex(ctx, obj);
502 break;
503 case GRN_COLUMN_INDEX :
504 grn_index_column_rebuild(ctx, obj);
505 break;
506 default :
507 {
508 grn_obj type_name;
509 GRN_TEXT_INIT(&type_name, 0);
510 grn_inspect_type(ctx, &type_name, obj->header.type);
511 ERR(GRN_INVALID_ARGUMENT,
512 "[object][reindex] object must be TABLE_HASH_KEY, "
513 "TABLE_PAT_KEY, TABLE_DAT_KEY or COLUMN_INDEX: <%.*s>",
514 (int)GRN_TEXT_LEN(&type_name),
515 GRN_TEXT_VALUE(&type_name));
516 GRN_OBJ_FIN(ctx, &type_name);
517 GRN_API_RETURN(ctx->rc);
518 }
519 break;
520 }
521
522 GRN_API_RETURN(ctx->rc);
523}
524
525const char *
526grn_obj_type_to_string(uint8_t type)
527{
528 switch (type) {
529 case GRN_VOID :
530 return "void";
531 case GRN_BULK :
532 return "bulk";
533 case GRN_PTR :
534 return "ptr";
535 case GRN_UVECTOR :
536 return "uvector";
537 case GRN_PVECTOR :
538 return "pvector";
539 case GRN_VECTOR :
540 return "vector";
541 case GRN_MSG :
542 return "msg";
543 case GRN_QUERY :
544 return "query";
545 case GRN_ACCESSOR :
546 return "accessor";
547 case GRN_SNIP :
548 return "snip";
549 case GRN_PATSNIP :
550 return "patsnip";
551 case GRN_STRING :
552 return "string";
553 case GRN_CURSOR_TABLE_HASH_KEY :
554 return "cursor:table:hash_key";
555 case GRN_CURSOR_TABLE_PAT_KEY :
556 return "cursor:table:pat_key";
557 case GRN_CURSOR_TABLE_DAT_KEY :
558 return "cursor:table:dat_key";
559 case GRN_CURSOR_TABLE_NO_KEY :
560 return "cursor:table:no_key";
561 case GRN_CURSOR_COLUMN_INDEX :
562 return "cursor:column:index";
563 case GRN_CURSOR_COLUMN_GEO_INDEX :
564 return "cursor:column:geo_index";
565 case GRN_CURSOR_CONFIG :
566 return "cursor:config";
567 case GRN_TYPE :
568 return "type";
569 case GRN_PROC :
570 return "proc";
571 case GRN_EXPR :
572 return "expr";
573 case GRN_TABLE_HASH_KEY :
574 return "table:hash_key";
575 case GRN_TABLE_PAT_KEY :
576 return "table:pat_key";
577 case GRN_TABLE_DAT_KEY :
578 return "table:dat_key";
579 case GRN_TABLE_NO_KEY :
580 return "table:no_key";
581 case GRN_DB :
582 return "db";
583 case GRN_COLUMN_FIX_SIZE :
584 return "column:fix_size";
585 case GRN_COLUMN_VAR_SIZE :
586 return "column:var_size";
587 case GRN_COLUMN_INDEX :
588 return "column:index";
589 default :
590 return "unknown";
591 }
592}
593
594grn_bool
595grn_obj_name_is_column(grn_ctx *ctx, const char *name, int name_len)
596{
597 if (!name) {
598 return GRN_FALSE;
599 }
600
601 if (name_len < 0) {
602 name_len = strlen(name);
603 }
604
605 return memchr(name, GRN_DB_DELIMITER, name_len) != NULL;
606}
607
608grn_io *
609grn_obj_get_io(grn_ctx *ctx, grn_obj *obj)
610{
611 grn_io *io = NULL;
612
613 if (!obj) {
614 return NULL;
615 }
616
617 if (obj->header.type == GRN_DB) {
618 obj = ((grn_db *)obj)->keys;
619 }
620
621 switch (obj->header.type) {
622 case GRN_TABLE_PAT_KEY :
623 io = ((grn_pat *)obj)->io;
624 break;
625 case GRN_TABLE_DAT_KEY :
626 io = ((grn_dat *)obj)->io;
627 break;
628 case GRN_TABLE_HASH_KEY :
629 io = ((grn_hash *)obj)->io;
630 break;
631 case GRN_TABLE_NO_KEY :
632 io = ((grn_array *)obj)->io;
633 break;
634 case GRN_COLUMN_VAR_SIZE :
635 io = ((grn_ja *)obj)->io;
636 break;
637 case GRN_COLUMN_FIX_SIZE :
638 io = ((grn_ra *)obj)->io;
639 break;
640 case GRN_COLUMN_INDEX :
641 io = ((grn_ii *)obj)->seg;
642 break;
643 }
644
645 return io;
646}
647
648size_t
649grn_obj_get_disk_usage(grn_ctx *ctx, grn_obj *obj)
650{
651 size_t usage = 0;
652
653 GRN_API_ENTER;
654
655 if (!obj) {
656 ERR(GRN_INVALID_ARGUMENT, "[object][disk-usage] object must not be NULL");
657 GRN_API_RETURN(0);
658 }
659
660 switch (obj->header.type) {
661 case GRN_DB :
662 {
663 grn_db *db = (grn_db *)obj;
664 usage = grn_obj_get_disk_usage(ctx, db->keys);
665 if (db->specs) {
666 usage += grn_obj_get_disk_usage(ctx, (grn_obj *)(db->specs));
667 }
668 usage += grn_obj_get_disk_usage(ctx, (grn_obj *)(db->config));
669 }
670 break;
671 case GRN_TABLE_DAT_KEY :
672 usage = grn_dat_get_disk_usage(ctx, (grn_dat *)obj);
673 break;
674 case GRN_COLUMN_INDEX :
675 usage = grn_ii_get_disk_usage(ctx, (grn_ii *)obj);
676 break;
677 default :
678 {
679 grn_io *io;
680 io = grn_obj_get_io(ctx, obj);
681 if (io) {
682 usage = grn_io_get_disk_usage(ctx, io);
683 }
684 }
685 break;
686 }
687
688 GRN_API_RETURN(usage);
689}
690