Kouhei Sutou
null+****@clear*****
Mon Jan 7 17:26:54 JST 2013
Kouhei Sutou 2013-01-07 17:26:54 +0900 (Mon, 07 Jan 2013) New Revision: 92fce9403960864ae70bcd50cf96d8df8ba03212 https://github.com/groonga/groonga/commit/92fce9403960864ae70bcd50cf96d8df8ba03212 Log: Add query() function We can use --match_columns and --query feature in --filter. Both of the following commands return the same result: --query version: select Users \ --output_columns name,_score \ --match_columns "name * 10" \ --query alice --filter version: select Users \ --output_columns name,_score \ --filter 'query("name * 10", "alice")' With query() function, we can specify multiple query()s in a select command. TODO: * Support query_expansion * Support query_flags * Document it Added files: test/command/suite/select/filter/query/function.expected test/command/suite/select/filter/query/function.test test/command/suite/select/filter/query/selector.expected test/command/suite/select/filter/query/selector.test Modified files: lib/proc.c Modified: lib/proc.c (+153 -1) =================================================================== --- lib/proc.c 2013-01-07 15:17:14 +0900 (da25d22) +++ lib/proc.c 2013-01-07 17:26:54 +0900 (56600c9) @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2009-2012 Brazil + Copyright(C) 2009-2013 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -3360,6 +3360,150 @@ func_snippet_html(grn_ctx *ctx, int nargs, grn_obj **args, return snippets; } +static grn_rc +run_query(grn_ctx *ctx, grn_obj *table, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + grn_obj *match_columns_string; + grn_obj *query_string; + grn_obj *match_columns = NULL; + grn_obj *condition = NULL; + grn_obj *dummy_variable; + + /* TODO: support expansion and flags by parameters */ + if (nargs != 2) { + ERR(GRN_INVALID_ARGUMENT, + "wrong number of arguments (%d for 2)", nargs); + goto exit; + } + + match_columns_string = args[0]; + query_string = args[1]; + + if (match_columns_string->header.domain == GRN_DB_TEXT && + GRN_TEXT_LEN(match_columns_string) > 0) { + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, match_columns, dummy_variable); + if (!match_columns) { + goto exit; + } + + grn_expr_parse(ctx, match_columns, + GRN_TEXT_VALUE(match_columns_string), + GRN_TEXT_LEN(match_columns_string), + NULL, GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + } + + if (query_string->header.domain == GRN_DB_TEXT && + GRN_TEXT_LEN(query_string) > 0) { + grn_expr_flags flags = + GRN_EXPR_SYNTAX_QUERY|GRN_EXPR_ALLOW_PRAGMA|GRN_EXPR_ALLOW_COLUMN; + + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, condition, dummy_variable); + if (!condition) { + goto exit; + } + grn_expr_parse(ctx, condition, + GRN_TEXT_VALUE(query_string), + GRN_TEXT_LEN(query_string), + match_columns, GRN_OP_MATCH, GRN_OP_AND, flags); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + grn_table_select(ctx, table, condition, res, op); + } + +exit: + if (match_columns) { + grn_obj_unlink(ctx, match_columns); + } + if (condition) { + grn_obj_unlink(ctx, condition); + } + + return ctx->rc; +} + +static grn_obj * +func_query(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *found; + grn_obj *command = ctx->impl->curr_expr; + grn_obj *condition_ptr = NULL; + grn_obj *condition = NULL; + grn_obj *variable; + grn_obj *table = NULL; + grn_obj *res = NULL; + + found = GRN_PROC_ALLOC(GRN_DB_BOOL, 0); + if (!found) { + goto exit; + } + GRN_BOOL_SET(ctx, found, GRN_FALSE); + + condition_ptr = grn_expr_get_var(ctx, command, + GRN_SELECT_INTERNAL_VAR_CONDITION, + strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); + if (!condition_ptr) { + goto exit; + } + + condition = GRN_PTR_VALUE(condition_ptr); + if (!condition) { + goto exit; + } + + variable = grn_expr_get_var_by_offset(ctx, condition, 0); + if (!variable) { + goto exit; + } + + table = grn_ctx_at(ctx, variable->header.domain); + if (!table) { + goto exit; + } + + res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL); + if (!res) { + goto exit; + } + { + grn_rset_posinfo pi; + unsigned int key_size; + memset(&pi, 0, sizeof(grn_rset_posinfo)); + pi.rid = GRN_RECORD_VALUE(variable); + key_size = ((grn_hash *)res)->key_size; + if (grn_table_add(ctx, res, &pi, key_size, NULL) == GRN_ID_NIL) { + goto exit; + } + } + if (run_query(ctx, table, nargs, args, res, GRN_OP_AND) == GRN_SUCCESS) { + GRN_BOOL_SET(ctx, found, grn_table_size(ctx, res) > 0); + } + +exit: + if (res) { + grn_obj_unlink(ctx, res); + } + if (table) { + grn_obj_unlink(ctx, table); + } + + return found; +} + +static grn_rc +selector_query(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + return run_query(ctx, table, nargs - 1, args + 1, res, op); +} #define DEF_VAR(v,name_str) do {\ (v).name = (name_str);\ @@ -3542,4 +3686,12 @@ grn_db_init_builtin_query(grn_ctx *ctx) /* experimental */ grn_proc_create(ctx, "snippet_html", -1, GRN_PROC_FUNCTION, func_snippet_html, NULL, NULL, 0, NULL); + + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "query", -1, GRN_PROC_FUNCTION, + func_query, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, selector_query); + } } Added: test/command/suite/select/filter/query/function.expected (+48 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/query/function.expected 2013-01-07 17:26:54 +0900 (66bb5fe) @@ -0,0 +1,48 @@ +table_create Users TABLE_NO_KEY +[[0,0.0,0.0],true] +column_create Users name COLUMN_SCALAR ShortText +[[0,0.0,0.0],true] +table_create Lexicon TABLE_HASH_KEY ShortText --default_tokenizer TokenBigramSplitSymbolAlphaDigit --normalizer NormalizerAuto +[[0,0.0,0.0],true] +column_create Lexicon users_name COLUMN_INDEX|WITH_POSITION Users name +[[0,0.0,0.0],true] +load --table Users +[ +{"name": "Alice"}, +{"name": "Alisa"}, +{"name": "Bob"} +] +[[0,0.0,0.0],3] +select Users --output_columns name,_score --filter 'query("name * 10", "ali") == true' +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 2 + ], + [ + [ + "name", + "ShortText" + ], + [ + "_score", + "Int32" + ] + ], + [ + "Alice", + 1 + ], + [ + "Alisa", + 1 + ] + ] + ] +] Added: test/command/suite/select/filter/query/function.test (+18 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/query/function.test 2013-01-07 17:26:54 +0900 (9eb9ded) @@ -0,0 +1,18 @@ +table_create Users TABLE_NO_KEY +column_create Users name COLUMN_SCALAR ShortText + +table_create Lexicon TABLE_HASH_KEY ShortText \ + --default_tokenizer TokenBigramSplitSymbolAlphaDigit \ + --normalizer NormalizerAuto +column_create Lexicon users_name COLUMN_INDEX|WITH_POSITION Users name + +load --table Users +[ +{"name": "Alice"}, +{"name": "Alisa"}, +{"name": "Bob"} +] + +select Users \ + --output_columns name,_score \ + --filter 'query("name * 10", "ali") == true' Added: test/command/suite/select/filter/query/selector.expected (+48 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/query/selector.expected 2013-01-07 17:26:54 +0900 (2d262f7) @@ -0,0 +1,48 @@ +table_create Users TABLE_NO_KEY +[[0,0.0,0.0],true] +column_create Users name COLUMN_SCALAR ShortText +[[0,0.0,0.0],true] +table_create Lexicon TABLE_HASH_KEY ShortText --default_tokenizer TokenBigramSplitSymbolAlphaDigit --normalizer NormalizerAuto +[[0,0.0,0.0],true] +column_create Lexicon users_name COLUMN_INDEX|WITH_POSITION Users name +[[0,0.0,0.0],true] +load --table Users +[ +{"name": "Alice"}, +{"name": "Alisa"}, +{"name": "Bob"} +] +[[0,0.0,0.0],3] +select Users --output_columns name,_score --filter 'query("name * 10", "ali")' +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 2 + ], + [ + [ + "name", + "ShortText" + ], + [ + "_score", + "Int32" + ] + ], + [ + "Alice", + 10 + ], + [ + "Alisa", + 10 + ] + ] + ] +] Added: test/command/suite/select/filter/query/selector.test (+18 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/query/selector.test 2013-01-07 17:26:54 +0900 (fe08aff) @@ -0,0 +1,18 @@ +table_create Users TABLE_NO_KEY +column_create Users name COLUMN_SCALAR ShortText + +table_create Lexicon TABLE_HASH_KEY ShortText \ + --default_tokenizer TokenBigramSplitSymbolAlphaDigit \ + --normalizer NormalizerAuto +column_create Lexicon users_name COLUMN_INDEX|WITH_POSITION Users name + +load --table Users +[ +{"name": "Alice"}, +{"name": "Alisa"}, +{"name": "Bob"} +] + +select Users \ + --output_columns name,_score \ + --filter 'query("name * 10", "ali")' -------------- next part -------------- HTML����������������������������... 다운로드