1 | /* -*- c-basic-offset: 2 -*- */ |
2 | /* |
3 | Copyright(C) 2013-2016 Brazil |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License version 2.1 as published by the Free Software Foundation. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with this library; if not, write to the Free Software |
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ |
18 | |
19 | #include "../grn_ctx_impl.h" |
20 | #include "../grn_db.h" |
21 | |
22 | #ifdef GRN_WITH_MRUBY |
23 | #include <mruby.h> |
24 | #include <mruby/array.h> |
25 | #include <mruby/data.h> |
26 | |
27 | #include "mrb_ctx.h" |
28 | #include "mrb_indexable.h" |
29 | #include "mrb_operator.h" |
30 | #include "mrb_converter.h" |
31 | |
32 | static mrb_value |
33 | indexable_find_index(mrb_state *mrb, mrb_value self) |
34 | { |
35 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
36 | grn_obj *object; |
37 | mrb_value mrb_operator; |
38 | grn_operator operator; |
39 | grn_index_datum index_datum; |
40 | int n_index_data; |
41 | |
42 | mrb_get_args(mrb, "o" , &mrb_operator); |
43 | object = DATA_PTR(self); |
44 | operator = grn_mrb_value_to_operator(mrb, mrb_operator); |
45 | n_index_data = grn_column_find_index_data(ctx, |
46 | object, |
47 | operator, |
48 | &index_datum, |
49 | 1); |
50 | if (n_index_data == 0) { |
51 | return mrb_nil_value(); |
52 | } else { |
53 | grn_mrb_data *data; |
54 | struct RClass *klass; |
55 | mrb_value args[2]; |
56 | |
57 | data = &(ctx->impl->mrb); |
58 | klass = mrb_class_get_under(mrb, data->module, "IndexInfo" ); |
59 | args[0] = grn_mrb_value_from_grn_obj(mrb, index_datum.index); |
60 | args[1] = mrb_fixnum_value(index_datum.section); |
61 | return mrb_obj_new(mrb, klass, 2, args); |
62 | } |
63 | } |
64 | |
65 | static mrb_value |
66 | indexable_indexes(mrb_state *mrb, mrb_value self) |
67 | { |
68 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
69 | grn_obj *object; |
70 | grn_index_datum index_datum; |
71 | grn_index_datum *index_data; |
72 | int i, n_index_data; |
73 | mrb_value mrb_indexes; |
74 | |
75 | object = DATA_PTR(self); |
76 | n_index_data = grn_column_get_all_index_data(ctx, object, &index_datum, 1); |
77 | if (n_index_data == 0) { |
78 | return mrb_ary_new(mrb); |
79 | } |
80 | |
81 | if (n_index_data == 1) { |
82 | index_data = &index_datum; |
83 | } else { |
84 | index_data = GRN_MALLOCN(grn_index_datum, n_index_data); |
85 | n_index_data = grn_column_get_all_index_data(ctx, |
86 | object, |
87 | index_data, |
88 | n_index_data); |
89 | } |
90 | |
91 | mrb_indexes = mrb_ary_new_capa(mrb, n_index_data); |
92 | for (i = 0; i < n_index_data; i++) { |
93 | grn_mrb_data *data; |
94 | struct RClass *klass; |
95 | mrb_value args[2]; |
96 | |
97 | data = &(ctx->impl->mrb); |
98 | klass = mrb_class_get_under(mrb, data->module, "IndexInfo" ); |
99 | args[0] = grn_mrb_value_from_grn_obj(mrb, index_data[i].index); |
100 | args[1] = mrb_fixnum_value(index_data[i].section); |
101 | mrb_ary_push(mrb, mrb_indexes, mrb_obj_new(mrb, klass, 2, args)); |
102 | } |
103 | |
104 | if (index_data != &index_datum) { |
105 | GRN_FREE(index_data); |
106 | } |
107 | |
108 | return mrb_indexes; |
109 | } |
110 | |
111 | static mrb_value |
112 | indexable_index_ids(mrb_state *mrb, mrb_value self) |
113 | { |
114 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
115 | grn_obj *object; |
116 | grn_hook_entry entry; |
117 | int i; |
118 | int n_indexes; |
119 | mrb_value mrb_index_ids; |
120 | grn_obj hook_data; |
121 | |
122 | object = DATA_PTR(self); |
123 | |
124 | if (grn_obj_is_key_accessor(ctx, object)) { |
125 | object = grn_ctx_at(ctx, object->header.domain); |
126 | } |
127 | if (grn_obj_is_table(ctx, object)) { |
128 | entry = GRN_HOOK_INSERT; |
129 | } else if (grn_obj_is_column(ctx, object)) { |
130 | entry = GRN_HOOK_SET; |
131 | } else { |
132 | return mrb_ary_new(mrb); |
133 | } |
134 | n_indexes = grn_obj_get_nhooks(ctx, object, entry); |
135 | |
136 | mrb_index_ids = mrb_ary_new_capa(mrb, n_indexes); |
137 | |
138 | GRN_TEXT_INIT(&hook_data, 0); |
139 | for (i = 0; i < n_indexes; i++) { |
140 | GRN_BULK_REWIND(&hook_data); |
141 | grn_obj_get_hook(ctx, object, entry, i, &hook_data); |
142 | if (GRN_BULK_VSIZE(&hook_data) == |
143 | sizeof(grn_obj_default_set_value_hook_data)) { |
144 | grn_obj_default_set_value_hook_data *data; |
145 | |
146 | data = (grn_obj_default_set_value_hook_data *)GRN_TEXT_VALUE(&hook_data); |
147 | mrb_ary_push(mrb, mrb_index_ids, mrb_fixnum_value(data->target)); |
148 | } |
149 | } |
150 | |
151 | return mrb_index_ids; |
152 | } |
153 | |
154 | void |
155 | grn_mrb_indexable_init(grn_ctx *ctx) |
156 | { |
157 | grn_mrb_data *data = &(ctx->impl->mrb); |
158 | mrb_state *mrb = data->state; |
159 | struct RClass *module; |
160 | |
161 | module = mrb_define_module_under(mrb, data->module, "Indexable" ); |
162 | |
163 | mrb_define_method(mrb, module, "find_index" , |
164 | indexable_find_index, MRB_ARGS_REQ(1)); |
165 | mrb_define_method(mrb, module, "indexes" , |
166 | indexable_indexes, MRB_ARGS_NONE()); |
167 | mrb_define_method(mrb, module, "index_ids" , |
168 | indexable_index_ids, MRB_ARGS_NONE()); |
169 | } |
170 | #endif |
171 | |