static mrb_value mrb_grn_table_sort_raw(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; grn_obj *table; mrb_value mrb_keys; grn_table_sort_key *keys; int i, n_keys; mrb_int offset; mrb_int limit; mrb_value mrb_result; grn_obj *result; table = DATA_PTR(self); mrb_get_args(mrb, "oiio", &mrb_keys, &offset, &limit, &mrb_result); mrb_keys = mrb_convert_type(mrb, mrb_keys, MRB_TT_ARRAY, "Array", "to_ary"); n_keys = RARRAY_LEN(mrb_keys); keys = GRN_MALLOCN(grn_table_sort_key, n_keys); for (i = 0; i < n_keys; i++) { memcpy(&(keys[i]), DATA_PTR(RARRAY_PTR(mrb_keys)[i]), sizeof(grn_table_sort_key)); } result = DATA_PTR(mrb_result); grn_table_sort(ctx, table, offset, limit, result, keys, n_keys); GRN_FREE(keys); grn_mrb_ctx_check(mrb); return mrb_result; }
/* FIXME: DON'T WORK!!! */ static VALUE rb_grn_view_sort (int argc, VALUE *argv, VALUE self) { VALUE rb_result = Qnil; #ifdef WIN32 rb_raise(rb_eNotImpError, "grn_view_add() isn't available on Windows."); #else grn_ctx *context = NULL; grn_obj *view; grn_obj *result; grn_table_sort_key *keys; int i, n_keys; int n_records, offset = 0, limit = -1; VALUE rb_keys, options; VALUE rb_offset, rb_limit; VALUE *rb_sort_keys; grn_table_cursor *cursor; VALUE exception; grn_obj id; rb_grn_table_deconstruct(SELF(self), &view, &context, NULL, NULL, NULL, NULL, NULL, NULL); rb_scan_args(argc, argv, "11", &rb_keys, &options); if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_keys, rb_cArray))) rb_raise(rb_eArgError, "keys should be an array of key: <%s>", rb_grn_inspect(rb_keys)); n_keys = RARRAY_LEN(rb_keys); rb_sort_keys = RARRAY_PTR(rb_keys); keys = ALLOCA_N(grn_table_sort_key, n_keys); for (i = 0; i < n_keys; i++) { VALUE rb_sort_options, rb_key, rb_resolved_key, rb_order; if (RVAL2CBOOL(rb_obj_is_kind_of(rb_sort_keys[i], rb_cHash))) { rb_sort_options = rb_sort_keys[i]; } else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_sort_keys[i], rb_cArray))) { rb_sort_options = rb_hash_new(); rb_hash_aset(rb_sort_options, RB_GRN_INTERN("key"), rb_ary_entry(rb_sort_keys[i], 0)); rb_hash_aset(rb_sort_options, RB_GRN_INTERN("order"), rb_ary_entry(rb_sort_keys[i], 1)); } else { rb_sort_options = rb_hash_new(); rb_hash_aset(rb_sort_options, RB_GRN_INTERN("key"), rb_sort_keys[i]); } rb_grn_scan_options(rb_sort_options, "key", &rb_key, "order", &rb_order, NULL); if (RVAL2CBOOL(rb_obj_is_kind_of(rb_key, rb_cString))) { rb_resolved_key = rb_grn_table_get_column(self, rb_key); } else { rb_resolved_key = rb_key; } keys[i].key = RVAL2GRNOBJECT(rb_resolved_key, &context); if (!keys[i].key) { rb_raise(rb_eGrnNoSuchColumn, "no such column: <%s>: <%s>", rb_grn_inspect(rb_key), rb_grn_inspect(self)); } if (NIL_P(rb_order)) { keys[i].flags = 0; } else if (rb_grn_equal_option(rb_order, "desc") || rb_grn_equal_option(rb_order, "descending")) { keys[i].flags = GRN_TABLE_SORT_DESC; } else if (rb_grn_equal_option(rb_order, "asc") || rb_grn_equal_option(rb_order, "ascending")) { keys[i].flags = GRN_TABLE_SORT_ASC; } else { rb_raise(rb_eArgError, "order should be one of " "[nil, :desc, :descending, :asc, :ascending]: %s", rb_grn_inspect(rb_order)); } } rb_grn_scan_options(options, "offset", &rb_offset, "limit", &rb_limit, NULL); if (!NIL_P(rb_offset)) offset = NUM2INT(rb_offset); if (!NIL_P(rb_limit)) limit = NUM2INT(rb_limit); result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_VIEW, NULL, NULL); grn_view_add(context, result, grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY, NULL, grn_ctx_get(context, "People", strlen("People")))); grn_view_add(context, result, grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY, NULL, grn_ctx_get(context, "People", strlen("People")))); n_records = grn_table_sort(context, view, offset, limit, result, keys, n_keys); exception = rb_grn_context_to_exception(context, self); if (!NIL_P(exception)) { grn_obj_unlink(context, result); rb_exc_raise(exception); } rb_result = rb_ary_new(); cursor = grn_table_cursor_open(context, result, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_ASCENDING); GRN_TEXT_INIT(&id, 0); while (grn_table_cursor_next_o(context, cursor, &id) == GRN_SUCCESS) { rb_ary_push(rb_result, rb_grn_view_record_new(self, &id)); } GRN_OBJ_FIN(context, &id); grn_table_cursor_close(context, cursor); grn_obj_unlink(context, result); #endif return rb_result; }
void test_near_geo_point(gpointer data) { grn_id id; int offset, limit; const GList *expected_keys; GList *actual_keys = NULL; grn_table_sort_key keys[2]; grn_obj base, base_string, location; create_geo_table(cut_take_printf(" [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"],\n" " [\"%s\"]", TAKEN_POINT(0, 0, 0, 180, 0, 0), TAKEN_POINT(0, 0, 0, -179, -59, -59), TAKEN_POINT(-1, -1, -1, 180, 0, 0), TAKEN_POINT(2, 1, 1, 180, 0, 0), TAKEN_POINT(-2, -1, -1, -179, -59, -59), TAKEN_POINT(1, 2, 1, -179, -59, -59), TAKEN_POINT(90, 0, 0, 0, 0, 0), TAKEN_POINT(-90, 0, 0, 1, 0, 0), TAKEN_POINT(1, 0, 0, 1, 0, 0), TAKEN_POINT(1, 1, 0, 1, 1, 0), TAKEN_POINT(1, 1, 1, 1, 1, 1), TAKEN_POINT(-1, 0, 0, 1, 1, 1), TAKEN_POINT(-1, -1, -1, 0, 0, 0), TAKEN_POINT(-1, -2, -1, -1, -1, -1), TAKEN_POINT(1, 1, 10, -1, -1, -1))); result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY, NULL, table); grn_test_assert_context(context); GRN_TEXT_INIT(&base_string, 0); GRN_TEXT_SETS(context, &base_string, gcut_data_get_string(data, "base")); GRN_WGS84_GEO_POINT_INIT(&base, 0); grn_obj_cast(context, &base_string, &base, FALSE); GRN_OBJ_FIN(context, &base_string); offset = gcut_data_get_int(data, "offset"); if (offset > 0) { cut_omit("geo sort doesn't support offset yet."); } limit = gcut_data_get_int(data, "limit"); keys[0].key = column; keys[0].flags = GRN_TABLE_SORT_GEO; keys[0].offset = 0; keys[1].key = &base; keys[1].flags = 0; keys[1].offset = 0; grn_table_sort(context, table, offset, limit, result, keys, 2); GRN_OBJ_FIN(context, &base); grn_test_assert_context(context); cursor = grn_table_cursor_open(context, result, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_ASCENDING); grn_test_assert_context(context); GRN_WGS84_GEO_POINT_INIT(&location, 0); while ((id = grn_table_cursor_next(context, cursor))) { gint32 *key; int key_size; gint latitude, longitude; key_size = grn_table_cursor_get_value(context, cursor, (void **)&key); GRN_BULK_REWIND(&location); grn_obj_get_value(context, column, *key, &location); GRN_GEO_POINT_VALUE(&location, latitude, longitude); actual_keys = g_list_append(actual_keys, inspect_point(latitude, longitude)); } GRN_OBJ_FIN(context, &location); gcut_take_list(actual_keys, g_free); expected_keys = gcut_data_get_pointer(data, "expected"); gcut_assert_equal_list_string(expected_keys, actual_keys); }
/* TODO: Fix memory leak on error */ static mrb_value mrb_grn_table_sort(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; grn_obj *table; grn_obj *result = NULL; grn_table_sort_key *keys; int i, n_keys; int offset = 0; int limit = -1; mrb_value mrb_keys; mrb_value mrb_options = mrb_nil_value(); table = DATA_PTR(self); mrb_get_args(mrb, "o|H", &mrb_keys, &mrb_options); mrb_keys = mrb_convert_type(mrb, mrb_keys, MRB_TT_ARRAY, "Array", "to_ary"); n_keys = RARRAY_LEN(mrb_keys); keys = GRN_MALLOCN(grn_table_sort_key, n_keys); for (i = 0; i < n_keys; i++) { mrb_value mrb_sort_options; mrb_value mrb_sort_key; mrb_value mrb_sort_order; mrb_sort_options = RARRAY_PTR(mrb_keys)[i]; mrb_sort_key = grn_mrb_options_get_lit(mrb, mrb_sort_options, "key"); switch (mrb_type(mrb_sort_key)) { case MRB_TT_STRING : keys[i].key = grn_obj_column(ctx, table, RSTRING_PTR(mrb_sort_key), RSTRING_LEN(mrb_sort_key)); break; case MRB_TT_SYMBOL : { const char *name; mrb_int name_length; name = mrb_sym2name_len(mrb, mrb_symbol(mrb_sort_key), &name_length); keys[i].key = grn_obj_column(ctx, table, name, name_length); } break; default : /* TODO: free */ mrb_raisef(mrb, E_ARGUMENT_ERROR, "sort key must be string or symbol: %S", mrb_sort_key); break; } keys[i].flags = 0; mrb_sort_order = grn_mrb_options_get_lit(mrb, mrb_sort_options, "order"); if (mrb_nil_p(mrb_sort_order) || (mrb_symbol(mrb_sort_order) == mrb_intern_lit(mrb, "ascending"))) { keys[i].flags |= GRN_TABLE_SORT_ASC; } else { keys[i].flags |= GRN_TABLE_SORT_DESC; } } if (!mrb_nil_p(mrb_options)) { mrb_value mrb_offset; mrb_value mrb_limit; mrb_offset = grn_mrb_options_get_lit(mrb, mrb_options, "offset"); if (!mrb_nil_p(mrb_offset)) { offset = mrb_fixnum(mrb_offset); } mrb_limit = grn_mrb_options_get_lit(mrb, mrb_options, "limit"); if (!mrb_nil_p(mrb_limit)) { limit = mrb_fixnum(mrb_limit); } } result = grn_table_create(ctx, NULL, 0, NULL, GRN_TABLE_NO_KEY, NULL, table); grn_table_sort(ctx, table, offset, limit, result, keys, n_keys); for (i = 0; i < n_keys; i++) { grn_obj_unlink(ctx, keys[i].key); } GRN_FREE(keys); grn_mrb_ctx_check(mrb); return grn_mrb_value_from_grn_obj(mrb, result); }
void test_array_sort(gpointer data) { const gint32 values[] = { 5, 6, 18, 9, 0, 4, 13, 12, 8, 14, 19, 11, 7, 3, 1, 10, 15, 2, 17, 16 }; const int n_values = sizeof(values) / sizeof(values[0]); const gchar table_name[] = "Store"; const gchar column_name[] = "sample_column"; const int n_keys = 1; grn_table_sort_key keys[n_keys]; grn_obj *table, *column, *result; grn_table_cursor *cursor; int n_results; guint i; guint n_expected_values; GList *expected_values, *sorted_values = NULL; table = grn_table_create(context, table_name, strlen(table_name), NULL, GRN_OBJ_TABLE_NO_KEY | GRN_OBJ_PERSISTENT, NULL, NULL); column = grn_column_create(context, table, column_name, strlen(column_name), NULL, 0, get_object("Int32")); keys[0].key = column; keys[0].flags = GRN_TABLE_SORT_ASC; for(i = 0; i < n_values; ++i) { grn_obj record_value; grn_id record_id; record_id = grn_table_add(context, table, NULL, 0, NULL); GRN_INT32_INIT(&record_value, 0); GRN_INT32_SET(context, &record_value, values[i]); grn_test_assert(grn_obj_set_value(context, column, record_id, &record_value, GRN_OBJ_SET)); GRN_OBJ_FIN(context, &record_value); } cut_assert_equal_int(n_values, grn_table_size(context, table)); result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY, NULL, table); n_results = grn_table_sort(context, table, gcut_data_get_int(data, "offset"), gcut_data_get_int(data, "limit"), result, keys, n_keys); expected_values = (GList *)gcut_data_get_pointer(data, "expected_values"); n_expected_values = g_list_length(expected_values); cut_assert_equal_int(n_expected_values, n_results); cut_assert_equal_int(n_expected_values, grn_table_size(context, result)); cursor = grn_table_cursor_open(context, result, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_ASCENDING); while (grn_table_cursor_next(context, cursor) != GRN_ID_NIL) { void *value; grn_id *id; grn_obj record_value; grn_table_cursor_get_value(context, cursor, &value); id = value; GRN_INT32_INIT(&record_value, 0); grn_obj_get_value(context, column, *id, &record_value); sorted_values = g_list_append(sorted_values, GINT_TO_POINTER(GRN_INT32_VALUE(&record_value))); GRN_OBJ_FIN(context, &record_value); } gcut_take_list(sorted_values, NULL); gcut_assert_equal_list_int(expected_values, sorted_values); grn_table_cursor_close(context, cursor); grn_obj_close(context, result); }