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)
{