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
32static mrb_value
33indexable_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
65static mrb_value
66indexable_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
111static mrb_value
112indexable_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
154void
155grn_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