/* * call-seq: * update(key, old_value, new_value, option={}) * * レコードを追加する場合は old_value に nil を指定する。 * レコードを削除する場合は new_value に nil を指定する。 * レコードを更新する場合は old_value, new_value の両方を指定する。 * * 有効な option: * :section [Integer] :: セクション番号 * * === Argument * key [String/Integer] :: インデックス値 * old_value [String/Senna::Values] :: 古いレコード * new_value [String/Senna::Values] :: 新しいレコード * * === Exception * RuntimeError :: インデックスがクローズ済み * RuntimeError :: key のサイズがインデックスファイルのものとあっていない * TypeError :: open() で key_size に Integer が指定されているのに、key が整数でない * TypeError :: old_value, new_value が String でも Senna::Values でもない */ static VALUE index_update(int argc, VALUE *argv, VALUE obj) { VALUE key, oldv, newv, opt, section; struct index_data *data; sen_rc rc; char *_key; long n; VALUE skey; int key_size; VALUE key_type; sen_values *_oldv=NULL, *_newv=NULL; unsigned int _section=1; rb_scan_args(argc, argv, "31", &key, &oldv, &newv, &opt); Data_Get_Struct(obj, struct index_data, data); if (data->closed) rb_raise(rb_eRuntimeError, "already closed"); key_size = NUM2INT(rb_iv_get(obj, "key_size")); key_type = rb_iv_get(obj, "key_type"); if (!NIL_P(key_type)) { if (!rb_obj_is_kind_of(key, key_type)) rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", rb_obj_classname(key), rb_class_name(key_type)); } if (key_size == 0) { skey = StringValue(key); _key = RSTRING_PTR(skey); } else { switch(TYPE(key)) { case T_FIXNUM: case T_BIGNUM: if (key_size != sizeof(n)) rb_raise(rb_eRuntimeError, "invalid key_size: %d != %d", key_size, sizeof(n)); n = NUM2LONG(key); _key = (char *)&n; break; default: skey = StringValue(key); if (key_size != RSTRING_LEN(skey)) rb_raise(rb_eRuntimeError, "invalid key_size: %d != %d", key_size, RSTRING_LEN(skey)); _key = RSTRING_PTR(skey); break; } } if (!NIL_P(oldv)) { if (TYPE(oldv) == T_STRING) { VALUE str = oldv; oldv = values_new(cSennaValues); values_add(oldv, str, INT2FIX(0)); } else { if (!rb_obj_is_kind_of(oldv, cSennaValues)) rb_raise(rb_eTypeError, "wrong argument type %s (expected Senna::Values)", rb_obj_classname(oldv)); } Data_Get_Struct(oldv, sen_values, _oldv); } if (!NIL_P(newv)) { if (TYPE(newv) == T_STRING) { VALUE str = newv; newv = values_new(cSennaValues); values_add(newv, str, INT2FIX(0)); } else { if (!rb_obj_is_kind_of(newv, cSennaValues)) rb_raise(rb_eTypeError, "wrong argument type %s (expected Senna::Values)", rb_obj_classname(newv)); } Data_Get_Struct(newv, sen_values, _newv); } if (!NIL_P(opt)) { Check_Type(opt, T_HASH); section = rb_hash_aref(opt, ID2SYM(rb_intern("section"))); _section = NIL_P(section) ? 1 : NUM2UINT(section); } rc = sen_index_update(data->indexp, _key, _section, _oldv, _newv); if (rc != sen_success) senna_error(rc, "cannot update: key=%s", _key); return obj; }