Kouhei Sutou
null+****@clear*****
Wed Dec 3 23:20:56 JST 2014
Kouhei Sutou 2014-12-03 23:20:56 +0900 (Wed, 03 Dec 2014) New Revision: f3c4aee295034c82841416272d4331c0ba142626 https://github.com/groonga/groonga/commit/f3c4aee295034c82841416272d4331c0ba142626 Message: Fix a regression bug that "equal" against nonexitent reference always matches grn_obj_get_value() returns value its type is not real value type for nonexistent reference in the middle of accessor. For example: Think about the following schema: table_create Bookmarks TABLE_HASH_KEY ShortText column_create Bookmarks title COLUMN_SCALAR ShortText table_create Users TABLE_HASH_KEY ShortText column_create Users bookmark COLUMN_SCALAR Bookmarks And the following data: load --table Bookmarks [ {"_key": "http://groonga.org/", "title": "Groonga"} ] load --table Users [ {"_key": "alice", "bookmark": "http://groonga.org/"}, {"_key": "bob"} ] "bob" user is important. "bob"'s bookmark column value is nonexistent. grn_obj_get_value() for "bookmark.name" accessor and "bob" user returns Bookmarks type value not ShortText type value. Because grn_obj_get_value() for accessor stops value resolving when there is nonexistent reference. With this change, grn_obj_get_value() always returns real value type even if there is nonexistent reference. Added files: test/command/suite/select/filter/no_index/equal/nonexistent_reference.expected test/command/suite/select/filter/no_index/equal/nonexistent_reference.test Modified files: lib/db.c Modified: lib/db.c (+89 -59) =================================================================== --- lib/db.c 2014-12-02 13:57:56 +0900 (38eb9b0) +++ lib/db.c 2014-12-03 23:20:56 +0900 (cbd36f4) @@ -5432,21 +5432,28 @@ grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value) break; case GRN_ACCESSOR_GET_KEY : if (!a->next && GRN_TABLE_IS_GROUPED(a->obj)) { - grn_obj raw_vector; - GRN_TEXT_INIT(&raw_vector, 0); - grn_table_get_key2(ctx, a->obj, id, &raw_vector); grn_obj_ensure_vector(ctx, value); - grn_vector_decode(ctx, value, - GRN_BULK_HEAD(&raw_vector), - GRN_BULK_VSIZE(&raw_vector)); - GRN_OBJ_FIN(ctx, &raw_vector); + if (id) { + grn_obj raw_vector; + GRN_TEXT_INIT(&raw_vector, 0); + grn_table_get_key2(ctx, a->obj, id, &raw_vector); + grn_vector_decode(ctx, value, + GRN_BULK_HEAD(&raw_vector), + GRN_BULK_VSIZE(&raw_vector)); + GRN_OBJ_FIN(ctx, &raw_vector); + } vp = NULL; vs = 0; } else { - grn_table_get_key2(ctx, a->obj, id, value); + if (id) { + grn_table_get_key2(ctx, a->obj, id, value); + vp = GRN_BULK_HEAD(value) + size0; + vs = GRN_BULK_VSIZE(value) - size0; + } else { + vp = NULL; + vs = 0; + } value->header.domain = a->obj->header.domain; - vp = GRN_BULK_HEAD(value) + size0; - vs = GRN_BULK_VSIZE(value) - size0; } break; case GRN_ACCESSOR_GET_VALUE : @@ -5455,16 +5462,20 @@ grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value) vs = GRN_BULK_VSIZE(value) - size0; break; case GRN_ACCESSOR_GET_SCORE : - { + if (id) { grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); GRN_INT32_PUT(ctx, value, ri->score); + } else { + GRN_INT32_PUT(ctx, value, 0); } value->header.domain = GRN_DB_INT32; break; case GRN_ACCESSOR_GET_NSUBRECS : - { + if (id) { grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); GRN_INT32_PUT(ctx, value, ri->n_subrecs); + } else { + GRN_INT32_PUT(ctx, value, 0); } value->header.domain = GRN_DB_INT32; break; @@ -5487,7 +5498,11 @@ grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value) break; } if ((a = a->next)) { - id = *((grn_id *)vp); + if (vs > 0) { + id = *((grn_id *)vp); + } else { + id = GRN_ID_NIL; + } } else { break; } @@ -6308,7 +6323,11 @@ grn_obj_get_value_column_index(grn_ctx *ctx, grn_obj *index_column, { grn_ii *ii = (grn_ii *)index_column; grn_obj_ensure_bulk(ctx, value); - GRN_UINT32_SET(ctx, value, grn_ii_estimate_size(ctx, ii, id)); + if (id) { + GRN_UINT32_SET(ctx, value, grn_ii_estimate_size(ctx, ii, id)); + } else { + GRN_UINT32_SET(ctx, value, 0); + } value->header.domain = GRN_DB_UINT32; } @@ -6321,15 +6340,19 @@ grn_obj_get_value_column_vector(grn_ctx *ctx, grn_obj *obj, lexicon = grn_ctx_at(ctx, DB_OBJ(obj)->range); if (lexicon && !GRN_OBJ_TABLEP(lexicon) && (lexicon->header.flags & GRN_OBJ_KEY_VAR_SIZE)) { - grn_obj v_; grn_obj_ensure_vector(ctx, value); - GRN_TEXT_INIT(&v_, 0); - grn_ja_get_value(ctx, (grn_ja *)obj, id, &v_); - grn_vector_decode(ctx, value, GRN_TEXT_VALUE(&v_), GRN_TEXT_LEN(&v_)); - GRN_OBJ_FIN(ctx, &v_); + if (id) { + grn_obj v_; + GRN_TEXT_INIT(&v_, 0); + grn_ja_get_value(ctx, (grn_ja *)obj, id, &v_); + grn_vector_decode(ctx, value, GRN_TEXT_VALUE(&v_), GRN_TEXT_LEN(&v_)); + GRN_OBJ_FIN(ctx, &v_); + } } else { grn_obj_ensure_bulk(ctx, value); - grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + if (id) { + grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + } value->header.type = GRN_UVECTOR; if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) { value->header.flags |= GRN_OBJ_WITH_WEIGHT; @@ -6345,7 +6368,6 @@ grn_obj * grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) { GRN_API_ENTER; - if (!id) { goto exit; } if (!obj) { ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed"); goto exit; @@ -6382,13 +6404,15 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) grn_pat *pat = (grn_pat *)obj; uint32_t size = pat->value_size; grn_obj_ensure_bulk(ctx, value); - if (grn_bulk_space(ctx, value, size)) { - MERR("grn_bulk_space failed"); - goto exit; - } - { - char *curr = GRN_BULK_CURR(value); - grn_pat_get_value(ctx, pat, id, curr - size); + if (id) { + if (grn_bulk_space(ctx, value, size)) { + MERR("grn_bulk_space failed"); + goto exit; + } + { + char *curr = GRN_BULK_CURR(value); + grn_pat_get_value(ctx, pat, id, curr - size); + } } value->header.type = GRN_BULK; value->header.domain = grn_obj_get_range(ctx, obj); @@ -6402,27 +6426,29 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) grn_bool processed = GRN_FALSE; grn_obj_ensure_bulk(ctx, value); value->header.domain = grn_obj_get_range(ctx, obj); - if (GRN_TABLE_IS_GROUPED(obj)) { - grn_obj *domain; - domain = grn_ctx_at(ctx, value->header.domain); - if (GRN_OBJ_TABLEP(domain)) { - grn_id subrec_id; - if (grn_table_get_subrecs(ctx, obj, id, &subrec_id, NULL, 1) == 1) { - GRN_RECORD_SET(ctx, value, subrec_id); - processed = GRN_TRUE; + if (id) { + if (GRN_TABLE_IS_GROUPED(obj)) { + grn_obj *domain; + domain = grn_ctx_at(ctx, value->header.domain); + if (GRN_OBJ_TABLEP(domain)) { + grn_id subrec_id; + if (grn_table_get_subrecs(ctx, obj, id, &subrec_id, NULL, 1) == 1) { + GRN_RECORD_SET(ctx, value, subrec_id); + processed = GRN_TRUE; + } } } - } - if (!processed) { - grn_hash *hash = (grn_hash *)obj; - uint32_t size = hash->value_size; - if (grn_bulk_space(ctx, value, size)) { - MERR("grn_bulk_space failed"); - goto exit; - } - { - char *curr = GRN_BULK_CURR(value); - grn_hash_get_value(ctx, hash, id, curr - size); + if (!processed) { + grn_hash *hash = (grn_hash *)obj; + uint32_t size = hash->value_size; + if (grn_bulk_space(ctx, value, size)) { + MERR("grn_bulk_space failed"); + goto exit; + } + { + char *curr = GRN_BULK_CURR(value); + grn_hash_get_value(ctx, hash, id, curr - size); + } } } } @@ -6432,13 +6458,15 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) grn_array *array = (grn_array *)obj; uint32_t size = array->value_size; grn_obj_ensure_bulk(ctx, value); - if (grn_bulk_space(ctx, value, size)) { - MERR("grn_bulk_space failed"); - goto exit; - } - { - char *curr = GRN_BULK_CURR(value); - grn_array_get_value(ctx, array, id, curr - size); + if (id) { + if (grn_bulk_space(ctx, value, size)) { + MERR("grn_bulk_space failed"); + goto exit; + } + { + char *curr = GRN_BULK_CURR(value); + grn_array_get_value(ctx, array, id, curr - size); + } } value->header.type = GRN_BULK; value->header.domain = grn_obj_get_range(ctx, obj); @@ -6451,7 +6479,9 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) break; case GRN_OBJ_COLUMN_SCALAR : grn_obj_ensure_bulk(ctx, value); - grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + if (id) { + grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + } value->header.type = GRN_BULK; break; default : @@ -6461,12 +6491,12 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) value->header.domain = grn_obj_get_range(ctx, obj); break; case GRN_COLUMN_FIX_SIZE : - { + grn_obj_ensure_bulk(ctx, value); + value->header.type = GRN_BULK; + value->header.domain = grn_obj_get_range(ctx, obj); + if (id) { unsigned int element_size; void *v = grn_ra_ref(ctx, (grn_ra *)obj, id); - grn_obj_ensure_bulk(ctx, value); - value->header.type = GRN_BULK; - value->header.domain = grn_obj_get_range(ctx, obj); if (v) { element_size = ((grn_ra *)obj)->header->element_size; grn_bulk_write(ctx, value, v, element_size); Added: test/command/suite/select/filter/no_index/equal/nonexistent_reference.expected (+53 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/no_index/equal/nonexistent_reference.expected 2014-12-03 23:20:56 +0900 (89b0168) @@ -0,0 +1,53 @@ +table_create Bookmarks TABLE_HASH_KEY ShortText +[[0,0.0,0.0],true] +column_create Bookmarks title COLUMN_SCALAR ShortText +[[0,0.0,0.0],true] +table_create Users TABLE_HASH_KEY ShortText +[[0,0.0,0.0],true] +column_create Users bookmark COLUMN_SCALAR Bookmarks +[[0,0.0,0.0],true] +load --table Bookmarks +[ +{"_key": "http://groonga.org/", "title": "Groonga"} +] +[[0,0.0,0.0],1] +load --table Users +[ +{"_key": "alice", "bookmark": "http://groonga.org/"}, +{"_key": "bob"} +] +[[0,0.0,0.0],2] +select Users --filter 'bookmark.title == "Groonga"' +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 1 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "_key", + "ShortText" + ], + [ + "bookmark", + "Bookmarks" + ] + ], + [ + 1, + "alice", + "http://groonga.org/" + ] + ] + ] +] Added: test/command/suite/select/filter/no_index/equal/nonexistent_reference.test (+18 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/no_index/equal/nonexistent_reference.test 2014-12-03 23:20:56 +0900 (4a95701) @@ -0,0 +1,18 @@ +table_create Bookmarks TABLE_HASH_KEY ShortText +column_create Bookmarks title COLUMN_SCALAR ShortText + +table_create Users TABLE_HASH_KEY ShortText +column_create Users bookmark COLUMN_SCALAR Bookmarks + +load --table Bookmarks +[ +{"_key": "http://groonga.org/", "title": "Groonga"} +] + +load --table Users +[ +{"_key": "alice", "bookmark": "http://groonga.org/"}, +{"_key": "bob"} +] + +select Users --filter 'bookmark.title == "Groonga"' -------------- next part -------------- HTML����������������������������... Download