class BDB1::Common
DATABASE
Public Class Methods
Creates a new temporary on-memory database, populated with the given hash or pairs of objects.
static VALUE bdb1_s_aref(int argc, VALUE *argv, VALUE obj) { VALUE res, tmp[2]; int i; res = rb_funcall2(obj, rb_intern("new"), 0, 0); if (argc == 1 && TYPE(argv[0]) == T_HASH) { rb_iterate(rb_each, argv[0], bdb1_i_create, res); return res; } if (argc % 2 != 0) { rb_raise(rb_eArgError, "odd number args for %s", rb_class2name(obj)); } for (i = 0; i < argc; i += 2) { bdb1_put(2, argv + i, res); } return res; }
Same as new
.
static VALUE bdb1_s_create(int argc, VALUE *argv, VALUE obj) { VALUE st, res; res = rb_funcall2(obj, rb_intern("allocate"), 0, 0); rb_obj_call_init(res, argc, argv); return res; }
Open the database.
-
name
The argument name is used as the name of a single physical file on disk that will be used to back the database.If
nil
is given, an on-memory database is created. -
flags
The flags must be the string “r”, “r+”, “w”, “w+”, “a”, “a+” or and integer value.The flags value must be set to 0 or by bitwise inclusively OR'ing together one or more of the following values
-
BDB1::CREATE
Create any underlying files, as necessary. If the files do not already exist and the DB_CREATE flag is not specified, the call will fail. -
BDB1::RDONLY
Open the database for reading only. Any attempt to modify items in the database will fail regardless of the actual permissions of any underlying files. -
BDB1::TRUNCATE
Physically truncate the underlying database file, discarding all previous subdatabases or databases. Underlying filesystem primitives are used to implement this flag. For this reason it is only applicable to the physical database file and cannot be used to discard subdatabases.The DB_TRUNCATE flag cannot be transaction protected, and it is an error to specify it in a transaction protected environment.
-
BDB1::WRITE
Open the database for writing. Without this flag, any attempt to modify items in the database will fail.
-
-
mode
mode to create the file -
options
Hash, Possible options are (see the documentation of Berkeley DB for more informations)-
set_flags
: general database configuration -
set_cachesize
: set the database cache size -
set_pagesize
: set the underlying database page size -
set_lorder
: set the database byte order -
set_store_key
: specify a Proc called before a key is stored -
set_fetch_key
: specify a Proc called after a key is read -
set_store_value
: specify a Proc called before a value is stored -
set_fetch_value
: specify a Proc called after a value is read
-
-
+options specific to BDB1::Btree+
-
+options specific to BDB1::Hash+
-
+options specific to BDB1::Recnum+
-
set_re_delim
: set the variable-length record delimiter -
set_re_len
: set the fixed-length record length -
set_re_pad
: set the fixed-length record pad byte
Proc given to
set_bt_compare
,set_bt_prefix
,set_h_hash
,set_store_key
,set_fetch_key
,set_store_value
andset_fetch_value
can be also specified as a method (replace the prefixset_
withbdb1_
)For example:
module BDB1 class Btreesort < Btree def bdb1_bt_compare(a, b) b.downcase <=> a.downcase end end end
-
VALUE bdb1_init(int argc, VALUE *argv, VALUE obj) { VALUE b, c, d, f; int mode, oflags; char *name; bdb1_DB *dbst; void *openinfo = NULL; f = Qnil; name = NULL; mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; oflags = DB_RDONLY; if (argc && TYPE(argv[argc - 1]) == T_HASH) { f = argv[argc - 1]; argc--; } switch(rb_scan_args(argc, argv, "03", &b, &c, &d)) { case 3: mode = NUM2INT(d); /* ... */ case 2: if (TYPE(c) == T_STRING) { char *m = StringValueCStr(c); if (strcmp(m, "r") == 0) { oflags = DB_RDONLY; } else if (strcmp(m, "r+") == 0) { oflags = DB_WRITE; } else if (strcmp(m, "w") == 0 || strcmp(m, "w+") == 0) { oflags = DB_CREATE | DB_TRUNCATE | DB_WRITE; } else if (strcmp(m, "a") == 0 || strcmp(m, "a+") == 0) { oflags = DB_CREATE | DB_WRITE; } else { rb_raise(bdb1_eFatal, "flags must be r, r+, w, w+, a or a+"); } } else if (NIL_P(c)) { oflags = DB_RDONLY; } else { oflags = NUM2INT(c); } /* ... */ case 1: if (!NIL_P(b)) { SafeStringValue(b); name = StringValueCStr(b); } else { name = NULL; } /* ... */ } Data_Get_Struct(obj, bdb1_DB, dbst); if (dbst->type < DB_BTREE || dbst->type > DB_RECNO) { rb_raise(bdb1_eFatal, "Unknown db185 type %d", dbst->type); } if (!NIL_P(f)) { if (TYPE(f) != T_HASH) { rb_raise(bdb1_eFatal, "options must be an hash"); } switch(dbst->type) { case 0: rb_iterate(rb_each, f, bdb1_i185_btree, obj); if (dbst->bt_compare == 0 && rb_respond_to(obj, id_bt_compare)) { dbst->has_info = Qtrue; dbst->options |= BDB1_BT_COMPARE; dbst->info.bi.compare = bdb1_bt_compare; } if (dbst->bt_prefix == 0 && rb_respond_to(obj, id_bt_prefix)) { dbst->has_info = Qtrue; dbst->options |= BDB1_BT_PREFIX; dbst->info.bi.prefix = bdb1_bt_prefix; } break; case 1: rb_iterate(rb_each, f, bdb1_i185_hash, obj); if (dbst->h_hash == 0 && rb_respond_to(obj, id_h_hash)) { dbst->has_info = Qtrue; dbst->options |= BDB1_H_HASH; dbst->info.hi.hash = bdb1_h_hash; } break; case 2: rb_iterate(rb_each, f, bdb1_i185_recno, obj); break; } rb_iterate(rb_each, f, bdb1_i185_common, obj); } if (name == NULL) oflags = O_CREAT | O_RDWR; if (dbst->has_info) openinfo = &dbst->info; dbst->dbp = dbopen(name, oflags, mode, dbst->type, openinfo); if (dbst->dbp == NULL) { rb_raise(bdb1_eFatal, "Failed `%s'", db_strerror(errno)); } dbst->options &= ~BDB1_NOT_OPEN; if (dbst->type == 2) { dbst->len = bdb1_hard_count(dbst->dbp); } return obj; }
Same as new
except that if a block is given it is called with
an initialized object which is automatically closed when done.
static VALUE bdb1_s_open(int argc, VALUE *argv, VALUE obj) { VALUE res = rb_funcall2(obj, rb_intern("new"), argc, argv); if (rb_block_given_p()) { return rb_ensure(rb_yield, res, bdb1_close, res); } return res; }
Public Instance Methods
Returns the value corresponding to key
.
static VALUE bdb1_get_dyna(int argc, VALUE *argv, VALUE obj) { return bdb1_get_internal(argc, argv, obj, Qnil, 1); }
static VALUE bdb1_assign(VALUE obj, VALUE a, VALUE b) { VALUE tmp[2]; tmp[0] = a; tmp[1] = b; bdb1_put(2, tmp, obj); return b; }
Returns true
if the association from key
is
value
.
static VALUE bdb1_has_both(VALUE obj, VALUE a, VALUE b) { bdb1_DB *dbst; DBT key, data; DBT keys, datas; int ret, flags; db_recno_t recno; volatile VALUE c = Qnil; volatile VALUE d = Qnil; GetDB(obj, dbst); DATA_ZERO(key); DATA_ZERO(data); c = test_recno(obj, &key, &recno, a); d = test_dump(obj, &data, b, FILTER_VALUE); MEMCPY(&keys, &key, DBT, 1); MEMCPY(&datas, &data, DBT, 1); flags = (dbst->type == DB_HASH)?DB_FIRST:R_CURSOR; while (1) { ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, flags)); if (ret == DB_NOTFOUND) { return Qfalse; } if (key.size == keys.size && memcmp(keys.data, key.data, key.size) == 0 && data.size == datas.size && memcmp(datas.data, data.data, data.size) == 0) { return Qtrue; } flags = DB_NEXT; } return Qnil; }
VALUE bdb1_clear(VALUE obj) { bdb1_DB *dbst; DBT key, data, save; int ret, value, flags; db_recno_t recno; rb_secure(4); GetDB(obj, dbst); INIT_RECNO(dbst, key, recno); DATA_ZERO(data); flags = DB_FIRST; value = 0; do { ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, flags)); if (ret == DB_NOTFOUND) { return INT2NUM(value); } value++; bdb1_test_error(dbst->dbp->del(dbst->dbp, 0, R_CURSOR)); } while (1); return INT2NUM(-1); }
Closes the file.
static VALUE bdb1_close(VALUE obj) { VALUE opt; bdb1_DB *dbst; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) { rb_raise(rb_eSecurityError, "Insecure: can't close the database"); } Data_Get_Struct(obj, bdb1_DB, dbst); bdb1_i_close(dbst); return Qnil; }
Closes the file.
static VALUE bdb1_close(VALUE obj) { VALUE opt; bdb1_DB *dbst; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) { rb_raise(rb_eSecurityError, "Insecure: can't close the database"); } Data_Get_Struct(obj, bdb1_DB, dbst); bdb1_i_close(dbst); return Qnil; }
Removes the association from the key
.
It returns the object deleted or nil
if the specified key
doesn't exist.
VALUE bdb1_del(VALUE obj, VALUE a) { bdb1_DB *dbst; DBT key; int ret; db_recno_t recno; volatile VALUE c = Qnil; rb_secure(4); GetDB(obj, dbst); if (dbst->type == DB_HASH) { rb_warning("delete can give strange result with DB_HASH"); } DATA_ZERO(key); c = test_recno(obj, &key, &recno, a); ret = bdb1_test_error(dbst->dbp->del(dbst->dbp, &key, 0)); if (ret == DB_NOTFOUND) return Qnil; else return obj; }
Returns the value corresponding to key
.
static VALUE bdb1_get_dyna(int argc, VALUE *argv, VALUE obj) { return bdb1_get_internal(argc, argv, obj, Qnil, 1); }
Stores the value
associating with key
and returns
the value stored.
flags
can have the value DBD::NOOVERWRITE
, in
this case it will return nil
if the specified key exist,
otherwise true
.
VALUE bdb1_put(int argc, VALUE *argv, VALUE obj) { volatile VALUE a0 = Qnil; volatile VALUE b0 = Qnil; VALUE a, b, c; bdb1_DB *dbst; DBT key, data; int ret, flags; db_recno_t recno; rb_secure(4); GetDB(obj, dbst); if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) flags = NUM2INT(c); else flags = 0; DATA_ZERO(key); DATA_ZERO(data); a0 = test_recno(obj, &key, &recno, a); b0 = test_dump(obj, &data, b, FILTER_VALUE); ret = bdb1_test_error(dbst->dbp->put(dbst->dbp, &key, &data, flags)); if (ret == DB_KEYEXIST) return Qfalse; return test_ret(obj, b0, b, FILTER_VALUE); }
static VALUE bdb1_sync(VALUE obj) { bdb1_DB *dbst; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't sync the database"); GetDB(obj, dbst); bdb1_test_error(dbst->dbp->sync(dbst->dbp, 0)); return Qtrue; }
Removes the association from the key
.
It returns the object deleted or nil
if the specified key
doesn't exist.
VALUE bdb1_del(VALUE obj, VALUE a) { bdb1_DB *dbst; DBT key; int ret; db_recno_t recno; volatile VALUE c = Qnil; rb_secure(4); GetDB(obj, dbst); if (dbst->type == DB_HASH) { rb_warning("delete can give strange result with DB_HASH"); } DATA_ZERO(key); c = test_recno(obj, &key, &recno, a); ret = bdb1_test_error(dbst->dbp->del(dbst->dbp, &key, 0)); if (ret == DB_NOTFOUND) return Qnil; else return obj; }
Removes the association from the key
.
It returns the object deleted or nil
if the specified key
doesn't exist.
VALUE bdb1_del(VALUE obj, VALUE a) { bdb1_DB *dbst; DBT key; int ret; db_recno_t recno; volatile VALUE c = Qnil; rb_secure(4); GetDB(obj, dbst); if (dbst->type == DB_HASH) { rb_warning("delete can give strange result with DB_HASH"); } DATA_ZERO(key); c = test_recno(obj, &key, &recno, a); ret = bdb1_test_error(dbst->dbp->del(dbst->dbp, &key, 0)); if (ret == DB_NOTFOUND) return Qnil; else return obj; }
static VALUE bdb1_delete_if(VALUE obj) { bdb1_DB *dbst; DBT key, data, save; int ret, ret1, flags; db_recno_t recno; rb_secure(4); GetDB(obj, dbst); INIT_RECNO(dbst, key, recno); DATA_ZERO(data); flags = DB_FIRST; do { ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, flags)); if (ret == DB_NOTFOUND) { return Qnil; } flags = DB_NEXT; if (RTEST(rb_yield(bdb1_assoc(obj, &key, &data)))) { bdb1_test_error(dbst->dbp->del(dbst->dbp, 0, R_CURSOR)); } } while (1); return obj; }
static VALUE bdb1_each_pair(VALUE obj) { return bdb1_each_common(obj, DB_NEXT); }
VALUE bdb1_each_key(VALUE obj) { return bdb1_each_keyc(obj, DB_NEXT); }
static VALUE bdb1_each_pair(VALUE obj) { return bdb1_each_common(obj, DB_NEXT); }
VALUE bdb1_each_value(VALUE obj) { return bdb1_each_valuec(obj, DB_NEXT, Qnil); }
static VALUE bdb1_empty(VALUE obj) { bdb1_DB *dbst; DBT key, data; int ret, flags; db_recno_t recno; GetDB(obj, dbst); INIT_RECNO(dbst, key, recno); DATA_ZERO(data); ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, DB_FIRST)); if (ret == DB_NOTFOUND) { return Qtrue; } FREE_KEY(dbst, key); return Qfalse; }
static VALUE bdb1_fetch(int argc, VALUE *argv, VALUE obj) { VALUE key, if_none; VALUE val; rb_scan_args(argc, argv, "11", &key, &if_none); val = bdb1_get_internal(1, argv, obj, Qundef, 1); if (val == Qundef) { if (rb_block_given_p()) { if (argc > 1) { rb_raise(rb_eArgError, "wrong # of arguments", argc); } return rb_yield(key); } if (argc == 1) { rb_raise(rb_eIndexError, "key not found"); } return if_none; } return val; }
static VALUE bdb1_sync(VALUE obj) { bdb1_DB *dbst; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't sync the database"); GetDB(obj, dbst); bdb1_test_error(dbst->dbp->sync(dbst->dbp, 0)); return Qtrue; }
Returns the value corresponding to key
.
static VALUE bdb1_get_dyna(int argc, VALUE *argv, VALUE obj) { return bdb1_get_internal(argc, argv, obj, Qnil, 1); }
Returns true
if the association from key
is
value
.
static VALUE bdb1_has_both(VALUE obj, VALUE a, VALUE b) { bdb1_DB *dbst; DBT key, data; DBT keys, datas; int ret, flags; db_recno_t recno; volatile VALUE c = Qnil; volatile VALUE d = Qnil; GetDB(obj, dbst); DATA_ZERO(key); DATA_ZERO(data); c = test_recno(obj, &key, &recno, a); d = test_dump(obj, &data, b, FILTER_VALUE); MEMCPY(&keys, &key, DBT, 1); MEMCPY(&datas, &data, DBT, 1); flags = (dbst->type == DB_HASH)?DB_FIRST:R_CURSOR; while (1) { ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, flags)); if (ret == DB_NOTFOUND) { return Qfalse; } if (key.size == keys.size && memcmp(keys.data, key.data, key.size) == 0 && data.size == datas.size && memcmp(datas.data, data.data, data.size) == 0) { return Qtrue; } flags = DB_NEXT; } return Qnil; }
static VALUE bdb1_has_key(VALUE obj, VALUE key) { return bdb1_get_internal(1, &key, obj, Qfalse, 0); }
VALUE bdb1_has_value(VALUE obj, VALUE a) { return bdb1_internal_value(obj, a, Qfalse, DB_NEXT); }
static VALUE bdb1_has_key(VALUE obj, VALUE key) { return bdb1_get_internal(1, &key, obj, Qfalse, 0); }
VALUE bdb1_key(VALUE obj, VALUE a) { return bdb1_internal_value(obj, a, Qtrue, DB_NEXT); }
static VALUE bdb1_invert(VALUE obj) { return bdb1_to_type(obj, rb_hash_new(), Qfalse); }
VALUE bdb1_key(VALUE obj, VALUE a) { return bdb1_internal_value(obj, a, Qtrue, DB_NEXT); }
static VALUE bdb1_has_key(VALUE obj, VALUE key) { return bdb1_get_internal(1, &key, obj, Qfalse, 0); }
static VALUE bdb1_keys(VALUE obj) { bdb1_DB *dbst; DBT key, data; int ret, flags; db_recno_t recno; VALUE ary; GetDB(obj, dbst); ary = rb_ary_new(); INIT_RECNO(dbst, key, recno); DATA_ZERO(data); flags = DB_FIRST; do { ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, flags)); if (ret == DB_NOTFOUND) { return ary; } rb_ary_push(ary, test_load_key(obj, &key)); FREE_KEY(dbst, key); flags = DB_NEXT; } while (1); return ary; }
static VALUE bdb1_length(VALUE obj) { bdb1_DB *dbst; DBT key, data; int ret, value, flags; db_recno_t recno; GetDB(obj, dbst); if (dbst->type == DB_RECNO) { return INT2NUM(bdb1_hard_count(dbst->dbp)); } INIT_RECNO(dbst, key, recno); DATA_ZERO(data); value = 0; flags = DB_FIRST; do { ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, flags)); if (ret == DB_NOTFOUND) { return INT2NUM(value); } flags = DB_NEXT; FREE_KEY(dbst, key); value++; } while (1); return INT2NUM(value); }
static VALUE bdb1_has_key(VALUE obj, VALUE key) { return bdb1_get_internal(1, &key, obj, Qfalse, 0); }
Stores the value
associating with key
and returns
the value stored.
flags
can have the value DBD::NOOVERWRITE
, in
this case it will return nil
if the specified key exist,
otherwise true
.
VALUE bdb1_put(int argc, VALUE *argv, VALUE obj) { volatile VALUE a0 = Qnil; volatile VALUE b0 = Qnil; VALUE a, b, c; bdb1_DB *dbst; DBT key, data; int ret, flags; db_recno_t recno; rb_secure(4); GetDB(obj, dbst); if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) flags = NUM2INT(c); else flags = 0; DATA_ZERO(key); DATA_ZERO(data); a0 = test_recno(obj, &key, &recno, a); b0 = test_dump(obj, &data, b, FILTER_VALUE); ret = bdb1_test_error(dbst->dbp->put(dbst->dbp, &key, &data, flags)); if (ret == DB_KEYEXIST) return Qfalse; return test_ret(obj, b0, b, FILTER_VALUE); }
static VALUE bdb1_reject(VALUE obj) { return rb_hash_delete_if(bdb1_to_hash(obj)); }
static VALUE bdb1_delete_if(VALUE obj) { bdb1_DB *dbst; DBT key, data, save; int ret, ret1, flags; db_recno_t recno; rb_secure(4); GetDB(obj, dbst); INIT_RECNO(dbst, key, recno); DATA_ZERO(data); flags = DB_FIRST; do { ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, flags)); if (ret == DB_NOTFOUND) { return Qnil; } flags = DB_NEXT; if (RTEST(rb_yield(bdb1_assoc(obj, &key, &data)))) { bdb1_test_error(dbst->dbp->del(dbst->dbp, 0, R_CURSOR)); } } while (1); return obj; }
static VALUE bdb1_each_riap(VALUE obj) { return bdb1_each_common(obj, DB_PREV); }
static VALUE bdb1_each_yek(VALUE obj) { return bdb1_each_keyc(obj, DB_PREV); }
static VALUE bdb1_each_riap(VALUE obj) { return bdb1_each_common(obj, DB_PREV); }
VALUE bdb1_each_eulav(VALUE obj) { return bdb1_each_valuec(obj, DB_PREV, Qnil); }
static VALUE bdb1_select(VALUE obj) { VALUE result = rb_ary_new(); if (rb_block_given_p()) { return bdb1_each_valuec(obj, DB_NEXT, result); } rb_raise(rb_eArgError, "block is not given"); }
Stores the value
associating with key
and returns
the value stored.
flags
can have the value DBD::NOOVERWRITE
, in
this case it will return nil
if the specified key exist,
otherwise true
.
VALUE bdb1_put(int argc, VALUE *argv, VALUE obj) { volatile VALUE a0 = Qnil; volatile VALUE b0 = Qnil; VALUE a, b, c; bdb1_DB *dbst; DBT key, data; int ret, flags; db_recno_t recno; rb_secure(4); GetDB(obj, dbst); if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) flags = NUM2INT(c); else flags = 0; DATA_ZERO(key); DATA_ZERO(data); a0 = test_recno(obj, &key, &recno, a); b0 = test_dump(obj, &data, b, FILTER_VALUE); ret = bdb1_test_error(dbst->dbp->put(dbst->dbp, &key, &data, flags)); if (ret == DB_KEYEXIST) return Qfalse; return test_ret(obj, b0, b, FILTER_VALUE); }
static VALUE bdb1_sync(VALUE obj) { bdb1_DB *dbst; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't sync the database"); GetDB(obj, dbst); bdb1_test_error(dbst->dbp->sync(dbst->dbp, 0)); return Qtrue; }
static VALUE bdb1_to_a(VALUE obj) { return bdb1_to_type(obj, rb_ary_new(), Qtrue); }
static VALUE bdb1_to_hash(VALUE obj) { return bdb1_to_type(obj, rb_hash_new(), Qtrue); }
VALUE bdb1_has_value(VALUE obj, VALUE a) { return bdb1_internal_value(obj, a, Qfalse, DB_NEXT); }
static VALUE bdb1_values(VALUE obj) { bdb1_DB *dbst; DBT key, data; int ret, flags; db_recno_t recno; VALUE ary; GetDB(obj, dbst); ary = rb_ary_new(); INIT_RECNO(dbst, key, recno); DATA_ZERO(data); flags = DB_FIRST; do { ret = bdb1_test_error(dbst->dbp->seq(dbst->dbp, &key, &data, flags)); if (ret == DB_NOTFOUND) { return ary; } flags = DB_NEXT; FREE_KEY(dbst, key); rb_ary_push(ary, bdb1_test_load(obj, &data, FILTER_VALUE)); } while (1); return ary; }
static VALUE bdb1_values_at(int argc, VALUE *argv, VALUE obj) { VALUE result = rb_ary_new2(argc); long i; for (i = 0; i < argc; i++) { rb_ary_push(result, bdb1_get(1, argv + i, obj)); } return result; }