Skip to content

Commit

Permalink
Support {"VALUE" => WEIGHT} style weight value assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
kou committed Mar 21, 2014
1 parent fa9202d commit 0a4ba1b
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 32 deletions.
97 changes: 66 additions & 31 deletions ext/groonga/rb-grn-variable-size-column.c
Expand Up @@ -210,6 +210,32 @@ rb_grn_variable_size_column_array_reference (VALUE self, VALUE rb_id)
return rb_value;
}

typedef struct {
grn_ctx *context;
grn_obj *vector;
grn_obj *element_value;
} HashElementToVectorElementData;

static int
hash_element_to_vector_element(VALUE key, VALUE value, VALUE user_data)
{
HashElementToVectorElementData *data =
(HashElementToVectorElementData *)user_data;
unsigned int weight;

GRN_BULK_REWIND(data->element_value);
RVAL2GRNBULK(key, data->context, data->element_value);

weight = NUM2UINT(value);
grn_vector_add_element(data->context, data->vector,
GRN_BULK_HEAD(data->element_value),
GRN_BULK_VSIZE(data->element_value),
weight,
data->element_value->header.domain);

return ST_CONTINUE;
}

/*
* It updates a value of variable size column value for the record
* that ID is _id_.
Expand Down Expand Up @@ -329,7 +355,6 @@ rb_grn_variable_size_column_array_set (VALUE self, VALUE rb_id, VALUE rb_value)
grn_rc rc;
grn_id id;
grn_obj *value, *element_value;
int i, n;
int flags = GRN_OBJ_SET;

rb_grn_variable_size_column_deconstruct(SELF(self), &column, &context,
Expand All @@ -345,42 +370,52 @@ rb_grn_variable_size_column_array_set (VALUE self, VALUE rb_id, VALUE rb_value)

id = RVAL2GRNID(rb_id, context, range, self);

if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_value, rb_cArray))) {
grn_obj_reinit(context, value,
value->header.domain,
value->header.flags | GRN_OBJ_VECTOR);
if (RVAL2CBOOL(rb_obj_is_kind_of(rb_value, rb_cArray))) {
int i, n;
n = RARRAY_LEN(rb_value);
for (i = 0; i < n; i++) {
unsigned int weight = 0;
VALUE rb_element_value, rb_weight;

rb_grn_scan_options(RARRAY_PTR(rb_value)[i],
"value", &rb_element_value,
"weight", &rb_weight,
NULL);

if (!NIL_P(rb_weight)) {
weight = NUM2UINT(rb_weight);
}

GRN_BULK_REWIND(element_value);
if (!NIL_P(rb_element_value)) {
RVAL2GRNBULK(rb_element_value, context, element_value);
}

grn_vector_add_element(context, value,
GRN_BULK_HEAD(element_value),
GRN_BULK_VSIZE(element_value),
weight,
element_value->header.domain);
}
} else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_value, rb_cHash))) {
HashElementToVectorElementData data;
data.context = context;
data.vector = value;
data.element_value = element_value;
rb_hash_foreach(rb_value, hash_element_to_vector_element, (VALUE)&data);
} else {
rb_raise(rb_eArgError,
"<%s>: "
"weight vector value must be an array of index value: <%s>",
"weight vector value must be an array of index value or "
"a hash that key is vector value and value is vector weight: "
"<%s>",
rb_grn_inspect(self),
rb_grn_inspect(rb_value));
}

grn_obj_reinit(context, value,
value->header.domain,
value->header.flags | GRN_OBJ_VECTOR);
n = RARRAY_LEN(rb_value);
for (i = 0; i < n; i++) {
unsigned int weight = 0;
VALUE rb_element_value, rb_weight;

rb_grn_scan_options(RARRAY_PTR(rb_value)[i],
"value", &rb_element_value,
"weight", &rb_weight,
NULL);

if (!NIL_P(rb_weight)) {
weight = NUM2UINT(rb_weight);
}

GRN_BULK_REWIND(element_value);
if (!NIL_P(rb_element_value)) {
RVAL2GRNBULK(rb_element_value, context, element_value);
}

grn_vector_add_element(context, value,
GRN_BULK_HEAD(element_value),
GRN_BULK_VSIZE(element_value),
weight,
element_value->header.domain);
}
rc = grn_obj_set_value(context, column, id, value, flags);
rb_grn_context_check(context, self);
rb_grn_rc_check(rc, self);
Expand Down
22 changes: 21 additions & 1 deletion test/test-variable-size-column.rb
Expand Up @@ -252,7 +252,7 @@ def setup_schema
@products = Groonga["Products"]
end

def test_accessor
def test_array
groonga = @products.add("Groonga")
groonga.tags = [
{
Expand All @@ -277,6 +277,26 @@ def test_accessor
],
groonga.tags)
end

def test_hash
groonga = @products.add("Groonga")
groonga.tags = {
"groonga" => 100,
"full text search" => 1000,
}

assert_equal([
{
:value => "groonga",
:weight => 100,
},
{
:value => "full text search",
:weight => 1000,
},
],
groonga.tags)
end
end
end
end

0 comments on commit 0a4ba1b

Please sign in to comment.