Kouhei Sutou
null+****@clear*****
Sun Feb 21 14:58:11 JST 2016
Kouhei Sutou 2016-02-21 14:58:11 +0900 (Sun, 21 Feb 2016) New Revision: 4d2595922bab3246c81dd4cc61631873ef684559 https://github.com/groonga/groonga/commit/4d2595922bab3246c81dd4cc61631873ef684559 Message: Support "XXX && column != xxx" with index It's treated as "XXX &! column == xxx". Modified files: lib/db.c lib/expr.c Modified: lib/db.c (+3 -0) =================================================================== --- lib/db.c 2016-02-21 12:45:44 +0900 (2abf09f) +++ lib/db.c 2016-02-21 14:58:11 +0900 (db1ab16) @@ -11822,6 +11822,7 @@ grn_column_find_index_data_accessor(grn_ctx *ctx, grn_obj *obj, } switch (op) { case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : case GRN_OP_TERM_EXTRACT : if (buf_size > 0) { index_buf[n] = obj; @@ -11899,6 +11900,7 @@ grn_column_index(grn_ctx *ctx, grn_obj *obj, grn_operator op, if (GRN_DB_OBJP(obj)) { switch (op) { case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : n = grn_column_find_index_data_column_equal(ctx, obj, op, NULL, 0, index_buf, buf_size, @@ -11949,6 +11951,7 @@ grn_column_find_index_data(grn_ctx *ctx, grn_obj *obj, grn_operator op, if (GRN_DB_OBJP(obj)) { switch (op) { case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : n = grn_column_find_index_data_column_equal(ctx, obj, op, index_data, n_index_data, NULL, 0, NULL); Modified: lib/expr.c (+116 -0) =================================================================== --- lib/expr.c 2016-02-21 12:45:44 +0900 (20a3e29) +++ lib/expr.c 2016-02-21 14:58:11 +0900 (b97de51) @@ -5613,6 +5613,119 @@ grn_table_select_index_equal(grn_ctx *ctx, } static inline grn_bool +grn_table_select_index_not_equal(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + scan_info *si, + grn_obj *res) +{ + grn_bool processed = GRN_FALSE; + + if (GRN_BULK_VSIZE(si->query) == 0) { + /* We can't use index for empty value. */ + return GRN_FALSE; + } + + if (si->logical_op != GRN_OP_AND) { + /* We can't use index for OR and AND_NOT. */ + return GRN_FALSE; + } + + if (si->flags & SCAN_ACCESSOR) { + if (index->header.type == GRN_ACCESSOR && !((grn_accessor *)index)->next) { + grn_obj dest; + grn_accessor *a = (grn_accessor *)index; + grn_id id; + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + grn_table_select_index_report(ctx, "[not-equal][accessor][id]", table); + GRN_UINT32_INIT(&dest, 0); + if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) { + id = GRN_UINT32_VALUE(&dest); + if (id != GRN_ID_NIL) { + if (id == grn_table_at(ctx, table, id)) { + grn_hash_delete(ctx, (grn_hash *)res, &id, sizeof(grn_id), NULL); + } + } + processed = GRN_TRUE; + } + GRN_OBJ_FIN(ctx, &dest); + break; + case GRN_ACCESSOR_GET_KEY : + grn_table_select_index_report(ctx, "[not-equal][accessor][key]", table); + GRN_OBJ_INIT(&dest, GRN_BULK, 0, table->header.domain); + if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) { + id = grn_table_get(ctx, table, + GRN_BULK_HEAD(&dest), + GRN_BULK_VSIZE(&dest)); + if (id != GRN_ID_NIL) { + grn_hash_delete(ctx, (grn_hash *)res, &id, sizeof(grn_id), NULL); + } + processed = GRN_TRUE; + } + GRN_OBJ_FIN(ctx, &dest); + break; + } + } + } else { + grn_obj *domain = grn_ctx_at(ctx, index->header.domain); + if (domain) { + grn_id tid; + if (GRN_OBJ_GET_DOMAIN(si->query) == DB_OBJ(domain)->id) { + tid = GRN_RECORD_VALUE(si->query); + } else { + tid = grn_table_get(ctx, domain, + GRN_BULK_HEAD(si->query), + GRN_BULK_VSIZE(si->query)); + } + if (tid == GRN_ID_NIL) { + processed = GRN_TRUE; + } else { + uint32_t sid; + int32_t weight; + grn_ii *ii = (grn_ii *)index; + grn_ii_cursor *ii_cursor; + + grn_table_select_index_report(ctx, "[not-equal]", index); + + sid = GRN_UINT32_VALUE_AT(&(si->wv), 0); + weight = GRN_INT32_VALUE_AT(&(si->wv), 1); + ii_cursor = grn_ii_cursor_open(ctx, ii, tid, + GRN_ID_NIL, GRN_ID_MAX, + ii->n_elements, 0); + if (ii_cursor) { + grn_posting *posting; + while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) { + if (!(sid == 0 || posting->sid == sid)) { + continue; + } + + if (si->position.specified) { + while ((posting = grn_ii_cursor_next_pos(ctx, ii_cursor))) { + if (posting->pos == si->position.start) { + break; + } + } + if (!posting) { + continue; + } + } + + grn_hash_delete(ctx, (grn_hash *)res, + &(posting->rid), sizeof(grn_id), + NULL); + } + grn_ii_cursor_close(ctx, ii_cursor); + processed = GRN_TRUE; + } + } + } + } + + return processed; +} + +static inline grn_bool grn_table_select_index_range_column(grn_ctx *ctx, grn_obj *table, grn_obj *index, scan_info *si, grn_operator logical_op, @@ -5925,6 +6038,9 @@ grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si, case GRN_OP_EQUAL : processed = grn_table_select_index_equal(ctx, table, index, si, res); break; + case GRN_OP_NOT_EQUAL : + processed = grn_table_select_index_not_equal(ctx, table, index, si, res); + break; case GRN_OP_SUFFIX : { grn_obj *domain; -------------- next part -------------- HTML����������������������������... Download