1 | /* -*- c-basic-offset: 2 -*- */ |
2 | /* |
3 | Copyright(C) 2015-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_proc.h" |
20 | |
21 | #include "../grn_db.h" |
22 | |
23 | #include <groonga/plugin.h> |
24 | |
25 | typedef struct { |
26 | grn_bool is_close_opened_object_mode; |
27 | } grn_schema_data; |
28 | |
29 | static void |
30 | command_schema_output_id(grn_ctx *ctx, grn_obj *obj) |
31 | { |
32 | if (obj) { |
33 | grn_id id; |
34 | id = grn_obj_id(ctx, obj); |
35 | grn_ctx_output_uint64(ctx, id); |
36 | } else { |
37 | grn_ctx_output_null(ctx); |
38 | } |
39 | } |
40 | |
41 | static void |
42 | command_schema_output_name(grn_ctx *ctx, grn_obj *obj) |
43 | { |
44 | if (obj) { |
45 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
46 | unsigned int name_size; |
47 | name_size = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE); |
48 | grn_ctx_output_str(ctx, name, name_size); |
49 | } else { |
50 | grn_ctx_output_null(ctx); |
51 | } |
52 | } |
53 | |
54 | static void |
55 | command_schema_output_column_name(grn_ctx *ctx, grn_obj *column) |
56 | { |
57 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
58 | unsigned int name_size; |
59 | name_size = grn_column_name(ctx, column, name, GRN_TABLE_MAX_KEY_SIZE); |
60 | grn_ctx_output_str(ctx, name, name_size); |
61 | } |
62 | |
63 | static void |
64 | command_schema_output_type(grn_ctx *ctx, const char *type_label, grn_obj *type) |
65 | { |
66 | if (!type) { |
67 | grn_ctx_output_null(ctx); |
68 | return; |
69 | } |
70 | |
71 | grn_ctx_output_map_open(ctx, type_label, 3); |
72 | |
73 | grn_ctx_output_cstr(ctx, "id" ); |
74 | command_schema_output_id(ctx, type); |
75 | |
76 | grn_ctx_output_cstr(ctx, "name" ); |
77 | command_schema_output_name(ctx, type); |
78 | |
79 | grn_ctx_output_cstr(ctx, "type" ); |
80 | if (grn_obj_is_table(ctx, type)) { |
81 | grn_ctx_output_cstr(ctx, "reference" ); |
82 | } else { |
83 | grn_ctx_output_cstr(ctx, "type" ); |
84 | } |
85 | grn_ctx_output_map_close(ctx); |
86 | } |
87 | |
88 | static void |
89 | command_schema_output_key_type(grn_ctx *ctx, grn_obj *key_type) |
90 | { |
91 | command_schema_output_type(ctx, "key_type" , key_type); |
92 | } |
93 | |
94 | static void |
95 | command_schema_output_value_type(grn_ctx *ctx, grn_obj *value_type) |
96 | { |
97 | command_schema_output_type(ctx, "value_type" , value_type); |
98 | } |
99 | |
100 | static void |
101 | command_schema_output_command(grn_ctx *ctx, |
102 | const char *command_name, |
103 | grn_obj *arguments) |
104 | { |
105 | grn_ctx_output_map_open(ctx, "command" , 3); |
106 | |
107 | grn_ctx_output_cstr(ctx, "name" ); |
108 | grn_ctx_output_cstr(ctx, command_name); |
109 | |
110 | grn_ctx_output_cstr(ctx, "arguments" ); |
111 | { |
112 | int i, n; |
113 | |
114 | n = grn_vector_size(ctx, arguments); |
115 | grn_ctx_output_map_open(ctx, "arguments" , n / 2); |
116 | for (i = 0; i < n; i += 2) { |
117 | const char *name; |
118 | unsigned int name_size; |
119 | const char *value; |
120 | unsigned int value_size; |
121 | |
122 | name_size = grn_vector_get_element(ctx, arguments, i, &name, |
123 | NULL, NULL); |
124 | value_size = grn_vector_get_element(ctx, arguments, i + 1, &value, |
125 | NULL, NULL); |
126 | grn_ctx_output_str(ctx, name, name_size); |
127 | grn_ctx_output_str(ctx, value, value_size); |
128 | } |
129 | grn_ctx_output_map_close(ctx); |
130 | } |
131 | |
132 | grn_ctx_output_cstr(ctx, "command_line" ); |
133 | { |
134 | int i, n; |
135 | grn_obj command_line; |
136 | |
137 | GRN_TEXT_INIT(&command_line, 0); |
138 | GRN_TEXT_PUTS(ctx, &command_line, command_name); |
139 | n = grn_vector_size(ctx, arguments); |
140 | for (i = 0; i < n; i += 2) { |
141 | const char *name; |
142 | unsigned int name_size; |
143 | const char *value; |
144 | unsigned int value_size; |
145 | |
146 | name_size = grn_vector_get_element(ctx, arguments, i, &name, |
147 | NULL, NULL); |
148 | value_size = grn_vector_get_element(ctx, arguments, i + 1, &value, |
149 | NULL, NULL); |
150 | grn_text_printf(ctx, &command_line, |
151 | " --%.*s %.*s" , |
152 | name_size, name, |
153 | value_size, value); |
154 | } |
155 | grn_ctx_output_str(ctx, |
156 | GRN_TEXT_VALUE(&command_line), |
157 | GRN_TEXT_LEN(&command_line)); |
158 | GRN_OBJ_FIN(ctx, &command_line); |
159 | } |
160 | |
161 | grn_ctx_output_map_close(ctx); |
162 | } |
163 | |
164 | static void |
165 | command_schema_output_plugins(grn_ctx *ctx) |
166 | { |
167 | grn_obj plugin_names; |
168 | unsigned int i, n; |
169 | |
170 | GRN_TEXT_INIT(&plugin_names, GRN_OBJ_VECTOR); |
171 | |
172 | grn_plugin_get_names(ctx, &plugin_names); |
173 | |
174 | grn_ctx_output_cstr(ctx, "plugins" ); |
175 | |
176 | n = grn_vector_size(ctx, &plugin_names); |
177 | grn_ctx_output_map_open(ctx, "plugins" , n); |
178 | for (i = 0; i < n; i++) { |
179 | const char *name; |
180 | unsigned int name_size; |
181 | |
182 | name_size = grn_vector_get_element(ctx, &plugin_names, i, &name, NULL, NULL); |
183 | grn_ctx_output_str(ctx, name, name_size); |
184 | |
185 | grn_ctx_output_map_open(ctx, "plugin" , 1); |
186 | grn_ctx_output_cstr(ctx, "name" ); |
187 | grn_ctx_output_str(ctx, name, name_size); |
188 | grn_ctx_output_map_close(ctx); |
189 | } |
190 | grn_ctx_output_map_close(ctx); |
191 | |
192 | GRN_OBJ_FIN(ctx, &plugin_names); |
193 | } |
194 | |
195 | static void |
196 | command_schema_output_types(grn_ctx *ctx) |
197 | { |
198 | unsigned int n_types; |
199 | |
200 | n_types = 0; |
201 | GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { |
202 | if (grn_id_is_builtin_type(ctx, id)) { |
203 | n_types++; |
204 | } |
205 | } GRN_DB_EACH_END(ctx, cursor); |
206 | |
207 | grn_ctx_output_cstr(ctx, "types" ); |
208 | |
209 | grn_ctx_output_map_open(ctx, "types" , n_types); |
210 | GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { |
211 | grn_obj *type; |
212 | |
213 | if (!grn_id_is_builtin_type(ctx, id)) { |
214 | continue; |
215 | } |
216 | |
217 | type = grn_ctx_at(ctx, id); |
218 | |
219 | command_schema_output_name(ctx, type); |
220 | |
221 | grn_ctx_output_map_open(ctx, "type" , 5); |
222 | |
223 | grn_ctx_output_cstr(ctx, "id" ); |
224 | command_schema_output_id(ctx, type); |
225 | |
226 | grn_ctx_output_cstr(ctx, "name" ); |
227 | command_schema_output_name(ctx, type); |
228 | |
229 | grn_ctx_output_cstr(ctx, "size" ); |
230 | grn_ctx_output_int64(ctx, grn_type_size(ctx, type)); |
231 | |
232 | grn_ctx_output_cstr(ctx, "can_be_key_type" ); |
233 | grn_ctx_output_bool(ctx, grn_type_size(ctx, type) <= GRN_TABLE_MAX_KEY_SIZE); |
234 | |
235 | grn_ctx_output_cstr(ctx, "can_be_value_type" ); |
236 | grn_ctx_output_bool(ctx, !(type->header.flags & GRN_OBJ_KEY_VAR_SIZE)); |
237 | |
238 | grn_ctx_output_map_close(ctx); |
239 | } GRN_DB_EACH_END(ctx, cursor); |
240 | grn_ctx_output_map_close(ctx); |
241 | } |
242 | |
243 | static void |
244 | command_schema_output_tokenizers(grn_ctx *ctx, grn_schema_data *data) |
245 | { |
246 | grn_obj tokenizer_ids; |
247 | unsigned int i, n; |
248 | |
249 | GRN_RECORD_INIT(&tokenizer_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); |
250 | GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { |
251 | void *name; |
252 | int name_size; |
253 | grn_obj *object; |
254 | |
255 | name_size = grn_table_cursor_get_key(ctx, cursor, &name); |
256 | if (grn_obj_name_is_column(ctx, name, name_size)) { |
257 | continue; |
258 | } |
259 | |
260 | if (data->is_close_opened_object_mode) { |
261 | grn_ctx_push_temporary_open_space(ctx); |
262 | } |
263 | |
264 | object = grn_ctx_at(ctx, id); |
265 | if (object) { |
266 | if (grn_obj_is_tokenizer_proc(ctx, object)) { |
267 | GRN_RECORD_PUT(ctx, &tokenizer_ids, id); |
268 | } |
269 | } else { |
270 | /* XXX: this clause is executed when MeCab tokenizer is enabled in |
271 | database but the groonga isn't supported MeCab. |
272 | We should return error mesage about it and error exit status |
273 | but it's too difficult for this architecture. :< */ |
274 | GRN_PLUGIN_CLEAR_ERROR(ctx); |
275 | } |
276 | |
277 | if (data->is_close_opened_object_mode) { |
278 | grn_ctx_pop_temporary_open_space(ctx); |
279 | } |
280 | } GRN_DB_EACH_END(ctx, cursor); |
281 | |
282 | grn_ctx_output_cstr(ctx, "tokenizers" ); |
283 | |
284 | n = GRN_BULK_VSIZE(&tokenizer_ids) / sizeof(grn_id); |
285 | grn_ctx_output_map_open(ctx, "tokenizers" , n); |
286 | for (i = 0; i < n; i++) { |
287 | grn_id tokenizer_id; |
288 | grn_obj *tokenizer; |
289 | |
290 | tokenizer_id = GRN_RECORD_VALUE_AT(&tokenizer_ids, i); |
291 | tokenizer = grn_ctx_at(ctx, tokenizer_id); |
292 | |
293 | command_schema_output_name(ctx, tokenizer); |
294 | |
295 | grn_ctx_output_map_open(ctx, "tokenizer" , 2); |
296 | |
297 | grn_ctx_output_cstr(ctx, "id" ); |
298 | command_schema_output_id(ctx, tokenizer); |
299 | |
300 | grn_ctx_output_cstr(ctx, "name" ); |
301 | command_schema_output_name(ctx, tokenizer); |
302 | |
303 | grn_ctx_output_map_close(ctx); |
304 | } |
305 | grn_ctx_output_map_close(ctx); |
306 | |
307 | GRN_OBJ_FIN(ctx, &tokenizer_ids); |
308 | } |
309 | |
310 | static void |
311 | command_schema_output_normalizers(grn_ctx *ctx, grn_schema_data *data) |
312 | { |
313 | grn_obj normalizer_ids; |
314 | unsigned int i, n; |
315 | |
316 | GRN_RECORD_INIT(&normalizer_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); |
317 | GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { |
318 | void *name; |
319 | int name_size; |
320 | grn_obj *object; |
321 | |
322 | name_size = grn_table_cursor_get_key(ctx, cursor, &name); |
323 | if (grn_obj_name_is_column(ctx, name, name_size)) { |
324 | continue; |
325 | } |
326 | |
327 | if (data->is_close_opened_object_mode) { |
328 | grn_ctx_push_temporary_open_space(ctx); |
329 | } |
330 | |
331 | object = grn_ctx_at(ctx, id); |
332 | if (object) { |
333 | if (grn_obj_is_normalizer_proc(ctx, object)) { |
334 | GRN_RECORD_PUT(ctx, &normalizer_ids, id); |
335 | } |
336 | } else { |
337 | /* XXX: this clause is executed when MeCab normalizer is enabled in |
338 | database but the groonga isn't supported MeCab. |
339 | We should return error mesage about it and error exit status |
340 | but it's too difficult for this architecture. :< */ |
341 | GRN_PLUGIN_CLEAR_ERROR(ctx); |
342 | } |
343 | |
344 | if (data->is_close_opened_object_mode) { |
345 | grn_ctx_pop_temporary_open_space(ctx); |
346 | } |
347 | } GRN_DB_EACH_END(ctx, cursor); |
348 | |
349 | grn_ctx_output_cstr(ctx, "normalizers" ); |
350 | |
351 | n = GRN_BULK_VSIZE(&normalizer_ids) / sizeof(grn_id); |
352 | grn_ctx_output_map_open(ctx, "normalizers" , n); |
353 | for (i = 0; i < n; i++) { |
354 | grn_id normalizer_id; |
355 | grn_obj *normalizer; |
356 | |
357 | normalizer_id = GRN_RECORD_VALUE_AT(&normalizer_ids, i); |
358 | normalizer = grn_ctx_at(ctx, normalizer_id); |
359 | |
360 | command_schema_output_name(ctx, normalizer); |
361 | |
362 | grn_ctx_output_map_open(ctx, "normalizer" , 2); |
363 | |
364 | grn_ctx_output_cstr(ctx, "id" ); |
365 | command_schema_output_id(ctx, normalizer); |
366 | |
367 | grn_ctx_output_cstr(ctx, "name" ); |
368 | command_schema_output_name(ctx, normalizer); |
369 | |
370 | grn_ctx_output_map_close(ctx); |
371 | } |
372 | grn_ctx_output_map_close(ctx); |
373 | |
374 | GRN_OBJ_FIN(ctx, &normalizer_ids); |
375 | } |
376 | |
377 | static void |
378 | command_schema_output_token_filters(grn_ctx *ctx, grn_schema_data *data) |
379 | { |
380 | grn_obj token_filter_ids; |
381 | unsigned int i, n; |
382 | |
383 | GRN_RECORD_INIT(&token_filter_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); |
384 | GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { |
385 | void *name; |
386 | int name_size; |
387 | grn_obj *object; |
388 | |
389 | name_size = grn_table_cursor_get_key(ctx, cursor, &name); |
390 | if (grn_obj_name_is_column(ctx, name, name_size)) { |
391 | continue; |
392 | } |
393 | |
394 | if (data->is_close_opened_object_mode) { |
395 | grn_ctx_push_temporary_open_space(ctx); |
396 | } |
397 | |
398 | object = grn_ctx_at(ctx, id); |
399 | if (object) { |
400 | if (grn_obj_is_token_filter_proc(ctx, object)) { |
401 | GRN_RECORD_PUT(ctx, &token_filter_ids, id); |
402 | } |
403 | } else { |
404 | /* XXX: this clause is executed when MeCab normalizer is enabled in |
405 | database but the groonga isn't supported MeCab. |
406 | We should return error mesage about it and error exit status |
407 | but it's too difficult for this architecture. :< */ |
408 | GRN_PLUGIN_CLEAR_ERROR(ctx); |
409 | } |
410 | |
411 | if (data->is_close_opened_object_mode) { |
412 | grn_ctx_pop_temporary_open_space(ctx); |
413 | } |
414 | } GRN_DB_EACH_END(ctx, cursor); |
415 | |
416 | grn_ctx_output_cstr(ctx, "token_filters" ); |
417 | |
418 | n = GRN_BULK_VSIZE(&token_filter_ids) / sizeof(grn_id); |
419 | grn_ctx_output_map_open(ctx, "token_filters" , n); |
420 | for (i = 0; i < n; i++) { |
421 | grn_id token_filter_id; |
422 | grn_obj *token_filter; |
423 | |
424 | token_filter_id = GRN_RECORD_VALUE_AT(&token_filter_ids, i); |
425 | token_filter = grn_ctx_at(ctx, token_filter_id); |
426 | |
427 | command_schema_output_name(ctx, token_filter); |
428 | |
429 | grn_ctx_output_map_open(ctx, "token_filter" , 2); |
430 | |
431 | grn_ctx_output_cstr(ctx, "id" ); |
432 | command_schema_output_id(ctx, token_filter); |
433 | |
434 | grn_ctx_output_cstr(ctx, "name" ); |
435 | command_schema_output_name(ctx, token_filter); |
436 | |
437 | grn_ctx_output_map_close(ctx); |
438 | } |
439 | grn_ctx_output_map_close(ctx); |
440 | |
441 | GRN_OBJ_FIN(ctx, &token_filter_ids); |
442 | } |
443 | |
444 | static const char * |
445 | command_schema_table_type_name(grn_ctx *ctx, grn_obj *table) |
446 | { |
447 | const char *name = "unknown" ; |
448 | |
449 | switch (table->header.type) { |
450 | case GRN_TABLE_NO_KEY : |
451 | name = "array" ; |
452 | break; |
453 | case GRN_TABLE_HASH_KEY : |
454 | name = "hash table" ; |
455 | break; |
456 | case GRN_TABLE_PAT_KEY : |
457 | name = "patricia trie" ; |
458 | break; |
459 | case GRN_TABLE_DAT_KEY : |
460 | name = "double array trie" ; |
461 | break; |
462 | default : |
463 | break; |
464 | } |
465 | |
466 | return name; |
467 | } |
468 | |
469 | static void |
470 | command_schema_table_output_key_type(grn_ctx *ctx, grn_obj *table) |
471 | { |
472 | grn_obj *key_type = NULL; |
473 | |
474 | if (table->header.type != GRN_TABLE_NO_KEY && |
475 | table->header.domain != GRN_ID_NIL) { |
476 | key_type = grn_ctx_at(ctx, table->header.domain); |
477 | } |
478 | |
479 | command_schema_output_key_type(ctx, key_type); |
480 | } |
481 | |
482 | static void |
483 | command_schema_table_output_value_type(grn_ctx *ctx, grn_obj *table) |
484 | { |
485 | grn_obj *value_type = NULL; |
486 | grn_id range = GRN_ID_NIL; |
487 | |
488 | if (table->header.type != GRN_TABLE_DAT_KEY) { |
489 | range = grn_obj_get_range(ctx, table); |
490 | } |
491 | if (range != GRN_ID_NIL) { |
492 | value_type = grn_ctx_at(ctx, range); |
493 | } |
494 | |
495 | command_schema_output_value_type(ctx, value_type); |
496 | } |
497 | |
498 | static void |
499 | command_schema_table_output_tokenizer(grn_ctx *ctx, grn_obj *table) |
500 | { |
501 | grn_obj *tokenizer; |
502 | |
503 | tokenizer = grn_obj_get_info(ctx, table, GRN_INFO_DEFAULT_TOKENIZER, NULL); |
504 | if (!tokenizer) { |
505 | grn_ctx_output_null(ctx); |
506 | return; |
507 | } |
508 | |
509 | grn_ctx_output_map_open(ctx, "tokenizer" , 2); |
510 | |
511 | grn_ctx_output_cstr(ctx, "id" ); |
512 | command_schema_output_id(ctx, tokenizer); |
513 | |
514 | grn_ctx_output_cstr(ctx, "name" ); |
515 | command_schema_output_name(ctx, tokenizer); |
516 | |
517 | grn_ctx_output_map_close(ctx); |
518 | } |
519 | |
520 | static void |
521 | command_schema_table_output_normalizer(grn_ctx *ctx, grn_obj *table) |
522 | { |
523 | grn_obj *normalizer; |
524 | |
525 | normalizer = grn_obj_get_info(ctx, table, GRN_INFO_NORMALIZER, NULL); |
526 | if (!normalizer) { |
527 | grn_ctx_output_null(ctx); |
528 | return; |
529 | } |
530 | |
531 | grn_ctx_output_map_open(ctx, "normalizer" , 2); |
532 | |
533 | grn_ctx_output_cstr(ctx, "id" ); |
534 | command_schema_output_id(ctx, normalizer); |
535 | |
536 | grn_ctx_output_cstr(ctx, "name" ); |
537 | command_schema_output_name(ctx, normalizer); |
538 | |
539 | grn_ctx_output_map_close(ctx); |
540 | } |
541 | |
542 | static void |
543 | command_schema_table_output_token_filters(grn_ctx *ctx, grn_obj *table) |
544 | { |
545 | grn_obj token_filters; |
546 | int i, n; |
547 | |
548 | GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, GRN_DB_OBJECT); |
549 | if (table->header.type != GRN_TABLE_NO_KEY) { |
550 | grn_obj_get_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); |
551 | } |
552 | |
553 | n = GRN_BULK_VSIZE(&token_filters) / sizeof(grn_obj *); |
554 | grn_ctx_output_array_open(ctx, "token_filters" , n); |
555 | for (i = 0; i < n; i++) { |
556 | grn_obj *token_filter; |
557 | |
558 | token_filter = GRN_PTR_VALUE_AT(&token_filters, i); |
559 | |
560 | grn_ctx_output_map_open(ctx, "token_filter" , 2); |
561 | |
562 | grn_ctx_output_cstr(ctx, "id" ); |
563 | command_schema_output_id(ctx, token_filter); |
564 | |
565 | grn_ctx_output_cstr(ctx, "name" ); |
566 | command_schema_output_name(ctx, token_filter); |
567 | |
568 | grn_ctx_output_map_close(ctx); |
569 | } |
570 | grn_ctx_output_array_close(ctx); |
571 | |
572 | GRN_OBJ_FIN(ctx, &token_filters); |
573 | } |
574 | |
575 | static void |
576 | command_schema_table_command_collect_arguments(grn_ctx *ctx, |
577 | grn_obj *table, |
578 | grn_obj *arguments) |
579 | { |
580 | #define ADD(name_, value_) \ |
581 | grn_vector_add_element(ctx, arguments, \ |
582 | name_, strlen(name_), \ |
583 | 0, GRN_DB_TEXT); \ |
584 | grn_vector_add_element(ctx, arguments, \ |
585 | value_, strlen(value_), \ |
586 | 0, GRN_DB_TEXT) |
587 | |
588 | #define ADD_OBJECT_NAME(name_, object_) do { \ |
589 | char object_name[GRN_TABLE_MAX_KEY_SIZE]; \ |
590 | unsigned int object_name_size; \ |
591 | object_name_size = grn_obj_name(ctx, object_, \ |
592 | object_name, \ |
593 | GRN_TABLE_MAX_KEY_SIZE); \ |
594 | object_name[object_name_size] = '\0'; \ |
595 | ADD(name_, object_name); \ |
596 | } while (GRN_FALSE) |
597 | |
598 | ADD_OBJECT_NAME("name" , table); |
599 | |
600 | { |
601 | grn_obj flags; |
602 | grn_table_flags table_flags; |
603 | grn_table_flags ignored_flags = GRN_OBJ_KEY_NORMALIZE | GRN_OBJ_PERSISTENT; |
604 | GRN_TEXT_INIT(&flags, 0); |
605 | grn_table_get_info(ctx, table, &table_flags, NULL, NULL, NULL, NULL); |
606 | grn_dump_table_create_flags(ctx, |
607 | table_flags & ~ignored_flags, |
608 | &flags); |
609 | GRN_TEXT_PUTC(ctx, &flags, '\0'); |
610 | ADD("flags" , GRN_TEXT_VALUE(&flags)); |
611 | GRN_OBJ_FIN(ctx, &flags); |
612 | } |
613 | |
614 | { |
615 | grn_obj *key_type = NULL; |
616 | |
617 | if (table->header.type != GRN_TABLE_NO_KEY && |
618 | table->header.domain != GRN_ID_NIL) { |
619 | key_type = grn_ctx_at(ctx, table->header.domain); |
620 | } |
621 | if (key_type) { |
622 | ADD_OBJECT_NAME("key_type" , key_type); |
623 | } |
624 | } |
625 | |
626 | { |
627 | grn_obj *value_type = NULL; |
628 | grn_id range = GRN_ID_NIL; |
629 | |
630 | if (table->header.type != GRN_TABLE_DAT_KEY) { |
631 | range = grn_obj_get_range(ctx, table); |
632 | } |
633 | if (range != GRN_ID_NIL) { |
634 | value_type = grn_ctx_at(ctx, range); |
635 | } |
636 | if (value_type) { |
637 | ADD_OBJECT_NAME("value_type" , value_type); |
638 | } |
639 | } |
640 | |
641 | { |
642 | grn_obj *tokenizer; |
643 | tokenizer = grn_obj_get_info(ctx, table, GRN_INFO_DEFAULT_TOKENIZER, NULL); |
644 | if (tokenizer) { |
645 | ADD_OBJECT_NAME("default_tokenizer" , tokenizer); |
646 | } |
647 | } |
648 | |
649 | { |
650 | grn_obj *normalizer; |
651 | normalizer = grn_obj_get_info(ctx, table, GRN_INFO_NORMALIZER, NULL); |
652 | if (!normalizer && (table->header.flags & GRN_OBJ_KEY_NORMALIZE)) { |
653 | normalizer = grn_ctx_get(ctx, "NormalizerAuto" , -1); |
654 | } |
655 | if (normalizer) { |
656 | ADD_OBJECT_NAME("normalizer" , normalizer); |
657 | } |
658 | } |
659 | |
660 | if (table->header.type != GRN_TABLE_NO_KEY) { |
661 | grn_obj token_filters; |
662 | int n; |
663 | |
664 | GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, GRN_DB_OBJECT); |
665 | grn_obj_get_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); |
666 | n = GRN_BULK_VSIZE(&token_filters) / sizeof(grn_obj *); |
667 | if (n > 0) { |
668 | grn_obj token_filter_names; |
669 | int i; |
670 | |
671 | GRN_TEXT_INIT(&token_filter_names, 0); |
672 | for (i = 0; i < n; i++) { |
673 | grn_obj *token_filter; |
674 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
675 | int name_size; |
676 | |
677 | token_filter = GRN_PTR_VALUE_AT(&token_filters, i); |
678 | name_size = grn_obj_name(ctx, token_filter, |
679 | name, GRN_TABLE_MAX_KEY_SIZE); |
680 | if (i > 0) { |
681 | GRN_TEXT_PUTC(ctx, &token_filter_names, ','); |
682 | } |
683 | GRN_TEXT_PUT(ctx, &token_filter_names, name, name_size); |
684 | } |
685 | GRN_TEXT_PUTC(ctx, &token_filter_names, '\0'); |
686 | ADD("token_filters" , GRN_TEXT_VALUE(&token_filter_names)); |
687 | GRN_OBJ_FIN(ctx, &token_filter_names); |
688 | } |
689 | GRN_OBJ_FIN(ctx, &token_filters); |
690 | } |
691 | |
692 | #undef ADD_OBJECT_NAME |
693 | #undef ADD |
694 | } |
695 | |
696 | static void |
697 | command_schema_table_output_command(grn_ctx *ctx, grn_obj *table) |
698 | { |
699 | grn_obj arguments; |
700 | |
701 | GRN_TEXT_INIT(&arguments, GRN_OBJ_VECTOR); |
702 | command_schema_table_command_collect_arguments(ctx, table, &arguments); |
703 | |
704 | command_schema_output_command(ctx, "table_create" , &arguments); |
705 | |
706 | GRN_OBJ_FIN(ctx, &arguments); |
707 | } |
708 | |
709 | static void |
710 | command_schema_column_output_type(grn_ctx *ctx, grn_obj *column) |
711 | { |
712 | switch (column->header.type) { |
713 | case GRN_COLUMN_FIX_SIZE : |
714 | case GRN_COLUMN_VAR_SIZE : |
715 | switch (column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { |
716 | case GRN_OBJ_COLUMN_SCALAR : |
717 | grn_ctx_output_cstr(ctx, "scalar" ); |
718 | break; |
719 | case GRN_OBJ_COLUMN_VECTOR : |
720 | grn_ctx_output_cstr(ctx, "vector" ); |
721 | break; |
722 | } |
723 | break; |
724 | case GRN_COLUMN_INDEX : |
725 | grn_ctx_output_cstr(ctx, "index" ); |
726 | break; |
727 | } |
728 | } |
729 | |
730 | static void |
731 | command_schema_column_output_value_type(grn_ctx *ctx, grn_obj *column) |
732 | { |
733 | grn_obj *value_type; |
734 | value_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); |
735 | command_schema_output_value_type(ctx, value_type); |
736 | } |
737 | |
738 | static void |
739 | command_schema_column_output_compress(grn_ctx *ctx, grn_obj *column) |
740 | { |
741 | const char *compress = NULL; |
742 | |
743 | if (column->header.type != GRN_COLUMN_INDEX) { |
744 | switch (column->header.flags & GRN_OBJ_COMPRESS_MASK) { |
745 | case GRN_OBJ_COMPRESS_ZLIB : |
746 | compress = "zlib" ; |
747 | break; |
748 | case GRN_OBJ_COMPRESS_LZ4 : |
749 | compress = "lz4" ; |
750 | break; |
751 | case GRN_OBJ_COMPRESS_ZSTD : |
752 | compress = "zstd" ; |
753 | break; |
754 | default : |
755 | break; |
756 | } |
757 | } |
758 | |
759 | if (compress) { |
760 | grn_ctx_output_cstr(ctx, compress); |
761 | } else { |
762 | grn_ctx_output_null(ctx); |
763 | } |
764 | } |
765 | |
766 | static void |
767 | command_schema_column_output_sources(grn_ctx *ctx, grn_obj *column) |
768 | { |
769 | grn_obj *source_table; |
770 | grn_obj source_ids; |
771 | unsigned int i, n_ids; |
772 | |
773 | source_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); |
774 | |
775 | GRN_RECORD_INIT(&source_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); |
776 | |
777 | if (column->header.type == GRN_COLUMN_INDEX) { |
778 | grn_obj_get_info(ctx, column, GRN_INFO_SOURCE, &source_ids); |
779 | } |
780 | |
781 | n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); |
782 | grn_ctx_output_array_open(ctx, "sources" , n_ids); |
783 | for (i = 0; i < n_ids; i++) { |
784 | grn_id source_id; |
785 | grn_obj *source; |
786 | |
787 | source_id = GRN_RECORD_VALUE_AT(&source_ids, i); |
788 | source = grn_ctx_at(ctx, source_id); |
789 | |
790 | grn_ctx_output_map_open(ctx, "source" , 4); |
791 | |
792 | grn_ctx_output_cstr(ctx, "id" ); |
793 | if (grn_obj_is_table(ctx, source)) { |
794 | command_schema_output_id(ctx, NULL); |
795 | } else { |
796 | command_schema_output_id(ctx, source); |
797 | } |
798 | |
799 | grn_ctx_output_cstr(ctx, "name" ); |
800 | if (grn_obj_is_table(ctx, source)) { |
801 | grn_ctx_output_cstr(ctx, "_key" ); |
802 | } else { |
803 | command_schema_output_column_name(ctx, source); |
804 | } |
805 | |
806 | grn_ctx_output_cstr(ctx, "table" ); |
807 | command_schema_output_name(ctx, source_table); |
808 | |
809 | grn_ctx_output_cstr(ctx, "full_name" ); |
810 | if (grn_obj_is_table(ctx, source)) { |
811 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
812 | unsigned int name_size; |
813 | name_size = grn_obj_name(ctx, source, name, GRN_TABLE_MAX_KEY_SIZE); |
814 | name[name_size] = '\0'; |
815 | grn_strcat(name, GRN_TABLE_MAX_KEY_SIZE, "._key" ); |
816 | grn_ctx_output_cstr(ctx, name); |
817 | } else { |
818 | command_schema_output_name(ctx, source); |
819 | } |
820 | |
821 | grn_ctx_output_map_close(ctx); |
822 | } |
823 | grn_ctx_output_array_close(ctx); |
824 | |
825 | GRN_OBJ_FIN(ctx, &source_ids); |
826 | } |
827 | |
828 | static void |
829 | command_schema_output_indexes(grn_ctx *ctx, grn_obj *object) |
830 | { |
831 | uint32_t i; |
832 | grn_index_datum *index_data = NULL; |
833 | uint32_t n_index_data = 0; |
834 | |
835 | n_index_data = grn_column_get_all_index_data(ctx, object, NULL, 0); |
836 | if (n_index_data > 0) { |
837 | index_data = GRN_PLUGIN_MALLOC(ctx, |
838 | sizeof(grn_index_datum) * n_index_data); |
839 | if (!index_data) { |
840 | GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, |
841 | "[schema] failed to allocate memory for indexes" ); |
842 | return; |
843 | } |
844 | grn_column_get_all_index_data(ctx, object, index_data, n_index_data); |
845 | } |
846 | |
847 | grn_ctx_output_array_open(ctx, "indexes" , n_index_data); |
848 | for (i = 0; i < n_index_data; i++) { |
849 | grn_obj *lexicon; |
850 | |
851 | grn_ctx_output_map_open(ctx, "index" , 5); |
852 | |
853 | grn_ctx_output_cstr(ctx, "id" ); |
854 | command_schema_output_id(ctx, index_data[i].index); |
855 | |
856 | grn_ctx_output_cstr(ctx, "full_name" ); |
857 | command_schema_output_name(ctx, index_data[i].index); |
858 | |
859 | grn_ctx_output_cstr(ctx, "table" ); |
860 | lexicon = grn_ctx_at(ctx, index_data[i].index->header.domain); |
861 | command_schema_output_name(ctx, lexicon); |
862 | |
863 | grn_ctx_output_cstr(ctx, "name" ); |
864 | command_schema_output_column_name(ctx, index_data[i].index); |
865 | |
866 | grn_ctx_output_cstr(ctx, "section" ); |
867 | grn_ctx_output_uint64(ctx, index_data[i].section); |
868 | |
869 | grn_ctx_output_map_close(ctx); |
870 | } |
871 | grn_ctx_output_array_close(ctx); |
872 | |
873 | if (index_data) { |
874 | GRN_PLUGIN_FREE(ctx, index_data); |
875 | } |
876 | } |
877 | |
878 | static void |
879 | command_schema_column_command_collect_arguments(grn_ctx *ctx, |
880 | grn_obj *table, |
881 | grn_obj *column, |
882 | grn_obj *arguments) |
883 | { |
884 | #define ADD(name_, value_) \ |
885 | grn_vector_add_element(ctx, arguments, \ |
886 | name_, strlen(name_), \ |
887 | 0, GRN_DB_TEXT); \ |
888 | grn_vector_add_element(ctx, arguments, \ |
889 | value_, strlen(value_), \ |
890 | 0, GRN_DB_TEXT) |
891 | |
892 | #define ADD_OBJECT_NAME(name_, object_) do { \ |
893 | char object_name[GRN_TABLE_MAX_KEY_SIZE]; \ |
894 | unsigned int object_name_size; \ |
895 | object_name_size = grn_obj_name(ctx, object_, \ |
896 | object_name, \ |
897 | GRN_TABLE_MAX_KEY_SIZE); \ |
898 | object_name[object_name_size] = '\0'; \ |
899 | ADD(name_, object_name); \ |
900 | } while (GRN_FALSE) |
901 | |
902 | ADD_OBJECT_NAME("table" , table); |
903 | { |
904 | char column_name[GRN_TABLE_MAX_KEY_SIZE]; |
905 | unsigned int column_name_size; |
906 | column_name_size = grn_column_name(ctx, column, |
907 | column_name, GRN_TABLE_MAX_KEY_SIZE); |
908 | column_name[column_name_size] = '\0'; |
909 | ADD("name" , column_name); |
910 | } |
911 | |
912 | { |
913 | grn_obj flags; |
914 | grn_column_flags column_flags; |
915 | |
916 | GRN_TEXT_INIT(&flags, 0); |
917 | column_flags = grn_column_get_flags(ctx, column); |
918 | grn_dump_column_create_flags(ctx, |
919 | column_flags & ~GRN_OBJ_PERSISTENT, |
920 | &flags); |
921 | GRN_TEXT_PUTC(ctx, &flags, '\0'); |
922 | ADD("flags" , GRN_TEXT_VALUE(&flags)); |
923 | GRN_OBJ_FIN(ctx, &flags); |
924 | } |
925 | |
926 | { |
927 | grn_obj *value_type; |
928 | |
929 | value_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); |
930 | ADD_OBJECT_NAME("type" , value_type); |
931 | } |
932 | |
933 | if (column->header.type == GRN_COLUMN_INDEX) { |
934 | grn_obj source_ids; |
935 | unsigned int n_ids; |
936 | |
937 | GRN_RECORD_INIT(&source_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); |
938 | grn_obj_get_info(ctx, column, GRN_INFO_SOURCE, &source_ids); |
939 | |
940 | n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); |
941 | if (n_ids > 0) { |
942 | grn_obj sources; |
943 | unsigned int i; |
944 | |
945 | GRN_TEXT_INIT(&sources, 0); |
946 | for (i = 0; i < n_ids; i++) { |
947 | grn_id source_id; |
948 | grn_obj *source; |
949 | char name[GRN_TABLE_MAX_KEY_SIZE]; |
950 | unsigned int name_size; |
951 | |
952 | source_id = GRN_RECORD_VALUE_AT(&source_ids, i); |
953 | source = grn_ctx_at(ctx, source_id); |
954 | |
955 | if (grn_obj_is_table(ctx, source)) { |
956 | grn_strcpy(name, GRN_TABLE_MAX_KEY_SIZE, "_key" ); |
957 | name_size = strlen(name); |
958 | } else { |
959 | name_size = grn_column_name(ctx, source, name, GRN_TABLE_MAX_KEY_SIZE); |
960 | } |
961 | if (i > 0) { |
962 | GRN_TEXT_PUTC(ctx, &sources, ','); |
963 | } |
964 | GRN_TEXT_PUT(ctx, &sources, name, name_size); |
965 | } |
966 | GRN_TEXT_PUTC(ctx, &sources, '\0'); |
967 | ADD("source" , GRN_TEXT_VALUE(&sources)); |
968 | GRN_OBJ_FIN(ctx, &sources); |
969 | } |
970 | GRN_OBJ_FIN(ctx, &source_ids); |
971 | } |
972 | |
973 | #undef ADD_OBJECT_NAME |
974 | #undef ADD |
975 | } |
976 | |
977 | static void |
978 | command_schema_column_output_command(grn_ctx *ctx, |
979 | grn_obj *table, |
980 | grn_obj *column) |
981 | { |
982 | grn_obj arguments; |
983 | |
984 | GRN_TEXT_INIT(&arguments, GRN_OBJ_VECTOR); |
985 | command_schema_column_command_collect_arguments(ctx, table, column, &arguments); |
986 | |
987 | command_schema_output_command(ctx, "column_create" , &arguments); |
988 | |
989 | GRN_OBJ_FIN(ctx, &arguments); |
990 | } |
991 | |
992 | static void |
993 | command_schema_column_output(grn_ctx *ctx, grn_obj *table, grn_obj *column) |
994 | { |
995 | if (!column) { |
996 | return; |
997 | } |
998 | |
999 | command_schema_output_column_name(ctx, column); |
1000 | |
1001 | grn_ctx_output_map_open(ctx, "column" , 13); |
1002 | |
1003 | grn_ctx_output_cstr(ctx, "id" ); |
1004 | command_schema_output_id(ctx, column); |
1005 | |
1006 | grn_ctx_output_cstr(ctx, "name" ); |
1007 | command_schema_output_column_name(ctx, column); |
1008 | |
1009 | grn_ctx_output_cstr(ctx, "table" ); |
1010 | command_schema_output_name(ctx, table); |
1011 | |
1012 | grn_ctx_output_cstr(ctx, "full_name" ); |
1013 | command_schema_output_name(ctx, column); |
1014 | |
1015 | grn_ctx_output_cstr(ctx, "type" ); |
1016 | command_schema_column_output_type(ctx, column); |
1017 | |
1018 | grn_ctx_output_cstr(ctx, "value_type" ); |
1019 | command_schema_column_output_value_type(ctx, column); |
1020 | |
1021 | grn_ctx_output_cstr(ctx, "compress" ); |
1022 | command_schema_column_output_compress(ctx, column); |
1023 | |
1024 | grn_ctx_output_cstr(ctx, "section" ); |
1025 | grn_ctx_output_bool(ctx, (column->header.flags & GRN_OBJ_WITH_SECTION) != 0); |
1026 | |
1027 | grn_ctx_output_cstr(ctx, "weight" ); |
1028 | grn_ctx_output_bool(ctx, (column->header.flags & GRN_OBJ_WITH_WEIGHT) != 0); |
1029 | |
1030 | grn_ctx_output_cstr(ctx, "position" ); |
1031 | grn_ctx_output_bool(ctx, (column->header.flags & GRN_OBJ_WITH_POSITION) != 0); |
1032 | |
1033 | grn_ctx_output_cstr(ctx, "sources" ); |
1034 | command_schema_column_output_sources(ctx, column); |
1035 | |
1036 | grn_ctx_output_cstr(ctx, "indexes" ); |
1037 | command_schema_output_indexes(ctx, column); |
1038 | |
1039 | grn_ctx_output_cstr(ctx, "command" ); |
1040 | command_schema_column_output_command(ctx, table, column); |
1041 | |
1042 | grn_ctx_output_map_close(ctx); |
1043 | } |
1044 | |
1045 | static void |
1046 | command_schema_table_output_columns(grn_ctx *ctx, |
1047 | grn_obj *table, |
1048 | grn_schema_data *data) |
1049 | { |
1050 | grn_hash *columns; |
1051 | |
1052 | columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
1053 | GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); |
1054 | if (!columns) { |
1055 | grn_ctx_output_map_open(ctx, "columns" , 0); |
1056 | grn_ctx_output_map_close(ctx); |
1057 | return; |
1058 | } |
1059 | |
1060 | grn_table_columns(ctx, table, "" , 0, (grn_obj *)columns); |
1061 | grn_ctx_output_map_open(ctx, "columns" , grn_hash_size(ctx, columns)); |
1062 | { |
1063 | grn_id *key; |
1064 | GRN_HASH_EACH(ctx, columns, id, &key, NULL, NULL, { |
1065 | grn_obj *column; |
1066 | |
1067 | if (data->is_close_opened_object_mode) { |
1068 | grn_ctx_push_temporary_open_space(ctx); |
1069 | } |
1070 | |
1071 | column = grn_ctx_at(ctx, *key); |
1072 | command_schema_column_output(ctx, table, column); |
1073 | |
1074 | if (data->is_close_opened_object_mode) { |
1075 | grn_ctx_pop_temporary_open_space(ctx); |
1076 | } |
1077 | }); |
1078 | } |
1079 | grn_ctx_output_map_close(ctx); |
1080 | grn_hash_close(ctx, columns); |
1081 | } |
1082 | |
1083 | static void |
1084 | command_schema_output_table(grn_ctx *ctx, |
1085 | grn_schema_data *data, |
1086 | grn_obj *table) |
1087 | { |
1088 | command_schema_output_name(ctx, table); |
1089 | |
1090 | grn_ctx_output_map_open(ctx, "table" , 11); |
1091 | |
1092 | grn_ctx_output_cstr(ctx, "id" ); |
1093 | command_schema_output_id(ctx, table); |
1094 | |
1095 | grn_ctx_output_cstr(ctx, "name" ); |
1096 | command_schema_output_name(ctx, table); |
1097 | |
1098 | grn_ctx_output_cstr(ctx, "type" ); |
1099 | grn_ctx_output_cstr(ctx, command_schema_table_type_name(ctx, table)); |
1100 | |
1101 | grn_ctx_output_cstr(ctx, "key_type" ); |
1102 | command_schema_table_output_key_type(ctx, table); |
1103 | |
1104 | grn_ctx_output_cstr(ctx, "value_type" ); |
1105 | command_schema_table_output_value_type(ctx, table); |
1106 | |
1107 | grn_ctx_output_cstr(ctx, "tokenizer" ); |
1108 | command_schema_table_output_tokenizer(ctx, table); |
1109 | |
1110 | grn_ctx_output_cstr(ctx, "normalizer" ); |
1111 | command_schema_table_output_normalizer(ctx, table); |
1112 | |
1113 | grn_ctx_output_cstr(ctx, "token_filters" ); |
1114 | command_schema_table_output_token_filters(ctx, table); |
1115 | |
1116 | grn_ctx_output_cstr(ctx, "indexes" ); |
1117 | command_schema_output_indexes(ctx, table); |
1118 | |
1119 | grn_ctx_output_cstr(ctx, "command" ); |
1120 | command_schema_table_output_command(ctx, table); |
1121 | |
1122 | grn_ctx_output_cstr(ctx, "columns" ); |
1123 | command_schema_table_output_columns(ctx, table, data); |
1124 | |
1125 | grn_ctx_output_map_close(ctx); |
1126 | } |
1127 | |
1128 | static void |
1129 | command_schema_output_tables(grn_ctx *ctx, grn_schema_data *data) |
1130 | { |
1131 | grn_obj table_ids; |
1132 | unsigned int i, n; |
1133 | |
1134 | GRN_RECORD_INIT(&table_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); |
1135 | GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { |
1136 | void *name; |
1137 | int name_size; |
1138 | grn_obj *object; |
1139 | |
1140 | if (grn_id_is_builtin(ctx, id)) { |
1141 | continue; |
1142 | } |
1143 | |
1144 | name_size = grn_table_cursor_get_key(ctx, cursor, &name); |
1145 | if (grn_obj_name_is_column(ctx, name, name_size)) { |
1146 | continue; |
1147 | } |
1148 | |
1149 | if (data->is_close_opened_object_mode) { |
1150 | grn_ctx_push_temporary_open_space(ctx); |
1151 | } |
1152 | |
1153 | object = grn_ctx_at(ctx, id); |
1154 | if (!object) { |
1155 | /* XXX: this clause is executed when MeCab tokenizer is enabled in |
1156 | database but the groonga isn't supported MeCab. |
1157 | We should return error mesage about it and error exit status |
1158 | but it's too difficult for this architecture. :< */ |
1159 | GRN_PLUGIN_CLEAR_ERROR(ctx); |
1160 | goto next_loop; |
1161 | } |
1162 | |
1163 | if (grn_obj_is_table(ctx, object)) { |
1164 | GRN_RECORD_PUT(ctx, &table_ids, id); |
1165 | } |
1166 | |
1167 | next_loop : |
1168 | if (data->is_close_opened_object_mode) { |
1169 | grn_ctx_pop_temporary_open_space(ctx); |
1170 | } |
1171 | } GRN_TABLE_EACH_END(ctx, cursor); |
1172 | |
1173 | n = GRN_BULK_VSIZE(&table_ids) / sizeof(grn_id); |
1174 | |
1175 | grn_ctx_output_cstr(ctx, "tables" ); |
1176 | grn_ctx_output_map_open(ctx, "tables" , n); |
1177 | for (i = 0; i < n; i++) { |
1178 | grn_id table_id; |
1179 | grn_obj *table; |
1180 | |
1181 | if (data->is_close_opened_object_mode) { |
1182 | grn_ctx_push_temporary_open_space(ctx); |
1183 | } |
1184 | |
1185 | table_id = GRN_RECORD_VALUE_AT(&table_ids, i); |
1186 | table = grn_ctx_at(ctx, table_id); |
1187 | |
1188 | command_schema_output_table(ctx, data, table); |
1189 | |
1190 | if (data->is_close_opened_object_mode) { |
1191 | grn_ctx_pop_temporary_open_space(ctx); |
1192 | } |
1193 | } |
1194 | grn_ctx_output_map_close(ctx); |
1195 | |
1196 | GRN_OBJ_FIN(ctx, &table_ids); |
1197 | } |
1198 | |
1199 | static grn_obj * |
1200 | command_schema(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) |
1201 | { |
1202 | grn_schema_data data; |
1203 | |
1204 | data.is_close_opened_object_mode = (grn_thread_get_limit() == 1); |
1205 | |
1206 | grn_ctx_output_map_open(ctx, "schema" , 6); |
1207 | command_schema_output_plugins(ctx); |
1208 | command_schema_output_types(ctx); |
1209 | command_schema_output_tokenizers(ctx, &data); |
1210 | command_schema_output_normalizers(ctx, &data); |
1211 | command_schema_output_token_filters(ctx, &data); |
1212 | command_schema_output_tables(ctx, &data); |
1213 | grn_ctx_output_map_close(ctx); |
1214 | |
1215 | return NULL; |
1216 | } |
1217 | |
1218 | void |
1219 | grn_proc_init_schema(grn_ctx *ctx) |
1220 | { |
1221 | grn_plugin_command_create(ctx, |
1222 | "schema" , -1, |
1223 | command_schema, |
1224 | 0, |
1225 | NULL); |
1226 | } |
1227 | |