コード例 #1
0
ファイル: operator.c プロジェクト: XLPE/groonga
static grn_bool
exec_match_uvector_bulk(grn_ctx *ctx, grn_obj *uvector, grn_obj *query)
{
  grn_bool matched = GRN_FALSE;
  unsigned int i, size;
  grn_obj element;
  unsigned int element_size;

  size = grn_uvector_size(ctx, uvector);
  element_size = grn_uvector_element_size(ctx, uvector);
  GRN_VALUE_FIX_SIZE_INIT(&element, 0, uvector->header.domain);
  for (i = 0; i < size; i++) {
    GRN_BULK_REWIND(&element);
    grn_bulk_write(ctx, &element,
                   GRN_BULK_HEAD(uvector) + (element_size * i),
                   element_size);
    if (grn_operator_exec_equal(ctx, &element, query)) {
      matched = GRN_TRUE;
      break;
    }
  }
  GRN_OBJ_FIN(ctx, &element);

  return matched;
}
コード例 #2
0
ファイル: util.c プロジェクト: pombredanne/groonga
static grn_rc
grn_vector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *vector)
{
  int i;
  grn_obj *body = vector->u.v.body;

  GRN_TEXT_PUTS(ctx, buffer, "[");
  for (i = 0; i < vector->u.v.n_sections; i++) {
    grn_section *section = &(vector->u.v.sections[i]);
    const char *value_raw;

    if (i > 0) {
      GRN_TEXT_PUTS(ctx, buffer, ", ");
    }

    value_raw = GRN_BULK_HEAD(body) + section->offset;
    GRN_TEXT_PUTS(ctx, buffer, "{");
    GRN_TEXT_PUTS(ctx, buffer, "\"value\":");
    {
      grn_obj value_object;
      GRN_OBJ_INIT(&value_object, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY,
                   section->domain);
      grn_bulk_write(ctx, &value_object, value_raw, section->length);
      grn_inspect(ctx, buffer, &value_object);
      GRN_OBJ_FIN(ctx, &value_object);
    }
    GRN_TEXT_PUTS(ctx, buffer, ", \"weight\":");
    grn_text_itoa(ctx, buffer, section->weight);
    GRN_TEXT_PUTS(ctx, buffer, "}");
  }
  GRN_TEXT_PUTS(ctx, buffer, "]");

  return GRN_SUCCESS;
}
コード例 #3
0
ファイル: test-table.c プロジェクト: temita/groonga
void
test_array_set_data(void)
{
  grn_obj *table;
  grn_id record_id;
  gchar value[] = "sample value";
  grn_obj *record_value;
  grn_obj *retrieved_record_value;
  const gchar *dupped_retrieved_record_value;
  gchar *value_type_name = "value_type";
  grn_obj *value_type;

  value_type = grn_type_create(context,
                               value_type_name, strlen(value_type_name),
                               0, sizeof(value));
  table = grn_table_create(context, NULL, 0, NULL,
                           GRN_OBJ_TABLE_NO_KEY,
                           NULL, value_type);
  record_id = grn_table_add(context, table, NULL, 0, NULL);

  record_value = grn_obj_open(context, GRN_BULK, 0, GRN_DB_TEXT);
  grn_bulk_write(context, record_value, value, sizeof(value));
  grn_test_assert(grn_obj_set_value(context, table, record_id,
                                    record_value, GRN_OBJ_SET));
  grn_obj_unlink(context, record_value);

  retrieved_record_value = grn_obj_get_value(context, table, record_id, NULL);
  dupped_retrieved_record_value =
    cut_take_strdup(GRN_BULK_HEAD(retrieved_record_value));
  grn_obj_unlink(context, retrieved_record_value);
  cut_assert_equal_string(value, dupped_retrieved_record_value);
}
コード例 #4
0
ファイル: operator.c プロジェクト: XLPE/groonga
static grn_bool
exec_match_vector_bulk(grn_ctx *ctx, grn_obj *vector, grn_obj *query)
{
  grn_bool matched = GRN_FALSE;
  unsigned int i, size;
  grn_obj element;

  size = grn_vector_size(ctx, vector);
  GRN_VOID_INIT(&element);
  for (i = 0; i < size; i++) {
    const char *content;
    unsigned int content_size;
    grn_id domain_id;

    content_size = grn_vector_get_element(ctx, vector, i,
                                          &content, NULL, &domain_id);
    grn_obj_reinit(ctx, &element, domain_id, 0);
    grn_bulk_write(ctx, &element, content, content_size);
    if (grn_operator_exec_equal(ctx, &element, query)) {
      matched = GRN_TRUE;
      break;
    }
  }
  GRN_OBJ_FIN(ctx, &element);

  return matched;
}
コード例 #5
0
ファイル: test-command-dump.c プロジェクト: bossato/groonga
void
test_uvector_column(gconstpointer data)
{
  const gchar *expected;
  grn_id id, type_id;
  grn_obj uvector;
  grn_obj *elements;
  grn_obj *table, *column;
  const gchar *type_name;
  type_name = gcut_data_get_string(data, "type_name");
  type_id = grn_obj_id(context, get_object(type_name));

  table = table_create("Table", GRN_OBJ_TABLE_NO_KEY, NULL, NULL);
  grn_test_assert_context(context);
  column = column_create("Table", "Column", GRN_OBJ_COLUMN_VECTOR,
                         type_name, NULL);
  grn_test_assert_context(context);
  id = grn_table_add(context, table, NULL, 0, NULL);
  grn_test_assert_context(context);
  cut_assert_equal_int(1, id);
  elements = construct_elements(data);

  GRN_OBJ_INIT(&uvector, GRN_UVECTOR, 0, type_id);
  grn_bulk_write(context, &uvector,
                 GRN_BULK_HEAD(&elements[0]), GRN_BULK_VSIZE(&elements[0]));
  grn_bulk_write(context, &uvector,
                 GRN_BULK_HEAD(&elements[1]), GRN_BULK_VSIZE(&elements[1]));
  grn_bulk_write(context, &uvector,
                 GRN_BULK_HEAD(&elements[2]), GRN_BULK_VSIZE(&elements[2]));
  grn_obj_set_value(context, column, id, &uvector, GRN_OBJ_SET);

  expected = cut_take_printf("table_create Table TABLE_NO_KEY\n"
                             "column_create Table Column COLUMN_VECTOR %s\n"
                             "load --table Table\n"
                             "[\n"
                             "[\"_id\",\"Column\"],\n"
                             "[1,%s]\n"
                             "]",
                             type_name,
                             gcut_data_get_string(data, "expected"));
  cut_assert_equal_string(expected, send_command("dump"));
  GRN_OBJ_FIN(context, &uvector);
}
コード例 #6
0
ファイル: ts.c プロジェクト: flaviommedeiros/groonga
/* grn_ts_geo_output() outputs a value. */
static grn_rc
grn_ts_geo_output(grn_ctx *ctx, grn_ts_geo value)
{
  grn_rc rc = grn_bulk_write(ctx, ctx->impl->output.buf, "\"", 1);
  if (rc != GRN_SUCCESS) {
    return rc;
  }
  rc = grn_text_itoa(ctx, ctx->impl->output.buf, value.latitude);
  if (rc != GRN_SUCCESS) {
    return rc;
  }
  rc = grn_bulk_write(ctx, ctx->impl->output.buf, "x", 1);
  if (rc != GRN_SUCCESS) {
    return rc;
  }
  rc = grn_text_itoa(ctx, ctx->impl->output.buf, value.longitude);
  if (rc != GRN_SUCCESS) {
    return rc;
  }
  return grn_bulk_write(ctx, ctx->impl->output.buf, "\"", 1);
}
コード例 #7
0
ファイル: test-expr.c プロジェクト: ikdttr/groonga
void
test_accessor(void)
{
  int i;
  grn_obj *t1, *t2, *c1, *c2, buf;
  t1 = grn_table_create(&context, "t1", 2, NULL,
                        GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, 0);
  cut_assert_not_null(t1);
  t2 = grn_table_create(&context, "t2", 2, NULL,
                        GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, 0);
  cut_assert_not_null(t2);
  c1 = grn_column_create(&context, t1, "c1", 2, NULL,
                         GRN_OBJ_PERSISTENT, t2);
  cut_assert_not_null(c1);
  c2 = grn_column_create(&context, t2, "c2", 2, NULL,
                         GRN_OBJ_PERSISTENT, t1);
  cut_assert_not_null(c2);
  GRN_TEXT_INIT(&buf, 0);
  for (i = 0; i < NRECORDS; i++) {
    grn_id i1, i2;
    i1 = grn_table_add(&context, t1, NULL, 0, NULL);
    i2 = grn_table_add(&context, t2, NULL, 0, NULL);
    GRN_BULK_REWIND(&buf);
    grn_bulk_write(&context, &buf, (char *)&i2, sizeof(grn_id));
    grn_obj_set_value(&context, c1, i1, &buf, GRN_OBJ_SET);
    grn_obj_set_value(&context, c2, i2, &buf, GRN_OBJ_SET);
  }
  {
    grn_id id;
    uint64_t et;
    int nerr = 0;
    struct timeval tvb, tve;
    grn_obj *a = grn_obj_column(&context, t1, "c1.c2.c1", 8);
    grn_table_cursor *tc = grn_table_cursor_open(&context, t1, NULL, 0, NULL, 0, 0);
    cut_assert_not_null(a);
    cut_assert_not_null(tc);
    gettimeofday(&tvb, NULL);
    while ((id = grn_table_cursor_next(&context, tc))) {
      GRN_BULK_REWIND(&buf);
      grn_obj_get_value(&context, a, id, &buf);
      if (GRN_RECORD_VALUE(&buf) != id) { nerr++; }
    }
    gettimeofday(&tve, NULL);
    et = (tve.tv_sec - tvb.tv_sec) * 1000000 + (tve.tv_usec - tvb.tv_usec);
    // printf("et=%zu\n", et);
    cut_assert_equal_uint(0, nerr);
    cut_assert_equal_uint(0, grn_table_cursor_close(&context, tc));
    cut_assert_equal_uint(0, grn_obj_close(&context, a));
  }
  cut_assert_equal_uint(0, grn_obj_close(&context, &buf));
}
コード例 #8
0
ファイル: rb-grn-utils.c プロジェクト: rutice/rroonga
static void
rb_grn_uvector_from_ruby_object_reference (UVectorFromRubyData *data)
{
    VALUE object;
    grn_ctx *context;
    grn_obj *uvector;
    VALUE related_object;
    VALUE *rb_values;
    int i, n;

    object = data->object;
    context = data->context;
    uvector = data->uvector;
    related_object = data->related_object;

    n = RARRAY_LEN(object);
    rb_values = RARRAY_PTR(object);
    for (i = 0; i < n; i++) {
        VALUE rb_value;
        grn_id id;
        void *grn_value;
        ID id_record_raw_id;

        rb_value = rb_values[i];
        switch (TYPE(rb_value)) {
        case T_FIXNUM:
            id = NUM2UINT(rb_value);
            break;
        default:
            CONST_ID(id_record_raw_id, "record_raw_id");
            if (rb_respond_to(rb_value, id_record_raw_id)) {
                id = NUM2UINT(rb_funcall(rb_value, id_record_raw_id, 0));
            } else {
                rb_raise(rb_eArgError,
                         "uvector value should be one of "
                         "[Fixnum or object that has #record_raw_id]: "
                         "%s (%s): %s",
                         rb_grn_inspect(rb_value),
                         rb_grn_inspect(object),
                         rb_grn_inspect(related_object));
            }
            break;
        }
        grn_value = &id;
        grn_bulk_write(context, uvector, grn_value, sizeof(grn_id));
    }

    data->succeeded = GRN_TRUE;
}
コード例 #9
0
ファイル: put.c プロジェクト: genki/hog
// <cmd> {<len> <column id>} <types> <#kvs> [{<len> <key>} {<len> <value>}]...
void put_or_set(server_t *s, grn_ctx *ctx, int set)
{
    uint32_t len;
    HOG_RECV(s, &len, sizeof(len), return);
    len = ntohl(len);
    char *buf = hog_alloc(NULL, len);
    HOG_RECV(s, buf, len, goto cleanup);
    grn_obj *col, *table;
    col = grn_ctx_get(ctx, buf, len);
    if(grn_obj_is_table(ctx, col)) table = col;
    else table = grn_column_table(ctx, col);
    // get key and value types
    char types[2];
    HOG_RECV(s, types, 2, goto cleanup);
    // receive keys and values
    uint32_t nkeys;
    HOG_RECV(s, &nkeys, sizeof(nkeys), goto cleanup);
    nkeys = ntohl(nkeys);
    grn_obj value;
    GRN_OBJ_INIT(&value, GRN_BULK, 0, types[1]);
    for(uint32_t i = 0; i < nkeys; ++i){
        HOG_RECV(s, &len, sizeof(len), goto value_fin);
        len = ntohl(len);
        buf = hog_alloc(buf, len);
        HOG_RECV(s, buf, len, goto value_fin);
        ntoh_buf(buf, len, types[0]);
        grn_id id;
        if(set){
            id = grn_table_get(ctx, table, buf, len);
        }else{
            id = grn_table_add(ctx, table, buf, len, NULL);
        }
        HOG_RECV(s, &len, sizeof(len), goto value_fin);
        len = ntohl(len);
        buf = hog_alloc(buf, len);
        HOG_RECV(s, buf, len, goto value_fin);
        if(id == GRN_ID_NIL) continue;
        ntoh_buf(buf, len, types[1]);
        GRN_BULK_REWIND(&value);
        grn_bulk_write(ctx, &value, buf, len);
        grn_obj_set_value(ctx, col, id, &value, GRN_OBJ_SET);
    }
    submit_one(s->socket);
value_fin:
    GRN_OBJ_FIN(ctx, &value);
cleanup:
    free(buf);
}
コード例 #10
0
ファイル: test-inverted-index.c プロジェクト: kazu/groonga
static grn_rc
set_index_source(grn_obj *index, grn_obj *source)
{
    grn_rc rc;
    grn_obj buf;
    grn_id id = grn_obj_id(context, source);
    GRN_TEXT_INIT(&buf, 0);
    grn_bulk_write(context, &buf, (void *)&id, sizeof(grn_id));
    cut_assert_equal_int(grn_obj_get_nhooks(context, source, GRN_HOOK_SET), 0);
    rc = grn_obj_set_info(context, index, GRN_INFO_SOURCE, &buf);
    cut_assert_equal_int(grn_obj_get_nhooks(context, source, GRN_HOOK_SET), 1);
    GRN_BULK_REWIND(&buf);
    cut_assert_null(grn_obj_get_hook(context, source, GRN_HOOK_SET, 0, &buf));
    cut_assert_equal_int(*((grn_id *)GRN_BULK_HEAD(&buf)), grn_obj_id(context, index));
    grn_obj_close(context, &buf);
    return rc;
}
コード例 #11
0
ファイル: rb-grn-utils.c プロジェクト: ryoqun/rroonga
grn_obj *
rb_grn_uvector_from_ruby_object (VALUE object, grn_ctx *context,
				 grn_obj *uvector, VALUE related_object)
{
    VALUE *values;
    int i, n;

    if (NIL_P(object))
	return NULL;

    n = RARRAY_LEN(object);
    values = RARRAY_PTR(object);
    for (i = 0; i < n; i++) {
	VALUE value;
	grn_id id;
	void *grn_value;

	value = values[i];
	switch (TYPE(value)) {
	  case T_FIXNUM:
	    id = NUM2UINT(value);
	    break;
	  default:
	    if (rb_respond_to(value, rb_intern("record_raw_id"))) {
		id = NUM2UINT(rb_funcall(value, rb_intern("record_raw_id"), 0));
	    } else {
		grn_obj_unlink(context, uvector);
		rb_raise(rb_eArgError,
			 "uvector value should be one of "
			 "[Fixnum or object that has #record_raw_id]: "
			 "%s (%s): %s",
			 rb_grn_inspect(value),
			 rb_grn_inspect(object),
			 rb_grn_inspect(related_object));
	    }
	    break;
	}
	grn_value = &id;
	grn_bulk_write(context, uvector, grn_value, sizeof(grn_id));
    }

    return uvector;
}
コード例 #12
0
ファイル: test-column.c プロジェクト: ikdttr/groonga
void
test_fix_size_set_value_set(void)
{
  gint32 count = 29;
  gint32 retrieved_count;
  grn_obj *record_value;
  grn_obj *retrieved_record_value;

  record_value = grn_obj_open(&context, GRN_BULK, 0, 0);
  grn_bulk_write(&context, record_value, (const char *)&count, sizeof(count));
  grn_test_assert(grn_obj_set_value(&context, count_column, groonga_bookmark_id,
                                    record_value, GRN_OBJ_SET));

  retrieved_record_value = grn_obj_get_value(&context, count_column,
                                             groonga_bookmark_id, NULL);
  memcpy(&retrieved_count,
         GRN_BULK_HEAD(retrieved_record_value),
         GRN_BULK_VSIZE(retrieved_record_value));
  cut_assert_equal_int(count, retrieved_count);
}
コード例 #13
0
ファイル: test-inverted-index.c プロジェクト: kazu/groonga
static void
insert_and_search(grn_obj *users, grn_obj *items, grn_obj *checks, grn_obj *checked)
{
    grn_id user1 = grn_table_add(context, users, NULL, 0, NULL);
    grn_id user2 = grn_table_add(context, users, NULL, 0, NULL);
    grn_id item = grn_table_add(context, items, NULL, 0, NULL);
    grn_obj value, *res;
    GRN_TEXT_INIT(&value, 0);
    res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY, users, 0);
    cut_assert_not_null(res);
    grn_bulk_write(context, &value, (void *)&item, sizeof(grn_id));
    value.header.domain = grn_obj_id(context, items);
    grn_test_assert(grn_obj_set_value(context, checks, user1, &value, GRN_OBJ_SET));
    grn_test_assert(grn_obj_search(context, checked, &value, res, GRN_OP_OR, NULL));
    cut_assert_equal_int(grn_table_size(context, res), 1);
    grn_test_assert(grn_obj_set_value(context, checks, user2, &value, GRN_OBJ_SET));
    grn_test_assert(grn_obj_search(context, checked, &value, res, GRN_OP_OR, NULL));
    cut_assert_equal_int(grn_table_size(context, res), 2);
    grn_obj_close(context, &value);
    grn_obj_close(context, res);
}
コード例 #14
0
ファイル: dat.cpp プロジェクト: mworrell/groonga
int
grn_dat_get_key2(grn_ctx *ctx, grn_dat *dat, grn_id id, grn_obj *bulk)
{
  if (!grn_dat_open_trie_if_needed(ctx, dat)) {
    return 0;
  }
  const grn::dat::Trie * const trie = static_cast<const grn::dat::Trie *>(dat->trie);
  if (!trie) {
    return 0;
  }
  const grn::dat::Key &key = trie->ith_key(id);
  if (!key.is_valid()) {
    return 0;
  }
  if (bulk->header.impl_flags & GRN_OBJ_REFER) {
    bulk->u.b.head = static_cast<char *>(const_cast<void *>(key.ptr()));
    bulk->u.b.curr = bulk->u.b.head + key.length();
  } else {
    grn_bulk_write(ctx, bulk, static_cast<const char *>(key.ptr()), key.length());
  }
  return (int)key.length();
}
コード例 #15
0
ファイル: proc_highlight.c プロジェクト: ohkubo/groonga
static grn_obj *
highlight_keyword_sets(grn_ctx *ctx, grn_user_data *user_data,
                       grn_obj **keyword_set_args, unsigned int n_keyword_args,
                       grn_obj *string, grn_obj *keywords,
                       grn_bool use_html_escape)
{
  grn_obj *highlighted = NULL;
#define KEYWORD_SET_SIZE 3
  {
    unsigned int i;
    unsigned int n_keyword_sets;
    grn_obj open_tags;
    grn_obj open_tag_lengths;
    grn_obj close_tags;
    grn_obj close_tag_lengths;

    n_keyword_sets = n_keyword_args / KEYWORD_SET_SIZE;

    GRN_OBJ_INIT(&open_tags, GRN_BULK, 0, GRN_DB_VOID);
    GRN_OBJ_INIT(&open_tag_lengths, GRN_BULK, 0, GRN_DB_VOID);
    GRN_OBJ_INIT(&close_tags, GRN_BULK, 0, GRN_DB_VOID);
    GRN_OBJ_INIT(&close_tag_lengths, GRN_BULK, 0, GRN_DB_VOID);

    for (i = 0; i < n_keyword_sets; i++) {
      grn_obj *keyword   = keyword_set_args[i * KEYWORD_SET_SIZE + 0];
      grn_obj *open_tag  = keyword_set_args[i * KEYWORD_SET_SIZE + 1];
      grn_obj *close_tag = keyword_set_args[i * KEYWORD_SET_SIZE + 2];

      grn_table_add(ctx, keywords,
                    GRN_TEXT_VALUE(keyword),
                    GRN_TEXT_LEN(keyword),
                    NULL);
      {
        const char *open_tag_content = GRN_TEXT_VALUE(open_tag);
        grn_bulk_write(ctx, &open_tags,
                       (const char *)(&open_tag_content),
                       sizeof(char *));
      }
      {
        unsigned int open_tag_length = GRN_TEXT_LEN(open_tag);
        grn_bulk_write(ctx, &open_tag_lengths,
                       (const char *)(&open_tag_length),
                       sizeof(unsigned int));
      }
      {
        const char *close_tag_content = GRN_TEXT_VALUE(close_tag);
        grn_bulk_write(ctx, &close_tags,
                       (const char *)(&close_tag_content),
                       sizeof(char *));
      }
      {
        unsigned int close_tag_length = GRN_TEXT_LEN(close_tag);
        grn_bulk_write(ctx, &close_tag_lengths,
                       (const char *)(&close_tag_length),
                       sizeof(unsigned int));
      }
    }

    highlighted = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_TEXT, 0);
    grn_pat_tag_keys(ctx, keywords,
                     GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string),
                     (const char **)GRN_BULK_HEAD(&open_tags),
                     (unsigned int *)GRN_BULK_HEAD(&open_tag_lengths),
                     (const char **)GRN_BULK_HEAD(&close_tags),
                     (unsigned int *)GRN_BULK_HEAD(&close_tag_lengths),
                     n_keyword_sets,
                     highlighted,
                     use_html_escape);
    grn_obj_unlink(ctx, &open_tags);
    grn_obj_unlink(ctx, &open_tag_lengths);
    grn_obj_unlink(ctx, &close_tags);
    grn_obj_unlink(ctx, &close_tag_lengths);
  }
#undef KEYWORD_SET_SIZE
  return highlighted;
}
コード例 #16
0
ファイル: test-inverted-index.c プロジェクト: kazu/groonga
void
test_int_index(void)
{
    gchar *db_path, *name;
    grn_obj *users, *items, *checks, *checked, *int_type;

    remove_tmp_directory();
    g_mkdir_with_parents(tmp_directory, 0700);
    db_path = g_build_filename(tmp_directory, "inverted-index", NULL);
    db = grn_db_create(context, db_path, NULL);
    g_free(db_path);

    int_type = grn_ctx_at(context, GRN_DB_INT32);
    cut_assert_not_null(int_type);

    name = "users";
    users = grn_table_create(context, name, strlen(name), NULL,
                             GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, 0);
    cut_assert_not_null(users);

    name = "items";
    items = grn_table_create(context, name, strlen(name), NULL,
                             GRN_OBJ_TABLE_PAT_KEY|GRN_OBJ_PERSISTENT, int_type, 0);
    cut_assert_not_null(items);

    name = "checks";
    checks = grn_column_create(context, users, name, strlen(name), NULL,
                               GRN_OBJ_COLUMN_SCALAR|GRN_OBJ_PERSISTENT, items);
    cut_assert_not_null(checks);

    name = "checked";
    checked = grn_column_create(context, items, name, strlen(name), NULL,
                                GRN_OBJ_COLUMN_INDEX|GRN_OBJ_PERSISTENT, users);
    cut_assert_not_null(checked);

    grn_test_assert(set_index_source(checked, checks));

    {
        int32_t key = 1;
        grn_obj value, query, *res;
        grn_id user1 = grn_table_add(context, users, NULL, 0, NULL);
        grn_id user2 = grn_table_add(context, users, NULL, 0, NULL);
        grn_id item = grn_table_add(context, items, &key, sizeof(int32_t), NULL);
        GRN_TEXT_INIT(&value, 0);
        GRN_TEXT_INIT(&query, 0);
        res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY, users, 0);
        cut_assert_not_null(res);
        grn_bulk_write(context, &value, (void *)&item, sizeof(grn_id));
        value.header.domain = grn_obj_id(context, items);
        grn_bulk_write(context, &query, (void *)&key, sizeof(int32_t));
        query.header.domain = GRN_DB_INT32;
        grn_test_assert(grn_obj_set_value(context, checks, user1, &value, GRN_OBJ_SET));
        grn_test_assert(grn_obj_search(context, checked, &value, res, GRN_OP_OR, NULL));
        cut_assert_equal_int(grn_table_size(context, res), 1);
        grn_test_assert(grn_obj_set_value(context, checks, user2, &value, GRN_OBJ_SET));
        grn_test_assert(grn_obj_search(context, checked, &query, res, GRN_OP_OR, NULL));
        cut_assert_equal_int(grn_table_size(context, res), 2);
        grn_obj_close(context, &query);
        grn_obj_close(context, &value);
        grn_obj_close(context, res);
    }

    grn_obj_close(context, checks);
    grn_obj_close(context, checked);
    grn_obj_close(context, items);
    grn_obj_close(context, users);
}
コード例 #17
0
ファイル: test-expr.c プロジェクト: ikdttr/groonga
void
test_persistent_expr(void)
{
  int i;
  grn_obj *t1, *t2, *c1, *c2, buf;
  t1 = grn_table_create(&context, "t1", 2, NULL,
                        GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, 0);
  cut_assert_not_null(t1);
  t2 = grn_table_create(&context, "t2", 2, NULL,
                        GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, 0);
  cut_assert_not_null(t2);
  c1 = grn_column_create(&context, t1, "c1", 2, NULL,
                         GRN_OBJ_PERSISTENT, t2);
  cut_assert_not_null(c1);
  c2 = grn_column_create(&context, t2, "c2", 2, NULL,
                         GRN_OBJ_PERSISTENT, t1);
  cut_assert_not_null(c2);
  GRN_TEXT_INIT(&buf, 0);
  for (i = 0; i < NRECORDS; i++) {
    grn_id i1, i2;
    i1 = grn_table_add(&context, t1, NULL, 0, NULL);
    i2 = grn_table_add(&context, t2, NULL, 0, NULL);
    GRN_BULK_REWIND(&buf);
    grn_bulk_write(&context, &buf, (char *)&i2, sizeof(grn_id));
    grn_obj_set_value(&context, c1, i1, &buf, GRN_OBJ_SET);
    grn_obj_set_value(&context, c2, i2, &buf, GRN_OBJ_SET);
  }
  {
    grn_obj *expr = grn_expr_create(&context, "test", 4);
    grn_obj *v;
    cut_assert_not_null(expr);
    v = grn_expr_add_var(&context, expr, "foo", 3);
    GRN_RECORD_INIT(v, 0, grn_obj_id(&context, t1));
    grn_expr_append_obj(&context, expr, v);

    GRN_TEXT_SETS(&context, &buf, "c1");
    grn_expr_append_const(&context, expr, &buf);
    grn_expr_append_op(&context, expr, GRN_OP_OBJ_GET_VALUE, 2);
    GRN_TEXT_SETS(&context, &buf, "c2");
    grn_expr_append_const(&context, expr, &buf);
    grn_expr_append_op(&context, expr, GRN_OP_OBJ_GET_VALUE, 2);
    GRN_TEXT_SETS(&context, &buf, "c1");
    grn_expr_append_const(&context, expr, &buf);

    /*
    GRN_TEXT_SETS(&context, &buf, "c1.c2.c1");
    grn_expr_append_const(&context, expr, &buf);
    */

    grn_expr_append_op(&context, expr, GRN_OP_OBJ_GET_VALUE, 2);
    grn_expr_compile(&context, expr);
  }
  cut_assert_equal_uint(0, grn_obj_close(&context, &buf));

  grn_db_close(&context, database);
  database = grn_db_open(&context, path);

  GRN_TEXT_INIT(&buf, 0);

  {
    grn_id id;
    uint64_t et;
    int nerr = 0;
    grn_obj *r, *v;
    grn_table_cursor *tc;
    struct timeval tvb, tve;
    grn_obj *expr = grn_ctx_get(&context, "test", 4);
    v = grn_expr_get_var(&context, expr, "foo", 3);
    t1 = grn_ctx_get(&context, "t1", 2);
    tc = grn_table_cursor_open(&context, t1, NULL, 0, NULL, 0, 0);
    cut_assert_not_null(tc);
    gettimeofday(&tvb, NULL);
    while ((id = grn_table_cursor_next(&context, tc))) {
      GRN_RECORD_SET(&context, v, id);
      r = grn_expr_exec(&context, expr);
      if (GRN_RECORD_VALUE(r) != id) { nerr++; }
    }
    gettimeofday(&tve, NULL);
    et = (tve.tv_sec - tvb.tv_sec) * 1000000 + (tve.tv_usec - tvb.tv_usec);
    // printf("et=%zu\n", et);
    cut_assert_equal_uint(0, nerr);
    cut_assert_equal_uint(0, grn_table_cursor_close(&context, tc));
  }
  cut_assert_equal_uint(0, grn_obj_close(&context, &buf));
}
コード例 #18
0
ファイル: operator.c プロジェクト: groonga/groonga
static grn_bool
exec_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y)
{
  switch (x->header.type) {
  case GRN_BULK :
    if (y->header.type == GRN_BULK) {
      grn_bool is_equal = GRN_FALSE;
      DO_EQ(x, y, is_equal);
      return is_equal;
    } else {
      return GRN_FALSE;
    }
    break;
  case GRN_VECTOR :
    if (y->header.type == GRN_VECTOR) {
      grn_bool is_equal = GRN_TRUE;
      unsigned int x_size = grn_vector_size(ctx, x);
      unsigned int y_size = grn_vector_size(ctx, y);
      unsigned int i;
      grn_obj x_element;
      grn_obj y_element;
      if (x_size != y_size) {
        return GRN_FALSE;
      }
      GRN_VOID_INIT(&x_element);
      GRN_VOID_INIT(&y_element);
      for (i = 0; i < x_size; i++) {
        const char *x_value;
        unsigned int x_size;
        unsigned int x_weight;
        grn_id x_domain;
        const char *y_value;
        unsigned int y_size;
        unsigned int y_weight;
        grn_id y_domain;

        x_size = grn_vector_get_element(ctx, x, i, &x_value, &x_weight, &x_domain);
        y_size = grn_vector_get_element(ctx, y, i, &y_value, &y_weight, &y_domain);
        if (x_weight != y_weight) {
          is_equal = GRN_FALSE;
          break;
        }
        grn_obj_reinit(ctx, &x_element, x_domain, 0);
        grn_bulk_write(ctx, &x_element, x_value, x_size);
        grn_obj_reinit(ctx, &y_element, y_domain, 0);
        grn_bulk_write(ctx, &y_element, y_value, y_size);
        DO_EQ((&x_element), (&y_element), is_equal);
        if (!is_equal) {
          break;
        }
      }
      GRN_OBJ_FIN(ctx, &x_element);
      GRN_OBJ_FIN(ctx, &y_element);
      return is_equal;
    } else {
      return GRN_FALSE;
    }
    break;
  case GRN_UVECTOR :
    if (y->header.type == GRN_UVECTOR) {
      grn_bool is_equal = GRN_TRUE;
      unsigned int x_size = grn_vector_size(ctx, x);
      unsigned int y_size = grn_vector_size(ctx, y);
      unsigned int i;
      grn_obj x_element;
      grn_obj y_element;
      unsigned int x_element_size = grn_uvector_element_size(ctx, x);
      unsigned int y_element_size = grn_uvector_element_size(ctx, y);
      if (x_size != y_size) {
        return GRN_FALSE;
      }
      GRN_OBJ_INIT(&x_element, GRN_BULK, 0, x->header.domain);
      GRN_OBJ_INIT(&y_element, GRN_BULK, 0, y->header.domain);
      for (i = 0; i < x_size; i++) {
        const char *x_value;
        const char *y_value;

        x_value = GRN_BULK_HEAD(x) + (x_element_size * i);
        y_value = GRN_BULK_HEAD(y) + (y_element_size * i);
        GRN_BULK_REWIND(&x_element);
        GRN_BULK_REWIND(&y_element);
        grn_bulk_write(ctx, &x_element, x_value, x_element_size);
        grn_bulk_write(ctx, &y_element, y_value, y_element_size);
        DO_EQ((&x_element), (&y_element), is_equal);
        if (!is_equal) {
          break;
        }
      }
      GRN_OBJ_FIN(ctx, &x_element);
      GRN_OBJ_FIN(ctx, &y_element);
      return is_equal;
    } else {
      return GRN_FALSE;
    }
    break;
  default :
    return GRN_FALSE;
  }
}
コード例 #19
0
ファイル: load.c プロジェクト: cosmo0920/groonga
static void
set_vector(grn_ctx *ctx, grn_obj *column, grn_id id, grn_obj *vector)
{
  int n = GRN_UINT32_VALUE(vector);
  grn_obj buf, *v = vector + 1;
  grn_id range_id;
  grn_obj *range;

  range_id = DB_OBJ(column)->range;
  range = grn_ctx_at(ctx, range_id);
  if (grn_obj_is_table(ctx, range)) {
    GRN_RECORD_INIT(&buf, GRN_OBJ_VECTOR, range_id);
    while (n--) {
      grn_bool cast_failed = GRN_FALSE;
      grn_obj record, *element = v;
      if (range_id != element->header.domain) {
        GRN_RECORD_INIT(&record, 0, range_id);
        if (grn_obj_cast(ctx, element, &record, GRN_TRUE)) {
          cast_failed = GRN_TRUE;
          ERR_CAST(column, range, element);
        }
        element = &record;
      }
      if (!cast_failed) {
        GRN_UINT32_PUT(ctx, &buf, GRN_RECORD_VALUE(element));
      }
      if (element == &record) { GRN_OBJ_FIN(ctx, element); }
      v = values_next(ctx, v);
    }
  } else {
    if (((struct _grn_type *)range)->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) {
      GRN_TEXT_INIT(&buf, GRN_OBJ_VECTOR);
      while (n--) {
        switch (v->header.domain) {
        case GRN_DB_TEXT :
        {
          grn_bool cast_failed = GRN_FALSE;
          grn_obj casted_element, *element = v;
          if (range_id != element->header.domain) {
            GRN_OBJ_INIT(&casted_element, GRN_BULK, 0, range_id);
            if (grn_obj_cast(ctx, element, &casted_element, GRN_TRUE)) {
              cast_failed = GRN_TRUE;
              ERR_CAST(column, range, element);
            }
            element = &casted_element;
          }
          if (!cast_failed) {
            grn_vector_add_element(ctx, &buf,
                                   GRN_TEXT_VALUE(element),
                                   GRN_TEXT_LEN(element),
                                   0,
                                   element->header.domain);
          }
          if (element == &casted_element) { GRN_OBJ_FIN(ctx, element); }
          break;
        }
        case GRN_JSON_LOAD_OPEN_BRACE :
          add_weight_vector(ctx, column, v, &buf);
          n -= GRN_UINT32_VALUE(v);
          break;
        default :
          ERR(GRN_INVALID_ARGUMENT, "array must contain string or object");
          break;
        }
        v = values_next(ctx, v);
      }
    } else {
      grn_id value_size = ((grn_db_obj *)range)->range;
      GRN_VALUE_FIX_SIZE_INIT(&buf, GRN_OBJ_VECTOR, range_id);
      while (n--) {
        grn_bool cast_failed = GRN_FALSE;
        grn_obj casted_element, *element = v;
        if (range_id != element->header.domain) {
          GRN_OBJ_INIT(&casted_element, GRN_BULK, 0, range_id);
          if (grn_obj_cast(ctx, element, &casted_element, GRN_TRUE)) {
            cast_failed = GRN_TRUE;
            ERR_CAST(column, range, element);
          }
          element = &casted_element;
        }
        if (!cast_failed) {
          grn_bulk_write(ctx, &buf, GRN_TEXT_VALUE(element), value_size);
        }
        if (element == &casted_element) { GRN_OBJ_FIN(ctx, element); }
        v = values_next(ctx, v);
      }
    }
  }
  grn_obj_set_value(ctx, column, id, &buf, GRN_OBJ_SET);
  GRN_OBJ_FIN(ctx, &buf);
}
コード例 #20
0
ファイル: ctx.c プロジェクト: minagawa-sho/groonga
static int
grn_msgpack_buffer_write(void *data, const char *buf, msgpack_size_t len)
{
  grn_ctx *ctx = (grn_ctx *)data;
  return grn_bulk_write(ctx, ctx->impl->output.buf, buf, len);
}
コード例 #21
0
ファイル: output.c プロジェクト: ueno/groonga
void
grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
               grn_obj *obj, grn_obj_format *format)
{
  grn_obj buf;
  GRN_TEXT_INIT(&buf, 0);
  switch (obj->header.type) {
  case GRN_BULK :
    switch (obj->header.domain) {
    case GRN_DB_VOID :
      grn_output_void(ctx, outbuf, output_type, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
      break;
    case GRN_DB_SHORT_TEXT :
    case GRN_DB_TEXT :
    case GRN_DB_LONG_TEXT :
      grn_output_str(ctx, outbuf, output_type, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
      break;
    case GRN_DB_BOOL :
      grn_output_bool(ctx, outbuf, output_type,
                       GRN_BULK_VSIZE(obj) ? GRN_UINT8_VALUE(obj) : 0);
      break;
    case GRN_DB_INT8 :
      grn_output_int32(ctx, outbuf, output_type,
                       GRN_BULK_VSIZE(obj) ? GRN_INT8_VALUE(obj) : 0);
      break;
    case GRN_DB_UINT8 :
      grn_output_int32(ctx, outbuf, output_type,
                       GRN_BULK_VSIZE(obj) ? GRN_UINT8_VALUE(obj) : 0);
      break;
    case GRN_DB_INT16 :
      grn_output_int32(ctx, outbuf, output_type,
                       GRN_BULK_VSIZE(obj) ? GRN_INT16_VALUE(obj) : 0);
      break;
    case GRN_DB_UINT16 :
      grn_output_int32(ctx, outbuf, output_type,
                       GRN_BULK_VSIZE(obj) ? GRN_UINT16_VALUE(obj) : 0);
      break;
    case GRN_DB_INT32 :
      grn_output_int32(ctx, outbuf, output_type,
                       GRN_BULK_VSIZE(obj) ? GRN_INT32_VALUE(obj) : 0);
      break;
    case GRN_DB_UINT32 :
      grn_output_int64(ctx, outbuf, output_type,
                       GRN_BULK_VSIZE(obj) ? GRN_UINT32_VALUE(obj) : 0);
      break;
    case GRN_DB_INT64 :
      grn_output_int64(ctx, outbuf, output_type,
                       GRN_BULK_VSIZE(obj) ? GRN_INT64_VALUE(obj) : 0);
      break;
    case GRN_DB_UINT64 :
      grn_output_uint64(ctx, outbuf, output_type,
                        GRN_BULK_VSIZE(obj) ? GRN_UINT64_VALUE(obj) : 0);
      break;
    case GRN_DB_FLOAT :
      grn_output_float(ctx, outbuf, output_type,
                       GRN_BULK_VSIZE(obj) ? GRN_FLOAT_VALUE(obj) : 0);
      break;
    case GRN_DB_TIME :
      grn_output_time(ctx, outbuf, output_type,
                      GRN_BULK_VSIZE(obj) ? GRN_INT64_VALUE(obj) : 0);
      break;
    case GRN_DB_TOKYO_GEO_POINT :
    case GRN_DB_WGS84_GEO_POINT :
      grn_output_geo_point(ctx, outbuf, output_type,
                           GRN_BULK_VSIZE(obj) ? (grn_geo_point *)GRN_BULK_HEAD(obj) : NULL);
      break;
    default :
      if (format) {
        int j;
        int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *);
        grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns);
        if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) {
          grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", ncolumns);
          for (j = 0; j < ncolumns; j++) {
            grn_id range_id;
            grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2);
            GRN_BULK_REWIND(&buf);
            grn_column_name_(ctx, columns[j], &buf);
            grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
            /* column range */
            range_id = grn_obj_get_range(ctx, columns[j]);
            if (range_id == GRN_ID_NIL) {
              GRN_TEXT_PUTS(ctx, outbuf, "null");
            } else {
              int name_len;
              grn_obj *range_obj;
              char name_buf[GRN_TABLE_MAX_KEY_SIZE];

              range_obj = grn_ctx_at(ctx, range_id);
              name_len = grn_obj_name(ctx, range_obj, name_buf,
                                      GRN_TABLE_MAX_KEY_SIZE);
              GRN_BULK_REWIND(&buf);
              GRN_TEXT_PUT(ctx, &buf, name_buf, name_len);
              grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
            }
            grn_output_array_close(ctx, outbuf, output_type);
          }
          grn_output_array_close(ctx, outbuf, output_type);
        }
        grn_output_array_open(ctx, outbuf, output_type, "HIT", ncolumns);
        for (j = 0; j < ncolumns; j++) {
          grn_text_atoj_o(ctx, outbuf, output_type, columns[j], obj);
        }
        grn_output_array_close(ctx, outbuf, output_type);
      } else {
        grn_obj *table = grn_ctx_at(ctx, obj->header.domain);
        grn_id id = *((grn_id *)GRN_BULK_HEAD(obj));
        if (table && table->header.type != GRN_TABLE_NO_KEY) {
          grn_obj *accessor = grn_obj_column(ctx, table, "_key", 4);
          if (accessor) {
            grn_obj_get_value(ctx, accessor, id, &buf);
            grn_obj_unlink(ctx, accessor);
          }
          grn_output_obj(ctx, outbuf, output_type, &buf, format);
        } else {
          grn_output_int64(ctx, outbuf, output_type, id);
        }
      }
      break;
    }
    break;
  case GRN_UVECTOR :
    if (format) {
      int i, j;
      grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), *ve = (grn_id *)GRN_BULK_CURR(obj);
      int ncolumns = GRN_BULK_VSIZE(&format->columns) / sizeof(grn_obj *);
      grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns);
      grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", -1);
      grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1);
      grn_text_itoa(ctx, outbuf, ve - v);
      grn_output_array_close(ctx, outbuf, output_type);
      if (v < ve) {
        if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) {
          grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", -1);
          for (j = 0; j < ncolumns; j++) {
            grn_id range_id;
            grn_output_array_open(ctx, outbuf, output_type, "COLUMN", -1);
            GRN_BULK_REWIND(&buf);
            grn_column_name_(ctx, columns[j], &buf);
            grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
            /* column range */
            range_id = grn_obj_get_range(ctx, columns[j]);
            if (range_id == GRN_ID_NIL) {
              GRN_TEXT_PUTS(ctx, outbuf, "null");
            } else {
              int name_len;
              grn_obj *range_obj;
              char name_buf[GRN_TABLE_MAX_KEY_SIZE];

              range_obj = grn_ctx_at(ctx, range_id);
              name_len = grn_obj_name(ctx, range_obj, name_buf,
                                      GRN_TABLE_MAX_KEY_SIZE);
              GRN_BULK_REWIND(&buf);
              GRN_TEXT_PUT(ctx, &buf, name_buf, name_len);
              grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
            }
            grn_output_array_close(ctx, outbuf, output_type);
          }
          grn_output_array_close(ctx, outbuf, output_type);
        }
        for (i = 0;; i++) {
          grn_output_array_open(ctx, outbuf, output_type, "HITS", -1);
          for (j = 0; j < ncolumns; j++) {
            GRN_BULK_REWIND(&buf);
            grn_obj_get_value(ctx, columns[j], *v, &buf);
            grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
          }
          grn_output_array_close(ctx, outbuf, output_type);
          v++;
          if (v < ve) {

          } else {
            break;
          }
        }
      }
      grn_output_array_close(ctx, outbuf, output_type);
    } else {
      grn_obj *range = grn_ctx_at(ctx, obj->header.domain);
      if (range && range->header.type == GRN_TYPE) {
        int value_size = ((struct _grn_type *)range)->obj.range;
        char *v = (char *)GRN_BULK_HEAD(obj),
             *ve = (char *)GRN_BULK_CURR(obj);
        grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1);
        if (v < ve) {
          for (;;) {
            grn_obj value;
            GRN_OBJ_INIT(&value, GRN_BULK, 0, obj->header.domain);
            grn_bulk_write_from(ctx, &value, v, 0, value_size);
            grn_output_obj(ctx, outbuf, output_type, &value, NULL);

            v += value_size;
            if (v < ve) {

            } else {
              break;
            }
          }
        }
        grn_output_array_close(ctx, outbuf, output_type);
      } else {
        grn_id *v = (grn_id *)GRN_BULK_HEAD(obj),
               *ve = (grn_id *)GRN_BULK_CURR(obj);
        grn_output_array_open(ctx, outbuf, output_type, "VECTOR", ve - v);
        if (v < ve) {
          grn_obj key;
          GRN_OBJ_INIT(&key, GRN_BULK, 0, range->header.domain);
          for (;;) {
            if (range->header.type != GRN_TABLE_NO_KEY) {
              grn_table_get_key2(ctx, range, *v, &key);
              grn_output_obj(ctx, outbuf, output_type, &key, NULL);
              GRN_BULK_REWIND(&key);
            } else {
              grn_obj id;
              GRN_UINT32_INIT(&id, 0);
              GRN_UINT32_SET(ctx, &id, *v);
              grn_output_obj(ctx, outbuf, output_type, &id, NULL);
              GRN_OBJ_FIN(ctx, &id);
            }
            v++;
            if (v < ve) {

            } else {
              break;
            }
          }
          GRN_OBJ_FIN(ctx, &key);
        }
        grn_output_array_close(ctx, outbuf, output_type);
      }
    }
    break;
  case GRN_VECTOR :
    if (obj->header.domain == GRN_DB_VOID) {
      ERR(GRN_INVALID_ARGUMENT, "invalid obj->header.domain");
    }
    if (format) {
      ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
          "cannot print GRN_VECTOR using grn_obj_format");
    } else {
      unsigned int i, n;
      grn_obj value;
      GRN_VOID_INIT(&value);
      n = grn_vector_size(ctx, obj);
      grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1);
      for (i = 0; i < n; i++) {
        const char *_value;
        unsigned int weight, length;
        grn_id domain;

        length = grn_vector_get_element(ctx, obj, i,
                                        &_value, &weight, &domain);
        if (domain != GRN_DB_VOID) {
          grn_obj_reinit(ctx, &value, domain, 0);
        } else {
          grn_obj_reinit(ctx, &value, obj->header.domain, 0);
        }
        grn_bulk_write(ctx, &value, _value, length);
        grn_output_obj(ctx, outbuf, output_type, &value, NULL);
      }
      grn_output_array_close(ctx, outbuf, output_type);
      GRN_OBJ_FIN(ctx, &value);
    }
    break;
  case GRN_PVECTOR :
    if (format) {
      ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
          "cannot print GRN_PVECTOR using grn_obj_format");
    } else {
      unsigned int i, n;
      grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1);
      n = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *);
      for (i = 0; i < n; i++) {
        grn_obj *value;

        value = GRN_PTR_VALUE_AT(obj, i);
        grn_output_obj(ctx, outbuf, output_type, value, NULL);
      }
      grn_output_array_close(ctx, outbuf, output_type);
    }
    break;
  case GRN_TABLE_HASH_KEY :
  case GRN_TABLE_PAT_KEY :
  case GRN_TABLE_NO_KEY :
  case GRN_TABLE_VIEW :
    if (format) {
      int i, j;
      int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *);
      grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns);
      grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0,
                                                   format->offset, format->limit,
                                                   GRN_CURSOR_ASCENDING);
      int resultset_size = -1;
      if (!tc) { ERRCLR(ctx); }
#ifdef HAVE_MESSAGE_PACK
      resultset_size = 1; /* [NHITS, (COLUMNS), (HITS)] */
      if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) {
        resultset_size++;
      }
      resultset_size += format->limit;
#endif
      grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", resultset_size);
      grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1);
      if (output_type == GRN_CONTENT_XML) {
        grn_text_itoa(ctx, outbuf, format->nhits);
      } else {
        grn_output_int32(ctx, outbuf, output_type, format->nhits);
      }
      grn_output_array_close(ctx, outbuf, output_type);
      if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) {
        grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", ncolumns);
        for (j = 0; j < ncolumns; j++) {
          grn_id range_id;
          grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2);
          GRN_BULK_REWIND(&buf);
          grn_column_name_(ctx, columns[j], &buf);
          grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
          /* column range */
          range_id = grn_obj_get_range(ctx, columns[j]);
          if (range_id == GRN_ID_NIL) {
            GRN_TEXT_PUTS(ctx, outbuf, "null");
          } else {
            int name_len;
            grn_obj *range_obj;
            char name_buf[GRN_TABLE_MAX_KEY_SIZE];

            range_obj = grn_ctx_at(ctx, range_id);
            name_len = grn_obj_name(ctx, range_obj, name_buf,
                                    GRN_TABLE_MAX_KEY_SIZE);
            GRN_BULK_REWIND(&buf);
            GRN_TEXT_PUT(ctx, &buf, name_buf, name_len);
            grn_output_obj(ctx, outbuf, output_type, &buf, NULL);
          }
          grn_output_array_close(ctx, outbuf, output_type);
        }
        grn_output_array_close(ctx, outbuf, output_type);
      }
      if (tc) {
        grn_obj id;
        GRN_TEXT_INIT(&id, 0);
        for (i = 0; !grn_table_cursor_next_o(ctx, tc, &id); i++) {
          grn_output_array_open(ctx, outbuf, output_type, "HIT", ncolumns);
          for (j = 0; j < ncolumns; j++) {
            grn_text_atoj_o(ctx, outbuf, output_type, columns[j], &id);
          }
          grn_output_array_close(ctx, outbuf, output_type);
        }
        GRN_OBJ_FIN(ctx, &id);
        grn_table_cursor_close(ctx, tc);
      }
      grn_output_array_close(ctx, outbuf, output_type);
    } else {
      int i;
      grn_obj *column = grn_obj_column(ctx, obj, "_key", 4);
      grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0,
                                                   0, -1, GRN_CURSOR_ASCENDING);
      grn_output_array_open(ctx, outbuf, output_type, "HIT", -1);
      if (tc) {
        grn_obj id;
        GRN_TEXT_INIT(&id, 0);
        for (i = 0; !grn_table_cursor_next_o(ctx, tc, &id); i++) {
          /* todo:
          grn_text_atoj_o(ctx, outbuf, output_type, column, &id);
          */
          GRN_BULK_REWIND(&buf);
          grn_obj_get_value_o(ctx, column, &id, &buf);
          grn_text_esc(ctx, outbuf, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf));
        }
        GRN_OBJ_FIN(ctx, &id);
        grn_table_cursor_close(ctx, tc);
      }
      grn_output_array_close(ctx, outbuf, output_type);
      grn_obj_unlink(ctx, column);
    }
    break;
  }
  GRN_OBJ_FIN(ctx, &buf);
}