[Groonga-commit] groonga/groonga at 40ba93a [master] table: add missing check for unexpected error case (#899)

Back to archive index
Kentaro Hayashi null+****@clear*****
Fri Apr 26 14:43:53 JST 2019


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>


More information about the Groonga-commit mailing list
Back to archive index