[Groonga-commit] groonga/groonga at 770f128 [master] Support columns for temporary table

Back to archive index

Kouhei Sutou null+****@clear*****
Wed Sep 16 00:06:43 JST 2015


Kouhei Sutou	2015-09-16 00:06:43 +0900 (Wed, 16 Sep 2015)

  New Revision: 770f1285fe391d3afbf8aff5c55fd4ac38568dc9
  https://github.com/groonga/groonga/commit/770f1285fe391d3afbf8aff5c55fd4ac38568dc9

  Merged b962058: Merge pull request #401 from groonga/support-column-for-temporary-table

  Message:
    Support columns for temporary table
    
    Use cases:
    
      * Named output columns in select like "AS" in SQL
        * Creating a column to temporary table and assigning return value
          of function to the column:
    
              select --filter all_records() \
                     --column[snippet].type ShortText \
                     --column[snippet].value 'snippet_html(body)' \
                     --output_columns _id,snippet
    
      * Drilldown by computed value
        * Select -> Create temporary column -> Compute value -> Drilldown:
    
              select --filter all_records() \
                     --column[year].type UInt8 \
                     --column[year].value 'time_to_year(updated_at)' \
                     --drilldown year

  Modified files:
    lib/ctx.c
    lib/db.c
    lib/grn_ctx_impl.h
    lib/grn_db.h
    test/unit/core/test-column.c

  Modified: lib/ctx.c (+20 -0)
===================================================================
--- lib/ctx.c    2015-09-15 18:37:28 +0900 (4f34f4f)
+++ lib/ctx.c    2015-09-16 00:06:43 +0900 (82c7986)
@@ -539,10 +539,21 @@ grn_ctx_impl_init(grn_ctx *ctx)
     ctx->impl = NULL;
     return ctx->rc;
   }
+  if (!(ctx->impl->temporary_columns = grn_pat_create(ctx, NULL,
+                                                      GRN_TABLE_MAX_KEY_SIZE,
+                                                      sizeof(grn_obj *),
+                                                      0))) {
+    grn_array_close(ctx, ctx->impl->values);
+    CRITICAL_SECTION_FIN(ctx->impl->lock);
+    grn_io_anon_unmap(ctx, &mi, IMPL_SIZE);
+    ctx->impl = NULL;
+    return ctx->rc;
+  }
   if (!(ctx->impl->ios = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE,
                                          sizeof(grn_io *),
                                          GRN_OBJ_KEY_VAR_SIZE|GRN_HASH_TINY))) {
     grn_array_close(ctx, ctx->impl->values);
+    grn_pat_close(ctx, ctx->impl->temporary_columns);
     CRITICAL_SECTION_FIN(ctx->impl->lock);
     grn_io_anon_unmap(ctx, &mi, IMPL_SIZE);
     ctx->impl = NULL;
@@ -735,6 +746,15 @@ grn_ctx_fin(grn_ctx *ctx)
 #endif
       grn_array_close(ctx, ctx->impl->values);
     }
+    if (ctx->impl->temporary_columns) {
+#ifndef USE_MEMORY_DEBUG
+      grn_obj *value;
+      GRN_PAT_EACH(ctx, ctx->impl->temporary_columns, id, NULL, NULL, &value, {
+        grn_obj_close(ctx, *((grn_obj **)value));
+      });
+#endif
+      grn_pat_close(ctx, ctx->impl->temporary_columns);
+    }
     if (ctx->impl->ios) {
       grn_hash_close(ctx, ctx->impl->ios);
     }

  Modified: lib/db.c (+203 -71)
===================================================================
--- lib/db.c    2015-09-15 18:37:28 +0900 (73b6b63)
+++ lib/db.c    2015-09-16 00:06:43 +0900 (c3c9ee0)
@@ -4112,20 +4112,34 @@ static grn_obj *grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj,
 static grn_obj *
 grn_obj_column_(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size)
 {
+  grn_id table_id = DB_OBJ(table)->id;
   grn_obj *column = NULL;
-  char buf[GRN_TABLE_MAX_KEY_SIZE];
-  int len = grn_obj_name(ctx, table, buf, GRN_TABLE_MAX_KEY_SIZE);
-  if (len) {
-    buf[len++] = GRN_DB_DELIMITER;
-    if (len + name_size <= GRN_TABLE_MAX_KEY_SIZE) {
-      grn_memcpy(buf + len, name, name_size);
-      column = grn_ctx_get(ctx, buf, len + name_size);
-    } else {
-      ERR(GRN_INVALID_ARGUMENT, "name is too long");
+
+  if (table_id & GRN_OBJ_TMP_OBJECT) {
+    char column_name[GRN_TABLE_MAX_KEY_SIZE];
+    void *value = NULL;
+    grn_snprintf(column_name, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE,
+                 "%u%c%.*s", table_id, GRN_DB_DELIMITER, name_size, name);
+    grn_pat_get(ctx, ctx->impl->temporary_columns,
+                column_name, strlen(column_name),
+                &value);
+    if (value) {
+      column = *((grn_obj **)value);
     }
   } else {
-    /* todo : support temporary table */
+    char buf[GRN_TABLE_MAX_KEY_SIZE];
+    int len = grn_obj_name(ctx, table, buf, GRN_TABLE_MAX_KEY_SIZE);
+    if (len) {
+      buf[len++] = GRN_DB_DELIMITER;
+      if (len + name_size <= GRN_TABLE_MAX_KEY_SIZE) {
+        grn_memcpy(buf + len, name, name_size);
+        column = grn_ctx_get(ctx, buf, len + name_size);
+      } else {
+        ERR(GRN_INVALID_ARGUMENT, "name is too long");
+      }
+    }
   }
+
   return column;
 }
 
@@ -4150,14 +4164,41 @@ grn_table_columns(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int n
                   grn_obj *res)
 {
   int n = 0;
+  grn_id id;
+
   GRN_API_ENTER;
-  if (GRN_OBJ_TABLEP(table) && DB_OBJ(table)->id &&
-      !(DB_OBJ(table)->id & GRN_OBJ_TMP_OBJECT)) {
+
+  if (!GRN_OBJ_TABLEP(table)) {
+    GRN_API_RETURN(n);
+  }
+
+  id = DB_OBJ(table)->id;
+  if (id & GRN_OBJ_TMP_OBJECT) {
+    char search_key[GRN_TABLE_MAX_KEY_SIZE];
+    grn_pat_cursor *cursor;
+    grn_snprintf(search_key, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE,
+                 "%u%c%.*s", id, GRN_DB_DELIMITER, name_size, name);
+    cursor = grn_pat_cursor_open(ctx, ctx->impl->temporary_columns,
+                                 search_key, strlen(search_key),
+                                 NULL, 0,
+                                 0, -1, GRN_CURSOR_PREFIX);
+    if (cursor) {
+      grn_id column_id;
+      while ((column_id = grn_pat_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+        column_id |= GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN;
+        grn_hash_add(ctx, (grn_hash *)res,
+                     &column_id, sizeof(grn_id),
+                     NULL, NULL);
+        n++;
+      }
+      grn_pat_cursor_close(ctx, cursor);
+    }
+  } else {
     grn_db *s = (grn_db *)DB_OBJ(table)->db;
     if (s->keys) {
       grn_obj bulk;
       GRN_TEXT_INIT(&bulk, 0);
-      grn_table_get_key2(ctx, s->keys, DB_OBJ(table)->id, &bulk);
+      grn_table_get_key2(ctx, s->keys, id, &bulk);
       GRN_TEXT_PUTC(ctx, &bulk, GRN_DB_DELIMITER);
       grn_bulk_write(ctx, &bulk, name, name_size);
       grn_table_search(ctx, s->keys, GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk),
@@ -4166,6 +4207,7 @@ grn_table_columns(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int n
       n = grn_table_size(ctx, res);
     }
   }
+
   GRN_API_RETURN(n);
 }
 
@@ -4211,8 +4253,10 @@ grn_column_create(grn_ctx *ctx, grn_obj *table,
   grn_id id = GRN_ID_NIL;
   grn_id range = GRN_ID_NIL;
   grn_id domain = GRN_ID_NIL;
+  grn_bool is_persistent_table;
   char fullname[GRN_TABLE_MAX_KEY_SIZE];
   char buffer[PATH_MAX];
+
   GRN_API_ENTER;
   if (!table) {
     ERR(GRN_INVALID_ARGUMENT, "[column][create] table is missing");
@@ -4237,40 +4281,50 @@ grn_column_create(grn_ctx *ctx, grn_obj *table,
         table_name_len, table_name, name_size, name);
     goto exit;
   }
-  if (DB_OBJ(table)->id & GRN_OBJ_TMP_OBJECT) {
-    ERR(GRN_INVALID_ARGUMENT,
-        "[column][create] temporary table doesn't support column: <%.*s>",
-        name_size, name);
+
+  if (grn_db_check_name(ctx, name, name_size)) {
+    GRN_DB_CHECK_NAME_ERR("[column][create]", name, name_size);
     goto exit;
   }
-  {
+
+  domain = DB_OBJ(table)->id;
+  is_persistent_table = !(domain & GRN_OBJ_TMP_OBJECT);
+  if (is_persistent_table) {
     uint32_t s = 0;
-    const char *n = _grn_table_key(ctx, ctx->impl->db, DB_OBJ(table)->id, &s);
+    const char *n = _grn_table_key(ctx, ctx->impl->db, domain, &s);
     GRN_LOG(ctx, GRN_LOG_NOTICE,
             "DDL:column_create %.*s %.*s", s, n, name_size, name);
   }
-  if (grn_db_check_name(ctx, name, name_size)) {
-    GRN_DB_CHECK_NAME_ERR("[column][create]", name, name_size);
+
+  if (!domain) {
+    ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
+        "[column][create] [todo] table-less column isn't supported yet");
     goto exit;
   }
-  if ((domain = DB_OBJ(table)->id)) {
-    int len = grn_table_get_key(ctx, s->keys, domain, fullname, GRN_TABLE_MAX_KEY_SIZE);
-    if (name_size + 1 + len > GRN_TABLE_MAX_KEY_SIZE) {
+
+  {
+    int table_name_len;
+    if (is_persistent_table) {
+      table_name_len = grn_table_get_key(ctx, s->keys, domain,
+                                         fullname, GRN_TABLE_MAX_KEY_SIZE);
+    } else {
+      grn_snprintf(fullname, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE,
+                   "%u", domain);
+      table_name_len = strlen(fullname);
+    }
+    if (name_size + 1 + table_name_len > GRN_TABLE_MAX_KEY_SIZE) {
       ERR(GRN_INVALID_ARGUMENT,
           "[column][create] too long column name: required name_size(%d) < %d"
           ": <%.*s>.<%.*s>",
-          name_size, GRN_TABLE_MAX_KEY_SIZE - 1 - len,
-          len, fullname, name_size, name);
+          name_size, GRN_TABLE_MAX_KEY_SIZE - 1 - table_name_len,
+          table_name_len, fullname, name_size, name);
       goto exit;
     }
-    fullname[len] = GRN_DB_DELIMITER;
-    grn_memcpy(fullname + len + 1, name, name_size);
-    name_size += len + 1;
-  } else {
-    ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
-        "[column][create] [todo] table-less column isn't supported yet");
-    goto exit;
+    fullname[table_name_len] = GRN_DB_DELIMITER;
+    grn_memcpy(fullname + table_name_len + 1, name, name_size);
+    name_size += table_name_len + 1;
   }
+
   range = DB_OBJ(type)->id;
   switch (type->header.type) {
   case GRN_TYPE :
@@ -4294,9 +4348,32 @@ grn_column_create(grn_ctx *ctx, grn_obj *table,
     */
     value_size = sizeof(grn_id);
   }
-  id = grn_obj_register(ctx, db, fullname, name_size);
-  if (ERRP(ctx, GRN_ERROR)) { goto exit;  }
-  if (GRN_OBJ_PERSISTENT & flags) {
+
+  if (is_persistent_table) {
+    id = grn_obj_register(ctx, db, fullname, name_size);
+    if (ERRP(ctx, GRN_ERROR)) { goto exit; }
+  } else {
+    int added;
+    id = grn_pat_add(ctx, ctx->impl->temporary_columns,
+                     fullname, name_size, NULL,
+                     &added);
+    if (!id) {
+      ERR(GRN_NO_MEMORY_AVAILABLE,
+          "[column][create][temporary] "
+          "failed to register temporary column name: <%.*s>",
+          name_size, fullname);
+      goto exit;
+    } else if (!added) {
+      id = GRN_ID_NIL;
+      ERR(GRN_NO_MEMORY_AVAILABLE,
+          "[column][create][temporary] already used name was assigned: <%.*s>",
+          name_size, fullname);
+      goto exit;
+    }
+    id |= GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN;
+  }
+
+  if (is_persistent_table && flags & GRN_OBJ_PERSISTENT) {
     if (!path) {
       if (GRN_DB_PERSISTENT_P(db)) {
         gen_pathname(grn_obj_io(db)->path, buffer, id);
@@ -9023,9 +9100,19 @@ grn_obj_delete_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, grn_bool removep)
   GRN_API_ENTER;
   if (id) {
     if (id & GRN_OBJ_TMP_OBJECT) {
-      if (ctx->impl && ctx->impl->values) {
-        rc = grn_array_delete_by_id(ctx, ctx->impl->values,
-                                      id & ~GRN_OBJ_TMP_OBJECT, NULL);
+      if (ctx->impl) {
+        if (id & GRN_OBJ_TMP_COLUMN) {
+          if (ctx->impl->temporary_columns) {
+            rc = grn_pat_delete_by_id(ctx, ctx->impl->temporary_columns,
+                                      id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT),
+                                      NULL);
+          }
+        } else {
+          if (ctx->impl->values) {
+            rc = grn_array_delete_by_id(ctx, ctx->impl->values,
+                                        id & ~GRN_OBJ_TMP_OBJECT, NULL);
+          }
+        }
       }
     } else {
       db_value *vp;
@@ -9074,9 +9161,17 @@ grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj)
   grn_rc rc = GRN_SUCCESS;
   if (id) {
     if (id & GRN_OBJ_TMP_OBJECT) {
-      if (ctx->impl && ctx->impl->values) {
-        rc = grn_array_set_value(ctx, ctx->impl->values,
-                                 id & ~GRN_OBJ_TMP_OBJECT, &obj, GRN_OBJ_SET);
+      if (id & GRN_OBJ_TMP_COLUMN) {
+        if (ctx->impl && ctx->impl->temporary_columns) {
+          grn_id real_id = id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT);
+          rc = grn_pat_set_value(ctx, ctx->impl->temporary_columns,
+                                 real_id, &obj, GRN_OBJ_SET);
+        }
+      } else {
+        if (ctx->impl && ctx->impl->values) {
+          rc = grn_array_set_value(ctx, ctx->impl->values,
+                                   id & ~GRN_OBJ_TMP_OBJECT, &obj, GRN_OBJ_SET);
+        }
       }
     } else {
       db_value *vp;
@@ -9198,11 +9293,27 @@ grn_ctx_at(grn_ctx *ctx, grn_id id)
   if (!ctx || !ctx->impl || !id) { return res; }
   GRN_API_ENTER;
   if (id & GRN_OBJ_TMP_OBJECT) {
-    if (ctx->impl->values) {
-      grn_obj **tmp_obj;
-      tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, id & ~GRN_OBJ_TMP_OBJECT);
-      if (tmp_obj) {
-        res = *tmp_obj;
+    if (id & GRN_OBJ_TMP_COLUMN) {
+      if (ctx->impl->temporary_columns) {
+        grn_id real_id = id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT);
+        grn_obj **tmp_obj;
+        uint32_t size;
+        tmp_obj = (grn_obj **)grn_pat_get_value_(ctx,
+                                                 ctx->impl->temporary_columns,
+                                                 real_id,
+                                                 &size);
+        if (tmp_obj) {
+          res = *tmp_obj;
+        }
+      }
+    } else {
+      if (ctx->impl->values) {
+        grn_obj **tmp_obj;
+        tmp_obj = _grn_array_get_value(ctx, ctx->impl->values,
+                                       id & ~GRN_OBJ_TMP_OBJECT);
+        if (tmp_obj) {
+          res = *tmp_obj;
+        }
       }
     }
   } else {
@@ -9801,8 +9912,15 @@ grn_obj_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size)
   if (GRN_DB_OBJP(obj)) {
     if (DB_OBJ(obj)->id) {
       grn_db *s = (grn_db *)DB_OBJ(obj)->db;
-      if (!(DB_OBJ(obj)->id & GRN_OBJ_TMP_OBJECT)) {
-        len = grn_table_get_key(ctx, s->keys, DB_OBJ(obj)->id, namebuf, buf_size);
+      grn_id id = DB_OBJ(obj)->id;
+      if (id & GRN_OBJ_TMP_OBJECT) {
+        if (id & GRN_OBJ_TMP_COLUMN) {
+          grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN);
+          len = grn_pat_get_key(ctx, ctx->impl->temporary_columns,
+                                real_id, namebuf, buf_size);
+        }
+      } else {
+        len = grn_table_get_key(ctx, s->keys, id, namebuf, buf_size);
       }
     }
   }
@@ -9817,19 +9935,26 @@ grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size)
   if (!obj) { return len; }
   GRN_API_ENTER;
   if (GRN_DB_OBJP(obj)) {
-    if (DB_OBJ(obj)->id && DB_OBJ(obj)->id < GRN_ID_MAX) {
+    grn_id id = DB_OBJ(obj)->id;
+    if (id & GRN_OBJ_TMP_OBJECT) {
+      if (id & GRN_OBJ_TMP_COLUMN) {
+        grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN);
+        len = grn_pat_get_key(ctx, ctx->impl->temporary_columns,
+                              real_id, buf, GRN_TABLE_MAX_KEY_SIZE);
+      }
+    } else if (id && id < GRN_ID_MAX) {
       grn_db *s = (grn_db *)DB_OBJ(obj)->db;
-      len = grn_table_get_key(ctx, s->keys, DB_OBJ(obj)->id, buf, GRN_TABLE_MAX_KEY_SIZE);
-      if (len) {
-        int cl;
-        char *p = buf, *p0 = p, *pe = p + len;
-        for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) {
-          if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; }
-        }
-        len = pe - p0;
-        if (len && len <= buf_size) {
-          grn_memcpy(namebuf, p0, len);
-        }
+      len = grn_table_get_key(ctx, s->keys, id, buf, GRN_TABLE_MAX_KEY_SIZE);
+    }
+    if (len) {
+      int cl;
+      char *p = buf, *p0 = p, *pe = p + len;
+      for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) {
+        if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; }
+      }
+      len = pe - p0;
+      if (len && len <= buf_size) {
+        grn_memcpy(namebuf, p0, len);
       }
     }
   } else if (obj->header.type == GRN_ACCESSOR) {
@@ -9885,18 +10010,25 @@ grn_rc
 grn_column_name_(grn_ctx *ctx, grn_obj *obj, grn_obj *buf)
 {
   if (GRN_DB_OBJP(obj)) {
-    if (DB_OBJ(obj)->id && DB_OBJ(obj)->id < GRN_ID_MAX) {
-      uint32_t len;
+    uint32_t len = 0;
+    const char *p = NULL;
+    grn_id id = DB_OBJ(obj)->id;
+    if (id & GRN_OBJ_TMP_OBJECT) {
+      if (id & GRN_OBJ_TMP_COLUMN) {
+        grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN);
+        p = _grn_pat_key(ctx, ctx->impl->temporary_columns, real_id, &len);
+      }
+    } else if (id && id < GRN_ID_MAX) {
       grn_db *s = (grn_db *)DB_OBJ(obj)->db;
-      const char *p = _grn_table_key(ctx, s->keys, DB_OBJ(obj)->id, &len);
-      if (len) {
-        int cl;
-        const char *p0 = p, *pe = p + len;
-        for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) {
-          if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; }
-        }
-        GRN_TEXT_PUT(ctx, buf, p0, pe - p0);
+      p = _grn_table_key(ctx, s->keys, id, &len);
+    }
+    if (len) {
+      int cl;
+      const char *p0 = p, *pe = p + len;
+      for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) {
+        if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; }
       }
+      GRN_TEXT_PUT(ctx, buf, p0, pe - p0);
     }
   } else if (obj->header.type == GRN_ACCESSOR) {
     grn_accessor *a;

  Modified: lib/grn_ctx_impl.h (+1 -0)
===================================================================
--- lib/grn_ctx_impl.h    2015-09-15 18:37:28 +0900 (b653f35)
+++ lib/grn_ctx_impl.h    2015-09-16 00:06:43 +0900 (fb3e032)
@@ -171,6 +171,7 @@ struct _grn_ctx_impl {
 
   grn_obj *db;
   grn_array *values;        /* temporary objects */
+  grn_pat *temporary_columns;
   grn_hash *ios;        /* IOs */
   grn_obj *outbuf;
   void (*output)(grn_ctx *, int, void *);

  Modified: lib/grn_db.h (+1 -0)
===================================================================
--- lib/grn_db.h    2015-09-15 18:37:28 +0900 (6c84ad9)
+++ lib/grn_db.h    2015-09-16 00:06:43 +0900 (dca1cfc)
@@ -111,6 +111,7 @@ struct _grn_type {
 #define GRN_TABLE_SORT_GEO            (0x02<<0)
 
 #define GRN_OBJ_TMP_OBJECT 0x80000000
+#define GRN_OBJ_TMP_COLUMN 0x40000000
 
 #define GRN_DB_OBJP(obj) \
   (obj &&\

  Modified: test/unit/core/test-column.c (+15 -5)
===================================================================
--- test/unit/core/test-column.c    2015-09-15 18:37:28 +0900 (23d5bac)
+++ test/unit/core/test-column.c    2015-09-16 00:06:43 +0900 (bbdba09)
@@ -1,6 +1,6 @@
 /* -*- c-basic-offset: 2; coding: utf-8 -*- */
 /*
-  Copyright (C) 2009-2012  Kouhei Sutou <kou �� clear-code.com>
+  Copyright (C) 2009-2015  Kouhei Sutou <kou �� clear-code.com>
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -33,6 +33,7 @@ static grn_obj *database;
 static grn_obj *bookmarks;
 static grn_obj *count_column;
 static grn_id groonga_bookmark_id;
+static grn_hash *columns;
 
 static void
 create_bookmarks_table(void)
@@ -88,6 +89,8 @@ cut_setup(void)
   context = g_new0(grn_ctx, 1);
   grn_ctx_init(context, 0);
   database = grn_db_create(context, NULL, NULL);
+  columns = grn_hash_create(context, NULL, sizeof(grn_id), 0,
+                            GRN_OBJ_TABLE_HASH_KEY);
 
   create_bookmarks_table();
   add_count_column_to_bookmarks_table();
@@ -97,6 +100,7 @@ cut_setup(void)
 void
 cut_teardown(void)
 {
+  grn_hash_close(context, columns);
   grn_obj_close(context, database);
   grn_ctx_fin(context);
   g_free(context);
@@ -173,8 +177,14 @@ test_create_on_temporary_table(void)
                              strlen(column_name),
                              NULL, 0,
                              get_object("Int32"));
-  grn_test_assert_error(GRN_INVALID_ARGUMENT,
-                        "[column][create] "
-                        "temporary table doesn't support column: <count>",
-                        context);
+  grn_test_assert_context(context);
+  cut_assert_equal_int(1,
+                       grn_table_columns(context, table, NULL, 0,
+                                         (grn_obj *)columns));
+  {
+    grn_id found_column_id = GRN_ID_NIL;
+    grn_hash_get_key(context, columns, 1, &found_column_id, sizeof(grn_id));
+    cut_assert_equal_uint(grn_obj_id(context, column),
+                          found_column_id);
+  }
 }
-------------- next part --------------
HTML����������������������������...
Download 



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