Class: LMDB::Database
- Inherits:
-
Object
- Object
- LMDB::Database
- Includes:
- Enumerable
- Defined in:
- ext/lmdb_ext/lmdb_ext.c,
lib/lmdb/database.rb,
ext/lmdb_ext/lmdb_ext.c
Overview
An LMDB Database is a table of key-value pairs. It is stored as part of the Environment.
By default, each key in a Database maps to one value. However, a Database can be configured at creation to allow duplicate keys, in which case one key will map to multiple values.
A Database stores the keys in a sorted order. The order can also be set with options when the database is created.
The basic operations on a database are to #put, #get, and #delete records. One can also iterate through the records in a database using a Cursor.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Retrieve the value of a record from a database.
-
#[]=(key, value) ⇒ Object
Set (write or update) a record in a database.
-
#cardinality(key) ⇒ Integer
Return the cardinality (number of duplicates) of a given key.
-
#clear ⇒ Object
Empty out the database.
-
#cursor {|cursor| ... } ⇒ Object
Create a cursor to iterate through a database.
-
#delete(key, value = nil) ⇒ Object
Deletes records from the database.
-
#delete?(key, value = nil) ⇒ void
Delete the key (and optional value pair) if it exists; do not complain about missing keys.
-
#drop ⇒ Object
Remove a database from the environment.
-
#dupfixed? ⇒ true, false
Returns whether the database is in
:dupfixedmode. -
#dupsort? ⇒ true, false
Returns whether the database is in
:dupsortmode. -
#each {|i| ... } ⇒ Object
Iterate through the records in a database.
-
#each_key(&block) ⇒ Enumerator
Iterate over each key in the database, skipping over duplicate records.
-
#each_value(key, &block) ⇒ Enumerator
Iterate over the duplicate values of a given key, using an implicit cursor.
-
#empty? ⇒ Boolean
Whether the database is empty.
- #env ⇒ Environment
-
#flags ⇒ Hash
Return the flags used to open the database.
-
#get(key) ⇒ Object
Retrieves one value associated with this key.
-
#has?(key, value = nil) ⇒ Boolean
Test if the database has a given key (or, if opened in
:dupsort, value). -
#keys ⇒ Array
Get the keys as an array.
-
#put(key, value, options) ⇒ Object
Stores items into a database.
-
#put?(key, value = nil, **options) ⇒ void
Conditionally put a value into the database.
-
#size ⇒ Object
Return how many records there are in this database.
-
#stat ⇒ Hash
Return useful statistics about a database.
Instance Method Details
#[](key) ⇒ Object
Retrieve the value of a record from a database
29 30 31 |
# File 'lib/lmdb/database.rb', line 29 def [](key) get(key) end |
#[]=(key, value) ⇒ Object
Set (write or update) a record in a database.
42 43 44 45 |
# File 'lib/lmdb/database.rb', line 42 def []=(key, value) put key, value value end |
#cardinality(key) ⇒ Integer
Return the cardinality (number of duplicates) of a given key. Works whether :dupsort is set or not.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/lmdb/database.rb', line 100 def cardinality(key) ret = 0 maybe_txn true do # env.transaction do if get key if dupsort? cursor do |c| c.set key ret = c.count end else ret = 1 end end end ret end |
#clear ⇒ Object
1517 1518 1519 1520 1521 1522 1523 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1517
static VALUE database_clear(VALUE self) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env))
return call_with_transaction(database->env, self, "clear", 0, 0, 0);
check(mdb_drop(need_txn(database->env), database->dbi, 0));
return Qnil;
}
|
#cursor {|cursor| ... } ⇒ Object
1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1744
static VALUE database_cursor(VALUE self) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env)) {
if (!rb_block_given_p()) {
rb_raise(cError, "Must call with block or active transaction.");
}
return call_with_transaction(database->env, self, "cursor", 0, 0, 0);
}
MDB_cursor* cur;
check(mdb_cursor_open(need_txn(database->env), database->dbi, &cur));
Cursor* cursor;
VALUE vcur = TypedData_Make_Struct(cCursor, Cursor,
&lmdb_cursor_type, cursor);
cursor->cur = cur;
cursor->db = self;
if (rb_block_given_p()) {
int exception;
VALUE ret = rb_protect(rb_yield, vcur, &exception);
if (exception) {
cursor_close(vcur);
rb_jump_tag(exception);
}
cursor_close(vcur);
return ret;
}
else {
VALUE vtxn = environment_active_txn(database->env);
if (NIL_P(vtxn)) {
rb_fatal("Internal error: transaction finished unexpectedly.");
}
else {
TRANSACTION(vtxn, &lmdb_transaction_type, txn);
rb_ary_push(txn->cursors, vcur);
}
}
return vcur;
}
|
#delete(key, value = nil) ⇒ Object
Deletes records from the database. This function removes key/data pairs from the database. If the database does not support sorted duplicate data items (:dupsort) the value parameter is ignored. If the database supports sorted duplicates and the value parameter is nil, all of the duplicate data items for the key will be deleted. Otherwise, if the data parameter is non-nil only the matching data item will be deleted.
1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1633
static VALUE database_delete(int argc, VALUE *argv, VALUE self) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env))
return call_with_transaction(database->env, self, "delete", argc, argv, 0);
VALUE vkey, vval;
rb_scan_args(argc, argv, "11", &vkey, &vval);
vkey = StringValue(vkey);
MDB_val key;
key.mv_size = RSTRING_LEN(vkey);
key.mv_data = RSTRING_PTR(vkey);
if (NIL_P(vval)) {
check(mdb_del(need_txn(database->env), database->dbi, &key, 0));
} else {
vval = StringValue(vval);
MDB_val value;
value.mv_size = RSTRING_LEN(vval);
value.mv_data = RSTRING_PTR(vval);
check(mdb_del(need_txn(database->env), database->dbi, &key, &value));
}
return Qnil;
}
|
#delete?(key, value = nil) ⇒ void
This method returns an undefined value.
Delete the key (and optional value pair) if it exists; do not complain about missing keys.
166 167 168 |
# File 'lib/lmdb/database.rb', line 166 def delete?(key, value = nil) env.transaction { |txn| delete(key, value) if has?(key, value) } end |
#drop ⇒ Object
1503 1504 1505 1506 1507 1508 1509 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1503
static VALUE database_drop(VALUE self) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env))
return call_with_transaction(database->env, self, "drop", 0, 0, 0);
check(mdb_drop(need_txn(database->env), database->dbi, 1));
return Qnil;
}
|
#dupfixed? ⇒ true, false
1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1486
static VALUE database_is_dupfixed(VALUE self) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env))
return call_with_transaction(database->env, self,
"dupfixed?", 0, 0, MDB_RDONLY);
unsigned int flags;
check(mdb_dbi_flags(need_txn(database->env), database->dbi, &flags));
return (flags & MDB_DUPFIXED) == 0 ? Qfalse : Qtrue;
}
|
#dupsort? ⇒ true, false
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1470
static VALUE database_is_dupsort(VALUE self) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env))
return call_with_transaction(database->env, self,
"dupsort?", 0, 0, MDB_RDONLY);
unsigned int flags;
check(mdb_dbi_flags(need_txn(database->env), database->dbi, &flags));
return (flags & MDB_DUPSORT) == 0 ? Qfalse : Qtrue;
}
|
#each {|i| ... } ⇒ Object
Iterate through the records in a database
13 14 15 16 17 18 19 20 21 22 |
# File 'lib/lmdb/database.rb', line 13 def each maybe_txn true do # env.transaction do cursor do |c| while i = c.next yield(i) end end end end |
#each_key(&block) ⇒ Enumerator
Iterate over each key in the database, skipping over duplicate records.
57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/lmdb/database.rb', line 57 def each_key(&block) return enum_for :each_key unless block_given? maybe_txn true do #env.transaction do cursor do |c| while (rec = c.next true) yield rec.first end end end end |
#each_value(key, &block) ⇒ Enumerator
Iterate over the duplicate values of a given key, using an implicit cursor. Works whether :dupsort is set or not.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/lmdb/database.rb', line 75 def each_value(key, &block) return enum_for :each_value, key unless block_given? value = get(key) or return unless dupsort? yield value return end maybe_txn true do # env.transaction do cursor do |c| rec = c.set key while rec yield rec.last rec = c.next_range key end end end end |
#empty? ⇒ Boolean
Returns whether the database is empty.
179 180 181 |
# File 'lib/lmdb/database.rb', line 179 def empty? stat[:entries] == 0 end |
#env ⇒ Environment
1790 1791 1792 1793 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1790
static VALUE database_env(VALUE self) {
DATABASE(self, &lmdb_database_type, database);
return database->env;
}
|
#flags ⇒ Hash
1453 1454 1455 1456 1457 1458 1459 1460 1461 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1453
static VALUE database_get_flags(VALUE self) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env))
return call_with_transaction(database->env,
self, "flags", 0, 0, MDB_RDONLY);
unsigned int flags;
check(mdb_dbi_flags(need_txn(database->env), database->dbi, &flags));
return flags2hash(flags);
}
|
#get(key) ⇒ Object
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1534
static VALUE database_get(VALUE self, VALUE vkey) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env))
return call_with_transaction(database->env, self, "get", 1, &vkey, MDB_RDONLY);
vkey = StringValue(vkey);
MDB_val key, value;
key.mv_size = RSTRING_LEN(vkey);
key.mv_data = RSTRING_PTR(vkey);
// rb_warn("lol database get %s", (char *)key.mv_data);
int ret = mdb_get(need_txn(database->env), database->dbi, &key, &value);
if (ret == MDB_NOTFOUND)
return Qnil;
check(ret);
return rb_str_new(value.mv_data, value.mv_size);
}
|
#has?(key, value = nil) ⇒ Boolean
Test if the database has a given key (or, if opened in :dupsort, value)
120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/lmdb/database.rb', line 120 def has?(key, value = nil) v = get(key) or return false return true if value.nil? or value.to_s == v return false unless dupsort? # warn "checking dupsort value `#{value.inspect}` (#{value.class})" ret = false # read-only txn was having trouble being nested inside a read-write # maybe_txn(true) { cursor { |c| ret = !!c.set(key, value) } } env.transaction(true) { cursor { |c| ret = !!c.set(key, value) } } ret end |
#keys ⇒ Array
Get the keys as an array.
49 50 51 |
# File 'lib/lmdb/database.rb', line 49 def keys each_key.to_a end |
#put(key, value, options) ⇒ Object
1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1587
static VALUE database_put(int argc, VALUE *argv, VALUE self) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env))
return call_with_transaction(database->env, self, "put", argc, argv, 0);
VALUE vkey, vval, option_hash = Qnil;
#ifdef RB_SCAN_ARGS_KEYWORDS
rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS,
argc, argv, "20:", &vkey, &vval, &option_hash);
#else
rb_scan_args(argc, argv, "20:", &vkey, &vval, &option_hash);
#endif
int flags = 0;
if (!NIL_P(option_hash))
rb_hash_foreach(option_hash, (int (*)(ANYARGS))database_put_flags,
(VALUE)&flags);
vkey = StringValue(vkey);
vval = StringValue(vval);
MDB_val key, value;
key.mv_size = RSTRING_LEN(vkey);
key.mv_data = RSTRING_PTR(vkey);
value.mv_size = RSTRING_LEN(vval);
value.mv_data = RSTRING_PTR(vval);
check(mdb_put(need_txn(database->env), database->dbi, &key, &value, flags));
return Qnil;
}
|
#put?(key, value = nil, **options) ⇒ void
This method returns an undefined value.
Conditionally put a value into the database.
145 146 147 148 149 150 151 152 153 154 |
# File 'lib/lmdb/database.rb', line 145 def put?(key, value = nil, **) # early bailout return if value.nil? flags = { (dupsort? ? :nodupdata : :nooverwrite) => true } env.transaction do |txn| put(key, value, **.merge(flags)) unless has?(key, value) end end |
#size ⇒ Object
Return how many records there are in this database.
173 174 175 |
# File 'lib/lmdb/database.rb', line 173 def size stat[:entries] end |
#stat ⇒ Hash
1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 |
# File 'ext/lmdb_ext/lmdb_ext.c', line 1437
static VALUE database_stat(VALUE self) {
DATABASE(self, &lmdb_database_type, database);
if (!active_txn(database->env))
return call_with_transaction(database->env,
self, "stat", 0, 0, MDB_RDONLY);
MDB_stat stat;
check(mdb_stat(need_txn(database->env), database->dbi, &stat));
return stat2hash(&stat);
}
|