mdbxmou 0.1.34 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CMakeLists.txt CHANGED
@@ -7,6 +7,10 @@ add_definitions(-DNAPI_CPP_EXCEPTIONS)
7
7
  set(CMAKE_CXX_STANDARD 17)
8
8
  set(CMAKE_CXX_STANDARD_REQUIRED ON)
9
9
 
10
+ if (MSVC)
11
+ add_compile_options(/Zc:__cplusplus)
12
+ endif()
13
+
10
14
  add_subdirectory("deps/libmdbx")
11
15
 
12
16
  add_library(${PROJECT_NAME} SHARED
@@ -19,6 +23,7 @@ add_library(${PROJECT_NAME} SHARED
19
23
  "src/querymou.cpp"
20
24
  "src/envmou.cpp"
21
25
  "src/txnmou.cpp"
26
+ "src/dbi.cpp"
22
27
  "src/dbimou.cpp")
23
28
 
24
29
  # Gives our library file a .node extension without any "lib" prefix
package/README.md CHANGED
@@ -5,7 +5,7 @@ High-performance Node.js binding for libmdbx — a fast, lightweight, embedded k
5
5
  ## Features
6
6
 
7
7
  - **Synchronous API** — Direct MDBX operations in main thread
8
- - **Asynchronous API** — Background operations via single Worker Thread
8
+ - **Asynchronous API** — Background operations with async/await
9
9
  - **Transactions** — ACID transactions with read/write modes
10
10
  - **Multiple key/value types** — String, binary, ordinal (integer) keys
11
11
  - **Batch operations** — Efficient multi-key read/write
@@ -33,14 +33,14 @@ await env.open({
33
33
  // Write data
34
34
  const txn = env.startWrite();
35
35
  const dbi = txn.createMap(MDBX_Param.keyMode.ordinal);
36
- dbi.put(1, "hello");
37
- dbi.put(2, "world");
36
+ dbi.put(txn, 1, "hello");
37
+ dbi.put(txn, 2, "world");
38
38
  txn.commit();
39
39
 
40
40
  // Read data
41
41
  const readTxn = env.startRead();
42
42
  const readDbi = readTxn.openMap(BigInt(MDBX_Param.keyMode.ordinal));
43
- const value = readDbi.get(1);
43
+ const value = readDbi.get(readTxn, 1);
44
44
  console.log(value); // "hello"
45
45
  readTxn.commit();
46
46
 
@@ -180,32 +180,37 @@ txn.abort();
180
180
 
181
181
  #### Methods
182
182
 
183
- **put(key, value, [flags])**
183
+ **put(txn, key, value)**
184
184
  ```javascript
185
- dbi.put(123, "value");
186
- dbi.put("key", Buffer.from("binary data"));
185
+ dbi.put(txn, 123, "value");
186
+ dbi.put(txn, "key", Buffer.from("binary data"));
187
187
  ```
188
188
 
189
- **get(key) → value**
189
+ **get(txn, key) → value**
190
190
  ```javascript
191
- const value = dbi.get(123);
192
- const binary = dbi.get("key");
191
+ const value = dbi.get(txn, 123);
192
+ const binary = dbi.get(txn, "key");
193
193
  ```
194
194
 
195
- **del(key) → boolean**
195
+ **del(txn, key) → boolean**
196
196
  ```javascript
197
- const deleted = dbi.del(123);
197
+ const deleted = dbi.del(txn, 123);
198
198
  ```
199
199
 
200
- **stat() → Object**
200
+ **has(txn, key) → boolean**
201
201
  ```javascript
202
- const stats = dbi.stat();
202
+ const exists = dbi.has(txn, 123);
203
+ ```
204
+
205
+ **stat(txn) → Object**
206
+ ```javascript
207
+ const stats = dbi.stat(txn);
203
208
  // { pageSize: 4096, depth: 1, entries: 10, ... }
204
209
  ```
205
210
 
206
- **forEach(callback)**
211
+ **forEach(txn, callback)**
207
212
  ```javascript
208
- dbi.forEach((key, value, index) => {
213
+ dbi.forEach(txn, (key, value, index) => {
209
214
  console.log(`${key}: ${value}`);
210
215
  return false; // continue iteration (or undefined)
211
216
  // return true; // stop iteration
@@ -214,34 +219,37 @@ dbi.forEach((key, value, index) => {
214
219
 
215
220
  > **Note**: forEach continues scanning while callback returns `undefined` or `false`, and stops when callback returns `true`.
216
221
 
217
- **keys() → Array**
222
+ **keys(txn) → Array**
218
223
  ```javascript
219
224
  // Get all keys
220
- const allKeys = dbi.keys();
225
+ const allKeys = dbi.keys(txn);
221
226
  ```
222
227
 
223
- **keysFrom(startKey, [limit], [cursorMode]) → Array**
228
+ **keysFrom(txn, startKey, [limit], [cursorMode]) → Array**
224
229
  ```javascript
225
230
  // Get keys starting from specific key
226
- const keys = dbi.keysFrom(42, 50); // 50 keys starting from 42
231
+ const keys = dbi.keysFrom(txn, 42, 50); // 50 keys starting from 42
227
232
 
228
233
  // With cursor mode
229
- const keys = dbi.keysFrom(42, 50, 'keyGreaterOrEqual');
234
+ const keys = dbi.keysFrom(txn, 42, 50, 'keyGreaterOrEqual');
230
235
 
231
236
  // BigInt keys
232
- const bigIntKeys = dbi.keysFrom(42n, 50);
237
+ const bigIntKeys = dbi.keysFrom(txn, 42n, 50);
233
238
 
234
239
  // Key equal mode (for multi-value databases)
235
- const equalKeys = dbi.keysFrom(5, 10, 'keyEqual');
240
+ const equalKeys = dbi.keysFrom(txn, 5, 10, 'keyEqual');
236
241
  ```
237
242
 
238
- **query(requests) → Promise<Array>** (Async batch operations)
243
+ **drop(txn, [delete_db]) → void**
239
244
  ```javascript
240
- dbi.forEach((key, value, index) => {
241
- console.log(`${key}: ${value}`);
242
- // return false; // continue iteration (or undefined)
243
- // return true; // stop iteration
244
- });
245
+ // Clear database contents (keep structure)
246
+ dbi.drop(txn, false);
247
+
248
+ // Delete database completely
249
+ dbi.drop(txn, true);
250
+
251
+ // Default behavior (clear contents)
252
+ dbi.drop(txn);
245
253
  ```
246
254
 
247
255
  ## Key and Value Types
@@ -280,7 +288,7 @@ function syncExample() {
280
288
  const dbi = writeTxn.createMap(MDBX_Param.keyMode.ordinal);
281
289
 
282
290
  for (let i = 0; i < 1000; i++) {
283
- dbi.put(i, `value_${i}`);
291
+ dbi.put(writeTxn, i, `value_${i}`);
284
292
  }
285
293
  writeTxn.commit();
286
294
 
@@ -288,17 +296,17 @@ function syncExample() {
288
296
  const readTxn = env.startRead();
289
297
  const readDbi = readTxn.openMap(MDBX_Param.keyMode.ordinal); // keys as numbers
290
298
 
291
- const value = readDbi.get(42);
299
+ const value = readDbi.get(readTxn, 42);
292
300
  console.log(value); // "value_42"
293
301
 
294
302
  // Iterate with cursor
295
- readDbi.forEach((key, value, index) => {
303
+ readDbi.forEach(readTxn, (key, value, index) => {
296
304
  console.log(`Key ${key} (type: ${typeof key}): ${value}`); // key is number
297
305
  return index >= 9; // stop after 10 items (indices 0-9)
298
306
  });
299
307
 
300
308
  // Get specific keys
301
- const someKeys = readDbi.keysFrom(100, { limit: 50 });
309
+ const someKeys = readDbi.keysFrom(readTxn, 100, 50);
302
310
  console.log(`Keys 100-149:`, someKeys); // array of numbers
303
311
 
304
312
  readTxn.commit();
@@ -316,7 +324,7 @@ async function asyncExample() {
316
324
  const dbi = writeTxn.createMap(MDBX_Param.keyMode.ordinal);
317
325
 
318
326
  for (let i = 0; i < 1000; i++) {
319
- dbi.put(i, `value_${i}`);
327
+ dbi.put(writeTxn, i, `value_${i}`);
320
328
  }
321
329
  writeTxn.commit();
322
330
 
@@ -324,17 +332,17 @@ async function asyncExample() {
324
332
  const readTxn = env.startRead();
325
333
  const readDbi = readTxn.openMap(BigInt(MDBX_Param.keyMode.ordinal)); // keys as BigInts
326
334
 
327
- const value = readDbi.get(42);
335
+ const value = readDbi.get(readTxn, 42);
328
336
  console.log(value); // "value_42"
329
337
 
330
338
  // Iterate with BigInt keys
331
- readDbi.forEach((key, value, index) => {
339
+ readDbi.forEach(readTxn, (key, value, index) => {
332
340
  console.log(`Key ${key} (type: ${typeof key}): ${value}`); // key is bigint
333
341
  return index >= 9; // stop after 10 items (indices 0-9)
334
342
  });
335
343
 
336
344
  // Get BigInt keys
337
- const bigIntKeys = readDbi.keysFrom(100n, { limit: 50 });
345
+ const bigIntKeys = readDbi.keysFrom(readTxn, 100n, 50);
338
346
  console.log(`Keys 100n-149n:`, bigIntKeys); // array of BigInts
339
347
 
340
348
  readTxn.commit();
@@ -355,16 +363,16 @@ function keyTypesExample() {
355
363
  const dbi = txn.createMap(MDBX_Param.keyMode.ordinal);
356
364
 
357
365
  // Store some data
358
- dbi.put(1, "one");
359
- dbi.put(2, "two");
360
- dbi.put(3, "three");
366
+ dbi.put(txn, 1, "one");
367
+ dbi.put(txn, 2, "two");
368
+ dbi.put(txn, 3, "three");
361
369
  txn.commit();
362
370
 
363
371
  // Read with number keyMode
364
372
  const readTxn1 = env.startRead();
365
373
  const numberDbi = readTxn1.openMap(MDBX_Param.keyMode.ordinal);
366
374
 
367
- numberDbi.forEach((key, value) => {
375
+ numberDbi.forEach(readTxn1, (key, value) => {
368
376
  console.log(`Number key: ${key} (${typeof key})`); // number
369
377
  // return undefined; // continue iteration (default)
370
378
  });
@@ -374,7 +382,7 @@ function keyTypesExample() {
374
382
  const readTxn2 = env.startRead();
375
383
  const bigintDbi = readTxn2.openMap(BigInt(MDBX_Param.keyMode.ordinal));
376
384
 
377
- bigintDbi.forEach((key, value) => {
385
+ bigintDbi.forEach(readTxn2, (key, value) => {
378
386
  console.log(`BigInt key: ${key} (${typeof key})`); // bigint
379
387
  // return false; // continue iteration
380
388
  });
@@ -398,7 +406,7 @@ function cursorExample() {
398
406
 
399
407
  // Store test data
400
408
  for (let i = 0; i < 100; i++) {
401
- dbi.put(i, `value_${i}`);
409
+ dbi.put(txn, i, `value_${i}`);
402
410
  }
403
411
  txn.commit();
404
412
 
@@ -406,25 +414,25 @@ function cursorExample() {
406
414
  const readDbi = readTxn.openMap(MDBX_Param.keyMode.ordinal);
407
415
 
408
416
  // Get all keys
409
- const allKeys = readDbi.keys();
417
+ const allKeys = readDbi.keys(readTxn);
410
418
  console.log(`Total keys: ${allKeys.length}`);
411
419
 
412
420
  // Get limited keys - use keysFrom with limit
413
- const firstTen = readDbi.keysFrom(0, 10);
421
+ const firstTen = readDbi.keysFrom(readTxn, 0, 10);
414
422
  console.log(`First 10 keys:`, firstTen);
415
423
 
416
424
  // Get keys from specific position
417
- const fromFifty = readDbi.keysFrom(50, 20);
425
+ const fromFifty = readDbi.keysFrom(readTxn, 50, 20);
418
426
  console.log(`Keys 50-69:`, fromFifty);
419
427
 
420
428
  // Reverse iteration - need manual logic or forEach
421
- const allKeysForReverse = readDbi.keys();
429
+ const allKeysForReverse = readDbi.keys(readTxn);
422
430
  const lastTen = allKeysForReverse.slice(-10).reverse();
423
431
  console.log(`Last 10 keys:`, lastTen);
424
432
 
425
433
  // Manual iteration with forEach
426
434
  let count = 0;
427
- readDbi.forEach((key, value, index) => {
435
+ readDbi.forEach(readTxn, (key, value, index) => {
428
436
  if (key >= 80) {
429
437
  console.log(`Key ${key}: ${value}`);
430
438
  count++;
@@ -437,52 +445,6 @@ function cursorExample() {
437
445
  }
438
446
  ```
439
447
 
440
- ### Batch Operations (Asynchronous)
441
-
442
- ```javascript
443
- const { MDBX_Async_Env } = require('mdbxmou/lib/mdbx_evn_async');
444
- const { MDBX_Param } = require('mdbxmou');
445
-
446
- async function batchExample() {
447
- const env = new MDBX_Async_Env();
448
- await env.open({ path: './async-data' });
449
-
450
- // Write transaction in worker thread
451
- const writeTxn = await env.startWrite();
452
- const dbi = await writeTxn.openMap({
453
- keyMode: MDBX_Param.keyMode.ordinal,
454
- create: true
455
- });
456
-
457
- // Batch write
458
- await dbi.putBatch([
459
- { key: 1n, value: "one" },
460
- { key: 2n, value: "two" },
461
- { key: 3n, value: "three" }
462
- ]);
463
-
464
- await writeTxn.commit();
465
-
466
- // Read transaction in worker thread
467
- const readTxn = await env.startRead();
468
- const readDbi = await readTxn.openMap({
469
- keyMode: MDBX_Param.keyMode.ordinal
470
- });
471
-
472
- // Batch read
473
- const results = await readDbi.getBatch([1n, 2n, 3n]);
474
- results.forEach((result, i) => {
475
- if (result.found) {
476
- console.log(`Key ${result.key}: ${result.value}`);
477
- }
478
- });
479
-
480
- await readTxn.commit();
481
- await env.close();
482
- await env.terminate();
483
- }
484
- ```
485
-
486
448
  ### Query API (Advanced Async)
487
449
 
488
450
  ```javascript
@@ -519,54 +481,6 @@ async function queryExample() {
519
481
  }
520
482
  ```
521
483
 
522
- ### Worker Thread Example
523
-
524
- ```javascript
525
- const { MDBX_Async_Env } = require('mdbxmou/lib/mdbx_evn_async');
526
-
527
- async function workerExample() {
528
- // Single worker thread for all async operations
529
- const env = new MDBX_Async_Env();
530
- await env.open({ path: './worker-data' });
531
-
532
- // Each transaction runs in the same worker thread
533
- const txn1 = await env.startWrite();
534
- const dbi1 = await txn1.openMap({
535
- keyMode: MDBX_Param.keyMode.ordinal,
536
- create: true
537
- });
538
- await dbi1.put(1n, "worker-value-1");
539
- await txn1.commit();
540
-
541
- // Another transaction in the same worker
542
- const txn2 = await env.startWrite();
543
- const dbi2 = await txn2.openMap({
544
- keyMode: MDBX_Param.keyMode.ordinal,
545
- create: true
546
- });
547
- await dbi2.put(2n, "worker-value-2");
548
- await txn2.commit();
549
-
550
- // Read transaction
551
- const readTxn = await env.startRead();
552
- const readDbi = await readTxn.openMap({
553
- keyMode: MDBX_Param.keyMode.ordinal
554
- });
555
-
556
- const results = await readDbi.getBatch([1n, 2n]);
557
- results.forEach(r => {
558
- if (r.found) {
559
- console.log(`Key ${r.key}: ${r.value}`);
560
- }
561
- });
562
-
563
- await readTxn.commit();
564
-
565
- await env.close();
566
- await env.terminate(); // Terminate the worker thread
567
- }
568
- ```
569
-
570
484
  ## Error Handling
571
485
 
572
486
  ```javascript
@@ -578,7 +492,7 @@ try {
578
492
  const dbi = txn.createMap(MDBX_Param.keyMode.ordinal);
579
493
 
580
494
  // This might throw if key already exists with MDBX_NOOVERWRITE
581
- dbi.put(123, "value", MDBX_Param.putFlag.nooverwrite);
495
+ dbi.put(txn, 123, "value", MDBX_Param.putFlag.nooverwrite);
582
496
 
583
497
  txn.commit();
584
498
  } catch (error) {
@@ -624,10 +538,10 @@ Note: For ordinal (integer) keys, use keyFlag.number or keyFlag.bigint to specif
624
538
  ## Performance Tips
625
539
 
626
540
  1. **Use ordinal keys** for integer data - much faster than string keys
627
- 2. **Batch operations** - Use query API or async worker thread for bulk operations
541
+ 2. **Batch operations** - Use query API for bulk operations
628
542
  3. **Reuse transactions** - Keep read transactions open for multiple operations
629
- 4. **Worker thread** - Use async API for CPU-intensive or I/O operations
630
- 5. **Memory mapping** - MDBX uses memory-mapped files for zero-copy access
543
+ 4. **Memory mapping** - MDBX uses memory-mapped files for zero-copy access
544
+ 5. **Transaction scope** - Always pass transaction object to DBI methods
631
545
 
632
546
  ## License
633
547
 
package/package.json CHANGED
@@ -16,17 +16,16 @@
16
16
  },
17
17
  "scripts": {
18
18
  "e3": "node ./test/e3.js",
19
+ "e33": "node ./test/e33.js",
19
20
  "e4": "node ./test/e4.js",
20
21
  "e5": "node ./test/e5.js",
21
- "test": "node ./test/e3.js && node ./test/e4.js && node ./test/e5.js",
22
22
  "build": "node build.js",
23
- "install-1": "git submodule update --init --recursive 2>/dev/null || true && node build.js",
24
- "install": "node build.js",
25
- "!prepublishOnly": "./prepare-npm.sh"
23
+ "build-dev": "node build-dev.js",
24
+ "install": "node build.js"
26
25
  },
27
26
  "gypfile": true,
28
27
  "name": "mdbxmou",
29
- "version": "0.1.34",
28
+ "version": "0.2.0",
30
29
  "description": "Node bindings for mdbx",
31
30
  "repository": {
32
31
  "type": "git",
@@ -35,16 +35,23 @@ static Napi::Value write_row(Napi::Env env, const keys_line& row)
35
35
  auto key_mode = row.key_mod;
36
36
  auto key_flag = row.key_flag;
37
37
  auto js_arr = Napi::Array::New(env, param.size());
38
- for (std::size_t j = 0; j < param.size(); ++j) {
38
+ for (std::uint32_t j = 0; j < param.size(); ++j) {
39
39
  const auto& item = param[j];
40
+ Napi::Value key_value;
40
41
  if (key_mode.val & key_mode::ordinal) {
41
- js_arr.Set(j, (key_flag.val & base_flag::number) ?
42
- Napi::Number::New(env, item.id_buf) : Napi::BigInt::New(env, item.id_buf));
42
+ if (key_flag.val & base_flag::number) {
43
+ key_value = Napi::Number::New(env, static_cast<double>(item.id_buf));
44
+ } else {
45
+ key_value = Napi::BigInt::New(env, item.id_buf);
46
+ }
43
47
  } else {
44
- js_arr.Set(j, (key_flag.val & base_flag::string) ?
45
- Napi::String::New(env, item.key_buf.data(), item.key_buf.size()) :
46
- Napi::Buffer<char>::Copy(env, item.key_buf.data(), item.key_buf.size()));
48
+ if (key_flag.val & base_flag::string) {
49
+ key_value = Napi::String::New(env, item.key_buf.data(), item.key_buf.size());
50
+ } else {
51
+ key_value = Napi::Buffer<char>::Copy(env, item.key_buf.data(), item.key_buf.size());
52
+ }
47
53
  }
54
+ js_arr.Set(j, key_value);
48
55
  }
49
56
  return js_arr;
50
57
  }
@@ -62,7 +69,7 @@ void async_keys::OnOK()
62
69
  }
63
70
 
64
71
  Napi::Array result = Napi::Array::New(env, query_.size());
65
- for (std::size_t i = 0; i < query_.size(); ++i) {
72
+ for (std::uint32_t i = 0; i < query_.size(); ++i) {
66
73
  Napi::Object js_row = Napi::Object::New(env);
67
74
  const auto& row = query_[i];
68
75
  if (!row.db.empty()) {
@@ -47,15 +47,22 @@ static Napi::Value write_row(Napi::Env env, const query_line& row)
47
47
  auto js_arr = Napi::Array::New(env, param.size());
48
48
  for (std::size_t j = 0; j < param.size(); ++j) {
49
49
  const auto& item = param[j];
50
+ Napi::Value key_value;
50
51
  Napi::Object js_item = Napi::Object::New(env);
51
52
  if (key_mode.val & key_mode::ordinal) {
52
- js_item.Set("key", (key_flag.val & base_flag::number) ?
53
- Napi::Number::New(env, item.id_buf) : Napi::BigInt::New(env, item.id_buf));
53
+ if (key_flag.val & base_flag::number) {
54
+ key_value = Napi::Number::New(env, static_cast<double>(item.id_buf));
55
+ } else {
56
+ key_value = Napi::BigInt::New(env, item.id_buf);
57
+ }
54
58
  } else {
55
- js_item.Set("key", (key_flag.val & base_flag::string) ?
56
- Napi::String::New(env, item.key_buf.data(), item.key_buf.size()) :
57
- Napi::Buffer<char>::Copy(env, item.key_buf.data(), item.key_buf.size()));
59
+ if (key_flag.val & base_flag::string) {
60
+ key_value = Napi::String::New(env, item.key_buf.data(), item.key_buf.size());
61
+ } else {
62
+ key_value = Napi::Buffer<char>::Copy(env, item.key_buf.data(), item.key_buf.size());
63
+ }
58
64
  }
65
+ js_item.Set("key", key_value);
59
66
 
60
67
  // все методы которые должны показать value в результате
61
68
  const auto mask{query_mode::get|query_mode::upsert|
@@ -67,9 +74,13 @@ static Napi::Value write_row(Napi::Env env, const query_line& row)
67
74
  js_item.Set("value", env.Null());
68
75
  } else {
69
76
  auto value_flag = row.value_flag;
70
- js_item.Set("value", (value_flag.val & base_flag::string) ?
71
- Napi::String::New(env, val_buf.data(), val_buf.size()) :
72
- Napi::Buffer<char>::Copy(env, val_buf.data(), val_buf.size()));
77
+ Napi::Value val_value;
78
+ if (value_flag.val & base_flag::string) {
79
+ val_value = Napi::String::New(env, val_buf.data(), val_buf.size());
80
+ } else {
81
+ val_value = Napi::Buffer<char>::Copy(env, val_buf.data(), val_buf.size());
82
+ }
83
+ js_item.Set("value", val_value);
73
84
  }
74
85
  }
75
86
 
@@ -77,7 +88,7 @@ static Napi::Value write_row(Napi::Env env, const query_line& row)
77
88
  if (mode.val & query_mode::del) {
78
89
  js_item.Set("found", Napi::Boolean::New(env, item.found));
79
90
  }
80
- js_arr.Set(j, js_item);
91
+ js_arr.Set(static_cast<uint32_t>(j), js_item);
81
92
  }
82
93
  return js_arr;
83
94
  }
@@ -103,7 +114,7 @@ void async_query::OnOK()
103
114
  if (!row.db.empty()) {
104
115
  js_row.Set("db", Napi::String::New(env, row.db_name));
105
116
  }
106
- result.Set(i, write_row(env, row));
117
+ result.Set(static_cast<uint32_t>(i), write_row(env, row));
107
118
  }
108
119
 
109
120
  deferred_.Resolve(result);
package/src/dbi.cpp ADDED
@@ -0,0 +1,66 @@
1
+ #include "dbi.hpp"
2
+
3
+ namespace mdbxmou {
4
+
5
+ MDBX_stat dbi::get_stat(const MDBX_txn* txn, MDBX_dbi dbi)
6
+ {
7
+ MDBX_stat stat;
8
+ auto rc = mdbx_dbi_stat(txn, dbi, &stat, sizeof(stat));
9
+ if (rc != MDBX_SUCCESS) {
10
+ throw std::runtime_error(mdbx_strerror(rc));
11
+ }
12
+ return stat;
13
+ }
14
+
15
+ valuemou dbi::get(const MDBX_txn* txn, const keymou& key) const
16
+ {
17
+ valuemou val{};
18
+ auto rc = mdbx_get(txn, id_, key, val);
19
+ if (rc == MDBX_NOTFOUND)
20
+ return {};
21
+ if (rc != MDBX_SUCCESS) {
22
+ throw std::runtime_error(mdbx_strerror(rc));
23
+ }
24
+ return val;
25
+ }
26
+
27
+ void dbi::put(MDBX_txn* txn, const keymou& key, valuemou& value, MDBX_put_flags_t flags)
28
+ {
29
+ auto rc = mdbx_put(txn, id_, key, value, flags);
30
+ if (rc != MDBX_SUCCESS) {
31
+ throw std::runtime_error(mdbx_strerror(rc));
32
+ }
33
+ }
34
+
35
+ bool dbi::del(MDBX_txn* txn, const keymou& key)
36
+ {
37
+ auto rc = mdbx_del(txn, id_, key, nullptr);
38
+ if (rc == MDBX_NOTFOUND) {
39
+ return false;
40
+ }
41
+ if (rc != MDBX_SUCCESS) {
42
+ throw std::runtime_error(mdbx_strerror(rc));
43
+ }
44
+ return true;
45
+ }
46
+
47
+
48
+ cursormou_managed dbi::open_cursor(MDBX_txn* txn) const
49
+ {
50
+ MDBX_cursor* cursor_ptr;
51
+ auto rc = mdbx_cursor_open(txn, id_, &cursor_ptr);
52
+ if (rc != MDBX_SUCCESS) {
53
+ throw std::runtime_error(mdbx_strerror(rc));
54
+ }
55
+ return cursormou_managed{ cursor_ptr };
56
+ }
57
+
58
+ void dbi::drop(MDBX_txn* txn, bool delete_db)
59
+ {
60
+ auto rc = mdbx_drop(txn, id_, delete_db);
61
+ if (rc != MDBX_SUCCESS) {
62
+ throw std::runtime_error(mdbx_strerror(rc));
63
+ }
64
+ }
65
+
66
+ } // namespace mdbxmou
package/src/dbi.hpp ADDED
@@ -0,0 +1,45 @@
1
+ #pragma once
2
+
3
+ #include "valuemou.hpp"
4
+ #include <memory>
5
+
6
+ namespace mdbxmou {
7
+
8
+ class dbi
9
+ {
10
+ protected:
11
+ MDBX_dbi id_{};
12
+
13
+ public:
14
+ dbi() = default;
15
+
16
+ void attach(MDBX_dbi id) noexcept {
17
+ id_ = id;
18
+ }
19
+
20
+ static MDBX_stat get_stat(const MDBX_txn* txn, MDBX_dbi dbi);
21
+
22
+ MDBX_stat get_stat(const MDBX_txn* txn) const
23
+ {
24
+ return get_stat(txn, id_);
25
+ }
26
+
27
+ valuemou get(const MDBX_txn* txn, const keymou& key) const;
28
+
29
+ bool has(const MDBX_txn* txn, const keymou& key) const
30
+ {
31
+ return !get(txn, key).is_null();
32
+ }
33
+
34
+ void put(MDBX_txn* txn, const keymou& key, valuemou& value,
35
+ MDBX_put_flags_t flags = MDBX_UPSERT);
36
+
37
+ bool del(MDBX_txn* txn, const keymou& key);
38
+
39
+ cursormou_managed open_cursor(MDBX_txn* txn) const;
40
+
41
+ // Drop database or delete it
42
+ void drop(MDBX_txn* txn, bool delete_db = false);
43
+ };
44
+
45
+ } // namespace mdbxmou