[Groonga-commit] groonga/groonga at f6b8adc [master] load: support _id in format 1 values

Back to archive index

Susumu Yata null+****@clear*****
Fri Mar 4 17:12:47 JST 2016


Susumu Yata	2016-03-04 17:12:47 +0900 (Fri, 04 Mar 2016)

  New Revision: f6b8adc3f3db3f1bbe8e7ffe27e49226413562e0
  https://github.com/groonga/groonga/commit/f6b8adc3f3db3f1bbe8e7ffe27e49226413562e0

  Message:
    load: support _id in format 1 values
    
    _id is ignored if it does not point to a valid record.
    
    GitHub: #496

  Modified files:
    lib/db.c

  Modified: lib/db.c (+131 -105)
===================================================================
--- lib/db.c    2016-03-04 15:42:53 +0900 (53aec71)
+++ lib/db.c    2016-03-04 17:12:47 +0900 (9c72905)
@@ -12674,15 +12674,48 @@ grn_loader_save_error(grn_ctx *ctx, grn_loader *loader)
   strcpy(loader->errbuf, ctx->errbuf);
 }
 
+static grn_id
+parse_id_value(grn_ctx *ctx, grn_obj *value)
+{
+  switch (value->header.type) {
+  case GRN_DB_UINT32 :
+    return GRN_UINT32_VALUE(value);
+  case GRN_DB_INT32 :
+    return GRN_INT32_VALUE(value);
+  default :
+    {
+      grn_id id = GRN_ID_NIL;
+      grn_obj casted_value;
+      GRN_UINT32_INIT(&casted_value, 0);
+      if (grn_obj_cast(ctx, value, &casted_value, GRN_FALSE) != GRN_SUCCESS) {
+        grn_obj inspected;
+        GRN_TEXT_INIT(&inspected, 0);
+        grn_inspect(ctx, &inspected, value);
+        ERR(GRN_INVALID_ARGUMENT,
+            "<%s>: failed to cast to <UInt32>: <%.*s>",
+            GRN_COLUMN_NAME_ID,
+            (int)GRN_TEXT_LEN(&inspected),
+            GRN_TEXT_VALUE(&inspected));
+        GRN_OBJ_FIN(ctx, &inspected);
+      } else {
+        id = GRN_UINT32_VALUE(&casted_value);
+      }
+      GRN_OBJ_FIN(ctx, &casted_value);
+      return id;
+    }
+  }
+}
+
 static void
 bracket_close(grn_ctx *ctx, grn_loader *loader)
 {
   grn_id id = GRN_ID_NIL;
-  grn_obj *value, *value_end, *key_value = NULL;
+  grn_obj *value, *value_end, *id_value = NULL, *key_value = NULL;
   grn_obj *col, **cols; /* Columns except _id and _key. */
   uint32_t i, begin;
   uint32_t ncols;   /* Number of columns except _id and _key. */
   uint32_t nvalues; /* Number of values in brackets. */
+  uint32_t expected_nvalues;
   uint32_t depth;
 
   cols = (grn_obj **)GRN_BULK_HEAD(&loader->columns);
@@ -12703,133 +12736,126 @@ bracket_close(grn_ctx *ctx, grn_loader *loader)
     goto exit;
   }
 
-  switch (loader->table->header.type) {
-  case GRN_TABLE_HASH_KEY :
-  case GRN_TABLE_PAT_KEY :
-  case GRN_TABLE_DAT_KEY :
-    if (loader->columns_status == GRN_LOADER_COLUMNS_SET) {
-      /* Target columns and _id or _key are already specified. */
-      if (nvalues == ncols + 1) {
-        /* The number of values is OK. */
-        key_value = value + loader->key_offset;
-        id = loader_add(ctx, key_value);
-      } else {
+  if (loader->columns_status == GRN_LOADER_COLUMNS_UNSET) {
+    /*
+     * Target columns and _id or _key are not specified yet and values are
+     * handled as column names and "_id" or "_key".
+     */
+    for (i = 0; i < nvalues; i++) {
+      if (value->header.domain != GRN_DB_TEXT) {
+        grn_obj buffer;
+        GRN_TEXT_INIT(&buffer, 0);
+        grn_inspect(ctx, &buffer, value);
         ERR(GRN_INVALID_ARGUMENT,
-            "unexpected #values: expected:%u, actual:%u",
-            ncols + 1, nvalues);
+            "column name must be string: <%.*s>",
+            (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
+        grn_loader_save_error(ctx, loader);
+        GRN_OBJ_FIN(ctx, &buffer);
+        loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
         goto exit;
       }
-    } else {
-      /*
-       * Target columns and _id or _key are not specified yet and values are
-       * handled as column names and "_id" or "_key".
-       */
-      grn_obj *key_column_name = NULL;
-      for (i = 0; i < nvalues; i++) {
-        char *column_name = GRN_TEXT_VALUE(value);
-        unsigned int column_name_size = GRN_TEXT_LEN(value);
-        if (value->header.domain == GRN_DB_TEXT &&
-            (name_equal(column_name, column_name_size, GRN_COLUMN_NAME_KEY) ||
-             name_equal(column_name, column_name_size, GRN_COLUMN_NAME_ID))) {
-          /* _id or _key must appear just once. */
-          if (loader->key_offset != -1) {
-            ERR(GRN_INVALID_ARGUMENT,
-                "duplicated key columns: <%.*s> at %d and <%.*s> at %d",
-                (int)GRN_TEXT_LEN(key_column_name),
-                GRN_TEXT_VALUE(key_column_name),
-                loader->key_offset,
-                column_name_size, column_name, i);
-            grn_loader_save_error(ctx, loader);
-            loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
-            goto exit;
-          }
-          key_column_name = value;
-          loader->key_offset = i;
-        } else {
-          col = grn_obj_column(ctx, loader->table,
-                               column_name, column_name_size);
-          if (!col) {
-            ERR(GRN_INVALID_ARGUMENT,
-                "nonexistent column: <%.*s>",
-                column_name_size, column_name);
-            grn_loader_save_error(ctx, loader);
-            loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
-            goto exit;
-          }
-          GRN_PTR_PUT(ctx, &loader->columns, col);
-        }
-        value++;
-      }
-      if (loader->key_offset == -1) {
-        ERR(GRN_INVALID_ARGUMENT, "missing id or key column");
+      const char *col_name = GRN_TEXT_VALUE(value);
+      unsigned int col_name_size = GRN_TEXT_LEN(value);
+      col = grn_obj_column(ctx, loader->table, col_name, col_name_size);
+      if (!col) {
+        ERR(GRN_INVALID_ARGUMENT, "nonexistent column: <%.*s>",
+            col_name_size, col_name);
         grn_loader_save_error(ctx, loader);
         loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
         goto exit;
       }
-      nvalues = 0;
-      loader->columns_status = GRN_LOADER_COLUMNS_SET;
-    }
-    break;
-  case GRN_TABLE_NO_KEY :
-    if (loader->columns_status == GRN_LOADER_COLUMNS_SET) {
-      /* Target columns are already specified. */
-/*    if (nvalues == 0 || nvalues == ncols) {*/
-      if (nvalues == ncols) {
-        id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
-      }
-    } else {
-      /*
-       * Target columns are not specified yet and values are handled as column
-       * names.
-       */
-      for (i = 0; i < nvalues; i++) {
-        if (value->header.domain == GRN_DB_TEXT) {
-          char *column_name = GRN_TEXT_VALUE(value);
-          unsigned int column_name_size = GRN_TEXT_LEN(value);
-          col = grn_obj_column(ctx, loader->table,
-                               column_name, column_name_size);
-          if (!col) {
+      if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_ID)) {
+        grn_obj_unlink(ctx, col);
+        if (loader->id_offset != -1 || loader->key_offset != -1) {
+          /* _id and _key must not appear more than once. */
+          if (loader->id_offset != -1) {
             ERR(GRN_INVALID_ARGUMENT,
-                "nonexistent column: <%.*s>",
-                column_name_size, column_name);
-            grn_loader_save_error(ctx, loader);
-            loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
-            goto exit;
+                "duplicated id and key columns: <%s> at %d and <%s> at %d",
+                GRN_COLUMN_NAME_ID, i,
+                GRN_COLUMN_NAME_ID, loader->id_offset);
+          } else {
+            ERR(GRN_INVALID_ARGUMENT,
+                "duplicated id and key columns: <%s> at %d and <%s> at %d",
+                GRN_COLUMN_NAME_ID, i,
+                GRN_COLUMN_NAME_KEY, loader->key_offset);
           }
-          GRN_PTR_PUT(ctx, &loader->columns, col);
-          value++;
-        } else {
-          grn_obj buffer;
-          GRN_TEXT_INIT(&buffer, 0);
-          grn_inspect(ctx, &buffer, value);
-          ERR(GRN_INVALID_ARGUMENT,
-              "column name must be string: <%.*s>",
-              (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
           grn_loader_save_error(ctx, loader);
-          GRN_OBJ_FIN(ctx, &buffer);
           loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
           goto exit;
         }
+        loader->id_offset = i;
+      } else if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_KEY)) {
+        grn_obj_unlink(ctx, col);
+        if (loader->id_offset != -1 || loader->key_offset != -1) {
+          /* _id and _key must not appear more than once. */
+          if (loader->id_offset != -1) {
+            ERR(GRN_INVALID_ARGUMENT,
+                "duplicated id and key columns: <%s> at %d and <%s> at %d",
+                GRN_COLUMN_NAME_KEY, i,
+                GRN_COLUMN_NAME_ID, loader->id_offset);
+          } else {
+            ERR(GRN_INVALID_ARGUMENT,
+                "duplicated id and key columns: <%s> at %d and <%s> at %d",
+                GRN_COLUMN_NAME_KEY, i,
+                GRN_COLUMN_NAME_KEY, loader->key_offset);
+          }
+          grn_loader_save_error(ctx, loader);
+          loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
+          goto exit;
+        }
+        loader->key_offset = i;
+      } else {
+        GRN_PTR_PUT(ctx, &loader->columns, col);
       }
-      nvalues = 0;
-      loader->columns_status = GRN_LOADER_COLUMNS_SET;
+      value++;
     }
-    break;
-  default :
-    break;
+    switch (loader->table->header.type) {
+    case GRN_TABLE_HASH_KEY :
+    case GRN_TABLE_PAT_KEY :
+    case GRN_TABLE_DAT_KEY :
+      if (loader->id_offset == -1 && loader->key_offset == -1) {
+        ERR(GRN_INVALID_ARGUMENT, "missing id or key column");
+        grn_loader_save_error(ctx, loader);
+        loader->columns_status = GRN_LOADER_COLUMNS_BROKEN;
+        goto exit;
+      }
+      break;
+    }
+    loader->columns_status = GRN_LOADER_COLUMNS_SET;
+    goto exit;
   }
 
+  /* Target columns and _id or _key are already specified. */
+  expected_nvalues = ncols;
+  if (loader->id_offset != -1 || loader->key_offset != -1) {
+    expected_nvalues++;
+  }
+  if (nvalues != expected_nvalues) {
+    ERR(GRN_INVALID_ARGUMENT,
+        "unexpected #values: expected:%u, actual:%u",
+        expected_nvalues, nvalues);
+    goto exit;
+  }
+  if (loader->id_offset != -1) {
+    id_value = value + loader->id_offset;
+    id = parse_id_value(ctx, id_value);
+    if (grn_table_at(ctx, loader->table, id) == GRN_ID_NIL) {
+      id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
+    }
+  } else if (loader->key_offset != -1) {
+    key_value = value + loader->key_offset;
+    id = loader_add(ctx, key_value);
+  } else {
+    id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
+  }
   if (id == GRN_ID_NIL) {
     /* Target record is not available. */
     goto exit;
   }
 
   for (i = 0; i < nvalues; i++, value = values_next(ctx, value)) {
-    if ((loader->table->header.type == GRN_TABLE_HASH_KEY ||
-         loader->table->header.type == GRN_TABLE_PAT_KEY ||
-         loader->table->header.type == GRN_TABLE_DAT_KEY) &&
-        i == loader->key_offset) {
-       /* Skip this value, because it's already used as key value. */
+    if (i == loader->id_offset || i == loader->key_offset) {
+       /* Skip _id and _key, because it's already used to get id. */
        continue;
     }
     col = *cols;
-------------- next part --------------
HTML����������������������������...
下载 



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