Kouhei Sutou
null+****@clear*****
Sat May 9 21:10:39 JST 2015
Kouhei Sutou 2015-05-09 21:10:39 +0900 (Sat, 09 May 2015) New Revision: d0cce9403275ae7b7e004c0d4c8ff609e9b455e2 https://github.com/groonga/groonga/commit/d0cce9403275ae7b7e004c0d4c8ff609e9b455e2 Message: select: support operator as table key See the committed test case for details. Added files: lib/expr_code.c lib/grn_expr_code.h test/command/suite/select/filter/record/key/operator.expected test/command/suite/select/filter/record/key/operator.test Modified files: lib/expr.c lib/output.c lib/sources.am Modified: lib/expr.c (+19 -2) =================================================================== --- lib/expr.c 2015-05-09 20:33:42 +0900 (3f13072) +++ lib/expr.c 2015-05-09 21:10:39 +0900 (dc047c4) @@ -22,6 +22,7 @@ #include "grn_ii.h" #include "grn_geo.h" #include "grn_expr.h" +#include "grn_expr_code.h" #include "grn_util.h" #include "grn_mrb.h" #include "mrb/mrb_expr.h" @@ -6157,14 +6158,30 @@ parse_script_extract_name_resolve_context(grn_ctx *ctx, efs_info *q) grn_expr_code *code_start; grn_expr_code *code_last; + if (expr->codes_curr == 0) { + return NULL; + } + code_start = expr->codes; code_last = code_start + (expr->codes_curr - 1); switch (code_last->op) { case GRN_OP_GET_MEMBER : + if (code_last - 1 < code_start) { + return NULL; + } { + unsigned int n_used_codes_for_key; + grn_expr_code *code_key; grn_expr_code *code_receiver; - /* TODO: Support non literal key case. */ - code_receiver = code_last - 2; + + code_key = code_last - 1; + n_used_codes_for_key = grn_expr_code_n_used_codes(ctx, + code_start, + code_key); + if (n_used_codes_for_key == 0) { + return NULL; + } + code_receiver = code_key - n_used_codes_for_key; if (code_receiver < code_start) { return NULL; } Added: lib/expr_code.c (+71 -0) 100644 =================================================================== --- /dev/null +++ lib/expr_code.c 2015-05-09 21:10:39 +0900 (4f03867) @@ -0,0 +1,71 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "grn_expr_code.h" + +unsigned int +grn_expr_code_n_used_codes(grn_ctx *ctx, + grn_expr_code *start, + grn_expr_code *target) +{ + unsigned int n_codes; + int i, n_args; + grn_bool have_proc_push_code = GRN_FALSE; + grn_expr_code *sub_code; + + if (start == target) { + return 0; + } + + n_args = target->nargs; + if (target->op == GRN_OP_CALL) { + if (!target->value) { + have_proc_push_code = GRN_TRUE; + } + } else { + if (target->value) { + n_args--; + if (n_args == 0) { + return 1; + } + } + } + + n_codes = 1; + sub_code = target - 1; + for (i = 0; i < n_args; i++) { + int sub_n_codes; + sub_n_codes = grn_expr_code_n_used_codes(ctx, start, sub_code); + n_codes += sub_n_codes; + sub_code -= sub_n_codes; + if (sub_code < start) { + /* TODO: report error */ + return 0; + } + } + + if (have_proc_push_code) { + n_codes++; + sub_code--; + if (sub_code < start) { + /* TODO: report error */ + return 0; + } + } + + return n_codes; +} Added: lib/grn_expr_code.h (+37 -0) 100644 =================================================================== --- /dev/null +++ lib/grn_expr_code.h 2015-05-09 21:10:39 +0900 (a0fd680) @@ -0,0 +1,37 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_EXPR_CODE_H +#define GRN_EXPR_CODE_H + +#include "grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned int grn_expr_code_n_used_codes(grn_ctx *ctx, + grn_expr_code *start, + grn_expr_code *target); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_EXPR_CODE_H */ + Modified: lib/output.c (+6 -57) =================================================================== --- lib/output.c 2015-05-09 20:33:42 +0900 (0036e9a) +++ lib/output.c 2015-05-09 21:10:39 +0900 (48ff6bc) @@ -1134,57 +1134,6 @@ count_n_elements_in_expression(grn_ctx *ctx, grn_obj *expression) return n_elements; } -static inline int -count_used_n_codes(grn_ctx *ctx, grn_expr_code *start, grn_expr_code *target) -{ - int n_codes; - int i, n_args; - grn_bool have_proc_push_code = GRN_FALSE; - grn_expr_code *sub_code; - - if (start == target) { - return 0; - } - - n_args = target->nargs; - if (target->op == GRN_OP_CALL) { - if (!target->value) { - have_proc_push_code = GRN_TRUE; - } - } else { - if (target->value) { - n_args--; - if (n_args == 0) { - return 1; - } - } - } - - n_codes = 1; - sub_code = target - 1; - for (i = 0; i < n_args; i++) { - int sub_n_codes; - sub_n_codes = count_used_n_codes(ctx, start, sub_code); - n_codes += sub_n_codes; - sub_code -= sub_n_codes; - if (sub_code < start) { - /* TODO: report error */ - return 0; - } - } - - if (have_proc_push_code) { - n_codes++; - sub_code--; - if (sub_code < start) { - /* TODO: report error */ - return 0; - } - } - - return n_codes; -} - static grn_bool is_score_accessor(grn_ctx *ctx, grn_obj *obj) { @@ -1305,10 +1254,10 @@ grn_output_table_columns_by_expression(grn_ctx *ctx, grn_obj *outbuf, have_comma = GRN_TRUE; if (is_first_comma) { - int n_used_codes; + unsigned int n_used_codes; int code_end_offset; - n_used_codes = count_used_n_codes(ctx, expr->codes, code - 1); + n_used_codes = grn_expr_code_n_used_codes(ctx, expr->codes, code - 1); code_end_offset = code - expr->codes - n_used_codes; grn_output_table_column_by_expression(ctx, outbuf, output_type, @@ -1417,12 +1366,12 @@ grn_output_table_records_by_expression(grn_ctx *ctx, grn_obj *outbuf, have_comma = GRN_TRUE; if (is_first_comma) { int second_code_offset; - int second_code_n_used_code; + unsigned int second_code_n_used_code; second_code_offset = code - expr->codes - 1; second_code_n_used_code = - count_used_n_codes(ctx, - expr->codes, - expr->codes + second_code_offset); + grn_expr_code_n_used_codes(ctx, + expr->codes, + expr->codes + second_code_offset); expr->codes_curr = second_code_offset - second_code_n_used_code + 1; grn_output_table_record_by_expression(ctx, outbuf, output_type, format->expression); Modified: lib/sources.am (+2 -0) =================================================================== --- lib/sources.am 2015-05-09 20:33:42 +0900 (459b737) +++ lib/sources.am 2015-05-09 21:10:39 +0900 (3ad3664) @@ -15,6 +15,8 @@ libgroonga_la_SOURCES = \ grn_error.h \ expr.c \ grn_expr.h \ + expr_code.c \ + grn_expr_code.h \ geo.c \ grn_geo.h \ grn.h \ Added: test/command/suite/select/filter/record/key/operator.expected (+59 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/record/key/operator.expected 2015-05-09 21:10:39 +0900 (c6a72b9) @@ -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["groo" + "nga"].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/operator.test (+20 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/record/key/operator.test 2015-05-09 21:10:39 +0900 (3baeced) @@ -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["groo" + "nga"].label' -------------- next part -------------- HTML����������������������������...Download