null+****@clear*****
null+****@clear*****
2010年 7月 1日 (木) 10:25:34 JST
Daijiro MORI 2010-07-01 01:25:34 +0000 (Thu, 01 Jul 2010) New Revision: 5ecfba725e61d32d872b5e279f5ae103250e483a Log: Added grn_geo_search(). Modified files: lib/db.c lib/expr.c lib/proc.c Modified: lib/db.c (+1 -0) =================================================================== --- lib/db.c 2010-06-30 01:34:55 +0000 (3cf15d9) +++ lib/db.c 2010-07-01 01:25:34 +0000 (d15ba14) @@ -6672,6 +6672,7 @@ grn_column_index(grn_ctx *ctx, grn_obj *obj, grn_operator op, case GRN_OP_GREATER : case GRN_OP_LESS_EQUAL : case GRN_OP_GREATER_EQUAL : + case GRN_OP_CALL : for (hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) { default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks); grn_obj *target = grn_ctx_at(ctx, data->target); Modified: lib/expr.c (+20 -5) =================================================================== --- lib/expr.c 2010-06-30 01:34:55 +0000 (cd07427) +++ lib/expr.c 2010-07-01 01:25:34 +0000 (671f271) @@ -3582,21 +3582,25 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, si->op = c->op; si->end = c - e->codes; sis[i++] = si; - /* index may be applicable occasionaly + /* better index resolving framework for functions should be implemented */ { - grn_obj **p = si->args, **pe = si->args + si->nargs; + uint32_t sid; + grn_obj *index, **p = si->args, **pe = si->args + si->nargs; for (; p < pe; p++) { if (GRN_DB_OBJP(*p)) { - grn_column_index(ctx, *p, c->op, &si->index, 1, &sid); + if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) { + scan_info_put_index(ctx, si, index, sid, 1); + } } else if (GRN_ACCESSORP(*p)) { si->flags |= SCAN_ACCESSOR; - grn_column_index(ctx, *p, c->op, &si->index, 1, &sid); + if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) { + scan_info_put_index(ctx, si, index, sid, 1); + } } else { si->query = *p; } } } - */ si = NULL; } else { stat = SCAN_COL2; @@ -3760,6 +3764,9 @@ grn_view_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, GRN_LOG(ctx, GRN_LOG_NONE, "%08x|:%012llu %s", (intptr_t)ctx, et, msg);\ } +grn_rc grn_geo_search(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int nargs, + grn_obj *res, grn_operator op); + grn_obj * grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *res, grn_operator op) @@ -3973,6 +3980,14 @@ grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, } } break; + case GRN_OP_CALL : + /* geo_in_circle only */ + if (si->flags & SCAN_ACCESSOR) { + } else { + grn_geo_search(ctx, index, si->args, si->nargs, res, si->logical_op); + done++; + } + break; default : /* todo : implement */ /* todo : handle SCAN_PRE_CONST */ Modified: lib/proc.c (+83 -0) =================================================================== --- lib/proc.c 2010-06-30 01:34:55 +0000 (048395f) +++ lib/proc.c 2010-07-01 01:25:34 +0000 (cf23748) @@ -22,6 +22,7 @@ #include <sys/stat.h> #include "proc.h" #include "ql.h" +#include "ii.h" #include "db.h" #include "util.h" #include "output.h" @@ -1929,6 +1930,88 @@ exit : return obj; } +grn_rc +grn_geo_search(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int nargs, + grn_obj *res, grn_operator op) +{ + grn_id domain; + double lng0, lat0, lng1, lat1, lng2, lat2, x, y, d; + grn_obj *pos1 = args[1], *pos2 = args[2], pos1_, pos2_; + grn_obj *pat = grn_ctx_at(ctx, obj->header.domain); + if (nargs != 3) { goto exit; } + domain = pat->header.domain; + if (domain != GRN_DB_TOKYO_GEO_POINT && domain != GRN_DB_WGS84_GEO_POINT) { goto exit; } + if (pos1->header.domain != domain) { + GRN_OBJ_INIT(&pos1_, GRN_BULK, 0, domain); + if (grn_obj_cast(ctx, pos1, &pos1_, 0)) { goto exit; } + pos1 = &pos1_; + } + lng1 = GEO_INT2RAD(((grn_geo_point *)GRN_BULK_HEAD(pos1))->longitude); + lat1 = GEO_INT2RAD(((grn_geo_point *)GRN_BULK_HEAD(pos1))->latitude); + switch (pos2->header.domain) { + case GRN_DB_INT32 : + d = GRN_INT32_VALUE(pos2); + d = d * d / GEO_RADIOUS; + break; + case GRN_DB_UINT32 : + d = GRN_UINT32_VALUE(pos2); + d = d * d / GEO_RADIOUS; + break; + case GRN_DB_INT64 : + d = GRN_INT64_VALUE(pos2); + d = d * d / GEO_RADIOUS; + break; + case GRN_DB_UINT64 : + d = GRN_UINT64_VALUE(pos2); + d = d * d / GEO_RADIOUS; + break; + case GRN_DB_FLOAT : + d = GRN_FLOAT_VALUE(pos2); + d = d * d / GEO_RADIOUS; + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + GRN_OBJ_INIT(&pos2_, GRN_BULK, 0, domain); + if (grn_obj_cast(ctx, pos2, &pos2_, 0)) { goto exit; } + pos2 = &pos2_; + /* fallthru */ + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + if (domain != pos2->header.domain) { /* todo */ goto exit; } + lng2 = GEO_INT2RAD(((grn_geo_point *)GRN_BULK_HEAD(pos2))->longitude); + lat2 = GEO_INT2RAD(((grn_geo_point *)GRN_BULK_HEAD(pos2))->latitude); + x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5); + y = (lat2 - lat1); + d = ((x * x) + (y * y)); + break; + default : + goto exit; + } + { + grn_id tid; + grn_geo_point pos; + grn_table_cursor *tc = grn_table_cursor_open(ctx, pat, NULL, 0, + GRN_BULK_HEAD(pos1), + sizeof(grn_geo_point), + 0, -1, GRN_CURSOR_PREFIX); + while ((tid = grn_table_cursor_next(ctx, tc))) { + grn_table_get_key(ctx, pat, tid, &pos, sizeof(grn_geo_point)); + lng0 = GEO_INT2RAD(pos.longitude); + lat0 = GEO_INT2RAD(pos.latitude); + x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5); + y = (lat1 - lat0); + if (((x * x) + (y * y)) <= d) { + grn_ii_at(ctx, (grn_ii *)index, tid, (grn_hash *)res, op); + } + } + grn_table_cursor_close(ctx, tc); + } +exit : + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + return ctx->rc; +} + static grn_obj * func_geo_in_rectangle(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) {