null+****@clear*****
null+****@clear*****
Fri Aug 10 17:24:12 JST 2012
Kouhei Sutou 2012-08-10 17:24:12 +0900 (Fri, 10 Aug 2012) New Revision: a110165aaa3b79e522764b96dd5d93a69bdb9257 https://github.com/groonga/groonga/commit/a110165aaa3b79e522764b96dd5d93a69bdb9257 Log: Support custom selector definition Selector is a function that collects matched records into resultset table. Selector works fast because it can use index. geo_in_circle() and geo_in_rectangle() are existing selectors. They are defined by the mechanism intruduced in the change. Modified files: lib/db.h lib/expr.c lib/geo.c lib/geo.h lib/proc.c Modified: lib/db.h (+9 -0) =================================================================== --- lib/db.h 2012-08-10 17:19:56 +0900 (b973242) +++ lib/db.h 2012-08-10 17:24:12 +0900 (9c20d32) @@ -153,6 +153,10 @@ typedef struct { (GRN_TABLE_HASH_KEY <= ((grn_db_obj *)obj)->header.type) &&\ (((grn_db_obj *)obj)->header.type <= GRN_DB)) +typedef grn_rc grn_selector_func(grn_ctx *ctx, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op); + typedef struct _grn_proc_ctx grn_proc_ctx; struct _grn_proc_ctx { @@ -177,6 +181,8 @@ struct _grn_proc { grn_proc_type type; grn_proc_func *funcs[3]; + grn_selector_func *selector; + grn_id module; // uint32_t nargs; // uint32_t nresults; @@ -196,6 +202,9 @@ GRN_API grn_obj *grn_proc_get_var_by_offset(grn_ctx *ctx, grn_user_data *user_da GRN_API grn_obj *grn_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, grn_id domain, grn_obj_flags flags); +grn_rc grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, + grn_selector_func selector); + grn_obj *grn_expr_get_or_add_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size); Modified: lib/expr.c (+24 -14) =================================================================== --- lib/expr.c 2012-08-10 17:19:56 +0900 (1f951c7) +++ lib/expr.c 2012-08-10 17:24:12 +0900 (5b7f48b) @@ -31,6 +31,11 @@ function_proc_p(grn_obj *obj) obj->header.type == GRN_PROC && ((grn_proc *)obj)->type == GRN_PROC_FUNCTION); } + +static inline int +selector_proc_p(grn_obj *obj) +{ + return (function_proc_p(obj) && ((grn_proc *)obj)->selector); } grn_obj * @@ -142,6 +147,17 @@ grn_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, grn_id domain, grn_obj_fl return pctx->caller ? grn_expr_alloc(ctx, (grn_obj *)pctx->caller, domain, flags) : NULL; } +grn_rc +grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, grn_selector_func selector) +{ + grn_proc *proc_ = (grn_proc *)proc; + if (!function_proc_p(proc)) { + return GRN_INVALID_ARGUMENT; + } + proc_->selector = selector; + return GRN_SUCCESS; +} + /* grn_expr */ static const char *opstrs[] = { @@ -4248,20 +4264,14 @@ grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, break; case GRN_OP_CALL : if (si->flags & SCAN_ACCESSOR) { - } else { - char buf[GRN_TABLE_MAX_KEY_SIZE]; - int len = grn_obj_name(ctx, si->args[0], buf, - GRN_TABLE_MAX_KEY_SIZE); - /* geo_in_circle and geo_in_rectangle only */ - if (len == 13 && !memcmp(buf, "geo_in_circle", 13)) { - /* TODO: error check */ - grn_selector_geo_in_circle(ctx, index, si->args, si->nargs, - res, si->logical_op); - done++; - } else if (len == 16 && !memcmp(buf, "geo_in_rectangle", 16)) { - /* TODO: error check */ - grn_selector_geo_in_rectangle(ctx, index, si->args, si->nargs, - res, si->logical_op); + } else if (selector_proc_p(si->args[0])) { + grn_rc rc; + grn_proc *proc = si->args[0]; + rc = proc->selector(ctx, index, si->nargs, si->args, + res, si->logical_op); + if (rc) { + /* TODO: report error */ + } else { done++; } } Modified: lib/geo.c (+3 -2) =================================================================== --- lib/geo.c 2012-08-10 17:19:56 +0900 (e474696) +++ lib/geo.c 2012-08-10 17:24:12 +0900 (4cd8258) @@ -673,7 +673,8 @@ typedef double (*grn_geo_distance_raw_func)(grn_ctx *ctx, grn_geo_point *point2); grn_rc -grn_selector_geo_in_circle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int nargs, +grn_selector_geo_in_circle(grn_ctx *ctx, grn_obj *obj, + int nargs, grn_obj **args, grn_obj *res, grn_operator op) { grn_geo_approximate_type type = GRN_GEO_APPROXIMATE_RECTANGLE; @@ -884,7 +885,7 @@ exit : grn_rc grn_selector_geo_in_rectangle(grn_ctx *ctx, grn_obj *obj, - grn_obj **args, int nargs, + int nargs, grn_obj **args, grn_obj *res, grn_operator op) { if (nargs == 4) { Modified: lib/geo.h (+6 -4) =================================================================== --- lib/geo.h 2012-08-10 17:19:56 +0900 (5a0ef36) +++ lib/geo.h 2012-08-10 17:24:12 +0900 (8fd2e7d) @@ -133,10 +133,12 @@ grn_rc grn_geo_select_in_circle(grn_ctx *ctx, grn_obj *res, grn_operator op); -grn_rc grn_selector_geo_in_circle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, - int nargs, grn_obj *res, grn_operator op); -grn_rc grn_selector_geo_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, - int nargs, grn_obj *res, grn_operator op); +grn_rc grn_selector_geo_in_circle(grn_ctx *ctx, grn_obj *obj, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op); +grn_rc grn_selector_geo_in_rectangle(grn_ctx *ctx, grn_obj *obj, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op); GRN_API grn_bool grn_geo_in_circle(grn_ctx *ctx, grn_obj *point, grn_obj *center, grn_obj *radius_or_point, Modified: lib/proc.c (+11 -4) =================================================================== --- lib/proc.c 2012-08-10 17:19:56 +0900 (5e855a4) +++ lib/proc.c 2012-08-10 17:24:12 +0900 (714e4ad) @@ -2968,11 +2968,18 @@ grn_db_init_builtin_query(grn_ctx *ctx) grn_proc_create(ctx, "now", 3, GRN_PROC_FUNCTION, func_now, NULL, NULL, 0, vars); - grn_proc_create(ctx, "geo_in_circle", 13, GRN_PROC_FUNCTION, - func_geo_in_circle, NULL, NULL, 0, NULL); + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "geo_in_circle", 13, GRN_PROC_FUNCTION, + func_geo_in_circle, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, grn_selector_geo_in_circle); - grn_proc_create(ctx, "geo_in_rectangle", 16, GRN_PROC_FUNCTION, - func_geo_in_rectangle, NULL, NULL, 0, NULL); + selector_proc = grn_proc_create(ctx, "geo_in_rectangle", 16, + GRN_PROC_FUNCTION, + func_geo_in_rectangle, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, grn_selector_geo_in_rectangle); + } grn_proc_create(ctx, "geo_distance", 12, GRN_PROC_FUNCTION, func_geo_distance, NULL, NULL, 0, NULL); -------------- next part -------------- HTML����������������������������... Download