1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2009-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-1301 USA
17*/
18
19#include "grn_load.h"
20#include "grn_ctx_impl.h"
21#include "grn_db.h"
22#include "grn_util.h"
23
24static void
25grn_loader_save_error(grn_ctx *ctx, grn_loader *loader)
26{
27 loader->rc = ctx->rc;
28 grn_strcpy(loader->errbuf, GRN_CTX_MSGSIZE, ctx->errbuf);
29}
30
31static grn_obj *
32values_add(grn_ctx *ctx, grn_loader *loader)
33{
34 grn_obj *res;
35 uint32_t curr_size = loader->values_size * sizeof(grn_obj);
36 if (curr_size < GRN_TEXT_LEN(&loader->values)) {
37 res = (grn_obj *)(GRN_TEXT_VALUE(&loader->values) + curr_size);
38 res->header.domain = GRN_DB_TEXT;
39 GRN_BULK_REWIND(res);
40 } else {
41 if (grn_bulk_space(ctx, &loader->values, sizeof(grn_obj))) { return NULL; }
42 res = (grn_obj *)(GRN_TEXT_VALUE(&loader->values) + curr_size);
43 GRN_TEXT_INIT(res, 0);
44 }
45 loader->values_size++;
46 loader->last = res;
47 return res;
48}
49
50static grn_obj *
51values_next(grn_ctx *ctx, grn_obj *value)
52{
53 if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET ||
54 value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) {
55 value += GRN_UINT32_VALUE(value);
56 }
57 return value + 1;
58}
59
60static int
61values_len(grn_ctx *ctx, grn_obj *head, grn_obj *tail)
62{
63 int len;
64 for (len = 0; head < tail; head = values_next(ctx, head), len++) ;
65 return len;
66}
67
68static grn_id
69loader_add(grn_ctx *ctx, grn_obj *key)
70{
71 int added = 0;
72 grn_loader *loader = &ctx->impl->loader;
73 grn_id id = grn_table_add_by_key(ctx, loader->table, key, &added);
74 if (id == GRN_ID_NIL) {
75 grn_loader_save_error(ctx, loader);
76 return id;
77 }
78 if (!added && loader->ifexists) {
79 grn_obj *v = grn_expr_get_var_by_offset(ctx, loader->ifexists, 0);
80 grn_obj *result;
81 GRN_RECORD_SET(ctx, v, id);
82 result = grn_expr_exec(ctx, loader->ifexists, 0);
83 if (!grn_obj_is_true(ctx, result)) {
84 id = 0;
85 }
86 }
87 return id;
88}
89
90static void
91add_weight_vector(grn_ctx *ctx,
92 grn_obj *column,
93 grn_obj *value,
94 grn_obj *vector)
95{
96 unsigned int i, n;
97 grn_obj weight_buffer;
98
99 n = GRN_UINT32_VALUE(value);
100 GRN_UINT32_INIT(&weight_buffer, 0);
101 for (i = 0; i < n; i += 2) {
102 grn_rc rc;
103 grn_obj *key, *weight;
104
105 key = value + 1 + i;
106 weight = key + 1;
107
108 GRN_BULK_REWIND(&weight_buffer);
109 rc = grn_obj_cast(ctx, weight, &weight_buffer, GRN_TRUE);
110 if (rc != GRN_SUCCESS) {
111 grn_obj *range;
112 range = grn_ctx_at(ctx, weight_buffer.header.domain);
113 ERR_CAST(column, range, weight);
114 grn_obj_unlink(ctx, range);
115 break;
116 }
117 grn_vector_add_element(ctx,
118 vector,
119 GRN_BULK_HEAD(key),
120 GRN_BULK_VSIZE(key),
121 GRN_UINT32_VALUE(&weight_buffer),
122 key->header.domain);
123 }
124 GRN_OBJ_FIN(ctx, &weight_buffer);
125}
126
127static void
128set_vector(grn_ctx *ctx, grn_obj *column, grn_id id, grn_obj *vector)
129{
130 int n = GRN_UINT32_VALUE(vector);
131 grn_obj buf, *v = vector + 1;
132 grn_id range_id;
133 grn_obj *range;
134
135 range_id = DB_OBJ(column)->range;
136 range = grn_ctx_at(ctx, range_id);
137 if (grn_obj_is_table(ctx, range)) {
138 GRN_RECORD_INIT(&buf, GRN_OBJ_VECTOR, range_id);
139 while (n--) {
140 grn_bool cast_failed = GRN_FALSE;
141 grn_obj record, *element = v;
142 if (range_id != element->header.domain) {
143 GRN_RECORD_INIT(&record, 0, range_id);
144 if (grn_obj_cast(ctx, element, &record, GRN_TRUE)) {
145 cast_failed = GRN_TRUE;
146 ERR_CAST(column, range, element);
147 }
148 element = &record;
149 }
150 if (!cast_failed) {
151 GRN_UINT32_PUT(ctx, &buf, GRN_RECORD_VALUE(element));
152 }
153 if (element == &record) { GRN_OBJ_FIN(ctx, element); }
154 v = values_next(ctx, v);
155 }
156 } else {
157 if (((struct _grn_type *)range)->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) {
158 GRN_TEXT_INIT(&buf, GRN_OBJ_VECTOR);
159 while (n--) {
160 switch (v->header.domain) {
161 case GRN_DB_TEXT :
162 {
163 grn_bool cast_failed = GRN_FALSE;
164 grn_obj casted_element, *element = v;
165 if (range_id != element->header.domain) {
166 GRN_OBJ_INIT(&casted_element, GRN_BULK, 0, range_id);
167 if (grn_obj_cast(ctx, element, &casted_element, GRN_TRUE)) {
168 cast_failed = GRN_TRUE;
169 ERR_CAST(column, range, element);
170 }
171 element = &casted_element;
172 }
173 if (!cast_failed) {
174 grn_vector_add_element(ctx, &buf,
175 GRN_TEXT_VALUE(element),
176 GRN_TEXT_LEN(element),
177 0,
178 element->header.domain);
179 }
180 if (element == &casted_element) { GRN_OBJ_FIN(ctx, element); }
181 break;
182 }
183 case GRN_JSON_LOAD_OPEN_BRACE :
184 add_weight_vector(ctx, column, v, &buf);
185 n -= GRN_UINT32_VALUE(v);
186 break;
187 default :
188 ERR(GRN_INVALID_ARGUMENT, "array must contain string or object");
189 break;
190 }
191 v = values_next(ctx, v);
192 }
193 } else {
194 grn_id value_size = ((grn_db_obj *)range)->range;
195 GRN_VALUE_FIX_SIZE_INIT(&buf, GRN_OBJ_VECTOR, range_id);
196 while (n--) {
197 grn_bool cast_failed = GRN_FALSE;
198 grn_obj casted_element, *element = v;
199 if (range_id != element->header.domain) {
200 GRN_OBJ_INIT(&casted_element, GRN_BULK, 0, range_id);
201 if (grn_obj_cast(ctx, element, &casted_element, GRN_TRUE)) {
202 cast_failed = GRN_TRUE;
203 ERR_CAST(column, range, element);
204 }
205 element = &casted_element;
206 }
207 if (!cast_failed) {
208 grn_bulk_write(ctx, &buf, GRN_TEXT_VALUE(element), value_size);
209 }
210 if (element == &casted_element) { GRN_OBJ_FIN(ctx, element); }
211 v = values_next(ctx, v);
212 }
213 }
214 }
215 grn_obj_set_value(ctx, column, id, &buf, GRN_OBJ_SET);
216 GRN_OBJ_FIN(ctx, &buf);
217}
218
219static void
220set_weight_vector(grn_ctx *ctx, grn_obj *column, grn_id id, grn_obj *value)
221{
222 if (!grn_obj_is_weight_vector_column(ctx, column)) {
223 char column_name[GRN_TABLE_MAX_KEY_SIZE];
224 int column_name_size;
225 column_name_size = grn_obj_name(ctx, column, column_name,
226 GRN_TABLE_MAX_KEY_SIZE);
227 ERR(GRN_INVALID_ARGUMENT,
228 "<%.*s>: columns except weight vector column don't support object value",
229 column_name_size, column_name);
230 return;
231 }
232
233 {
234 grn_obj vector;
235
236 GRN_TEXT_INIT(&vector, GRN_OBJ_VECTOR);
237 add_weight_vector(ctx, column, value, &vector);
238 grn_obj_set_value(ctx, column, id, &vector, GRN_OBJ_SET);
239 GRN_OBJ_FIN(ctx, &vector);
240 }
241}
242
243static inline int
244name_equal(const char *p, unsigned int size, const char *name)
245{
246 if (strlen(name) != size) { return 0; }
247 if (*p != GRN_DB_PSEUDO_COLUMN_PREFIX) { return 0; }
248 return !memcmp(p + 1, name + 1, size - 1);
249}
250
251static void
252report_set_column_value_failure(grn_ctx *ctx,
253 grn_obj *key,
254 const char *column_name,
255 unsigned int column_name_size,
256 grn_obj *column_value)
257{
258 grn_obj key_inspected, column_value_inspected;
259
260 GRN_TEXT_INIT(&key_inspected, 0);
261 GRN_TEXT_INIT(&column_value_inspected, 0);
262 grn_inspect_limited(ctx, &key_inspected, key);
263 grn_inspect_limited(ctx, &column_value_inspected, column_value);
264 GRN_LOG(ctx, GRN_LOG_ERROR,
265 "[table][load] failed to set column value: %s: "
266 "key: <%.*s>, column: <%.*s>, value: <%.*s>",
267 ctx->errbuf,
268 (int)GRN_TEXT_LEN(&key_inspected),
269 GRN_TEXT_VALUE(&key_inspected),
270 column_name_size,
271 column_name,
272 (int)GRN_TEXT_LEN(&column_value_inspected),
273 GRN_TEXT_VALUE(&column_value_inspected));
274 GRN_OBJ_FIN(ctx, &key_inspected);
275 GRN_OBJ_FIN(ctx, &column_value_inspected);
276}
277
278static grn_id
279parse_id_value(grn_ctx *ctx, grn_obj *value)
280{
281 switch (value->header.type) {
282 case GRN_DB_UINT32 :
283 return GRN_UINT32_VALUE(value);
284 case GRN_DB_INT32 :
285 return GRN_INT32_VALUE(value);
286 default :
287 {
288 grn_id id = GRN_ID_NIL;
289 grn_obj casted_value;
290 GRN_UINT32_INIT(&casted_value, 0);
291 if (grn_obj_cast(ctx, value, &casted_value, GRN_FALSE) != GRN_SUCCESS) {
292 grn_obj inspected;
293 GRN_TEXT_INIT(&inspected, 0);
294 grn_inspect(ctx, &inspected, value);
295 ERR(GRN_INVALID_ARGUMENT,
296 "<%s>: failed to cast to <UInt32>: <%.*s>",
297 GRN_COLUMN_NAME_ID,
298 (int)GRN_TEXT_LEN(&inspected),
299 GRN_TEXT_VALUE(&inspected));
300 GRN_OBJ_FIN(ctx, &inspected);
301 } else {
302 id = GRN_UINT32_VALUE(&casted_value);
303 }
304 GRN_OBJ_FIN(ctx, &casted_value);
305 return id;
306 }
307 }
308}
309
310static void
311bracket_close(grn_ctx *ctx, grn_loader *loader)
312{
313 grn_id id = GRN_ID_NIL;
314 grn_obj *value, *value_end, *id_value = NULL, *key_value = NULL;
315 grn_obj *col, **cols; /* Columns except _id and _key. */
316 uint32_t i, begin;
317 uint32_t ncols; /* Number of columns except _id and _key. */
318 uint32_t nvalues; /* Number of values in brackets. */
319 uint32_t depth;
320 grn_bool is_record_load = GRN_FALSE;
321
322 cols = (grn_obj **)GRN_BULK_HEAD(&loader->columns);
323 ncols = GRN_BULK_VSIZE(&loader->columns) / sizeof(grn_obj *);
324 GRN_UINT32_POP(&loader->level, begin);
325 value = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + begin;
326 value_end = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + loader->values_size;
327 GRN_ASSERT(value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET);
328 GRN_UINT32_SET(ctx, value, loader->values_size - begin - 1);
329 value++;
330 depth = GRN_BULK_VSIZE(&loader->level);
331 if (depth > sizeof(uint32_t) * loader->emit_level) {
332 return;
333 }
334 if (depth == 0 || !loader->table ||
335 loader->columns_status == GRN_LOADER_COLUMNS_BROKEN) {
336 goto exit;
337 }
338 nvalues = values_len(ctx, value, value_end);
339
340 if (loader->columns_status == GRN_LOADER_COLUMNS_UNSET) {
341 /*
342 * Target columns and _id or _key are not specified yet and values are
343 * handled as column names and "_id" or "_key".
344 */
345 for (i = 0; i < nvalues; i++) {
346 const char *col_name;
347 unsigned int col_name_size;
348 if (value->header.domain != GRN_DB_TEXT) {
349 grn_obj buffer;
350 GRN_TEXT_INIT(&buffer, 0);
351 grn_inspect(ctx, &buffer, value);
352 ERR(GRN_INVALID_ARGUMENT,
353 "column name must be string: <%.*s>",
354 (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
355 grn_loader_save_error(ctx, loader);
356 GRN_OBJ_FIN(ctx, &buffer);
357 loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
358 goto exit;
359 }
360 col_name = GRN_TEXT_VALUE(value);
361 col_name_size = GRN_TEXT_LEN(value);
362 col = grn_obj_column(ctx, loader->table, col_name, col_name_size);
363 if (!col) {
364 ERR(GRN_INVALID_ARGUMENT, "nonexistent column: <%.*s>",
365 col_name_size, col_name);
366 grn_loader_save_error(ctx, loader);
367 loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
368 goto exit;
369 }
370 if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_ID)) {
371 grn_obj_unlink(ctx, col);
372 if (loader->id_offset != -1 || loader->key_offset != -1) {
373 /* _id and _key must not appear more than once. */
374 if (loader->id_offset != -1) {
375 ERR(GRN_INVALID_ARGUMENT,
376 "duplicated id and key columns: <%s> at %d and <%s> at %d",
377 GRN_COLUMN_NAME_ID, i,
378 GRN_COLUMN_NAME_ID, loader->id_offset);
379 } else {
380 ERR(GRN_INVALID_ARGUMENT,
381 "duplicated id and key columns: <%s> at %d and <%s> at %d",
382 GRN_COLUMN_NAME_ID, i,
383 GRN_COLUMN_NAME_KEY, loader->key_offset);
384 }
385 grn_loader_save_error(ctx, loader);
386 loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
387 goto exit;
388 }
389 loader->id_offset = i;
390 } else if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_KEY)) {
391 grn_obj_unlink(ctx, col);
392 if (loader->id_offset != -1 || loader->key_offset != -1) {
393 /* _id and _key must not appear more than once. */
394 if (loader->id_offset != -1) {
395 ERR(GRN_INVALID_ARGUMENT,
396 "duplicated id and key columns: <%s> at %d and <%s> at %d",
397 GRN_COLUMN_NAME_KEY, i,
398 GRN_COLUMN_NAME_ID, loader->id_offset);
399 } else {
400 ERR(GRN_INVALID_ARGUMENT,
401 "duplicated id and key columns: <%s> at %d and <%s> at %d",
402 GRN_COLUMN_NAME_KEY, i,
403 GRN_COLUMN_NAME_KEY, loader->key_offset);
404 }
405 grn_loader_save_error(ctx, loader);
406 loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
407 goto exit;
408 }
409 loader->key_offset = i;
410 } else {
411 GRN_PTR_PUT(ctx, &loader->columns, col);
412 }
413 value++;
414 }
415 switch (loader->table->header.type) {
416 case GRN_TABLE_HASH_KEY :
417 case GRN_TABLE_PAT_KEY :
418 case GRN_TABLE_DAT_KEY :
419 if (loader->id_offset == -1 && loader->key_offset == -1) {
420 ERR(GRN_INVALID_ARGUMENT, "missing id or key column");
421 grn_loader_save_error(ctx, loader);
422 loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
423 goto exit;
424 }
425 break;
426 }
427 loader->columns_status = GRN_LOADER_COLUMNS_SET;
428 goto exit;
429 }
430
431 is_record_load = GRN_TRUE;
432
433 /* Target columns and _id or _key are already specified. */
434 if (!nvalues) {
435 /*
436 * Accept empty arrays because a dump command may output a load command
437 * which contains empty arrays for a table with deleted records.
438 */
439 id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
440 } else {
441 uint32_t expected_nvalues = ncols;
442 if (loader->id_offset != -1 || loader->key_offset != -1) {
443 expected_nvalues++;
444 }
445 if (nvalues != expected_nvalues) {
446 ERR(GRN_INVALID_ARGUMENT,
447 "unexpected #values: expected:%u, actual:%u",
448 expected_nvalues, nvalues);
449 grn_loader_save_error(ctx, loader);
450 goto exit;
451 }
452 if (loader->id_offset != -1) {
453 id_value = value + loader->id_offset;
454 id = parse_id_value(ctx, id_value);
455 if (grn_table_at(ctx, loader->table, id) == GRN_ID_NIL) {
456 id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
457 }
458 } else if (loader->key_offset != -1) {
459 key_value = value + loader->key_offset;
460 id = loader_add(ctx, key_value);
461 } else {
462 id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
463 }
464 }
465 if (id == GRN_ID_NIL) {
466 /* Target record is not available. */
467 goto exit;
468 }
469
470 for (i = 0; i < nvalues; i++, value = values_next(ctx, value)) {
471 if (i == loader->id_offset || i == loader->key_offset) {
472 /* Skip _id and _key, because it's already used to get id. */
473 continue;
474 }
475 col = *cols;
476 if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) {
477 set_vector(ctx, col, id, value);
478 } else if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) {
479 set_weight_vector(ctx, col, id, value);
480 } else {
481 grn_obj_set_value(ctx, col, id, value, GRN_OBJ_SET);
482 }
483 if (ctx->rc != GRN_SUCCESS) {
484 char column_name[GRN_TABLE_MAX_KEY_SIZE];
485 unsigned int column_name_size;
486 grn_loader_save_error(ctx, loader);
487 column_name_size = grn_obj_name(ctx, col, column_name,
488 GRN_TABLE_MAX_KEY_SIZE);
489 report_set_column_value_failure(ctx, key_value,
490 column_name, column_name_size,
491 value);
492 ERRCLR(ctx);
493 }
494 cols++;
495 }
496 if (loader->each) {
497 grn_obj *v = grn_expr_get_var_by_offset(ctx, loader->each, 0);
498 GRN_RECORD_SET(ctx, v, id);
499 grn_expr_exec(ctx, loader->each, 0);
500 }
501 loader->nrecords++;
502exit:
503 if (is_record_load) {
504 if (loader->output_ids) {
505 GRN_UINT32_PUT(ctx, &(loader->ids), id);
506 }
507 if (loader->output_errors) {
508 GRN_INT32_PUT(ctx, &(loader->return_codes), ctx->rc);
509 grn_vector_add_element(ctx,
510 &(loader->error_messages),
511 ctx->errbuf,
512 strlen(ctx->errbuf),
513 0,
514 GRN_DB_TEXT);
515 }
516 }
517 loader->values_size = begin;
518 ERRCLR(ctx);
519}
520
521static void
522brace_close(grn_ctx *ctx, grn_loader *loader)
523{
524 grn_id id = GRN_ID_NIL;
525 grn_obj *value, *value_begin, *value_end;
526 grn_obj *id_value = NULL, *key_value = NULL;
527 uint32_t begin;
528
529 GRN_UINT32_POP(&loader->level, begin);
530 value_begin = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + begin;
531 value_end = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + loader->values_size;
532 GRN_ASSERT(value->header.domain == GRN_JSON_LOAD_OPEN_BRACE);
533 GRN_UINT32_SET(ctx, value_begin, loader->values_size - begin - 1);
534 value_begin++;
535 if (GRN_BULK_VSIZE(&loader->level) > sizeof(uint32_t) * loader->emit_level) {
536 return;
537 }
538 if (!loader->table) {
539 goto exit;
540 }
541
542 /* Scan values to find _id or _key. */
543 for (value = value_begin; value + 1 < value_end;
544 value = values_next(ctx, value)) {
545 const char *name = GRN_TEXT_VALUE(value);
546 unsigned int name_size = GRN_TEXT_LEN(value);
547 if (value->header.domain != GRN_DB_TEXT) {
548 grn_obj buffer;
549 GRN_TEXT_INIT(&buffer, 0);
550 grn_inspect(ctx, &buffer, value);
551 GRN_LOG(ctx, GRN_LOG_ERROR,
552 "column name must be string: <%.*s>",
553 (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
554 GRN_OBJ_FIN(ctx, &buffer);
555 goto exit;
556 }
557 value++;
558 if (name_equal(name, name_size, GRN_COLUMN_NAME_ID)) {
559 if (id_value || key_value) {
560 if (loader->table->header.type == GRN_TABLE_NO_KEY) {
561 GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated '_id' column");
562 goto exit;
563 } else {
564 GRN_LOG(ctx, GRN_LOG_ERROR,
565 "duplicated key columns: %s and %s",
566 id_value ? GRN_COLUMN_NAME_ID : GRN_COLUMN_NAME_KEY,
567 GRN_COLUMN_NAME_ID);
568 goto exit;
569 }
570 }
571 id_value = value;
572 } else if (name_equal(name, name_size, GRN_COLUMN_NAME_KEY)) {
573 if (id_value || key_value) {
574 GRN_LOG(ctx, GRN_LOG_ERROR,
575 "duplicated key columns: %s and %s",
576 id_value ? GRN_COLUMN_NAME_ID : GRN_COLUMN_NAME_KEY,
577 GRN_COLUMN_NAME_KEY);
578 goto exit;
579 }
580 key_value = value;
581 }
582 }
583
584 switch (loader->table->header.type) {
585 case GRN_TABLE_HASH_KEY :
586 case GRN_TABLE_PAT_KEY :
587 case GRN_TABLE_DAT_KEY :
588 /* The target table requires _id or _key. */
589 if (!id_value && !key_value) {
590 GRN_LOG(ctx, GRN_LOG_ERROR, "neither _key nor _id is assigned");
591 goto exit;
592 }
593 break;
594 default :
595 /* The target table does not have _key. */
596 if (key_value) {
597 GRN_LOG(ctx, GRN_LOG_ERROR, "nonexistent key value");
598 goto exit;
599 }
600 break;
601 }
602
603 if (id_value) {
604 id = parse_id_value(ctx, id_value);
605 if (grn_table_at(ctx, loader->table, id) == GRN_ID_NIL) {
606 if (ctx->rc == GRN_SUCCESS) {
607 id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
608 }
609 }
610 } else if (key_value) {
611 id = loader_add(ctx, key_value);
612 } else {
613 id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
614 }
615 if (id == GRN_ID_NIL) {
616 /* Target record is not available. */
617 goto exit;
618 }
619
620 for (value = value_begin; value + 1 < value_end;
621 value = values_next(ctx, value)) {
622 grn_obj *col;
623 const char *name = GRN_TEXT_VALUE(value);
624 unsigned int name_size = GRN_TEXT_LEN(value);
625 value++;
626 if (value == id_value || value == key_value) {
627 /* Skip _id and _key, because it's already used to get id. */
628 continue;
629 }
630 col = grn_obj_column(ctx, loader->table, name, name_size);
631 if (!col) {
632 GRN_LOG(ctx, GRN_LOG_ERROR, "invalid column('%.*s')",
633 (int)name_size, name);
634 /* Automatic column creation is disabled. */
635 /*
636 if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) {
637 grn_obj *v = value + 1;
638 col = grn_column_create(ctx, loader->table, name, name_size,
639 NULL, GRN_OBJ_PERSISTENT|GRN_OBJ_COLUMN_VECTOR,
640 grn_ctx_at(ctx, v->header.domain));
641 } else {
642 col = grn_column_create(ctx, loader->table, name, name_size,
643 NULL, GRN_OBJ_PERSISTENT,
644 grn_ctx_at(ctx, value->header.domain));
645 }
646 */
647 } else {
648 if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) {
649 set_vector(ctx, col, id, value);
650 } else if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) {
651 set_weight_vector(ctx, col, id, value);
652 } else {
653 grn_obj_set_value(ctx, col, id, value, GRN_OBJ_SET);
654 }
655 if (ctx->rc != GRN_SUCCESS) {
656 grn_loader_save_error(ctx, loader);
657 report_set_column_value_failure(ctx, key_value,
658 name, name_size, value);
659 ERRCLR(ctx);
660 }
661 grn_obj_unlink(ctx, col);
662 }
663 }
664 if (loader->each) {
665 value = grn_expr_get_var_by_offset(ctx, loader->each, 0);
666 GRN_RECORD_SET(ctx, value, id);
667 grn_expr_exec(ctx, loader->each, 0);
668 }
669 loader->nrecords++;
670exit:
671 if (loader->output_ids) {
672 GRN_UINT32_PUT(ctx, &(loader->ids), id);
673 }
674 if (loader->output_errors) {
675 GRN_INT32_PUT(ctx, &(loader->return_codes), ctx->rc);
676 grn_vector_add_element(ctx,
677 &(loader->error_messages),
678 ctx->errbuf,
679 strlen(ctx->errbuf),
680 0,
681 GRN_DB_TEXT);
682 }
683 loader->values_size = begin;
684 ERRCLR(ctx);
685}
686
687#define JSON_READ_OPEN_BRACKET() do {\
688 GRN_UINT32_PUT(ctx, &loader->level, loader->values_size);\
689 values_add(ctx, loader);\
690 loader->last->header.domain = GRN_JSON_LOAD_OPEN_BRACKET;\
691 loader->stat = GRN_LOADER_TOKEN;\
692 str++;\
693} while (0)
694
695#define JSON_READ_OPEN_BRACE() do {\
696 GRN_UINT32_PUT(ctx, &loader->level, loader->values_size);\
697 values_add(ctx, loader);\
698 loader->last->header.domain = GRN_JSON_LOAD_OPEN_BRACE;\
699 loader->stat = GRN_LOADER_TOKEN;\
700 str++;\
701} while (0)
702
703static void
704json_read(grn_ctx *ctx, grn_loader *loader, const char *str, unsigned int str_len)
705{
706 const char *const beg = str;
707 char c;
708 int len;
709 const char *se = str + str_len;
710 while (str < se) {
711 c = *str;
712 switch (loader->stat) {
713 case GRN_LOADER_BEGIN :
714 if ((len = grn_isspace(str, ctx->encoding))) {
715 str += len;
716 continue;
717 }
718 switch (c) {
719 case '[' :
720 JSON_READ_OPEN_BRACKET();
721 break;
722 case '{' :
723 JSON_READ_OPEN_BRACE();
724 break;
725 default :
726 ERR(GRN_INVALID_ARGUMENT,
727 "JSON must start with '[' or '{': <%.*s>", str_len, beg);
728 loader->stat = GRN_LOADER_END;
729 break;
730 }
731 break;
732 case GRN_LOADER_TOKEN :
733 if ((len = grn_isspace(str, ctx->encoding))) {
734 str += len;
735 continue;
736 }
737 switch (c) {
738 case '"' :
739 loader->stat = GRN_LOADER_STRING;
740 values_add(ctx, loader);
741 str++;
742 break;
743 case '[' :
744 JSON_READ_OPEN_BRACKET();
745 break;
746 case '{' :
747 JSON_READ_OPEN_BRACE();
748 break;
749 case ':' :
750 str++;
751 break;
752 case ',' :
753 str++;
754 break;
755 case ']' :
756 bracket_close(ctx, loader);
757 loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
758 if (ctx->rc == GRN_CANCEL) {
759 loader->stat = GRN_LOADER_END;
760 }
761 str++;
762 break;
763 case '}' :
764 brace_close(ctx, loader);
765 loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
766 if (ctx->rc == GRN_CANCEL) {
767 loader->stat = GRN_LOADER_END;
768 }
769 str++;
770 break;
771 case '+' : case '-' : case '0' : case '1' : case '2' : case '3' :
772 case '4' : case '5' : case '6' : case '7' : case '8' : case '9' :
773 loader->stat = GRN_LOADER_NUMBER;
774 values_add(ctx, loader);
775 break;
776 default :
777 if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('_' == c)) {
778 loader->stat = GRN_LOADER_SYMBOL;
779 values_add(ctx, loader);
780 } else {
781 if ((len = grn_charlen(ctx, str, se))) {
782 GRN_LOG(ctx, GRN_LOG_ERROR, "ignored invalid char('%c') at", c);
783 GRN_LOG(ctx, GRN_LOG_ERROR, "%.*s", (int)(str - beg) + len, beg);
784 GRN_LOG(ctx, GRN_LOG_ERROR, "%*s", (int)(str - beg) + 1, "^");
785 str += len;
786 } else {
787 GRN_LOG(ctx, GRN_LOG_ERROR, "ignored invalid char(\\x%.2x) after", c);
788 GRN_LOG(ctx, GRN_LOG_ERROR, "%.*s", (int)(str - beg), beg);
789 str = se;
790 }
791 }
792 break;
793 }
794 break;
795 case GRN_LOADER_SYMBOL :
796 if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') ||
797 ('0' <= c && c <= '9') || ('_' == c)) {
798 GRN_TEXT_PUTC(ctx, loader->last, c);
799 str++;
800 } else {
801 char *v = GRN_TEXT_VALUE(loader->last);
802 switch (*v) {
803 case 'n' :
804 if (GRN_TEXT_LEN(loader->last) == 4 && !memcmp(v, "null", 4)) {
805 loader->last->header.domain = GRN_DB_VOID;
806 GRN_BULK_REWIND(loader->last);
807 }
808 break;
809 case 't' :
810 if (GRN_TEXT_LEN(loader->last) == 4 && !memcmp(v, "true", 4)) {
811 loader->last->header.domain = GRN_DB_BOOL;
812 GRN_BOOL_SET(ctx, loader->last, GRN_TRUE);
813 }
814 break;
815 case 'f' :
816 if (GRN_TEXT_LEN(loader->last) == 5 && !memcmp(v, "false", 5)) {
817 loader->last->header.domain = GRN_DB_BOOL;
818 GRN_BOOL_SET(ctx, loader->last, GRN_FALSE);
819 }
820 break;
821 default :
822 break;
823 }
824 loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
825 }
826 break;
827 case GRN_LOADER_NUMBER :
828 switch (c) {
829 case '+' : case '-' : case '.' : case 'e' : case 'E' :
830 case '0' : case '1' : case '2' : case '3' : case '4' :
831 case '5' : case '6' : case '7' : case '8' : case '9' :
832 GRN_TEXT_PUTC(ctx, loader->last, c);
833 str++;
834 break;
835 default :
836 {
837 const char *cur, *str = GRN_BULK_HEAD(loader->last);
838 const char *str_end = GRN_BULK_CURR(loader->last);
839 int64_t i = grn_atoll(str, str_end, &cur);
840 if (cur == str_end) {
841 loader->last->header.domain = GRN_DB_INT64;
842 GRN_INT64_SET(ctx, loader->last, i);
843 } else if (cur != str) {
844 uint64_t i = grn_atoull(str, str_end, &cur);
845 if (cur == str_end) {
846 loader->last->header.domain = GRN_DB_UINT64;
847 GRN_UINT64_SET(ctx, loader->last, i);
848 } else if (cur != str) {
849 double d;
850 char *end;
851 grn_obj buf;
852 GRN_TEXT_INIT(&buf, 0);
853 GRN_TEXT_PUT(ctx, &buf, str, GRN_BULK_VSIZE(loader->last));
854 GRN_TEXT_PUTC(ctx, &buf, '\0');
855 errno = 0;
856 d = strtod(GRN_TEXT_VALUE(&buf), &end);
857 if (!errno && end + 1 == GRN_BULK_CURR(&buf)) {
858 loader->last->header.domain = GRN_DB_FLOAT;
859 GRN_FLOAT_SET(ctx, loader->last, d);
860 }
861 GRN_OBJ_FIN(ctx, &buf);
862 }
863 }
864 }
865 loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
866 break;
867 }
868 break;
869 case GRN_LOADER_STRING :
870 switch (c) {
871 case '\\' :
872 loader->stat = GRN_LOADER_STRING_ESC;
873 str++;
874 break;
875 case '"' :
876 str++;
877 loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
878 /*
879 *(GRN_BULK_CURR(loader->last)) = '\0';
880 GRN_LOG(ctx, GRN_LOG_ALERT, "read str(%s)", GRN_TEXT_VALUE(loader->last));
881 */
882 break;
883 default :
884 if ((len = grn_charlen(ctx, str, se))) {
885 GRN_TEXT_PUT(ctx, loader->last, str, len);
886 str += len;
887 } else {
888 GRN_LOG(ctx, GRN_LOG_ERROR, "ignored invalid char(\\x%.2x) after", c);
889 GRN_LOG(ctx, GRN_LOG_ERROR, "%.*s", (int)(str - beg), beg);
890 str = se;
891 }
892 break;
893 }
894 break;
895 case GRN_LOADER_STRING_ESC :
896 switch (c) {
897 case 'b' :
898 GRN_TEXT_PUTC(ctx, loader->last, '\b');
899 loader->stat = GRN_LOADER_STRING;
900 break;
901 case 'f' :
902 GRN_TEXT_PUTC(ctx, loader->last, '\f');
903 loader->stat = GRN_LOADER_STRING;
904 break;
905 case 'n' :
906 GRN_TEXT_PUTC(ctx, loader->last, '\n');
907 loader->stat = GRN_LOADER_STRING;
908 break;
909 case 'r' :
910 GRN_TEXT_PUTC(ctx, loader->last, '\r');
911 loader->stat = GRN_LOADER_STRING;
912 break;
913 case 't' :
914 GRN_TEXT_PUTC(ctx, loader->last, '\t');
915 loader->stat = GRN_LOADER_STRING;
916 break;
917 case 'u' :
918 loader->stat = GRN_LOADER_UNICODE0;
919 break;
920 default :
921 GRN_TEXT_PUTC(ctx, loader->last, c);
922 loader->stat = GRN_LOADER_STRING;
923 break;
924 }
925 str++;
926 break;
927 case GRN_LOADER_UNICODE0 :
928 switch (c) {
929 case '0' : case '1' : case '2' : case '3' : case '4' :
930 case '5' : case '6' : case '7' : case '8' : case '9' :
931 loader->unichar = (c - '0') * 0x1000;
932 break;
933 case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' :
934 loader->unichar = (c - 'a' + 10) * 0x1000;
935 break;
936 case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' :
937 loader->unichar = (c - 'A' + 10) * 0x1000;
938 break;
939 default :
940 ;// todo : error
941 }
942 loader->stat = GRN_LOADER_UNICODE1;
943 str++;
944 break;
945 case GRN_LOADER_UNICODE1 :
946 switch (c) {
947 case '0' : case '1' : case '2' : case '3' : case '4' :
948 case '5' : case '6' : case '7' : case '8' : case '9' :
949 loader->unichar += (c - '0') * 0x100;
950 break;
951 case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' :
952 loader->unichar += (c - 'a' + 10) * 0x100;
953 break;
954 case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' :
955 loader->unichar += (c - 'A' + 10) * 0x100;
956 break;
957 default :
958 ;// todo : error
959 }
960 loader->stat = GRN_LOADER_UNICODE2;
961 str++;
962 break;
963 case GRN_LOADER_UNICODE2 :
964 switch (c) {
965 case '0' : case '1' : case '2' : case '3' : case '4' :
966 case '5' : case '6' : case '7' : case '8' : case '9' :
967 loader->unichar += (c - '0') * 0x10;
968 break;
969 case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' :
970 loader->unichar += (c - 'a' + 10) * 0x10;
971 break;
972 case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' :
973 loader->unichar += (c - 'A' + 10) * 0x10;
974 break;
975 default :
976 ;// todo : error
977 }
978 loader->stat = GRN_LOADER_UNICODE3;
979 str++;
980 break;
981 case GRN_LOADER_UNICODE3 :
982 switch (c) {
983 case '0' : case '1' : case '2' : case '3' : case '4' :
984 case '5' : case '6' : case '7' : case '8' : case '9' :
985 loader->unichar += (c - '0');
986 break;
987 case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' :
988 loader->unichar += (c - 'a' + 10);
989 break;
990 case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' :
991 loader->unichar += (c - 'A' + 10);
992 break;
993 default :
994 ;// todo : error
995 }
996 {
997 uint32_t u = loader->unichar;
998 if (u < 0x80) {
999 GRN_TEXT_PUTC(ctx, loader->last, u);
1000 } else {
1001 if (u < 0x800) {
1002 GRN_TEXT_PUTC(ctx, loader->last, ((u >> 6) & 0x1f) | 0xc0);
1003 } else {
1004 GRN_TEXT_PUTC(ctx, loader->last, (u >> 12) | 0xe0);
1005 GRN_TEXT_PUTC(ctx, loader->last, ((u >> 6) & 0x3f) | 0x80);
1006 }
1007 GRN_TEXT_PUTC(ctx, loader->last, (u & 0x3f) | 0x80);
1008 }
1009 }
1010 loader->stat = GRN_LOADER_STRING;
1011 str++;
1012 break;
1013 case GRN_LOADER_END :
1014 str = se;
1015 break;
1016 }
1017 }
1018}
1019
1020#undef JSON_READ_OPEN_BRACKET
1021#undef JSON_READ_OPEN_BRACE
1022
1023/*
1024 * grn_loader_parse_columns parses a columns parameter.
1025 * Columns except _id and _key are appended to loader->columns.
1026 * If it contains _id or _key, loader->id_offset or loader->key_offset is set.
1027 */
1028static grn_rc
1029grn_loader_parse_columns(grn_ctx *ctx, grn_loader *loader,
1030 const char *str, unsigned int str_size)
1031{
1032 const char *ptr = str, *ptr_end = ptr + str_size, *rest;
1033 const char *tokens[256], *token_end;
1034 while (ptr < ptr_end) {
1035 int i, n = grn_tokenize(ptr, ptr_end - ptr, tokens, 256, &rest);
1036 for (i = 0; i < n; i++) {
1037 grn_obj *column;
1038 token_end = tokens[i];
1039 while (ptr < token_end && (' ' == *ptr || ',' == *ptr)) {
1040 ptr++;
1041 }
1042 column = grn_obj_column(ctx, loader->table, ptr, token_end - ptr);
1043 if (!column) {
1044 ERR(GRN_INVALID_ARGUMENT, "nonexistent column: <%.*s>",
1045 (int)(token_end - ptr), ptr);
1046 return ctx->rc;
1047 }
1048 if (name_equal(ptr, token_end - ptr, GRN_COLUMN_NAME_ID)) {
1049 grn_obj_unlink(ctx, column);
1050 if (loader->id_offset != -1 || loader->key_offset != -1) {
1051 /* _id and _key must not appear more than once. */
1052 if (loader->id_offset != -1) {
1053 ERR(GRN_INVALID_ARGUMENT,
1054 "duplicated id and key columns: <%s> at %d and <%s> at %d",
1055 GRN_COLUMN_NAME_ID, i,
1056 GRN_COLUMN_NAME_ID, loader->id_offset);
1057 } else {
1058 ERR(GRN_INVALID_ARGUMENT,
1059 "duplicated id and key columns: <%s> at %d and <%s> at %d",
1060 GRN_COLUMN_NAME_ID, i,
1061 GRN_COLUMN_NAME_KEY, loader->key_offset);
1062 }
1063 return ctx->rc;
1064 }
1065 loader->id_offset = i;
1066 } else if (name_equal(ptr, token_end - ptr, GRN_COLUMN_NAME_KEY)) {
1067 grn_obj_unlink(ctx, column);
1068 if (loader->id_offset != -1 || loader->key_offset != -1) {
1069 /* _id and _key must not appear more than once. */
1070 if (loader->id_offset != -1) {
1071 ERR(GRN_INVALID_ARGUMENT,
1072 "duplicated id and key columns: <%s> at %d and <%s> at %d",
1073 GRN_COLUMN_NAME_KEY, i,
1074 GRN_COLUMN_NAME_ID, loader->id_offset);
1075 } else {
1076 ERR(GRN_INVALID_ARGUMENT,
1077 "duplicated id and key columns: <%s> at %d and <%s> at %d",
1078 GRN_COLUMN_NAME_KEY, i,
1079 GRN_COLUMN_NAME_KEY, loader->key_offset);
1080 }
1081 return ctx->rc;
1082 }
1083 loader->key_offset = i;
1084 } else {
1085 GRN_PTR_PUT(ctx, &loader->columns, column);
1086 }
1087 ptr = token_end;
1088 }
1089 ptr = rest;
1090 }
1091 switch (loader->table->header.type) {
1092 case GRN_TABLE_HASH_KEY :
1093 case GRN_TABLE_PAT_KEY :
1094 case GRN_TABLE_DAT_KEY :
1095 if (loader->id_offset == -1 && loader->key_offset == -1) {
1096 ERR(GRN_INVALID_ARGUMENT, "missing id or key column");
1097 return ctx->rc;
1098 }
1099 break;
1100 }
1101 return ctx->rc;
1102}
1103
1104static grn_com_addr *addr;
1105
1106void
1107grn_load_internal(grn_ctx *ctx, grn_load_input *input)
1108{
1109 grn_loader *loader = &ctx->impl->loader;
1110
1111 loader->emit_level = input->emit_level;
1112 if (ctx->impl->edge) {
1113 grn_edge *edge = grn_edges_add_communicator(ctx, addr);
1114 grn_obj *msg = grn_msg_open(ctx, edge->com, &ctx->impl->edge->send_old);
1115 /* build msg */
1116 grn_edge_dispatch(ctx, edge, msg);
1117 }
1118 if (input->table.length > 0) {
1119 grn_ctx_loader_clear(ctx);
1120 loader->input_type = input->type;
1121 if (grn_db_check_name(ctx, input->table.value, input->table.length)) {
1122 GRN_DB_CHECK_NAME_ERR("[table][load]",
1123 input->table.value,
1124 (int)(input->table.length));
1125 loader->stat = GRN_LOADER_END;
1126 return;
1127 }
1128 loader->table = grn_ctx_get(ctx, input->table.value, input->table.length);
1129 if (!loader->table) {
1130 ERR(GRN_INVALID_ARGUMENT,
1131 "nonexistent table: <%.*s>",
1132 (int)(input->table.length),
1133 input->table.value);
1134 loader->stat = GRN_LOADER_END;
1135 return;
1136 }
1137 if (input->columns.length > 0) {
1138 grn_rc rc = grn_loader_parse_columns(ctx,
1139 loader,
1140 input->columns.value,
1141 input->columns.length);
1142 if (rc != GRN_SUCCESS) {
1143 loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
1144 loader->stat = GRN_LOADER_END;
1145 return;
1146 }
1147 loader->columns_status = GRN_LOADER_COLUMNS_SET;
1148 }
1149 if (input->if_exists.length > 0) {
1150 grn_obj *v;
1151 GRN_EXPR_CREATE_FOR_QUERY(ctx, loader->table, loader->ifexists, v);
1152 if (loader->ifexists && v) {
1153 grn_expr_parse(ctx,
1154 loader->ifexists,
1155 input->if_exists.value,
1156 input->if_exists.length,
1157 NULL, GRN_OP_EQUAL, GRN_OP_AND,
1158 GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE);
1159 }
1160 }
1161 if (input->each.length > 0) {
1162 grn_obj *v;
1163 GRN_EXPR_CREATE_FOR_QUERY(ctx, loader->table, loader->each, v);
1164 if (loader->each && v) {
1165 grn_expr_parse(ctx, loader->each,
1166 input->each.value,
1167 input->each.length,
1168 NULL, GRN_OP_EQUAL, GRN_OP_AND,
1169 GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE);
1170 }
1171 }
1172 loader->output_ids = input->output_ids;
1173 loader->output_errors = input->output_errors;
1174 } else {
1175 if (!loader->table) {
1176 ERR(GRN_INVALID_ARGUMENT, "mandatory \"table\" parameter is absent");
1177 loader->stat = GRN_LOADER_END;
1178 return;
1179 }
1180 }
1181 switch (loader->input_type) {
1182 case GRN_CONTENT_JSON :
1183 json_read(ctx, loader, input->values.value, input->values.length);
1184 break;
1185 case GRN_CONTENT_NONE :
1186 case GRN_CONTENT_TSV :
1187 case GRN_CONTENT_XML :
1188 case GRN_CONTENT_MSGPACK :
1189 case GRN_CONTENT_GROONGA_COMMAND_LIST :
1190 ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "unsupported input_type");
1191 loader->stat = GRN_LOADER_END;
1192 // todo
1193 break;
1194 }
1195}
1196
1197grn_rc
1198grn_load(grn_ctx *ctx, grn_content_type input_type,
1199 const char *table, unsigned int table_len,
1200 const char *columns, unsigned int columns_len,
1201 const char *values, unsigned int values_len,
1202 const char *ifexists, unsigned int ifexists_len,
1203 const char *each, unsigned int each_len)
1204{
1205 if (!ctx || !ctx->impl) {
1206 ERR(GRN_INVALID_ARGUMENT, "db not initialized");
1207 return ctx->rc;
1208 }
1209 GRN_API_ENTER;
1210 {
1211 grn_load_input input;
1212 input.type = input_type;
1213 input.table.value = table;
1214 input.table.length = table_len;
1215 input.columns.value = columns;
1216 input.columns.length = columns_len;
1217 input.values.value = values;
1218 input.values.length = values_len;
1219 input.if_exists.value = ifexists;
1220 input.if_exists.length = ifexists_len;
1221 input.each.value = each;
1222 input.each.length = each_len;
1223 input.output_ids = GRN_FALSE;
1224 input.output_errors = GRN_FALSE;
1225 input.emit_level = 1;
1226 grn_load_internal(ctx, &input);
1227 }
1228 GRN_API_RETURN(ctx->rc);
1229}
1230