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-1335  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 
25 grn_bool
grn_obj_is_true(grn_ctx * ctx,grn_obj * obj)26 grn_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 
70 grn_bool
grn_obj_is_builtin(grn_ctx * ctx,grn_obj * obj)71 grn_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 
81 grn_bool
grn_obj_is_bulk(grn_ctx * ctx,grn_obj * obj)82 grn_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 
91 grn_bool
grn_obj_is_text_family_bulk(grn_ctx * ctx,grn_obj * obj)92 grn_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 
101 grn_bool
grn_obj_is_table(grn_ctx * ctx,grn_obj * obj)102 grn_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 
123 grn_bool
grn_obj_is_column(grn_ctx * ctx,grn_obj * obj)124 grn_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 
144 grn_bool
grn_obj_is_scalar_column(grn_ctx * ctx,grn_obj * obj)145 grn_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 
154 grn_bool
grn_obj_is_vector_column(grn_ctx * ctx,grn_obj * obj)155 grn_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 
166 grn_bool
grn_obj_is_weight_vector_column(grn_ctx * ctx,grn_obj * obj)167 grn_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 
176 grn_bool
grn_obj_is_reference_column(grn_ctx * ctx,grn_obj * obj)177 grn_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 
201 grn_bool
grn_obj_is_data_column(grn_ctx * ctx,grn_obj * obj)202 grn_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 
212 grn_bool
grn_obj_is_index_column(grn_ctx * ctx,grn_obj * obj)213 grn_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 
222 grn_bool
grn_obj_is_accessor(grn_ctx * ctx,grn_obj * obj)223 grn_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 
232 grn_bool
grn_obj_is_key_accessor(grn_ctx * ctx,grn_obj * obj)233 grn_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 
249 grn_bool
grn_obj_is_type(grn_ctx * ctx,grn_obj * obj)250 grn_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 
259 grn_bool
grn_obj_is_text_family_type(grn_ctx * ctx,grn_obj * obj)260 grn_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 
269 grn_bool
grn_obj_is_proc(grn_ctx * ctx,grn_obj * obj)270 grn_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 
279 grn_bool
grn_obj_is_tokenizer_proc(grn_ctx * ctx,grn_obj * obj)280 grn_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 
292 grn_bool
grn_obj_is_function_proc(grn_ctx * ctx,grn_obj * obj)293 grn_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 
305 grn_bool
grn_obj_is_selector_proc(grn_ctx * ctx,grn_obj * obj)306 grn_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 
318 grn_bool
grn_obj_is_selector_only_proc(grn_ctx * ctx,grn_obj * obj)319 grn_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 
331 grn_bool
grn_obj_is_normalizer_proc(grn_ctx * ctx,grn_obj * obj)332 grn_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 
344 grn_bool
grn_obj_is_token_filter_proc(grn_ctx * ctx,grn_obj * obj)345 grn_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 
357 grn_bool
grn_obj_is_scorer_proc(grn_ctx * ctx,grn_obj * obj)358 grn_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 
370 grn_bool
grn_obj_is_window_function_proc(grn_ctx * ctx,grn_obj * obj)371 grn_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 
383 grn_bool
grn_obj_is_expr(grn_ctx * ctx,grn_obj * obj)384 grn_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 
393 static void
grn_db_reindex(grn_ctx * ctx,grn_obj * db)394 grn_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 
435 static void
grn_table_reindex(grn_ctx * ctx,grn_obj * table)436 grn_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 
460 static void
grn_data_column_reindex(grn_ctx * ctx,grn_obj * data_column)461 grn_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 
480 grn_rc
grn_obj_reindex(grn_ctx * ctx,grn_obj * obj)481 grn_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 
525 const char *
grn_obj_type_to_string(uint8_t type)526 grn_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 
594 grn_bool
grn_obj_name_is_column(grn_ctx * ctx,const char * name,int name_len)595 grn_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 
608 grn_io *
grn_obj_get_io(grn_ctx * ctx,grn_obj * obj)609 grn_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 
648 size_t
grn_obj_get_disk_usage(grn_ctx * ctx,grn_obj * obj)649 grn_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