1 /* -*- c-basic-offset: 2 -*- */ 2 /* 3 Copyright(C) 2014-2017 Brazil 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License version 2.1 as published by the Free Software Foundation. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with this library; if not, write to the Free Software 16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 17 */ 18 19 #include "../grn_ctx_impl.h" 20 #include <string.h> 21 22 #ifdef GRN_WITH_MRUBY 23 #include <mruby.h> 24 #include <mruby/class.h> 25 #include <mruby/data.h> 26 #include <mruby/hash.h> 27 #include <mruby/array.h> 28 #include <mruby/string.h> 29 30 #include "mrb_ctx.h" 31 #include "mrb_table.h" 32 #include "mrb_converter.h" 33 #include "mrb_options.h" 34 35 static mrb_value 36 mrb_grn_table_array_reference(mrb_state *mrb, mrb_value self) 37 { 38 grn_ctx *ctx = (grn_ctx *)mrb->ud; 39 grn_obj *table; 40 grn_id key_domain_id; 41 mrb_value mrb_key; 42 grn_id record_id; 43 grn_mrb_value_to_raw_data_buffer buffer; 44 void *key; 45 unsigned int key_size; 46 47 mrb_get_args(mrb, "o", &mrb_key); 48 49 table = DATA_PTR(self); 50 if (table->header.type == GRN_DB) { 51 key_domain_id = GRN_DB_SHORT_TEXT; 52 } else { 53 key_domain_id = table->header.domain; 54 } 55 56 grn_mrb_value_to_raw_data_buffer_init(mrb, &buffer); 57 grn_mrb_value_to_raw_data(mrb, "key", mrb_key, key_domain_id, 58 &buffer, &key, &key_size); 59 record_id = grn_table_get(ctx, table, key, key_size); 60 grn_mrb_value_to_raw_data_buffer_fin(mrb, &buffer); 61 62 if (record_id == GRN_ID_NIL) { 63 return mrb_nil_value(); 64 } else { 65 return mrb_fixnum_value(record_id); 66 } 67 } 68 69 static mrb_value 70 mrb_grn_table_is_id(mrb_state *mrb, mrb_value self) 71 { 72 grn_ctx *ctx = (grn_ctx *)mrb->ud; 73 grn_obj *table; 74 mrb_int mrb_record_id; 75 grn_id record_id; 76 grn_id real_record_id; 77 78 mrb_get_args(mrb, "i", &mrb_record_id); 79 80 table = DATA_PTR(self); 81 record_id = (grn_id)mrb_record_id; 82 real_record_id = grn_table_at(ctx, table, record_id); 83 if (real_record_id == record_id) { 84 return mrb_true_value(); 85 } else { 86 return mrb_false_value(); 87 } 88 } 89 90 static mrb_value 91 mrb_grn_table_find_column(mrb_state *mrb, mrb_value self) 92 { 93 grn_ctx *ctx = (grn_ctx *)mrb->ud; 94 grn_obj *table; 95 mrb_value mrb_column_name; 96 grn_obj *column; 97 98 mrb_get_args(mrb, "o", &mrb_column_name); 99 100 table = DATA_PTR(self); 101 column = grn_obj_column(ctx, table, 102 RSTRING_PTR(mrb_column_name), 103 RSTRING_LEN(mrb_column_name)); 104 grn_mrb_ctx_check(mrb); 105 106 return grn_mrb_value_from_grn_obj(mrb, column); 107 } 108 109 static mrb_value 110 mrb_grn_table_get_column_ids(mrb_state *mrb, mrb_value self) 111 { 112 grn_ctx *ctx = (grn_ctx *)mrb->ud; 113 grn_obj *table; 114 grn_hash *columns; 115 int n_columns; 116 mrb_value mrb_column_ids; 117 118 table = DATA_PTR(self); 119 columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, 120 GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); 121 if (!columns) { 122 grn_mrb_ctx_check(mrb); 123 return mrb_ary_new(mrb); 124 } 125 126 n_columns = grn_table_columns(ctx, table, "", 0, (grn_obj *)columns); 127 mrb_column_ids = mrb_ary_new_capa(mrb, n_columns); 128 { 129 grn_id *key; 130 GRN_HASH_EACH(ctx, columns, id, &key, NULL, NULL, { 131 mrb_ary_push(mrb, mrb_column_ids, mrb_fixnum_value(*key)); 132 }); 133 } 134 grn_hash_close(ctx, columns); 135 136 grn_mrb_ctx_check(mrb); 137 138 return mrb_column_ids; 139 } 140 141 static mrb_value 142 mrb_grn_table_create_column(mrb_state *mrb, mrb_value self) 143 { 144 grn_ctx *ctx = (grn_ctx *)mrb->ud; 145 grn_obj *table; 146 mrb_value mrb_name; 147 mrb_int flags; 148 mrb_value mrb_type; 149 grn_obj *type; 150 grn_obj *column; 151 152 mrb_get_args(mrb, "oio", &mrb_name, &flags, &mrb_type); 153 154 table = DATA_PTR(self); 155 type = DATA_PTR(mrb_type); 156 column = grn_column_create(ctx, table, 157 RSTRING_PTR(mrb_name), 158 RSTRING_LEN(mrb_name), 159 NULL, 160 flags, 161 type); 162 grn_mrb_ctx_check(mrb); 163 164 return grn_mrb_value_from_grn_obj(mrb, column); 165 } 166 167 static mrb_value 168 mrb_grn_table_is_locked(mrb_state *mrb, mrb_value self) 169 { 170 grn_ctx *ctx = (grn_ctx *)mrb->ud; 171 unsigned int is_locked; 172 173 is_locked = grn_obj_is_locked(ctx, DATA_PTR(self)); 174 grn_mrb_ctx_check(mrb); 175 176 return mrb_bool_value(is_locked != 0); 177 } 178 179 static mrb_value 180 mrb_grn_table_get_size(mrb_state *mrb, mrb_value self) 181 { 182 grn_ctx *ctx = (grn_ctx *)mrb->ud; 183 unsigned int size; 184 185 size = grn_table_size(ctx, DATA_PTR(self)); 186 grn_mrb_ctx_check(mrb); 187 188 return mrb_fixnum_value(size); 189 } 190 191 static mrb_value 192 mrb_grn_table_is_empty(mrb_state *mrb, mrb_value self) 193 { 194 grn_ctx *ctx = (grn_ctx *)mrb->ud; 195 unsigned int size; 196 197 size = grn_table_size(ctx, DATA_PTR(self)); 198 grn_mrb_ctx_check(mrb); 199 200 return mrb_bool_value(size == 0); 201 } 202 203 static mrb_value 204 mrb_grn_table_select(mrb_state *mrb, mrb_value self) 205 { 206 grn_ctx *ctx = (grn_ctx *)mrb->ud; 207 grn_obj *table; 208 grn_obj *expr; 209 grn_obj *result = NULL; 210 grn_operator operator = GRN_OP_OR; 211 mrb_value mrb_expr; 212 mrb_value mrb_options = mrb_nil_value(); 213 214 table = DATA_PTR(self); 215 mrb_get_args(mrb, "o|H", &mrb_expr, &mrb_options); 216 217 expr = DATA_PTR(mrb_expr); 218 219 if (!mrb_nil_p(mrb_options)) { 220 mrb_value mrb_result; 221 mrb_value mrb_operator; 222 223 mrb_result = grn_mrb_options_get_lit(mrb, mrb_options, "result"); 224 if (!mrb_nil_p(mrb_result)) { 225 result = DATA_PTR(mrb_result); 226 } 227 228 mrb_operator = grn_mrb_options_get_lit(mrb, mrb_options, "operator"); 229 if (!mrb_nil_p(mrb_operator)) { 230 operator = mrb_fixnum(mrb_operator); 231 } 232 } 233 234 result = grn_table_select(ctx, table, expr, result, operator); 235 if (ctx->rc != GRN_SUCCESS) { 236 grn_mrb_ctx_check(mrb); 237 } 238 239 return grn_mrb_value_from_grn_obj(mrb, result); 240 } 241 242 static mrb_value 243 mrb_grn_table_sort_raw(mrb_state *mrb, mrb_value self) 244 { 245 grn_ctx *ctx = (grn_ctx *)mrb->ud; 246 grn_obj *table; 247 mrb_value mrb_keys; 248 grn_table_sort_key *keys; 249 int i, n_keys; 250 mrb_int offset; 251 mrb_int limit; 252 mrb_value mrb_result; 253 grn_obj *result; 254 255 table = DATA_PTR(self); 256 mrb_get_args(mrb, "oiio", &mrb_keys, &offset, &limit, &mrb_result); 257 258 mrb_keys = mrb_convert_type(mrb, mrb_keys, 259 MRB_TT_ARRAY, "Array", "to_ary"); 260 261 n_keys = RARRAY_LEN(mrb_keys); 262 keys = GRN_MALLOCN(grn_table_sort_key, n_keys); 263 for (i = 0; i < n_keys; i++) { 264 grn_memcpy(&(keys[i]), 265 DATA_PTR(RARRAY_PTR(mrb_keys)[i]), 266 sizeof(grn_table_sort_key)); 267 } 268 result = DATA_PTR(mrb_result); 269 grn_table_sort(ctx, table, offset, limit, result, keys, n_keys); 270 GRN_FREE(keys); 271 grn_mrb_ctx_check(mrb); 272 273 return mrb_result; 274 } 275 276 static mrb_value 277 mrb_grn_table_group_raw(mrb_state *mrb, mrb_value self) 278 { 279 grn_ctx *ctx = (grn_ctx *)mrb->ud; 280 grn_obj *table; 281 mrb_value mrb_keys; 282 grn_table_sort_key *keys; 283 int i, n_keys; 284 mrb_value mrb_result; 285 grn_table_group_result *result; 286 287 table = DATA_PTR(self); 288 mrb_get_args(mrb, "oo", &mrb_keys, &mrb_result); 289 290 mrb_keys = mrb_convert_type(mrb, mrb_keys, 291 MRB_TT_ARRAY, "Array", "to_ary"); 292 293 n_keys = RARRAY_LEN(mrb_keys); 294 keys = GRN_MALLOCN(grn_table_sort_key, n_keys); 295 for (i = 0; i < n_keys; i++) { 296 grn_memcpy(&(keys[i]), 297 DATA_PTR(RARRAY_PTR(mrb_keys)[i]), 298 sizeof(grn_table_sort_key)); 299 } 300 result = DATA_PTR(mrb_result); 301 grn_table_group(ctx, table, keys, n_keys, result, 1); 302 GRN_FREE(keys); 303 grn_mrb_ctx_check(mrb); 304 305 return mrb_result; 306 } 307 308 static mrb_value 309 mrb_grn_table_delete(mrb_state *mrb, mrb_value self) 310 { 311 grn_ctx *ctx = (grn_ctx *)mrb->ud; 312 grn_obj *table; 313 mrb_value mrb_options; 314 mrb_value mrb_id; 315 mrb_value mrb_key; 316 mrb_value mrb_expression; 317 318 table = DATA_PTR(self); 319 mrb_get_args(mrb, "H", &mrb_options); 320 321 mrb_id = grn_mrb_options_get_lit(mrb, mrb_options, "id"); 322 if (!mrb_nil_p(mrb_id)) { 323 grn_table_delete_by_id(ctx, table, mrb_fixnum(mrb_id)); 324 grn_mrb_ctx_check(mrb); 325 return mrb_nil_value(); 326 } 327 328 mrb_key = grn_mrb_options_get_lit(mrb, mrb_options, "key"); 329 if (!mrb_nil_p(mrb_key)) { 330 grn_id key_domain_id; 331 void *key; 332 unsigned int key_size; 333 grn_mrb_value_to_raw_data_buffer buffer; 334 335 key_domain_id = table->header.domain; 336 grn_mrb_value_to_raw_data_buffer_init(mrb, &buffer); 337 grn_mrb_value_to_raw_data(mrb, "key", mrb_key, key_domain_id, 338 &buffer, &key, &key_size); 339 grn_table_delete(ctx, table, key, key_size); 340 grn_mrb_value_to_raw_data_buffer_fin(mrb, &buffer); 341 grn_mrb_ctx_check(mrb); 342 return mrb_nil_value(); 343 } 344 345 mrb_expression = grn_mrb_options_get_lit(mrb, mrb_options, "expression"); 346 if (!mrb_nil_p(mrb_expression)) { 347 grn_obj *expression; 348 grn_obj *selected_records; 349 grn_table_cursor *cursor; 350 351 expression = DATA_PTR(mrb_expression); 352 selected_records = grn_table_select(ctx, table, expression, NULL, GRN_OP_OR); 353 grn_mrb_ctx_check(mrb); 354 cursor = grn_table_cursor_open(ctx, selected_records, 355 NULL, 0, 356 NULL, 0, 357 0, -1, 0); 358 if (cursor) { 359 while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) { 360 grn_id *id; 361 grn_table_cursor_get_key(ctx, cursor, (void **)&id); 362 grn_table_delete_by_id(ctx, table, *id); 363 } 364 grn_table_cursor_close(ctx, cursor); 365 } 366 grn_mrb_ctx_check(mrb); 367 368 return mrb_nil_value(); 369 } 370 371 mrb_raisef(mrb, E_ARGUMENT_ERROR, 372 "must have :id, :key or :expression: %S", 373 mrb_options); 374 375 return mrb_nil_value(); 376 } 377 378 static mrb_value 379 mrb_grn_table_truncate(mrb_state *mrb, mrb_value self) 380 { 381 grn_ctx *ctx = (grn_ctx *)mrb->ud; 382 grn_obj *table; 383 384 table = DATA_PTR(self); 385 grn_table_truncate(ctx, table); 386 grn_mrb_ctx_check(mrb); 387 return mrb_nil_value(); 388 } 389 390 static mrb_value 391 mrb_grn_table_apply_expression(mrb_state *mrb, mrb_value self) 392 { 393 grn_ctx *ctx = (grn_ctx *)mrb->ud; 394 mrb_value mrb_output_column; 395 mrb_value mrb_expression; 396 grn_obj *table; 397 grn_obj *output_column = NULL; 398 grn_obj *expression = NULL; 399 400 mrb_get_args(mrb, "oo", &mrb_output_column, &mrb_expression); 401 402 table = DATA_PTR(self); 403 output_column = GRN_MRB_DATA_PTR(mrb_output_column); 404 expression = GRN_MRB_DATA_PTR(mrb_expression); 405 grn_table_apply_expr(ctx, table, output_column, expression); 406 grn_mrb_ctx_check(mrb); 407 408 return mrb_nil_value(); 409 } 410 411 static mrb_value 412 mrb_grn_table_apply_window_function_raw(mrb_state *mrb, mrb_value self) 413 { 414 grn_ctx *ctx = (grn_ctx *)mrb->ud; 415 mrb_value mrb_output_column; 416 mrb_value mrb_window_definition; 417 mrb_value mrb_window_function_call; 418 grn_obj *table; 419 grn_obj *output_column = NULL; 420 grn_window_definition *window_definition = NULL; 421 grn_obj *window_function_call = NULL; 422 423 mrb_get_args(mrb, "ooo", 424 &mrb_output_column, 425 &mrb_window_definition, 426 &mrb_window_function_call); 427 428 table = DATA_PTR(self); 429 output_column = GRN_MRB_DATA_PTR(mrb_output_column); 430 window_definition = GRN_MRB_DATA_PTR(mrb_window_definition); 431 window_function_call = GRN_MRB_DATA_PTR(mrb_window_function_call); 432 grn_table_apply_window_function(ctx, 433 table, 434 output_column, 435 window_definition, 436 window_function_call); 437 grn_mrb_ctx_check(mrb); 438 439 return mrb_nil_value(); 440 } 441 442 void 443 grn_mrb_table_init(grn_ctx *ctx) 444 { 445 grn_mrb_data *data = &(ctx->impl->mrb); 446 mrb_state *mrb = data->state; 447 struct RClass *module = data->module; 448 struct RClass *object_class = data->object_class; 449 struct RClass *klass; 450 451 klass = mrb_define_class_under(mrb, module, "Table", object_class); 452 MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); 453 454 mrb_define_method(mrb, klass, "[]", 455 mrb_grn_table_array_reference, MRB_ARGS_REQ(1)); 456 mrb_define_method(mrb, klass, "id?", 457 mrb_grn_table_is_id, MRB_ARGS_REQ(1)); 458 459 mrb_define_method(mrb, klass, "find_column", 460 mrb_grn_table_find_column, MRB_ARGS_REQ(1)); 461 mrb_define_method(mrb, klass, "column_ids", 462 mrb_grn_table_get_column_ids, MRB_ARGS_NONE()); 463 464 mrb_define_method(mrb, klass, "create_column", 465 mrb_grn_table_create_column, MRB_ARGS_REQ(3)); 466 467 mrb_define_method(mrb, klass, "locked?", 468 mrb_grn_table_is_locked, MRB_ARGS_NONE()); 469 470 mrb_define_method(mrb, klass, "size", 471 mrb_grn_table_get_size, MRB_ARGS_NONE()); 472 mrb_define_method(mrb, klass, "empty?", 473 mrb_grn_table_is_empty, MRB_ARGS_NONE()); 474 475 mrb_define_method(mrb, klass, "select", 476 mrb_grn_table_select, MRB_ARGS_ARG(1, 1)); 477 mrb_define_method(mrb, klass, "sort_raw", 478 mrb_grn_table_sort_raw, MRB_ARGS_REQ(4)); 479 mrb_define_method(mrb, klass, "group_raw", 480 mrb_grn_table_group_raw, MRB_ARGS_REQ(2)); 481 482 mrb_define_method(mrb, klass, "delete", 483 mrb_grn_table_delete, MRB_ARGS_REQ(1)); 484 485 mrb_define_method(mrb, klass, "truncate", 486 mrb_grn_table_truncate, MRB_ARGS_NONE()); 487 488 mrb_define_method(mrb, klass, "apply_expression", 489 mrb_grn_table_apply_expression, MRB_ARGS_REQ(2)); 490 mrb_define_method(mrb, klass, "apply_window_function_raw", 491 mrb_grn_table_apply_window_function_raw, MRB_ARGS_REQ(4)); 492 } 493 #endif 494