1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2009-2015 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_index_column.h"
20#include "grn_ii.h"
21#include "grn_hash.h"
22
23#include <string.h>
24
25static uint64_t grn_index_sparsity = 10;
26static grn_bool grn_index_chunk_split_enable = GRN_TRUE;
27
28void
29grn_index_column_init_from_env(void)
30{
31 {
32 char grn_index_sparsity_env[GRN_ENV_BUFFER_SIZE];
33 grn_getenv("GRN_INDEX_SPARSITY",
34 grn_index_sparsity_env,
35 GRN_ENV_BUFFER_SIZE);
36 if (grn_index_sparsity_env[0]) {
37 uint64_t sparsity;
38 errno = 0;
39 sparsity = strtoull(grn_index_sparsity_env, NULL, 0);
40 if (errno == 0) {
41 grn_index_sparsity = sparsity;
42 }
43 }
44 }
45
46 {
47 char grn_index_chunk_split_enable_env[GRN_ENV_BUFFER_SIZE];
48 grn_getenv("GRN_INDEX_CHUNK_SPLIT_ENABLE",
49 grn_index_chunk_split_enable_env,
50 GRN_ENV_BUFFER_SIZE);
51 if (strcmp(grn_index_chunk_split_enable_env, "no") == 0) {
52 grn_index_chunk_split_enable = GRN_FALSE;
53 } else {
54 grn_index_chunk_split_enable = GRN_TRUE;
55 }
56 }
57}
58
59inline static void
60grn_index_column_build_call_hook(grn_ctx *ctx, grn_obj *obj,
61 grn_id id, grn_obj *value, int flags)
62{
63 grn_hook *hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET];
64
65 if (hooks) {
66 grn_obj oldvalue;
67 /* todo : grn_proc_ctx_open() */
68 grn_obj id_, flags_;
69 grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4};
70 GRN_TEXT_INIT(&oldvalue, 0);
71 GRN_UINT32_INIT(&id_, 0);
72 GRN_UINT32_INIT(&flags_, 0);
73 GRN_UINT32_SET(ctx, &id_, id);
74 GRN_UINT32_SET(ctx, &flags_, flags);
75 while (hooks) {
76 grn_ctx_push(ctx, &id_);
77 grn_ctx_push(ctx, &oldvalue);
78 grn_ctx_push(ctx, value);
79 grn_ctx_push(ctx, &flags_);
80 pctx.caller = NULL;
81 pctx.currh = hooks;
82 if (hooks->proc) {
83 hooks->proc->funcs[PROC_INIT](ctx, 1, &obj, &pctx.user_data);
84 } else {
85 grn_obj_default_set_value_hook(ctx, 1, &obj, &pctx.user_data);
86 }
87 if (ctx->rc) {
88 grn_obj_close(ctx, &oldvalue);
89 return;
90 }
91 hooks = hooks->next;
92 pctx.offset++;
93 }
94 grn_obj_close(ctx, &oldvalue);
95 }
96}
97
98grn_rc
99grn_index_column_build(grn_ctx *ctx, grn_obj *index_column)
100{
101 grn_obj *src, **cp, **col, *target;
102 grn_id *s = DB_OBJ(index_column)->source;
103 if (!(DB_OBJ(index_column)->source_size) || !s) { return ctx->rc; }
104 if ((src = grn_ctx_at(ctx, *s))) {
105 target = GRN_OBJ_TABLEP(src) ? src : grn_ctx_at(ctx, src->header.domain);
106 if (target) {
107 int i, ncol = DB_OBJ(index_column)->source_size / sizeof(grn_id);
108 grn_table_flags flags;
109 grn_ii *ii = (grn_ii *)index_column;
110 grn_bool use_grn_ii_build;
111 grn_obj *tokenizer = NULL;
112 grn_table_get_info(ctx, ii->lexicon, &flags, NULL, &tokenizer, NULL, NULL);
113 switch (flags & GRN_OBJ_TABLE_TYPE_MASK) {
114 case GRN_OBJ_TABLE_PAT_KEY :
115 case GRN_OBJ_TABLE_DAT_KEY :
116 use_grn_ii_build = GRN_TRUE;
117 break;
118 default :
119 use_grn_ii_build = GRN_FALSE;
120 break;
121 }
122 if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
123 use_grn_ii_build = GRN_FALSE;
124 }
125 if ((ii->header->flags & GRN_OBJ_WITH_POSITION) &&
126 (!tokenizer &&
127 !GRN_TYPE_IS_TEXT_FAMILY(ii->lexicon->header.domain))) {
128 /* TODO: Support offline index construction for WITH_POSITION
129 * index against UInt32 vector column. */
130 use_grn_ii_build = GRN_FALSE;
131 }
132 if ((col = GRN_MALLOC(ncol * sizeof(grn_obj *)))) {
133 for (cp = col, i = ncol; i; s++, cp++, i--) {
134 if (!(*cp = grn_ctx_at(ctx, *s))) {
135 ERR(GRN_INVALID_ARGUMENT, "source invalid, n=%d",i);
136 GRN_FREE(col);
137 return ctx->rc;
138 }
139 if (GRN_OBJ_TABLEP(grn_ctx_at(ctx, DB_OBJ(*cp)->range))) {
140 use_grn_ii_build = GRN_FALSE;
141 }
142 }
143 if (use_grn_ii_build) {
144 if (grn_index_chunk_split_enable) {
145 grn_ii_build2(ctx, ii, NULL);
146 } else {
147 grn_ii_build(ctx, ii, grn_index_sparsity);
148 }
149 } else {
150 grn_table_cursor *tc;
151 if ((tc = grn_table_cursor_open(ctx, target, NULL, 0, NULL, 0,
152 0, -1, GRN_CURSOR_BY_ID))) {
153 grn_id id;
154 grn_obj rv;
155 GRN_TEXT_INIT(&rv, 0);
156 while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) {
157 for (cp = col, i = ncol; i; i--, cp++) {
158 GRN_BULK_REWIND(&rv);
159 if (GRN_OBJ_TABLEP(*cp)) {
160 grn_table_get_key2(ctx, *cp, id, &rv);
161 } else {
162 grn_obj_get_value(ctx, *cp, id, &rv);
163 }
164 grn_index_column_build_call_hook(ctx, *cp, id, &rv, 0);
165 }
166 }
167 GRN_OBJ_FIN(ctx, &rv);
168 grn_table_cursor_close(ctx, tc);
169 }
170 }
171 GRN_FREE(col);
172 grn_obj_touch(ctx, index_column, NULL);
173 }
174 } else {
175 ERR(GRN_INVALID_ARGUMENT, "invalid target");
176 }
177 } else {
178 ERR(GRN_INVALID_ARGUMENT, "invalid source");
179 }
180 return ctx->rc;
181}
182
183grn_rc
184grn_index_column_rebuild(grn_ctx *ctx, grn_obj *index_column)
185{
186 grn_ii *ii = (grn_ii *)index_column;
187
188 GRN_API_ENTER;
189
190 grn_ii_truncate(ctx, ii);
191 grn_index_column_build(ctx, index_column);
192
193 GRN_API_RETURN(ctx->rc);
194}
195