Kouhei Sutou
null+****@clear*****
Tue Nov 11 13:46:25 JST 2014
Kouhei Sutou 2014-11-11 13:46:25 +0900 (Tue, 11 Nov 2014) New Revision: 7c2e7d6f167658ee90968ebcee105590d3450334 https://github.com/groonga/groonga/commit/7c2e7d6f167658ee90968ebcee105590d3450334 Message: between: optimize for small result set If result set is small and indexed records are large, searching with index is slower than sequential search. This change uses sequential search for the case. You can custom the behavior by GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO environment variable: * -1: Disable the optimization * other value: Use the optimization if ("# of result set" / "# of indexed records") > GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO The default GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO is 0.01. It means that "# of indexed records" * 0.01 >= "# of result set" case is "small result set" case. Limitations: * "# of indexed records" isn't exact number. * It is too rough value. * We assume the followings: * homogeneous index key distribution. * each index key matches only 1 record. * Time value is only supported for now. * Integer family values and Float can be supported easily. Added files: test/command/suite/select/function/between/with_index/sequential_search/time.expected test/command/suite/select/function/between/with_index/sequential_search/time.test Modified files: lib/proc.c Modified: lib/proc.c (+311 -86) =================================================================== --- lib/proc.c 2014-11-11 13:20:36 +0900 (b0a44d2) +++ lib/proc.c 2014-11-11 13:46:25 +0900 (cfd6c21) @@ -4780,11 +4780,27 @@ typedef enum { typedef struct { grn_obj *value; grn_obj *min; + grn_obj casted_min; between_border_type min_border_type; grn_obj *max; + grn_obj casted_max; between_border_type max_border_type; } between_data; +static void +between_data_init(grn_ctx *ctx, between_data *data) +{ + GRN_VOID_INIT(&(data->casted_min)); + GRN_VOID_INIT(&(data->casted_max)); +} + +static void +between_data_fin(grn_ctx *ctx, between_data *data) +{ + GRN_OBJ_FIN(ctx, &(data->casted_min)); + GRN_OBJ_FIN(ctx, &(data->casted_max)); +} + static between_border_type between_parse_border(grn_ctx *ctx, grn_obj *border, const char *argument_description) @@ -4813,6 +4829,41 @@ between_parse_border(grn_ctx *ctx, grn_obj *border, } static grn_rc +between_cast(grn_ctx *ctx, grn_obj *source, grn_obj *destination, grn_id domain, + const char *target_argument_name) +{ + grn_rc rc; + + GRN_OBJ_INIT(destination, GRN_BULK, 0, domain); + rc = grn_obj_cast(ctx, source, destination, GRN_FALSE); + if (rc != GRN_SUCCESS) { + grn_obj inspected_source; + grn_obj *domain_object; + char domain_name[GRN_TABLE_MAX_KEY_SIZE]; + int domain_name_length; + + GRN_TEXT_INIT(&inspected_source, 0); + grn_inspect(ctx, &inspected_source, source); + + domain_object = grn_ctx_at(ctx, domain); + domain_name_length = + grn_obj_name(ctx, domain_object, domain_name, GRN_TABLE_MAX_KEY_SIZE); + + ERR(rc, "between(): failed to cast %s: <%.*s> -> <%.*s>", + target_argument_name, + (int)GRN_TEXT_LEN(&inspected_source), + GRN_TEXT_VALUE(&inspected_source), + domain_name_length, + domain_name); + + grn_obj_unlink(ctx, &inspected_source); + grn_obj_unlink(ctx, domain_object); + } + + return rc; +} + +static grn_rc between_parse_args(grn_ctx *ctx, int nargs, grn_obj **args, between_data *data) { grn_rc rc = GRN_SUCCESS; @@ -4846,43 +4897,70 @@ between_parse_args(grn_ctx *ctx, int nargs, grn_obj **args, between_data *data) goto exit; } + { + grn_id value_type; + if (data->value->header.type == GRN_BULK) { + value_type = data->value->header.domain; + } else { + value_type = grn_obj_get_range(ctx, data->value); + } + if (value_type != data->min->header.domain) { + rc = between_cast(ctx, data->min, &data->casted_min, value_type, "min"); + if (rc != GRN_SUCCESS) { + goto exit; + } + data->min = &(data->casted_min); + } + + if (value_type != data->max->header.domain) { + rc = between_cast(ctx, data->max, &data->casted_max, value_type, "max"); + if (rc != GRN_SUCCESS) { + goto exit; + } + data->max = &(data->casted_max); + } + } + exit : return rc; } -static grn_rc -between_cast(grn_ctx *ctx, grn_obj *source, grn_obj *destination, grn_id domain, - const char *target_argument_name) +static grn_bool +between_create_expr(grn_ctx *ctx, grn_obj *table, between_data *data, + grn_obj **expr, grn_obj **variable) { - grn_rc rc; - - GRN_OBJ_INIT(destination, GRN_BULK, 0, domain); - rc = grn_obj_cast(ctx, source, destination, GRN_FALSE); - if (rc != GRN_SUCCESS) { - grn_obj inspected_source; - grn_obj *domain_object; - char domain_name[GRN_TABLE_MAX_KEY_SIZE]; - int domain_name_length; - - GRN_TEXT_INIT(&inspected_source, 0); - grn_inspect(ctx, &inspected_source, source); - - domain_object = grn_ctx_at(ctx, domain); - domain_name_length = - grn_obj_name(ctx, domain_object, domain_name, GRN_TABLE_MAX_KEY_SIZE); + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, *expr, *variable); + if (!*expr) { + return GRN_FALSE; + } - ERR(rc, "between(): failed to cast %s: <%.*s> -> <%.*s>", - target_argument_name, - (int)GRN_TEXT_LEN(&inspected_source), - GRN_TEXT_VALUE(&inspected_source), - domain_name_length, - domain_name); + if (data->value->header.type == GRN_BULK) { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_PUSH, 1); + } else { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_GET_VALUE, 1); + } + grn_expr_append_obj(ctx, *expr, data->min, GRN_OP_PUSH, 1); + if (data->min_border_type == BETWEEN_BORDER_INCLUDE) { + grn_expr_append_op(ctx, *expr, GRN_OP_GREATER_EQUAL, 2); + } else { + grn_expr_append_op(ctx, *expr, GRN_OP_GREATER, 2); + } - grn_obj_unlink(ctx, &inspected_source); - grn_obj_unlink(ctx, domain_object); + if (data->value->header.type == GRN_BULK) { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_PUSH, 1); + } else { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_GET_VALUE, 1); + } + grn_expr_append_obj(ctx, *expr, data->max, GRN_OP_PUSH, 1); + if (data->max_border_type == BETWEEN_BORDER_INCLUDE) { + grn_expr_append_op(ctx, *expr, GRN_OP_LESS_EQUAL, 2); + } else { + grn_expr_append_op(ctx, *expr, GRN_OP_LESS, 2); } - return rc; + grn_expr_append_op(ctx, *expr, GRN_OP_AND, 2); + + return GRN_TRUE; } static grn_obj * @@ -4893,7 +4971,7 @@ func_between(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) between_data data; grn_obj *condition = NULL; grn_obj *variable; - grn_obj *table; + grn_obj *table = NULL; grn_obj *between_expr; grn_obj *between_variable; grn_obj *result; @@ -4914,39 +4992,20 @@ func_between(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) return found; } + between_data_init(ctx, &data); rc = between_parse_args(ctx, nargs, args, &data); if (rc != GRN_SUCCESS) { - return found; + goto exit; } table = grn_ctx_at(ctx, variable->header.domain); if (!table) { - return found; - } - GRN_EXPR_CREATE_FOR_QUERY(ctx, table, between_expr, between_variable); - if (!between_expr) { - grn_obj_unlink(ctx, table); - return found; - } - - grn_expr_append_obj(ctx, between_expr, data.value, GRN_OP_PUSH, 1); - grn_expr_append_obj(ctx, between_expr, data.min, GRN_OP_PUSH, 1); - if (data.min_border_type == BETWEEN_BORDER_INCLUDE) { - grn_expr_append_op(ctx, between_expr, GRN_OP_GREATER_EQUAL, 2); - } else { - grn_expr_append_op(ctx, between_expr, GRN_OP_GREATER, 2); + goto exit; } - - grn_expr_append_obj(ctx, between_expr, data.value, GRN_OP_PUSH, 1); - grn_expr_append_obj(ctx, between_expr, data.max, GRN_OP_PUSH, 1); - if (data.max_border_type == BETWEEN_BORDER_INCLUDE) { - grn_expr_append_op(ctx, between_expr, GRN_OP_LESS_EQUAL, 2); - } else { - grn_expr_append_op(ctx, between_expr, GRN_OP_LESS, 2); + if (!between_create_expr(ctx, table, &data, &between_expr, &between_variable)) { + goto exit; } - grn_expr_append_op(ctx, between_expr, GRN_OP_AND, 2); - GRN_RECORD_SET(ctx, between_variable, GRN_RECORD_VALUE(variable)); result = grn_expr_exec(ctx, between_expr, 0); if (result) { @@ -4960,9 +5019,197 @@ func_between(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) grn_obj_unlink(ctx, between_expr); grn_obj_unlink(ctx, table); +exit : + between_data_fin(ctx, &data); + if (table) { + grn_obj_unlink(ctx, table); + } + return found; } +static grn_bool +selector_between_sequential_search(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, grn_obj *index_table, + between_data *data, + grn_obj *res, grn_operator op) +{ + double too_many_index_match_ratio = 0.01; + int n_existing_records; + int n_index_keys; + + { + const char *too_many_index_match_ratio_env = + getenv("GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO"); + if (too_many_index_match_ratio_env) { + too_many_index_match_ratio = atof(too_many_index_match_ratio_env); + } + } + + if (too_many_index_match_ratio < 0.0) { + return GRN_FALSE; + } + + if (op != GRN_OP_AND) { + return GRN_FALSE; + } + + if (index->header.flags & GRN_OBJ_WITH_WEIGHT) { + return GRN_FALSE; + } + + n_existing_records = grn_table_size(ctx, res); + if (n_existing_records == 0) { + return GRN_TRUE; + } + + n_index_keys = grn_table_size(ctx, index_table); + if (n_index_keys == 0) { + return GRN_FALSE; + } + + switch (index_table->header.domain) { + /* TODO: */ + /* case GRN_DB_INT8 : */ + /* case GRN_DB_UINT8 : */ + /* case GRN_DB_INT16 : */ + /* case GRN_DB_UINT16 : */ + /* case GRN_DB_INT32 : */ + /* case GRN_DB_UINT32 : */ + /* case GRN_DB_INT64 : */ + /* case GRN_DB_UINT64 : */ + /* case GRN_DB_FLOAT : */ + case GRN_DB_TIME : + break; + default : + return GRN_FALSE; + } + + { + grn_table_cursor *cursor; + long long int all_min; + long long int all_max; + cursor = grn_table_cursor_open(ctx, index_table, + NULL, -1, + NULL, -1, + 0, 1, + GRN_CURSOR_BY_KEY | GRN_CURSOR_ASCENDING); + if (!cursor) { + return GRN_FALSE; + } + if (grn_table_cursor_next(ctx, cursor) == GRN_ID_NIL) { + return GRN_FALSE; + } + { + long long int *key; + grn_table_cursor_get_key(ctx, cursor, (void **)&key); + all_min = *key; + } + grn_table_cursor_close(ctx, cursor); + + cursor = grn_table_cursor_open(ctx, index_table, + NULL, 0, NULL, 0, + 0, 1, + GRN_CURSOR_BY_KEY | GRN_CURSOR_DESCENDING); + if (!cursor) { + return GRN_FALSE; + } + if (grn_table_cursor_next(ctx, cursor) == GRN_ID_NIL) { + return GRN_FALSE; + } + { + long long int *key; + grn_table_cursor_get_key(ctx, cursor, (void **)&key); + all_max = *key; + } + grn_table_cursor_close(ctx, cursor); + + /* + * We assume the following: + * * homogeneous index key distribution. + * * each index key matches only 1 record. + * TODO: Improve me. + */ + { + int n_indexed_records; + long long int all_difference; + long long int argument_difference; + all_difference = all_max - all_min; + if (all_difference <= 0) { + return GRN_FALSE; + } + argument_difference = + GRN_TIME_VALUE(data->max) - GRN_TIME_VALUE(data->min); + if (argument_difference <= 0) { + return GRN_FALSE; + } + n_indexed_records = + n_index_keys * ((double)argument_difference / (double)all_difference); + /* + * Same as: + * ((n_existing_record / n_indexed_records) > too_many_index_match_ratio) + */ + if (n_existing_records > (n_indexed_records * too_many_index_match_ratio)) { + return GRN_FALSE; + } + } + } + + { + int offset = 0; + int limit = -1; + int flags = 0; + grn_table_cursor *cursor; + grn_obj *expr; + grn_obj *variable; + grn_id id; + + if (!between_create_expr(ctx, table, data, &expr, &variable)) { + return GRN_FALSE; + } + + cursor = grn_table_cursor_open(ctx, res, + NULL, 0, + NULL, 0, + offset, limit, flags); + if (!cursor) { + grn_obj_unlink(ctx, expr); + return GRN_FALSE; + } + + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_id record_id; + grn_obj *result; + { + grn_id *key; + grn_table_cursor_get_key(ctx, cursor, (void **)&key); + record_id = *key; + } + GRN_RECORD_SET(ctx, variable, record_id); + result = grn_expr_exec(ctx, expr, 0); + if (result) { + grn_bool result_boolean; + GRN_TRUEP(ctx, result, result_boolean); + if (result_boolean) { + grn_ii_posting posting; + posting.rid = record_id; + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + } + } + grn_obj_unlink(ctx, expr); + grn_table_cursor_close(ctx, cursor); + + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + } + + return GRN_TRUE; +} + static grn_rc selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index, int nargs, grn_obj **args, @@ -4973,9 +5220,6 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index, int limit = -1; int flags = GRN_CURSOR_ASCENDING | GRN_CURSOR_BY_KEY; between_data data; - grn_obj casted_min, casted_max; - grn_obj *used_min = NULL; - grn_obj *used_max = NULL; grn_obj *index_table = NULL; grn_table_cursor *cursor; grn_id id; @@ -4984,9 +5228,10 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index, return GRN_INVALID_ARGUMENT; } + between_data_init(ctx, &data); rc = between_parse_args(ctx, nargs - 1, args + 1, &data); if (rc != GRN_SUCCESS) { - return rc; + goto exit; } if (data.min_border_type == BETWEEN_BORDER_EXCLUDE) { @@ -4997,31 +5242,16 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index, } index_table = grn_ctx_at(ctx, index->header.domain); - if (data.min->header.domain == index_table->header.domain) { - used_min = data.min; - } else { - used_min = &casted_min; - rc = between_cast(ctx, data.min, &casted_min, index_table->header.domain, - "min"); - if (rc != GRN_SUCCESS) { - goto exit; - } - } - if (data.max->header.domain == index_table->header.domain) { - used_max = data.max; - } else { - used_max = &casted_max; - rc = between_cast(ctx, data.max, &casted_max, index_table->header.domain, - "max"); - if (rc != GRN_SUCCESS) { - goto exit; - } + if (selector_between_sequential_search(ctx, table, index, index_table, + &data, res, op)) { + goto exit; } + cursor = grn_table_cursor_open(ctx, index_table, - GRN_BULK_HEAD(used_min), - GRN_BULK_VSIZE(used_min), - GRN_BULK_HEAD(used_max), - GRN_BULK_VSIZE(used_max), + GRN_BULK_HEAD(data.min), + GRN_BULK_VSIZE(data.min), + GRN_BULK_HEAD(data.max), + GRN_BULK_VSIZE(data.max), offset, limit, flags); if (!cursor) { rc = ctx->rc; @@ -5035,12 +5265,7 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index, grn_table_cursor_close(ctx, cursor); exit : - if (used_min == &casted_min) { - grn_obj_unlink(ctx, &casted_min); - } - if (used_max == &casted_max) { - grn_obj_unlink(ctx, &casted_max); - } + between_data_fin(ctx, &data); if (index_table) { grn_obj_unlink(ctx, index_table); } Added: test/command/suite/select/function/between/with_index/sequential_search/time.expected (+246 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/function/between/with_index/sequential_search/time.expected 2014-11-11 13:46:25 +0900 (6cee9a8) @@ -0,0 +1,246 @@ +table_create Memos TABLE_HASH_KEY ShortText +[[0,0.0,0.0],true] +column_create Memos timestamp COLUMN_SCALAR Time +[[0,0.0,0.0],true] +table_create Times TABLE_PAT_KEY Time +[[0,0.0,0.0],true] +column_create Times memos_timestamp COLUMN_INDEX Memos timestamp +[[0,0.0,0.0],true] +load --table Memos +[ +{"_key": "001", "timestamp": "2014-11-10 07:25:23"}, +{"_key": "002", "timestamp": "2014-11-10 07:25:24"}, +{"_key": "003", "timestamp": "2014-11-10 07:25:25"}, +{"_key": "004", "timestamp": "2014-11-10 07:25:26"}, +{"_key": "005", "timestamp": "2014-11-10 07:25:27"}, +{"_key": "006", "timestamp": "2014-11-10 07:25:28"}, +{"_key": "007", "timestamp": "2014-11-10 07:25:29"}, +{"_key": "008", "timestamp": "2014-11-10 07:25:30"}, +{"_key": "009", "timestamp": "2014-11-10 07:25:31"}, +{"_key": "010", "timestamp": "2014-11-10 07:25:32"}, +{"_key": "011", "timestamp": "2014-11-10 07:25:33"}, +{"_key": "012", "timestamp": "2014-11-10 07:25:34"}, +{"_key": "013", "timestamp": "2014-11-10 07:25:35"}, +{"_key": "014", "timestamp": "2014-11-10 07:25:36"}, +{"_key": "015", "timestamp": "2014-11-10 07:25:37"}, +{"_key": "016", "timestamp": "2014-11-10 07:25:38"}, +{"_key": "017", "timestamp": "2014-11-10 07:25:39"}, +{"_key": "018", "timestamp": "2014-11-10 07:25:40"}, +{"_key": "019", "timestamp": "2014-11-10 07:25:41"}, +{"_key": "020", "timestamp": "2014-11-10 07:25:42"}, +{"_key": "021", "timestamp": "2014-11-10 07:25:43"}, +{"_key": "022", "timestamp": "2014-11-10 07:25:44"}, +{"_key": "023", "timestamp": "2014-11-10 07:25:45"}, +{"_key": "024", "timestamp": "2014-11-10 07:25:46"}, +{"_key": "025", "timestamp": "2014-11-10 07:25:47"}, +{"_key": "026", "timestamp": "2014-11-10 07:25:48"}, +{"_key": "027", "timestamp": "2014-11-10 07:25:49"}, +{"_key": "028", "timestamp": "2014-11-10 07:25:50"}, +{"_key": "029", "timestamp": "2014-11-10 07:25:51"}, +{"_key": "030", "timestamp": "2014-11-10 07:25:52"}, +{"_key": "031", "timestamp": "2014-11-10 07:25:53"}, +{"_key": "032", "timestamp": "2014-11-10 07:25:54"}, +{"_key": "033", "timestamp": "2014-11-10 07:25:55"}, +{"_key": "034", "timestamp": "2014-11-10 07:25:56"}, +{"_key": "035", "timestamp": "2014-11-10 07:25:57"}, +{"_key": "036", "timestamp": "2014-11-10 07:25:58"}, +{"_key": "037", "timestamp": "2014-11-10 07:25:59"}, +{"_key": "038", "timestamp": "2014-11-10 07:26:00"}, +{"_key": "039", "timestamp": "2014-11-10 07:26:01"}, +{"_key": "040", "timestamp": "2014-11-10 07:26:02"}, +{"_key": "041", "timestamp": "2014-11-10 07:26:03"}, +{"_key": "042", "timestamp": "2014-11-10 07:26:04"}, +{"_key": "043", "timestamp": "2014-11-10 07:26:05"}, +{"_key": "044", "timestamp": "2014-11-10 07:26:06"}, +{"_key": "045", "timestamp": "2014-11-10 07:26:07"}, +{"_key": "046", "timestamp": "2014-11-10 07:26:08"}, +{"_key": "047", "timestamp": "2014-11-10 07:26:09"}, +{"_key": "048", "timestamp": "2014-11-10 07:26:10"}, +{"_key": "049", "timestamp": "2014-11-10 07:26:11"}, +{"_key": "050", "timestamp": "2014-11-10 07:26:12"}, +{"_key": "051", "timestamp": "2014-11-10 07:26:13"}, +{"_key": "052", "timestamp": "2014-11-10 07:26:14"}, +{"_key": "053", "timestamp": "2014-11-10 07:26:15"}, +{"_key": "054", "timestamp": "2014-11-10 07:26:16"}, +{"_key": "055", "timestamp": "2014-11-10 07:26:17"}, +{"_key": "056", "timestamp": "2014-11-10 07:26:18"}, +{"_key": "057", "timestamp": "2014-11-10 07:26:19"}, +{"_key": "058", "timestamp": "2014-11-10 07:26:20"}, +{"_key": "059", "timestamp": "2014-11-10 07:26:21"}, +{"_key": "060", "timestamp": "2014-11-10 07:26:22"}, +{"_key": "061", "timestamp": "2014-11-10 07:26:23"}, +{"_key": "062", "timestamp": "2014-11-10 07:26:24"}, +{"_key": "063", "timestamp": "2014-11-10 07:26:25"}, +{"_key": "064", "timestamp": "2014-11-10 07:26:26"}, +{"_key": "065", "timestamp": "2014-11-10 07:26:27"}, +{"_key": "066", "timestamp": "2014-11-10 07:26:28"}, +{"_key": "067", "timestamp": "2014-11-10 07:26:29"}, +{"_key": "068", "timestamp": "2014-11-10 07:26:30"}, +{"_key": "069", "timestamp": "2014-11-10 07:26:31"}, +{"_key": "070", "timestamp": "2014-11-10 07:26:32"}, +{"_key": "071", "timestamp": "2014-11-10 07:26:33"}, +{"_key": "072", "timestamp": "2014-11-10 07:26:34"}, +{"_key": "073", "timestamp": "2014-11-10 07:26:35"}, +{"_key": "074", "timestamp": "2014-11-10 07:26:36"}, +{"_key": "075", "timestamp": "2014-11-10 07:26:37"}, +{"_key": "076", "timestamp": "2014-11-10 07:26:38"}, +{"_key": "077", "timestamp": "2014-11-10 07:26:39"}, +{"_key": "078", "timestamp": "2014-11-10 07:26:40"}, +{"_key": "079", "timestamp": "2014-11-10 07:26:41"}, +{"_key": "080", "timestamp": "2014-11-10 07:26:42"}, +{"_key": "081", "timestamp": "2014-11-10 07:26:43"}, +{"_key": "082", "timestamp": "2014-11-10 07:26:44"}, +{"_key": "083", "timestamp": "2014-11-10 07:26:45"}, +{"_key": "084", "timestamp": "2014-11-10 07:26:46"}, +{"_key": "085", "timestamp": "2014-11-10 07:26:47"}, +{"_key": "086", "timestamp": "2014-11-10 07:26:48"}, +{"_key": "087", "timestamp": "2014-11-10 07:26:49"}, +{"_key": "088", "timestamp": "2014-11-10 07:26:50"}, +{"_key": "089", "timestamp": "2014-11-10 07:26:51"}, +{"_key": "090", "timestamp": "2014-11-10 07:26:52"}, +{"_key": "091", "timestamp": "2014-11-10 07:26:53"}, +{"_key": "092", "timestamp": "2014-11-10 07:26:54"}, +{"_key": "093", "timestamp": "2014-11-10 07:26:55"}, +{"_key": "094", "timestamp": "2014-11-10 07:26:56"}, +{"_key": "095", "timestamp": "2014-11-10 07:26:57"}, +{"_key": "096", "timestamp": "2014-11-10 07:26:58"}, +{"_key": "097", "timestamp": "2014-11-10 07:26:59"}, +{"_key": "098", "timestamp": "2014-11-10 07:27:00"}, +{"_key": "099", "timestamp": "2014-11-10 07:27:01"}, +{"_key": "100", "timestamp": "2014-11-10 07:27:02"}, +{"_key": "101", "timestamp": "2014-11-10 07:27:03"}, +{"_key": "102", "timestamp": "2014-11-10 07:27:04"}, +{"_key": "103", "timestamp": "2014-11-10 07:27:05"}, +{"_key": "104", "timestamp": "2014-11-10 07:27:06"}, +{"_key": "105", "timestamp": "2014-11-10 07:27:07"}, +{"_key": "106", "timestamp": "2014-11-10 07:27:08"}, +{"_key": "107", "timestamp": "2014-11-10 07:27:09"}, +{"_key": "108", "timestamp": "2014-11-10 07:27:10"}, +{"_key": "109", "timestamp": "2014-11-10 07:27:11"}, +{"_key": "110", "timestamp": "2014-11-10 07:27:12"}, +{"_key": "111", "timestamp": "2014-11-10 07:27:13"}, +{"_key": "112", "timestamp": "2014-11-10 07:27:14"}, +{"_key": "113", "timestamp": "2014-11-10 07:27:15"}, +{"_key": "114", "timestamp": "2014-11-10 07:27:16"}, +{"_key": "115", "timestamp": "2014-11-10 07:27:17"}, +{"_key": "116", "timestamp": "2014-11-10 07:27:18"}, +{"_key": "117", "timestamp": "2014-11-10 07:27:19"}, +{"_key": "118", "timestamp": "2014-11-10 07:27:20"}, +{"_key": "119", "timestamp": "2014-11-10 07:27:21"}, +{"_key": "120", "timestamp": "2014-11-10 07:27:22"}, +{"_key": "121", "timestamp": "2014-11-10 07:27:23"}, +{"_key": "122", "timestamp": "2014-11-10 07:27:24"}, +{"_key": "123", "timestamp": "2014-11-10 07:27:25"}, +{"_key": "124", "timestamp": "2014-11-10 07:27:26"}, +{"_key": "125", "timestamp": "2014-11-10 07:27:27"}, +{"_key": "126", "timestamp": "2014-11-10 07:27:28"}, +{"_key": "127", "timestamp": "2014-11-10 07:27:29"}, +{"_key": "128", "timestamp": "2014-11-10 07:27:30"}, +{"_key": "129", "timestamp": "2014-11-10 07:27:31"}, +{"_key": "130", "timestamp": "2014-11-10 07:27:32"}, +{"_key": "131", "timestamp": "2014-11-10 07:27:33"}, +{"_key": "132", "timestamp": "2014-11-10 07:27:34"}, +{"_key": "133", "timestamp": "2014-11-10 07:27:35"}, +{"_key": "134", "timestamp": "2014-11-10 07:27:36"}, +{"_key": "135", "timestamp": "2014-11-10 07:27:37"}, +{"_key": "136", "timestamp": "2014-11-10 07:27:38"}, +{"_key": "137", "timestamp": "2014-11-10 07:27:39"}, +{"_key": "138", "timestamp": "2014-11-10 07:27:40"}, +{"_key": "139", "timestamp": "2014-11-10 07:27:41"}, +{"_key": "140", "timestamp": "2014-11-10 07:27:42"}, +{"_key": "141", "timestamp": "2014-11-10 07:27:43"}, +{"_key": "142", "timestamp": "2014-11-10 07:27:44"}, +{"_key": "143", "timestamp": "2014-11-10 07:27:45"}, +{"_key": "144", "timestamp": "2014-11-10 07:27:46"}, +{"_key": "145", "timestamp": "2014-11-10 07:27:47"}, +{"_key": "146", "timestamp": "2014-11-10 07:27:48"}, +{"_key": "147", "timestamp": "2014-11-10 07:27:49"}, +{"_key": "148", "timestamp": "2014-11-10 07:27:50"}, +{"_key": "149", "timestamp": "2014-11-10 07:27:51"}, +{"_key": "150", "timestamp": "2014-11-10 07:27:52"}, +{"_key": "151", "timestamp": "2014-11-10 07:27:53"}, +{"_key": "152", "timestamp": "2014-11-10 07:27:54"}, +{"_key": "153", "timestamp": "2014-11-10 07:27:55"}, +{"_key": "154", "timestamp": "2014-11-10 07:27:56"}, +{"_key": "155", "timestamp": "2014-11-10 07:27:57"}, +{"_key": "156", "timestamp": "2014-11-10 07:27:58"}, +{"_key": "157", "timestamp": "2014-11-10 07:27:59"}, +{"_key": "158", "timestamp": "2014-11-10 07:28:00"}, +{"_key": "159", "timestamp": "2014-11-10 07:28:01"}, +{"_key": "160", "timestamp": "2014-11-10 07:28:02"}, +{"_key": "161", "timestamp": "2014-11-10 07:28:03"}, +{"_key": "162", "timestamp": "2014-11-10 07:28:04"}, +{"_key": "163", "timestamp": "2014-11-10 07:28:05"}, +{"_key": "164", "timestamp": "2014-11-10 07:28:06"}, +{"_key": "165", "timestamp": "2014-11-10 07:28:07"}, +{"_key": "166", "timestamp": "2014-11-10 07:28:08"}, +{"_key": "167", "timestamp": "2014-11-10 07:28:09"}, +{"_key": "168", "timestamp": "2014-11-10 07:28:10"}, +{"_key": "169", "timestamp": "2014-11-10 07:28:11"}, +{"_key": "170", "timestamp": "2014-11-10 07:28:12"}, +{"_key": "171", "timestamp": "2014-11-10 07:28:13"}, +{"_key": "172", "timestamp": "2014-11-10 07:28:14"}, +{"_key": "173", "timestamp": "2014-11-10 07:28:15"}, +{"_key": "174", "timestamp": "2014-11-10 07:28:16"}, +{"_key": "175", "timestamp": "2014-11-10 07:28:17"}, +{"_key": "176", "timestamp": "2014-11-10 07:28:18"}, +{"_key": "177", "timestamp": "2014-11-10 07:28:19"}, +{"_key": "178", "timestamp": "2014-11-10 07:28:20"}, +{"_key": "179", "timestamp": "2014-11-10 07:28:21"}, +{"_key": "180", "timestamp": "2014-11-10 07:28:22"}, +{"_key": "181", "timestamp": "2014-11-10 07:28:23"}, +{"_key": "182", "timestamp": "2014-11-10 07:28:24"}, +{"_key": "183", "timestamp": "2014-11-10 07:28:25"}, +{"_key": "184", "timestamp": "2014-11-10 07:28:26"}, +{"_key": "185", "timestamp": "2014-11-10 07:28:27"}, +{"_key": "186", "timestamp": "2014-11-10 07:28:28"}, +{"_key": "187", "timestamp": "2014-11-10 07:28:29"}, +{"_key": "188", "timestamp": "2014-11-10 07:28:30"}, +{"_key": "189", "timestamp": "2014-11-10 07:28:31"}, +{"_key": "190", "timestamp": "2014-11-10 07:28:32"}, +{"_key": "191", "timestamp": "2014-11-10 07:28:33"}, +{"_key": "192", "timestamp": "2014-11-10 07:28:34"}, +{"_key": "193", "timestamp": "2014-11-10 07:28:35"}, +{"_key": "194", "timestamp": "2014-11-10 07:28:36"}, +{"_key": "195", "timestamp": "2014-11-10 07:28:37"}, +{"_key": "196", "timestamp": "2014-11-10 07:28:38"}, +{"_key": "197", "timestamp": "2014-11-10 07:28:39"}, +{"_key": "198", "timestamp": "2014-11-10 07:28:40"}, +{"_key": "199", "timestamp": "2014-11-10 07:28:41"}, +{"_key": "200", "timestamp": "2014-11-10 07:28:42"} +] +[[0,0.0,0.0],200] +select Memos --filter '_key == "003" && between(timestamp, "2014-11-10 07:25:24", "include", "2014-11-10 07:27:26", "exclude")' +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 1 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "_key", + "ShortText" + ], + [ + "timestamp", + "Time" + ] + ], + [ + 3, + "003", + 1415571925.0 + ] + ] + ] +] Added: test/command/suite/select/function/between/with_index/sequential_search/time.test (+212 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/function/between/with_index/sequential_search/time.test 2014-11-11 13:46:25 +0900 (aa7fc53) @@ -0,0 +1,212 @@ +table_create Memos TABLE_HASH_KEY ShortText +column_create Memos timestamp COLUMN_SCALAR Time + +table_create Times TABLE_PAT_KEY Time +column_create Times memos_timestamp COLUMN_INDEX Memos timestamp + +load --table Memos +[ +{"_key": "001", "timestamp": "2014-11-10 07:25:23"}, +{"_key": "002", "timestamp": "2014-11-10 07:25:24"}, +{"_key": "003", "timestamp": "2014-11-10 07:25:25"}, +{"_key": "004", "timestamp": "2014-11-10 07:25:26"}, +{"_key": "005", "timestamp": "2014-11-10 07:25:27"}, +{"_key": "006", "timestamp": "2014-11-10 07:25:28"}, +{"_key": "007", "timestamp": "2014-11-10 07:25:29"}, +{"_key": "008", "timestamp": "2014-11-10 07:25:30"}, +{"_key": "009", "timestamp": "2014-11-10 07:25:31"}, +{"_key": "010", "timestamp": "2014-11-10 07:25:32"}, +{"_key": "011", "timestamp": "2014-11-10 07:25:33"}, +{"_key": "012", "timestamp": "2014-11-10 07:25:34"}, +{"_key": "013", "timestamp": "2014-11-10 07:25:35"}, +{"_key": "014", "timestamp": "2014-11-10 07:25:36"}, +{"_key": "015", "timestamp": "2014-11-10 07:25:37"}, +{"_key": "016", "timestamp": "2014-11-10 07:25:38"}, +{"_key": "017", "timestamp": "2014-11-10 07:25:39"}, +{"_key": "018", "timestamp": "2014-11-10 07:25:40"}, +{"_key": "019", "timestamp": "2014-11-10 07:25:41"}, +{"_key": "020", "timestamp": "2014-11-10 07:25:42"}, +{"_key": "021", "timestamp": "2014-11-10 07:25:43"}, +{"_key": "022", "timestamp": "2014-11-10 07:25:44"}, +{"_key": "023", "timestamp": "2014-11-10 07:25:45"}, +{"_key": "024", "timestamp": "2014-11-10 07:25:46"}, +{"_key": "025", "timestamp": "2014-11-10 07:25:47"}, +{"_key": "026", "timestamp": "2014-11-10 07:25:48"}, +{"_key": "027", "timestamp": "2014-11-10 07:25:49"}, +{"_key": "028", "timestamp": "2014-11-10 07:25:50"}, +{"_key": "029", "timestamp": "2014-11-10 07:25:51"}, +{"_key": "030", "timestamp": "2014-11-10 07:25:52"}, +{"_key": "031", "timestamp": "2014-11-10 07:25:53"}, +{"_key": "032", "timestamp": "2014-11-10 07:25:54"}, +{"_key": "033", "timestamp": "2014-11-10 07:25:55"}, +{"_key": "034", "timestamp": "2014-11-10 07:25:56"}, +{"_key": "035", "timestamp": "2014-11-10 07:25:57"}, +{"_key": "036", "timestamp": "2014-11-10 07:25:58"}, +{"_key": "037", "timestamp": "2014-11-10 07:25:59"}, +{"_key": "038", "timestamp": "2014-11-10 07:26:00"}, +{"_key": "039", "timestamp": "2014-11-10 07:26:01"}, +{"_key": "040", "timestamp": "2014-11-10 07:26:02"}, +{"_key": "041", "timestamp": "2014-11-10 07:26:03"}, +{"_key": "042", "timestamp": "2014-11-10 07:26:04"}, +{"_key": "043", "timestamp": "2014-11-10 07:26:05"}, +{"_key": "044", "timestamp": "2014-11-10 07:26:06"}, +{"_key": "045", "timestamp": "2014-11-10 07:26:07"}, +{"_key": "046", "timestamp": "2014-11-10 07:26:08"}, +{"_key": "047", "timestamp": "2014-11-10 07:26:09"}, +{"_key": "048", "timestamp": "2014-11-10 07:26:10"}, +{"_key": "049", "timestamp": "2014-11-10 07:26:11"}, +{"_key": "050", "timestamp": "2014-11-10 07:26:12"}, +{"_key": "051", "timestamp": "2014-11-10 07:26:13"}, +{"_key": "052", "timestamp": "2014-11-10 07:26:14"}, +{"_key": "053", "timestamp": "2014-11-10 07:26:15"}, +{"_key": "054", "timestamp": "2014-11-10 07:26:16"}, +{"_key": "055", "timestamp": "2014-11-10 07:26:17"}, +{"_key": "056", "timestamp": "2014-11-10 07:26:18"}, +{"_key": "057", "timestamp": "2014-11-10 07:26:19"}, +{"_key": "058", "timestamp": "2014-11-10 07:26:20"}, +{"_key": "059", "timestamp": "2014-11-10 07:26:21"}, +{"_key": "060", "timestamp": "2014-11-10 07:26:22"}, +{"_key": "061", "timestamp": "2014-11-10 07:26:23"}, +{"_key": "062", "timestamp": "2014-11-10 07:26:24"}, +{"_key": "063", "timestamp": "2014-11-10 07:26:25"}, +{"_key": "064", "timestamp": "2014-11-10 07:26:26"}, +{"_key": "065", "timestamp": "2014-11-10 07:26:27"}, +{"_key": "066", "timestamp": "2014-11-10 07:26:28"}, +{"_key": "067", "timestamp": "2014-11-10 07:26:29"}, +{"_key": "068", "timestamp": "2014-11-10 07:26:30"}, +{"_key": "069", "timestamp": "2014-11-10 07:26:31"}, +{"_key": "070", "timestamp": "2014-11-10 07:26:32"}, +{"_key": "071", "timestamp": "2014-11-10 07:26:33"}, +{"_key": "072", "timestamp": "2014-11-10 07:26:34"}, +{"_key": "073", "timestamp": "2014-11-10 07:26:35"}, +{"_key": "074", "timestamp": "2014-11-10 07:26:36"}, +{"_key": "075", "timestamp": "2014-11-10 07:26:37"}, +{"_key": "076", "timestamp": "2014-11-10 07:26:38"}, +{"_key": "077", "timestamp": "2014-11-10 07:26:39"}, +{"_key": "078", "timestamp": "2014-11-10 07:26:40"}, +{"_key": "079", "timestamp": "2014-11-10 07:26:41"}, +{"_key": "080", "timestamp": "2014-11-10 07:26:42"}, +{"_key": "081", "timestamp": "2014-11-10 07:26:43"}, +{"_key": "082", "timestamp": "2014-11-10 07:26:44"}, +{"_key": "083", "timestamp": "2014-11-10 07:26:45"}, +{"_key": "084", "timestamp": "2014-11-10 07:26:46"}, +{"_key": "085", "timestamp": "2014-11-10 07:26:47"}, +{"_key": "086", "timestamp": "2014-11-10 07:26:48"}, +{"_key": "087", "timestamp": "2014-11-10 07:26:49"}, +{"_key": "088", "timestamp": "2014-11-10 07:26:50"}, +{"_key": "089", "timestamp": "2014-11-10 07:26:51"}, +{"_key": "090", "timestamp": "2014-11-10 07:26:52"}, +{"_key": "091", "timestamp": "2014-11-10 07:26:53"}, +{"_key": "092", "timestamp": "2014-11-10 07:26:54"}, +{"_key": "093", "timestamp": "2014-11-10 07:26:55"}, +{"_key": "094", "timestamp": "2014-11-10 07:26:56"}, +{"_key": "095", "timestamp": "2014-11-10 07:26:57"}, +{"_key": "096", "timestamp": "2014-11-10 07:26:58"}, +{"_key": "097", "timestamp": "2014-11-10 07:26:59"}, +{"_key": "098", "timestamp": "2014-11-10 07:27:00"}, +{"_key": "099", "timestamp": "2014-11-10 07:27:01"}, +{"_key": "100", "timestamp": "2014-11-10 07:27:02"}, +{"_key": "101", "timestamp": "2014-11-10 07:27:03"}, +{"_key": "102", "timestamp": "2014-11-10 07:27:04"}, +{"_key": "103", "timestamp": "2014-11-10 07:27:05"}, +{"_key": "104", "timestamp": "2014-11-10 07:27:06"}, +{"_key": "105", "timestamp": "2014-11-10 07:27:07"}, +{"_key": "106", "timestamp": "2014-11-10 07:27:08"}, +{"_key": "107", "timestamp": "2014-11-10 07:27:09"}, +{"_key": "108", "timestamp": "2014-11-10 07:27:10"}, +{"_key": "109", "timestamp": "2014-11-10 07:27:11"}, +{"_key": "110", "timestamp": "2014-11-10 07:27:12"}, +{"_key": "111", "timestamp": "2014-11-10 07:27:13"}, +{"_key": "112", "timestamp": "2014-11-10 07:27:14"}, +{"_key": "113", "timestamp": "2014-11-10 07:27:15"}, +{"_key": "114", "timestamp": "2014-11-10 07:27:16"}, +{"_key": "115", "timestamp": "2014-11-10 07:27:17"}, +{"_key": "116", "timestamp": "2014-11-10 07:27:18"}, +{"_key": "117", "timestamp": "2014-11-10 07:27:19"}, +{"_key": "118", "timestamp": "2014-11-10 07:27:20"}, +{"_key": "119", "timestamp": "2014-11-10 07:27:21"}, +{"_key": "120", "timestamp": "2014-11-10 07:27:22"}, +{"_key": "121", "timestamp": "2014-11-10 07:27:23"}, +{"_key": "122", "timestamp": "2014-11-10 07:27:24"}, +{"_key": "123", "timestamp": "2014-11-10 07:27:25"}, +{"_key": "124", "timestamp": "2014-11-10 07:27:26"}, +{"_key": "125", "timestamp": "2014-11-10 07:27:27"}, +{"_key": "126", "timestamp": "2014-11-10 07:27:28"}, +{"_key": "127", "timestamp": "2014-11-10 07:27:29"}, +{"_key": "128", "timestamp": "2014-11-10 07:27:30"}, +{"_key": "129", "timestamp": "2014-11-10 07:27:31"}, +{"_key": "130", "timestamp": "2014-11-10 07:27:32"}, +{"_key": "131", "timestamp": "2014-11-10 07:27:33"}, +{"_key": "132", "timestamp": "2014-11-10 07:27:34"}, +{"_key": "133", "timestamp": "2014-11-10 07:27:35"}, +{"_key": "134", "timestamp": "2014-11-10 07:27:36"}, +{"_key": "135", "timestamp": "2014-11-10 07:27:37"}, +{"_key": "136", "timestamp": "2014-11-10 07:27:38"}, +{"_key": "137", "timestamp": "2014-11-10 07:27:39"}, +{"_key": "138", "timestamp": "2014-11-10 07:27:40"}, +{"_key": "139", "timestamp": "2014-11-10 07:27:41"}, +{"_key": "140", "timestamp": "2014-11-10 07:27:42"}, +{"_key": "141", "timestamp": "2014-11-10 07:27:43"}, +{"_key": "142", "timestamp": "2014-11-10 07:27:44"}, +{"_key": "143", "timestamp": "2014-11-10 07:27:45"}, +{"_key": "144", "timestamp": "2014-11-10 07:27:46"}, +{"_key": "145", "timestamp": "2014-11-10 07:27:47"}, +{"_key": "146", "timestamp": "2014-11-10 07:27:48"}, +{"_key": "147", "timestamp": "2014-11-10 07:27:49"}, +{"_key": "148", "timestamp": "2014-11-10 07:27:50"}, +{"_key": "149", "timestamp": "2014-11-10 07:27:51"}, +{"_key": "150", "timestamp": "2014-11-10 07:27:52"}, +{"_key": "151", "timestamp": "2014-11-10 07:27:53"}, +{"_key": "152", "timestamp": "2014-11-10 07:27:54"}, +{"_key": "153", "timestamp": "2014-11-10 07:27:55"}, +{"_key": "154", "timestamp": "2014-11-10 07:27:56"}, +{"_key": "155", "timestamp": "2014-11-10 07:27:57"}, +{"_key": "156", "timestamp": "2014-11-10 07:27:58"}, +{"_key": "157", "timestamp": "2014-11-10 07:27:59"}, +{"_key": "158", "timestamp": "2014-11-10 07:28:00"}, +{"_key": "159", "timestamp": "2014-11-10 07:28:01"}, +{"_key": "160", "timestamp": "2014-11-10 07:28:02"}, +{"_key": "161", "timestamp": "2014-11-10 07:28:03"}, +{"_key": "162", "timestamp": "2014-11-10 07:28:04"}, +{"_key": "163", "timestamp": "2014-11-10 07:28:05"}, +{"_key": "164", "timestamp": "2014-11-10 07:28:06"}, +{"_key": "165", "timestamp": "2014-11-10 07:28:07"}, +{"_key": "166", "timestamp": "2014-11-10 07:28:08"}, +{"_key": "167", "timestamp": "2014-11-10 07:28:09"}, +{"_key": "168", "timestamp": "2014-11-10 07:28:10"}, +{"_key": "169", "timestamp": "2014-11-10 07:28:11"}, +{"_key": "170", "timestamp": "2014-11-10 07:28:12"}, +{"_key": "171", "timestamp": "2014-11-10 07:28:13"}, +{"_key": "172", "timestamp": "2014-11-10 07:28:14"}, +{"_key": "173", "timestamp": "2014-11-10 07:28:15"}, +{"_key": "174", "timestamp": "2014-11-10 07:28:16"}, +{"_key": "175", "timestamp": "2014-11-10 07:28:17"}, +{"_key": "176", "timestamp": "2014-11-10 07:28:18"}, +{"_key": "177", "timestamp": "2014-11-10 07:28:19"}, +{"_key": "178", "timestamp": "2014-11-10 07:28:20"}, +{"_key": "179", "timestamp": "2014-11-10 07:28:21"}, +{"_key": "180", "timestamp": "2014-11-10 07:28:22"}, +{"_key": "181", "timestamp": "2014-11-10 07:28:23"}, +{"_key": "182", "timestamp": "2014-11-10 07:28:24"}, +{"_key": "183", "timestamp": "2014-11-10 07:28:25"}, +{"_key": "184", "timestamp": "2014-11-10 07:28:26"}, +{"_key": "185", "timestamp": "2014-11-10 07:28:27"}, +{"_key": "186", "timestamp": "2014-11-10 07:28:28"}, +{"_key": "187", "timestamp": "2014-11-10 07:28:29"}, +{"_key": "188", "timestamp": "2014-11-10 07:28:30"}, +{"_key": "189", "timestamp": "2014-11-10 07:28:31"}, +{"_key": "190", "timestamp": "2014-11-10 07:28:32"}, +{"_key": "191", "timestamp": "2014-11-10 07:28:33"}, +{"_key": "192", "timestamp": "2014-11-10 07:28:34"}, +{"_key": "193", "timestamp": "2014-11-10 07:28:35"}, +{"_key": "194", "timestamp": "2014-11-10 07:28:36"}, +{"_key": "195", "timestamp": "2014-11-10 07:28:37"}, +{"_key": "196", "timestamp": "2014-11-10 07:28:38"}, +{"_key": "197", "timestamp": "2014-11-10 07:28:39"}, +{"_key": "198", "timestamp": "2014-11-10 07:28:40"}, +{"_key": "199", "timestamp": "2014-11-10 07:28:41"}, +{"_key": "200", "timestamp": "2014-11-10 07:28:42"} +] + +select Memos \ + --filter '_key == "003" && between(timestamp, "2014-11-10 07:25:24", "include", "2014-11-10 07:27:26", "exclude")' -------------- next part -------------- HTML����������������������������... 下載