Kouhei Sutou
null+****@clear*****
Sat May 9 20:33:42 JST 2015
Kouhei Sutou 2015-05-09 20:33:42 +0900 (Sat, 09 May 2015) New Revision: 792f0d6c7398081eb5b58dbe632e9cfc0d6394e1 https://github.com/groonga/groonga/commit/792f0d6c7398081eb5b58dbe632e9cfc0d6394e1 Message: select: support accessing other table's record in filter See the committed test case for details. Added files: test/command/suite/select/filter/record/key/literal.expected test/command/suite/select/filter/record/key/literal.test Modified files: lib/expr.c Modified: lib/expr.c (+86 -10) =================================================================== --- lib/expr.c 2015-05-09 10:51:55 +0900 (f13502a) +++ lib/expr.c 2015-05-09 20:33:42 +0900 (3f13072) @@ -2226,11 +2226,11 @@ grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller) } while (0) inline static void -grn_expr_exec_get_member(grn_ctx *ctx, - grn_obj *expr, - grn_obj *column_and_record_id, - grn_obj *index, - grn_obj *result) +grn_expr_exec_get_member_vector(grn_ctx *ctx, + grn_obj *expr, + grn_obj *column_and_record_id, + grn_obj *index, + grn_obj *result) { grn_obj *column; grn_id record_id; @@ -2268,6 +2268,34 @@ grn_expr_exec_get_member(grn_ctx *ctx, GRN_OBJ_FIN(ctx, &values); } +inline static void +grn_expr_exec_get_member_table(grn_ctx *ctx, + grn_obj *expr, + grn_obj *table, + grn_obj *key, + grn_obj *result) +{ + grn_id id; + + if (table->header.domain == key->header.domain) { + id = grn_table_get(ctx, table, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key)); + } else { + grn_obj casted_key; + GRN_OBJ_INIT(&casted_key, GRN_BULK, 0, table->header.domain); + if (grn_obj_cast(ctx, key, &casted_key, GRN_FALSE) == GRN_SUCCESS) { + id = grn_table_get(ctx, table, + GRN_BULK_HEAD(&casted_key), + GRN_BULK_VSIZE(&casted_key)); + } else { + id = GRN_ID_NIL; + } + GRN_OBJ_FIN(ctx, &casted_key); + } + + grn_obj_reinit(ctx, result, DB_OBJ(table)->id, 0); + GRN_RECORD_SET(ctx, result, id); +} + static inline grn_bool grn_expr_exec_is_simple_expr(grn_ctx *ctx, grn_obj *expr) { @@ -3458,9 +3486,15 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_GET_MEMBER : { - grn_obj *column_and_record_id, *index; - POP2ALLOC1(column_and_record_id, index, res); - grn_expr_exec_get_member(ctx, expr, column_and_record_id, index, res); + grn_obj *receiver, *index_or_key; + POP2ALLOC1(receiver, index_or_key, res); + if (receiver->header.type == GRN_PTR) { + grn_obj *index = index_or_key; + grn_expr_exec_get_member_vector(ctx, expr, receiver, index, res); + } else { + grn_obj *key = index_or_key; + grn_expr_exec_get_member_table(ctx, expr, receiver, key, res); + } code++; } break; @@ -5996,7 +6030,7 @@ resolve_top_level_name(grn_ctx *ctx, const char *name, unsigned int name_size) } static grn_rc -get_identifier(grn_ctx *ctx, efs_info *q) +get_identifier(grn_ctx *ctx, efs_info *q, grn_obj *name_resolve_context) { const char *s; unsigned int len; @@ -6072,6 +6106,14 @@ done : grn_obj *obj; const char *name = q->cur; unsigned int name_size = s - q->cur; + if (name_resolve_context) { + if ((obj = grn_obj_column(ctx, name_resolve_context, name, name_size))) { + grn_expr_take_obj(ctx, q->e, obj); + PARSE(GRN_EXPR_TOKEN_IDENTIFIER); + grn_expr_append_obj(ctx, q->e, obj, GRN_OP_GET_VALUE, 2); + goto exit; + } + } if ((obj = grn_expr_get_var(ctx, q->e, name, name_size))) { PARSE(GRN_EXPR_TOKEN_IDENTIFIER); grn_expr_append_obj(ctx, q->e, obj, GRN_OP_PUSH, 1); @@ -6108,11 +6150,42 @@ set_tos_minor_to_curr(grn_ctx *ctx, efs_info *q) yytos->minor.yy0 = ((grn_expr *)(q->e))->codes_curr; } +static grn_obj * +parse_script_extract_name_resolve_context(grn_ctx *ctx, efs_info *q) +{ + grn_expr *expr = (grn_expr *)(q->e); + grn_expr_code *code_start; + grn_expr_code *code_last; + + code_start = expr->codes; + code_last = code_start + (expr->codes_curr - 1); + switch (code_last->op) { + case GRN_OP_GET_MEMBER : + { + grn_expr_code *code_receiver; + /* TODO: Support non literal key case. */ + code_receiver = code_last - 2; + if (code_receiver < code_start) { + return NULL; + } + return code_receiver->value; + } + break; + default : + /* TODO: Support other operators. */ + return NULL; + break; + } +} + static grn_rc parse_script(grn_ctx *ctx, efs_info *q) { grn_rc rc = GRN_SUCCESS; + grn_obj *name_resolve_context = NULL; for (;;) { + grn_obj *current_name_resolve_context = name_resolve_context; + name_resolve_context = NULL; skip_space(ctx, q); if (q->cur >= q->str_end) { rc = GRN_END_OF_DATA; goto exit; } switch (*q->cur) { @@ -6150,6 +6223,7 @@ parse_script(grn_ctx *ctx, efs_info *q) break; case '.' : PARSE(GRN_EXPR_TOKEN_DOT); + name_resolve_context = parse_script_extract_name_resolve_context(ctx, q); q->cur++; break; case ':' : @@ -6538,7 +6612,9 @@ parse_script(grn_ctx *ctx, efs_info *q) } break; default : - if ((rc = get_identifier(ctx, q))) { goto exit; } + if ((rc = get_identifier(ctx, q, current_name_resolve_context))) { + goto exit; + } break; } if (ctx->rc) { rc = ctx->rc; break; } Added: test/command/suite/select/filter/record/key/literal.expected (+59 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/record/key/literal.expected 2015-05-09 20:33:42 +0900 (ac7b261) @@ -0,0 +1,59 @@ +table_create Keywords TABLE_HASH_KEY ShortText --normalizer NormalizerAuto +[[0,0.0,0.0],true] +column_create Keywords label COLUMN_SCALAR ShortText +[[0,0.0,0.0],true] +table_create Memos TABLE_HASH_KEY ShortText +[[0,0.0,0.0],true] +column_create Memos tag COLUMN_SCALAR ShortText +[[0,0.0,0.0],true] +load --table Keywords +[ +{"_key": "groonga", "label": "Groonga"} +] +[[0,0.0,0.0],1] +load --table Memos +[ +{"_key": "Groonga is very fast", "tag": "Groonga"}, +{"_key": "Groonga is easy to install", "tag": "Groonga"}, +{"_key": "Mroonga is very fast", "tag": "Mroonga"} +] +[[0,0.0,0.0],3] +select Memos --filter 'tag == Keywords["groonga"].label' +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 2 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "_key", + "ShortText" + ], + [ + "tag", + "ShortText" + ] + ], + [ + 1, + "Groonga is very fast", + "Groonga" + ], + [ + 2, + "Groonga is easy to install", + "Groonga" + ] + ] + ] +] Added: test/command/suite/select/filter/record/key/literal.test (+20 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/record/key/literal.test 2015-05-09 20:33:42 +0900 (8f06f27) @@ -0,0 +1,20 @@ +table_create Keywords TABLE_HASH_KEY ShortText \ + --normalizer NormalizerAuto +column_create Keywords label COLUMN_SCALAR ShortText + +table_create Memos TABLE_HASH_KEY ShortText +column_create Memos tag COLUMN_SCALAR ShortText + +load --table Keywords +[ +{"_key": "groonga", "label": "Groonga"} +] + +load --table Memos +[ +{"_key": "Groonga is very fast", "tag": "Groonga"}, +{"_key": "Groonga is easy to install", "tag": "Groonga"}, +{"_key": "Mroonga is very fast", "tag": "Mroonga"} +] + +select Memos --filter 'tag == Keywords["groonga"].label' -------------- next part -------------- HTML����������������������������...Download