Skip to content

Commit

Permalink
Allow passing std::string_view to dbi::open
Browse files Browse the repository at this point in the history
- Useful in case the DBI names are themselves stored in the DB.
- Fixes hoytech#5
- Requested by @deepbluev7
  • Loading branch information
hoytech committed Mar 2, 2021
1 parent 029fb68 commit bd08913
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,8 @@ This C++17 version is a fork of Arto Bendiken's C++11 version with the following

* If an exception was throw by `txn.commit()` (ie `MDB_MAP_FULL`), and this transaction was later aborted (because it went out of scope while unwinding the stack), then a double-free would occur. This was [fixed](https://github.com/hoytech/lmdbxx/pull/3) by Niklas Salmoukas.

* `dbi::open()` now optionally accepts the DBI name as a `string_view`. This is useful when the DBI names themselves are stored in the DB. [Requested](https://github.com/hoytech/lmdbxx/issues/5) by deepbluev7.



## Author
Expand Down
36 changes: 35 additions & 1 deletion check.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int main() {
lmdb::dbi mydb;
lmdb::dbi mydbdups;

// Put some values in and read them back out
// Put some values in

{
auto txn = lmdb::txn::begin(env);
Expand All @@ -28,6 +28,8 @@ int main() {
txn.commit();
}

// Read them back out

{
auto txn = lmdb::txn::begin(env, nullptr, MDB_RDONLY);

Expand All @@ -38,6 +40,36 @@ int main() {
longLivedValue = v;
}

// Open DBI with a string_view

{
std::string mydbStr = "mydbJUNK";

auto txn = lmdb::txn::begin(env, nullptr, MDB_RDONLY);
auto mydb2 = lmdb::dbi::open(txn, std::string_view(mydbStr).substr(0, 4));

std::string_view v;
mydb2.get(txn, "hello", v);
if (v != "world") throw std::runtime_error("bad read 1.5");
}

// Loop over null DB, to make sure it contains the table we just created

{
auto txn = lmdb::txn::begin(env, nullptr, MDB_RDONLY);

auto emptyDb = lmdb::dbi::open(txn, nullptr);

auto cursor = lmdb::cursor::open(txn, emptyDb);
std::string_view key, val;

if (!cursor.get(key, val, MDB_FIRST)) throw std::runtime_error("emptyDb cursor err 1");
if (key != "mydb") throw std::runtime_error("emptyDb cursor err 2");

if (cursor.get(key, val, MDB_NEXT)) throw std::runtime_error("emptyDb cursor err 3");

cursor.close();
}

// Update one of the values

Expand All @@ -49,6 +81,8 @@ int main() {
txn.commit();
}

// Make sure updated value was stored

{
auto txn = lmdb::txn::begin(env, nullptr, MDB_RDONLY);

Expand Down
21 changes: 19 additions & 2 deletions lmdb++.h
Original file line number Diff line number Diff line change
Expand Up @@ -1265,8 +1265,8 @@ class lmdb::dbi {
* Opens a database handle.
*
* @param txn the transaction handle
* @param name
* @param flags
* @param name the database name, or nullptr
* @param flags dbi flags, ie MDB_CREATE
* @throws lmdb::error on failure
*/
static dbi
Expand All @@ -1278,6 +1278,23 @@ class lmdb::dbi {
return dbi{handle};
}

/*
* This overload is so that DBI names can be passed in as string_views, which can be
* useful when storing the names of DBIs in the database itself. We need to convert it
* to a std::string to ensure that it is NUL-byte terminated. This overload comes after
* the const char* one above so that in that case there is no std::string overhead.
*/

static dbi
open(MDB_txn* const txn,
std::string_view name,
const unsigned int flags = default_flags) {
MDB_dbi handle{};
std::string nameStr(name);
lmdb::dbi_open(txn, nameStr.c_str(), flags, &handle);
return dbi{handle};
}

/**
* Constructor.
*
Expand Down

0 comments on commit bd08913

Please sign in to comment.