Kentaro Hayashi 2019-04-26 14:43:53 +0900 (Fri, 26 Apr 2019) Revision: 40ba93a1da665ee64294e75f3b2e68faac0d9dd9 https://github.com/groonga/groonga/commit/40ba93a1da665ee64294e75f3b2e68faac0d9dd9 Message: table: add missing check for unexpected error case (#899) * grn_table_add: check error when it returns GRN_ID_NIL * grn_pat_add: error check when it returns GRN_ID_NIL * grn_dat_add: error check when it returns GRN_ID_NIL * grn_hash_add: check error when it returns GRN_ID_NIL * test: follow additional error message * grn_table: don't inspect null table * grn_table: check type of table key in advance * grn_util: extract inspect code * grn_table: use extracted utility function * grn_table: fix error message label * grn_hash: use more suitable label in error message * test: follow changed error message * grn_pat: unify to [pat][add] in error message * grn_util: remove redundant _with_table suffix * grn_util: follow style to other grn_inspect * test: follow fixed grn_inspect_key output * grn_util: remove needless temporary buffer * grn_util: remove needless ":" * test: follow changed inspect output Modified files: lib/dat.cpp lib/db.c lib/grn_util.h lib/hash.c lib/pat.c lib/util.c test/command/suite/load/command_version/3/output_ids/array.expected Modified: lib/dat.cpp (+20 -0) =================================================================== --- lib/dat.cpp 2019-04-26 13:17:55 +0900 (fc58dbdfc) +++ lib/dat.cpp 2019-04-26 14:43:53 +0900 (b6aebe23f) @@ -63,6 +63,21 @@ class CriticalSection { CriticalSection &operator=(const CriticalSection &); }; +grn_inline static int +grn_dat_name(grn_ctx *ctx, grn_dat *dat, char *buffer, int buffer_size) +{ + int name_size; + + if (DB_OBJ(dat)->id == GRN_ID_NIL) { + grn_strcpy(buffer, buffer_size, "(anonymous)"); + name_size = strlen(buffer); + } else { + name_size = grn_obj_name(ctx, (grn_obj *)dat, buffer, buffer_size); + } + + return name_size; +} + /* grn_dat_remove_file() removes a file specified by `path' and then returns true on success, false on failure. Note that grn_dat_remove_file() does not @@ -498,6 +513,11 @@ grn_dat_add(grn_ctx *ctx, grn_dat *dat, const void *key, unsigned int key_size, void **, int *added) { if (!key_size) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_dat_name(ctx, dat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[dat] key size must not zero: <%.*s>", + name_size, name); return GRN_ID_NIL; } else if (!grn_dat_open_trie_if_needed(ctx, dat)) { return GRN_ID_NIL; Modified: lib/db.c (+47 -0) =================================================================== --- lib/db.c 2019-04-26 13:17:55 +0900 (cf5fca61a) +++ lib/db.c 2019-04-26 14:43:53 +0900 (516383756) @@ -74,6 +74,14 @@ static const uint32_t GRN_TABLE_PAT_KEY_CACHE_SIZE = 1 << 15; grn_string_get_normalized(ctx, nstr, &key, &key_size, NULL);\ block\ grn_obj_close(ctx, nstr);\ + } else {\ + char name[GRN_TABLE_MAX_KEY_SIZE];\ + int name_size;\ + name_size = grn_obj_name(ctx, (grn_obj *)(table), name, GRN_TABLE_MAX_KEY_SIZE);\ + ERR(GRN_INVALID_ARGUMENT,\ + "[key][normalize] failed to normalize: <%.*s>: <%.*s>",\ + name_size, name,\ + (int)key_size, (const char *)key);\ }\ } else {\ block\ @@ -1614,6 +1622,15 @@ grn_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_si } GRN_TABLE_LOCK_END(ctx, table); }); if (added) { *added = added_; } + if (id == GRN_ID_NIL) { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_inspect_key(ctx, &buffer, table, key, key_size); + ERR(GRN_INVALID_ARGUMENT, + "[table][add][pat] failed to add: %.*s", + (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + } } break; case GRN_TABLE_DAT_KEY : @@ -1625,6 +1642,15 @@ grn_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_si } GRN_TABLE_LOCK_END(ctx, table); }); if (added) { *added = added_; } + if (id == GRN_ID_NIL) { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_inspect_key(ctx, &buffer, table, key, key_size); + ERR(GRN_INVALID_ARGUMENT, + "[table][add][dat] failed to add: %.*s", + (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + } } break; case GRN_TABLE_HASH_KEY : @@ -1636,6 +1662,15 @@ grn_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_si } GRN_TABLE_LOCK_END(ctx, table); }); if (added) { *added = added_; } + if (id == GRN_ID_NIL) { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_inspect_key(ctx, &buffer, table, key, key_size); + ERR(GRN_INVALID_ARGUMENT, + "[table][add][hash] failed to add: %.*s", + (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + } } break; case GRN_TABLE_NO_KEY : @@ -1646,6 +1681,15 @@ grn_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_si } GRN_TABLE_LOCK_END(ctx, table); added_ = id ? 1 : 0; if (added) { *added = added_; } + if (id == GRN_ID_NIL) { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_inspect_key(ctx, &buffer, table, key, key_size); + ERR(GRN_INVALID_ARGUMENT, + "[table][add] failed to add: %.*s", + (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + } } break; } @@ -1685,6 +1729,9 @@ grn_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_si GRN_OBJ_FIN(ctx, &value_); } } + } else { + ERR(GRN_INVALID_ARGUMENT, + "[table][add] failed to add: table must not NULL"); } GRN_API_RETURN(id); } Modified: lib/grn_util.h (+4 -0) =================================================================== --- lib/grn_util.h 2019-04-26 13:17:55 +0900 (cf5e21b19) +++ lib/grn_util.h 2019-04-26 14:43:53 +0900 (3265bff61) @@ -50,6 +50,10 @@ int grn_tokenize(const char *str, size_t str_len, const char **tokbuf, int buf_size, const char **rest); +grn_obj * +grn_inspect_key(grn_ctx *ctx, grn_obj *buffer, + grn_obj *table, const void *key, unsigned int key_size); + #ifdef __cplusplus } #endif Modified: lib/hash.c (+95 -9) =================================================================== --- lib/hash.c 2019-04-26 13:17:55 +0900 (fc6412594) +++ lib/hash.c 2019-04-26 14:43:53 +0900 (91df6ace9) @@ -2236,6 +2236,11 @@ grn_io_hash_add(grn_ctx *ctx, grn_hash *hash, uint32_t hash_value, if (entry_id) { entry = grn_io_hash_entry_at(ctx, hash, entry_id, GRN_TABLE_ADD); if (!entry) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][io][add] failed to reuse entry: <%.*s>: <%u>", + name_size, name, entry_id); return GRN_ID_NIL; } garbages[key_size - 1] = *(grn_id *)entry; @@ -2253,18 +2258,49 @@ grn_io_hash_add(grn_ctx *ctx, grn_hash *hash, uint32_t hash_value, entry_id = header->curr_rec + 1; entry = grn_hash_entry_at(ctx, hash, entry_id, GRN_TABLE_ADD); if (!entry) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][io][add] failed to add entry: <%.*s>: <%u>", + name_size, name, entry_id); return GRN_ID_NIL; } header->curr_rec = entry_id; } if (!grn_io_array_bit_on(ctx, hash->io, GRN_HASH_BITMAP_SEGMENT, entry_id)) { - /* TODO: error handling. */ + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][io][add] failed to set a bit for the entry: <%.*s>: <%u>", + name_size, name, entry_id); + return GRN_ID_NIL; } - if (grn_hash_entry_put_key(ctx, hash, entry, hash_value, key, key_size)) { - grn_hash_delete_by_id(ctx, hash, entry_id, NULL); - return GRN_ID_NIL; + { + grn_rc rc; + rc = grn_hash_entry_put_key(ctx, hash, entry, hash_value, key, key_size); + if (rc != GRN_SUCCESS) { + grn_obj buffer, key_buffer; + GRN_TEXT_INIT(&buffer, 0); + GRN_OBJ_INIT(&key_buffer, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, ((grn_obj *)hash)->header.domain); + GRN_TEXT_SET(ctx, &key_buffer, key, key_size); + grn_inspect(ctx, &buffer, &key_buffer); + GRN_OBJ_FIN(ctx, &key_buffer); + + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(rc, "[hash][io][add] failed to put key: <%.*s>: <%.*s>", + name_size, name, (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + rc = grn_hash_delete_by_id(ctx, hash, entry_id, NULL); + if (rc != GRN_SUCCESS) { + ERR(rc, "[hash][io][add] failed to delete by id: <%.*s>: <%u>", + name_size, name, entry_id); + } + return GRN_ID_NIL; + } } if (value) { @@ -2314,18 +2350,39 @@ grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key, if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { return GRN_ID_NIL; } - if (!key || !key_size) { + if (!key) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][add] key must not NULL: <%.*s>", + name_size, name); + return GRN_ID_NIL; + } + if (!key_size) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][add] key size must not zero: <%.*s>", + name_size, name); return GRN_ID_NIL; } if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { if (key_size > hash->key_size) { - ERR(GRN_INVALID_ARGUMENT, "too long key"); + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][add] too long key: <%.*s>", + name_size, name); return GRN_ID_NIL; } hash_value = grn_hash_calculate_hash_value(key, key_size); } else { if (key_size != hash->key_size) { - ERR(GRN_INVALID_ARGUMENT, "key size unmatch"); + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][add] key size unmatch: <%.*s>", + name_size, name); return GRN_ID_NIL; } if (key_size == sizeof(uint32_t)) { @@ -2344,15 +2401,34 @@ grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key, /* lock */ if ((*hash->n_entries + *hash->n_garbages) * 2 > *hash->max_offset) { if (*hash->max_offset > (1 << 29)) { - ERR(GRN_TOO_LARGE_OFFSET, "hash table size limit"); + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_TOO_LARGE_OFFSET, "[hash][add] hash table size limit: <%.*s>", + name_size, name); return GRN_ID_NIL; } - grn_hash_reset(ctx, hash, 0); + { + grn_rc rc; + rc = grn_hash_reset(ctx, hash, 0); + if (rc != GRN_SUCCESS) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(rc, "[hash][add] failed to reset hash: <%.*s>", name_size, name); + return GRN_ID_NIL; + } + } } for (i = hash_value; ; i += step) { index = grn_hash_idx_at(ctx, hash, i); if (!index) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][add] failed to detect index: <%.*s>: <%u>", + name_size, name, i); return GRN_ID_NIL; } id = *index; @@ -2368,6 +2444,11 @@ grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key, entry = grn_hash_entry_at(ctx, hash, id, GRN_TABLE_ADD); if (!entry) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][add] failed to find an entry: <%.*s>: <%u>", + name_size, name, id); return GRN_ID_NIL; } if (grn_hash_entry_compare_key(ctx, hash, entry, hash_value, @@ -2388,6 +2469,11 @@ grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key, id = grn_tiny_hash_add(ctx, hash, hash_value, key, key_size, value); } if (!id) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[hash][add] failed to add: <%.*s>: <%.*s>", + name_size, name, (int)key_size, (const char *)key); return GRN_ID_NIL; } if (garbage_index) { Modified: lib/pat.c (+76 -8) =================================================================== --- lib/pat.c 2019-04-26 13:17:55 +0900 (d756ac0f9) +++ lib/pat.c 2019-04-26 14:43:53 +0900 (428c224b3) @@ -804,7 +804,14 @@ _grn_pat_add(grn_ctx *ctx, grn_pat *pat, const uint8_t *key, uint32_t size, uint const uint8_t *s, *d; for (;;) { if (!(r0 = *p0)) { - if (!(s = pat_node_get_key(ctx, pat, rn0))) { return GRN_ID_NIL; } + if (!(s = pat_node_get_key(ctx, pat, rn0))) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[pat][add] failed to get key from node: <%.*s>", + name_size, name); + return GRN_ID_NIL; + } size2 = PAT_LEN(rn0); break; } @@ -819,7 +826,15 @@ _grn_pat_add(grn_ctx *ctx, grn_pat *pat, const uint8_t *key, uint32_t size, uint p0 = &rn0->lr[nth_bit(key, c0, len)]; } } else { - if (!(s = pat_node_get_key(ctx, pat, rn0))) { return GRN_ID_NIL; } + if (!(s = pat_node_get_key(ctx, pat, rn0))) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[pat][add] failed to get key from node " + "c0 < rn0->check < len: <%.*s>: <%d> <%d> <%d>", + name_size, name, c0, rn0->check, len); + return GRN_ID_NIL; + } size2 = PAT_LEN(rn0); if (size == size2 && !memcmp(s, key, size)) { if (pat->cache) { pat->cache[cache_id] = r0; } @@ -848,7 +863,13 @@ _grn_pat_add(grn_ctx *ctx, grn_pat *pat, const uint8_t *key, uint32_t size, uint p0 = &rn0->lr[1]; while ((r0 = *p0)) { PAT_AT(pat, r0, rn0); - if (!rn0) { return GRN_ID_NIL; } + if (!rn0) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[pat][add] failed to detect by node: <%.*s>", name_size, name); + return GRN_ID_NIL; + } c0 = PAT_CHK(rn0); if (c < c0) { break; } if (c0 & 1) { @@ -890,7 +911,14 @@ _grn_pat_add(grn_ctx *ctx, grn_pat *pat, const uint8_t *key, uint32_t size, uint r = pat->header->garbages[size2]; PAT_AT(pat, r, rn); if (!rn) { return GRN_ID_NIL; } - if (!(keybuf = pat_node_get_key(ctx, pat, rn))) { return GRN_ID_NIL; } + if (!(keybuf = pat_node_get_key(ctx, pat, rn))) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[pat][add] failed to get key from node. header garbages[%u]: <%.*s>", + size2, name_size, name); + return GRN_ID_NIL; + } pat->header->n_entries++; pat->header->n_garbages--; pat->header->garbages[size2] = rn->lr[0]; @@ -900,7 +928,21 @@ _grn_pat_add(grn_ctx *ctx, grn_pat *pat, const uint8_t *key, uint32_t size, uint r = pat->header->curr_rec + 1; rn = pat_get(ctx, pat, r); if (!rn) { return GRN_ID_NIL; } - if (pat_node_set_key(ctx, pat, rn, key, size)) { return GRN_ID_NIL; } + if (pat_node_set_key(ctx, pat, rn, key, size)) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + grn_obj buffer, key_buffer; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + GRN_TEXT_INIT(&buffer, 0); + GRN_OBJ_INIT(&key_buffer, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, ((grn_obj *)pat)->header.domain); + GRN_TEXT_SET(ctx, &key_buffer, key, size); + grn_inspect(ctx, &buffer, &key_buffer); + GRN_OBJ_FIN(ctx, &key_buffer); + ERR(GRN_INVALID_ARGUMENT, "[pat][add] failed to set key to pat node: <%.*s>: <%.*s>", + name_size, name, (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + return GRN_ID_NIL; + } pat->header->curr_rec = r; pat->header->n_entries++; } @@ -1007,14 +1049,40 @@ grn_pat_add(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size, if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { return GRN_ID_NIL; } - if (!key || !key_size) { return GRN_ID_NIL; } + if (!key) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[pat][add] key must not NULL: <%.*s>", + name_size, name); + return GRN_ID_NIL; + } + if (!key_size) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[pat][add] key size must not zero: <%.*s>", + name_size, name); + return GRN_ID_NIL; + } if (key_size > GRN_TABLE_MAX_KEY_SIZE) { - ERR(GRN_INVALID_ARGUMENT, "too long key: (%u)", key_size); + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[pat][add] too long key: <%.*s>: <%u>", + name_size, name, key_size); return GRN_ID_NIL; } KEY_ENCODE(pat, keybuf, key, key_size); r0 = _grn_pat_add(ctx, pat, (uint8_t *)key, key_size, &new, &lkey); - if (r0 == GRN_ID_NIL) { return GRN_ID_NIL; } + if (r0 == GRN_ID_NIL) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, "[pat][add] failed to add a key: <%.*s>: <%u>: <%u>", + name_size, name, new, lkey); + return GRN_ID_NIL; + } if (added) { *added = new; } if (r0 && (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) && (*((uint8_t *)key) & 0x80)) { // todo: refine!! Modified: lib/util.c (+41 -0) =================================================================== --- lib/util.c 2019-04-26 13:17:55 +0900 (4ee0dd1bd) +++ lib/util.c 2019-04-26 14:43:53 +0900 (855284c4d) @@ -1460,6 +1460,47 @@ grn_inspect_limited(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj) return buffer; } +grn_obj * +grn_inspect_key(grn_ctx *ctx, grn_obj *buffer, grn_obj *table, const void *key, unsigned int key_size) +{ + if (!buffer) { + buffer = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT); + } + + if (!table) { + GRN_TEXT_PUTS(ctx, buffer, "(NULL)"); + return buffer; + } + + if (table->header.type == GRN_TABLE_NO_KEY) { + GRN_TEXT_PUTS(ctx, buffer, "#<key (nil) table:#<"); + grn_table_type_inspect(ctx, buffer, table); + GRN_TEXT_PUTS(ctx, buffer, " "); + grn_inspect_name(ctx, buffer, table); + GRN_TEXT_PUTS(ctx, buffer, ">>"); + return buffer; + } + if (key && key_size > 0) { + grn_obj key_buffer; + GRN_TEXT_INIT(&key_buffer, 0); + GRN_OBJ_INIT(&key_buffer, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, table->header.domain); + GRN_TEXT_SET(ctx, &key_buffer, key, key_size); + GRN_TEXT_PUTS(ctx, buffer, "#<key "); + grn_inspect(ctx, buffer, &key_buffer); + GRN_OBJ_FIN(ctx, &key_buffer); + } else { + GRN_TEXT_PUTS(ctx, buffer, "#<key (nil)"); + } + GRN_TEXT_PUTS(ctx, buffer, " table:#<"); + grn_table_type_inspect(ctx, buffer, table); + GRN_TEXT_PUTS(ctx, buffer, " "); + grn_inspect_name(ctx, buffer, table); + GRN_TEXT_PUTS(ctx, buffer, " "); + grn_table_key_inspect(ctx, buffer, table); + GRN_TEXT_PUTS(ctx, buffer, ">>"); + return buffer; +} + void grn_p(grn_ctx *ctx, grn_obj *obj) { Modified: test/command/suite/load/command_version/3/output_ids/array.expected (+2 -0) =================================================================== --- test/command/suite/load/command_version/3/output_ids/array.expected 2019-04-26 13:17:55 +0900 (3f1d8b73c) +++ test/command/suite/load/command_version/3/output_ids/array.expected 2019-04-26 14:43:53 +0900 (228d1ae1f) @@ -22,3 +22,5 @@ load --table Users --command_version 3 --output_ids yes ] } } +#|e| [hash][add] key must not NULL: <Users> +#|e| [table][add][hash] failed to add: #<key (nil) table:#<hash Users key:ShortText>> -------------- next part -------------- An HTML attachment was scrubbed... URL: <https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20190426/7df68078/attachment-0001.html>