mdbxmou 0.3.10 → 0.3.12
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 +1 -1
- package/README.md +203 -12
- package/lib/async.d.mts +6 -4
- package/lib/types.d.ts +30 -2
- package/package.json +5 -1
- package/src/async/envmou_keys.cpp +54 -65
- package/src/async/envmou_query.cpp +22 -38
- package/src/convmou.cpp +51 -0
- package/src/convmou.hpp +26 -0
- package/src/cursormou.cpp +6 -75
- package/src/cursormou.hpp +1 -0
- package/src/dbimou.cpp +380 -196
- package/src/dbimou.hpp +10 -0
- package/src/envmou.cpp +0 -14
- package/src/modulemou.cpp +35 -22
- package/src/querymou.cpp +16 -16
- package/src/querymou.hpp +3 -1
- package/src/txnmou.cpp +19 -3
- package/src/txnmou.hpp +3 -0
- package/src/typemou.hpp +138 -34
- package/src/valuemou.hpp +62 -83
package/CMakeLists.txt
CHANGED
|
@@ -23,6 +23,7 @@ add_library(${PROJECT_NAME} SHARED
|
|
|
23
23
|
"src/querymou.cpp"
|
|
24
24
|
"src/envmou.cpp"
|
|
25
25
|
"src/txnmou.cpp"
|
|
26
|
+
"src/convmou.cpp"
|
|
26
27
|
"src/dbimou.cpp"
|
|
27
28
|
"src/cursormou.cpp"
|
|
28
29
|
"src/dbi.cpp")
|
|
@@ -63,4 +64,3 @@ string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
|
|
|
63
64
|
string(REPLACE "\"" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
|
|
64
65
|
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR} "src")
|
|
65
66
|
|
|
66
|
-
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# mdbxmou
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Node.js binding for [libmdbx](https://github.com/Mithril-mine/libmdbx) — a fast, lightweight, embedded key-value database.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Synchronous API** — Direct MDBX operations in main thread
|
|
8
8
|
- **Asynchronous API** — Background operations with async/await
|
|
9
9
|
- **Transactions** — ACID transactions with read/write modes
|
|
10
|
-
- **Multiple key/value types** — String, binary, ordinal
|
|
10
|
+
- **Multiple key/value types** — String, binary, ordinal keys and ordinal duplicate values
|
|
11
11
|
- **Batch operations** — Efficient multi-key read/write
|
|
12
12
|
- **Memory-mapped** — High-performance memory-mapped I/O
|
|
13
13
|
|
|
@@ -86,6 +86,8 @@ Options:
|
|
|
86
86
|
- `keyFlag` - Default key encoding for all operations (optional, defaults to Buffer)
|
|
87
87
|
- Only `string` can be set (ordinal mode uses `number`/`bigint` separately)
|
|
88
88
|
- `valueFlag` - Default value encoding for all operations (optional, defaults to Buffer)
|
|
89
|
+
- `string` affects normal string values
|
|
90
|
+
- `number` and `bigint` are meaningful for `valueMode.multiOrdinal`
|
|
89
91
|
- `maxDbi` - Maximum number of databases (optional, default `32`)
|
|
90
92
|
- `mode` - Filesystem permissions mode (optional, default `0664`)
|
|
91
93
|
- `geometry` - Map size/geometry options (optional)
|
|
@@ -190,14 +192,21 @@ const txn = env.startRead();
|
|
|
190
192
|
```javascript
|
|
191
193
|
const result = await env.query([
|
|
192
194
|
{
|
|
193
|
-
|
|
194
|
-
keyMode: MDBX_Param.keyMode.ordinal,
|
|
195
|
+
dbi,
|
|
195
196
|
mode: MDBX_Param.queryMode.get,
|
|
196
197
|
item: [{ key: 1 }, { key: 2 }]
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
dbi,
|
|
201
|
+
mode: MDBX_Param.queryMode.upsert,
|
|
202
|
+
putFlag: MDBX_Param.putFlag.noOverwrite,
|
|
203
|
+
item: [{ key: 3, value: "v3" }]
|
|
197
204
|
}
|
|
198
205
|
]);
|
|
199
206
|
```
|
|
200
207
|
|
|
208
|
+
`query()` uses the passed `dbi` and inherits key/value settings from it. `queryMode` selects the operation (`get`, `del`, or base write mode), and optional `putFlag` adds write-only MDBX flags. In `query()` only `noOverwrite`, `noDupData`, `current`, `append`, and `appendDup` are supported.
|
|
209
|
+
|
|
201
210
|
### Transaction
|
|
202
211
|
|
|
203
212
|
#### Methods
|
|
@@ -271,6 +280,8 @@ const dbi = txn.openMap({
|
|
|
271
280
|
> - `keyMode: BigInt(number)` → keys returned as `BigInt`
|
|
272
281
|
> - When you pass `keyMode.ordinal` as a positional argument (Number/BigInt), it also updates `keyFlag` to number/bigint unless a numeric keyFlag was already set in env or explicitly provided.
|
|
273
282
|
|
|
283
|
+
> **Note**: When `valueMode.multiOrdinal` is used and `valueFlag` is not specified, values are returned as `number` by default. Set `valueFlag: MDBX_Param.valueFlag.bigint` if you need `BigInt` on read.
|
|
284
|
+
|
|
274
285
|
**commit()**
|
|
275
286
|
```javascript
|
|
276
287
|
txn.commit();
|
|
@@ -285,10 +296,16 @@ txn.abort();
|
|
|
285
296
|
|
|
286
297
|
#### Methods
|
|
287
298
|
|
|
288
|
-
**put(txn, key, value)**
|
|
299
|
+
**put(txn, key, value, [flags])**
|
|
289
300
|
```javascript
|
|
290
301
|
dbi.put(txn, 123, "value");
|
|
291
302
|
dbi.put(txn, "key", Buffer.from("binary data"));
|
|
303
|
+
|
|
304
|
+
// Insert only if key does not exist
|
|
305
|
+
dbi.put(txn, 123, "value", MDBX_Param.putFlag.noOverwrite);
|
|
306
|
+
|
|
307
|
+
// Fast append for sorted inserts
|
|
308
|
+
dbi.put(txn, 124, "value", MDBX_Param.putFlag.append);
|
|
292
309
|
```
|
|
293
310
|
|
|
294
311
|
**get(txn, key) → value**
|
|
@@ -297,6 +314,8 @@ const value = dbi.get(txn, 123);
|
|
|
297
314
|
const binary = dbi.get(txn, "key");
|
|
298
315
|
```
|
|
299
316
|
|
|
317
|
+
For `valueMode.multiOrdinal`, `get()` returns the first duplicate value for the key, decoded as `number` by default.
|
|
318
|
+
|
|
300
319
|
**del(txn, key) → boolean**
|
|
301
320
|
```javascript
|
|
302
321
|
const deleted = dbi.del(txn, 123);
|
|
@@ -345,6 +364,47 @@ const bigIntKeys = dbi.keysFrom(txn, 42n, 50);
|
|
|
345
364
|
const equalKeys = dbi.keysFrom(txn, 5, 10, 'keyEqual');
|
|
346
365
|
```
|
|
347
366
|
|
|
367
|
+
**getRange(txn, [options]) → Array<{ key, value }>**
|
|
368
|
+
```javascript
|
|
369
|
+
const rows = dbi.getRange(txn, { start: 10, end: 15 });
|
|
370
|
+
// [
|
|
371
|
+
// { key: 10, value: ... },
|
|
372
|
+
// { key: 11, value: ... },
|
|
373
|
+
// ...
|
|
374
|
+
// ]
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**getCount(txn, [options]) → number**
|
|
378
|
+
```javascript
|
|
379
|
+
const total = dbi.getCount(txn, { start: 10, end: 20 });
|
|
380
|
+
// 11
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**keysRange(txn, [options]) → Array**
|
|
384
|
+
```javascript
|
|
385
|
+
const keys = dbi.keysRange(txn, { start: 10, end: 20, limit: 5 });
|
|
386
|
+
// [10, 11, 12, 13, 14]
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**valuesRange(txn, [options]) → Array**
|
|
390
|
+
```javascript
|
|
391
|
+
const values = dbi.valuesRange(txn, {
|
|
392
|
+
start: 10,
|
|
393
|
+
end: 15,
|
|
394
|
+
reverse: true,
|
|
395
|
+
includeEnd: false
|
|
396
|
+
});
|
|
397
|
+
// values for keys 14, 13, 12, 11, 10
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Range options:
|
|
401
|
+
- `start`, `end` - inclusive bounds by default
|
|
402
|
+
- `includeStart`, `includeEnd` - control bound inclusion
|
|
403
|
+
- `reverse` - scan from upper bound to lower bound
|
|
404
|
+
- `limit` - maximum number of returned items
|
|
405
|
+
- `offset` - skip N items after initial positioning
|
|
406
|
+
- `getCount()` ignores `offset` and `limit` and returns the total size of the bounded range
|
|
407
|
+
|
|
348
408
|
**drop(txn, [delete_db]) → void**
|
|
349
409
|
```javascript
|
|
350
410
|
// Clear database contents (keep structure)
|
|
@@ -427,7 +487,7 @@ Insert or update a record at cursor position.
|
|
|
427
487
|
cursor.put('newKey', 'newValue');
|
|
428
488
|
|
|
429
489
|
// With flags (MDBX_NOOVERWRITE, etc.)
|
|
430
|
-
cursor.put('key', 'value', MDBX_Param.
|
|
490
|
+
cursor.put('key', 'value', MDBX_Param.putFlag.noOverwrite);
|
|
431
491
|
```
|
|
432
492
|
|
|
433
493
|
**del([flags]) → boolean**
|
|
@@ -561,12 +621,20 @@ txn.commit();
|
|
|
561
621
|
### Value Modes (MDBX_Param.valueMode)
|
|
562
622
|
|
|
563
623
|
- **single** - Single value per key (default)
|
|
564
|
-
- **multi** -
|
|
624
|
+
- **multi** - `MDBX_DUPSORT`, multiple values per key
|
|
625
|
+
- **multiReverse** - `MDBX_DUPSORT | MDBX_REVERSEDUP`
|
|
626
|
+
- **multiSamelength** - `MDBX_DUPSORT | MDBX_DUPFIXED`
|
|
627
|
+
- **multiOrdinal** - `MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP`
|
|
628
|
+
- **multiReverseSamelength** - `MDBX_DUPSORT | MDBX_REVERSEDUP | MDBX_DUPFIXED`
|
|
565
629
|
|
|
566
630
|
### Value Flags (MDBX_Param.valueFlag)
|
|
567
631
|
|
|
568
|
-
- **binary** - Raw binary data (default)
|
|
632
|
+
- **binary** - Raw binary data (default, represented by `0`)
|
|
569
633
|
- **string** - UTF-8 strings
|
|
634
|
+
- **number** - Numeric decode for ordinal duplicate values
|
|
635
|
+
- **bigint** - BigInt decode for ordinal duplicate values
|
|
636
|
+
|
|
637
|
+
`valueFlag.number` and `valueFlag.bigint` matter primarily for `valueMode.multiOrdinal`. For ordinary values, use Buffer (default) or `valueFlag.string`.
|
|
570
638
|
|
|
571
639
|
## Examples
|
|
572
640
|
|
|
@@ -750,6 +818,101 @@ function cursorExample() {
|
|
|
750
818
|
cursorExample();
|
|
751
819
|
```
|
|
752
820
|
|
|
821
|
+
### Range Queries
|
|
822
|
+
|
|
823
|
+
```javascript
|
|
824
|
+
const { MDBX_Env, MDBX_Param } = require('mdbxmou');
|
|
825
|
+
|
|
826
|
+
function rangeExample() {
|
|
827
|
+
const env = new MDBX_Env();
|
|
828
|
+
env.openSync({
|
|
829
|
+
path: './range-data',
|
|
830
|
+
valueFlag: MDBX_Param.valueFlag.string
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
const writeTxn = env.startWrite();
|
|
834
|
+
const dbi = writeTxn.createMap(MDBX_Param.keyMode.ordinal);
|
|
835
|
+
for (let i = 0; i < 10; i++) {
|
|
836
|
+
dbi.put(writeTxn, i, `value_${i}`);
|
|
837
|
+
}
|
|
838
|
+
writeTxn.commit();
|
|
839
|
+
|
|
840
|
+
const readTxn = env.startRead();
|
|
841
|
+
const readDbi = readTxn.openMap(MDBX_Param.keyMode.ordinal);
|
|
842
|
+
|
|
843
|
+
const rows = readDbi.getRange(readTxn, { start: 3, end: 6 });
|
|
844
|
+
console.log(rows);
|
|
845
|
+
// [
|
|
846
|
+
// { key: 3, value: 'value_3' },
|
|
847
|
+
// { key: 4, value: 'value_4' },
|
|
848
|
+
// { key: 5, value: 'value_5' },
|
|
849
|
+
// { key: 6, value: 'value_6' }
|
|
850
|
+
// ]
|
|
851
|
+
|
|
852
|
+
const total = readDbi.getCount(readTxn, { start: 3, end: 8 });
|
|
853
|
+
console.log(total); // 6
|
|
854
|
+
|
|
855
|
+
const keys = readDbi.keysRange(readTxn, {
|
|
856
|
+
start: 3,
|
|
857
|
+
end: 8,
|
|
858
|
+
offset: 1,
|
|
859
|
+
limit: 3
|
|
860
|
+
});
|
|
861
|
+
console.log(keys); // [4, 5, 6]
|
|
862
|
+
|
|
863
|
+
const values = readDbi.valuesRange(readTxn, {
|
|
864
|
+
start: 3,
|
|
865
|
+
end: 6,
|
|
866
|
+
reverse: true,
|
|
867
|
+
includeEnd: false
|
|
868
|
+
});
|
|
869
|
+
console.log(values); // ['value_5', 'value_4', 'value_3']
|
|
870
|
+
|
|
871
|
+
readTxn.commit();
|
|
872
|
+
env.closeSync();
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
rangeExample();
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
### MultiOrdinal Values
|
|
879
|
+
|
|
880
|
+
```javascript
|
|
881
|
+
const { MDBX_Env, MDBX_Param } = require('mdbxmou');
|
|
882
|
+
|
|
883
|
+
function multiOrdinalExample() {
|
|
884
|
+
const env = new MDBX_Env();
|
|
885
|
+
env.openSync({ path: './multi-ordinal-data' });
|
|
886
|
+
|
|
887
|
+
const writeTxn = env.startWrite();
|
|
888
|
+
const dbi = writeTxn.createMap({
|
|
889
|
+
name: 'dup-ids',
|
|
890
|
+
keyMode: MDBX_Param.keyMode.ordinal,
|
|
891
|
+
valueMode: MDBX_Param.valueMode.multiOrdinal
|
|
892
|
+
});
|
|
893
|
+
|
|
894
|
+
dbi.put(writeTxn, 5, 30);
|
|
895
|
+
dbi.put(writeTxn, 5, 10);
|
|
896
|
+
dbi.put(writeTxn, 5, 20n);
|
|
897
|
+
writeTxn.commit();
|
|
898
|
+
|
|
899
|
+
const readTxn = env.startRead();
|
|
900
|
+
const readDbi = readTxn.openMap({
|
|
901
|
+
name: 'dup-ids',
|
|
902
|
+
keyMode: MDBX_Param.keyMode.ordinal,
|
|
903
|
+
valueMode: MDBX_Param.valueMode.multiOrdinal
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
console.log(readDbi.get(readTxn, 5)); // 10
|
|
907
|
+
console.log(readDbi.valuesRange(readTxn, { start: 5, end: 5 })); // [10, 20, 30]
|
|
908
|
+
|
|
909
|
+
readTxn.commit();
|
|
910
|
+
env.closeSync();
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
multiOrdinalExample();
|
|
914
|
+
```
|
|
915
|
+
|
|
753
916
|
### Query API (Advanced Async)
|
|
754
917
|
|
|
755
918
|
```javascript
|
|
@@ -768,7 +931,8 @@ async function queryExample() {
|
|
|
768
931
|
const results = await env.query([
|
|
769
932
|
{
|
|
770
933
|
dbi,
|
|
771
|
-
mode: MDBX_Param.queryMode.
|
|
934
|
+
mode: MDBX_Param.queryMode.upsert,
|
|
935
|
+
putFlag: MDBX_Param.putFlag.noOverwrite,
|
|
772
936
|
item: [
|
|
773
937
|
{ key: 1, value: JSON.stringify({ name: "Alice" }) },
|
|
774
938
|
{ key: 2, value: JSON.stringify({ name: "Bob" }) }
|
|
@@ -869,6 +1033,7 @@ node test/readme-sync-example.js
|
|
|
869
1033
|
node test/readme-async-example.js
|
|
870
1034
|
node test/readme-key-types.js
|
|
871
1035
|
node test/readme-cursor-example.js
|
|
1036
|
+
node test/readme-range-example.js
|
|
872
1037
|
node test/readme-query-example.js
|
|
873
1038
|
node test/readme-keys-example.js
|
|
874
1039
|
node test/readme-error-handling.js
|
|
@@ -892,7 +1057,21 @@ MDBX_Param.keyFlag.number // Number type (used with ordinal mode)
|
|
|
892
1057
|
MDBX_Param.keyFlag.bigint // BigInt type (used with ordinal mode)
|
|
893
1058
|
// Default - Buffer representation
|
|
894
1059
|
|
|
1060
|
+
// Value modes
|
|
1061
|
+
MDBX_Param.valueMode.multi // MDBX_DUPSORT
|
|
1062
|
+
MDBX_Param.valueMode.multiReverse // MDBX_DUPSORT | MDBX_REVERSEDUP
|
|
1063
|
+
MDBX_Param.valueMode.multiSamelength // MDBX_DUPSORT | MDBX_DUPFIXED
|
|
1064
|
+
MDBX_Param.valueMode.multiOrdinal // MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP
|
|
1065
|
+
MDBX_Param.valueMode.multiReverseSamelength // MDBX_DUPSORT | MDBX_REVERSEDUP | MDBX_DUPFIXED
|
|
1066
|
+
|
|
1067
|
+
// Value flags (optional, control value representation)
|
|
1068
|
+
MDBX_Param.valueFlag.string // UTF-8 string values
|
|
1069
|
+
MDBX_Param.valueFlag.number // Number values for multiOrdinal
|
|
1070
|
+
MDBX_Param.valueFlag.bigint // BigInt values for multiOrdinal
|
|
1071
|
+
// Default - Buffer representation
|
|
1072
|
+
|
|
895
1073
|
Note: For ordinal (integer) keys, use keyFlag.number or keyFlag.bigint to specify the data type.
|
|
1074
|
+
For `valueMode.multiOrdinal`, values are returned as `number` by default, or as `bigint` when `valueFlag.bigint` is used.
|
|
896
1075
|
```
|
|
897
1076
|
|
|
898
1077
|
### Environment Flags
|
|
@@ -938,11 +1117,23 @@ Note: For ordinal (integer) keys, use keyFlag.number or keyFlag.bigint to specif
|
|
|
938
1117
|
|
|
939
1118
|
### Query Modes
|
|
940
1119
|
- `MDBX_Param.queryMode.get` - Read operations
|
|
941
|
-
- `MDBX_Param.queryMode.upsert` -
|
|
942
|
-
- `MDBX_Param.queryMode.update` -
|
|
943
|
-
- `MDBX_Param.queryMode.insertUnique` -
|
|
1120
|
+
- `MDBX_Param.queryMode.upsert` - Base write mode (insert or update)
|
|
1121
|
+
- `MDBX_Param.queryMode.update` - Base write mode with `MDBX_CURRENT`
|
|
1122
|
+
- `MDBX_Param.queryMode.insertUnique` - Base write mode with `MDBX_NOOVERWRITE`
|
|
944
1123
|
- `MDBX_Param.queryMode.del` - Delete operations
|
|
945
1124
|
|
|
1125
|
+
### Put Flags
|
|
1126
|
+
- `MDBX_Param.putFlag.noOverwrite` - `MDBX_NOOVERWRITE`
|
|
1127
|
+
- `MDBX_Param.putFlag.noDupData` - `MDBX_NODUPDATA`
|
|
1128
|
+
- `MDBX_Param.putFlag.current` - `MDBX_CURRENT`
|
|
1129
|
+
- `MDBX_Param.putFlag.allDups` - `MDBX_ALLDUPS`
|
|
1130
|
+
- `MDBX_Param.putFlag.reserve` - `MDBX_RESERVE`
|
|
1131
|
+
- `MDBX_Param.putFlag.append` - `MDBX_APPEND`
|
|
1132
|
+
- `MDBX_Param.putFlag.appendDup` - `MDBX_APPENDDUP`
|
|
1133
|
+
- `MDBX_Param.putFlag.multiple` - `MDBX_MULTIPLE`
|
|
1134
|
+
|
|
1135
|
+
For `env.query()` write requests, only `noOverwrite`, `noDupData`, `current`, `append`, and `appendDup` are supported.
|
|
1136
|
+
|
|
946
1137
|
### Cursor Modes
|
|
947
1138
|
- `MDBX_Param.cursorMode.first` - First key
|
|
948
1139
|
- `MDBX_Param.cursorMode.last` - Last key
|
package/lib/async.d.mts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { MDBXDbiStat, MDBXEnvOpenOptions, MDBXKey
|
|
1
|
+
import type { MDBXDbiStat, MDBXEnvOpenOptions, MDBXKey } from "./types.js";
|
|
2
|
+
|
|
3
|
+
type MDBXAsyncValue = Buffer | string;
|
|
2
4
|
|
|
3
5
|
export interface MDBXAsyncMapOpenOptions {
|
|
4
6
|
name?: string;
|
|
@@ -35,15 +37,15 @@ export interface MDBXAsyncDelBatchResultItem {
|
|
|
35
37
|
export declare class MDBX_Async_Dbi {
|
|
36
38
|
readonly meta: MDBXAsyncDbiMeta;
|
|
37
39
|
|
|
38
|
-
put(key: MDBXKey, value:
|
|
40
|
+
put(key: MDBXKey, value: MDBXAsyncValue, flags?: number): Promise<boolean>;
|
|
39
41
|
get(key: MDBXKey): Promise<string | null | undefined>;
|
|
40
42
|
del(key: MDBXKey): Promise<boolean>;
|
|
41
43
|
stat(): Promise<MDBXDbiStat>;
|
|
42
44
|
|
|
43
|
-
forEach(cb: (key: MDBXKey, value:
|
|
45
|
+
forEach(cb: (key: MDBXKey, value: MDBXAsyncValue, index: number) => void): Promise<void>;
|
|
44
46
|
|
|
45
47
|
getBatch(keys: MDBXKey[]): Promise<MDBXAsyncGetBatchResultItem[]>;
|
|
46
|
-
putBatch(items: Array<{ key: MDBXKey; value:
|
|
48
|
+
putBatch(items: Array<{ key: MDBXKey; value: MDBXAsyncValue }>, flags?: number): Promise<MDBXAsyncPutBatchResultItem[]>;
|
|
47
49
|
delBatch(keys: MDBXKey[]): Promise<MDBXAsyncDelBatchResultItem[]>;
|
|
48
50
|
}
|
|
49
51
|
|
package/lib/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
|
|
3
3
|
export type MDBXKey = Buffer | string | number | bigint;
|
|
4
|
-
export type MDBXValue = Buffer | string;
|
|
4
|
+
export type MDBXValue = Buffer | string | number | bigint;
|
|
5
5
|
|
|
6
6
|
export type MDBXCursorMode =
|
|
7
7
|
| number
|
|
@@ -79,6 +79,16 @@ export interface MDBXCursorResult<K extends MDBXKey = MDBXKey, V extends MDBXVal
|
|
|
79
79
|
value: V;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
export interface MDBXRangeOptions<K extends MDBXKey = MDBXKey> {
|
|
83
|
+
start?: K;
|
|
84
|
+
end?: K;
|
|
85
|
+
limit?: number;
|
|
86
|
+
offset?: number;
|
|
87
|
+
reverse?: boolean;
|
|
88
|
+
includeStart?: boolean;
|
|
89
|
+
includeEnd?: boolean;
|
|
90
|
+
}
|
|
91
|
+
|
|
82
92
|
/**
|
|
83
93
|
* Database cursor for sequential access and range queries.
|
|
84
94
|
* Must be closed before transaction commit/abort.
|
|
@@ -192,7 +202,7 @@ export interface MDBX_Dbi<K extends MDBXKey = MDBXKey, V extends MDBXValue = MDB
|
|
|
192
202
|
readonly keyFlag: number;
|
|
193
203
|
readonly valueFlag: number;
|
|
194
204
|
|
|
195
|
-
put(txn: MDBX_Txn, key: K, value: MDBXValue): void;
|
|
205
|
+
put(txn: MDBX_Txn, key: K, value: MDBXValue, flags?: number): void;
|
|
196
206
|
get(txn: MDBX_Txn, key: K): V | undefined;
|
|
197
207
|
del(txn: MDBX_Txn, key: K): boolean;
|
|
198
208
|
has(txn: MDBX_Txn, key: K): boolean;
|
|
@@ -213,6 +223,10 @@ export interface MDBX_Dbi<K extends MDBXKey = MDBXKey, V extends MDBXValue = MDB
|
|
|
213
223
|
stat(txn: MDBX_Txn): MDBXDbiStat;
|
|
214
224
|
keys(txn: MDBX_Txn): K[];
|
|
215
225
|
keysFrom(txn: MDBX_Txn, fromKey: K, limit?: number, cursorMode?: MDBXCursorMode): K[];
|
|
226
|
+
getRange(txn: MDBX_Txn, options?: MDBXRangeOptions<K>): MDBXCursorResult<K, V>[];
|
|
227
|
+
getCount(txn: MDBX_Txn, options?: MDBXRangeOptions<K>): number;
|
|
228
|
+
keysRange(txn: MDBX_Txn, options?: MDBXRangeOptions<K>): K[];
|
|
229
|
+
valuesRange(txn: MDBX_Txn, options?: MDBXRangeOptions<K>): V[];
|
|
216
230
|
drop(txn: MDBX_Txn, deleteDb?: boolean): void;
|
|
217
231
|
}
|
|
218
232
|
|
|
@@ -251,6 +265,7 @@ export interface MDBXQueryRequest {
|
|
|
251
265
|
dbi: MDBX_Dbi;
|
|
252
266
|
mode?: number;
|
|
253
267
|
queryMode?: number;
|
|
268
|
+
putFlag?: number;
|
|
254
269
|
item: MDBXQueryItem[];
|
|
255
270
|
}
|
|
256
271
|
|
|
@@ -361,6 +376,8 @@ export interface MDBX_Param {
|
|
|
361
376
|
|
|
362
377
|
readonly valueFlag: {
|
|
363
378
|
readonly string: number;
|
|
379
|
+
readonly number: number;
|
|
380
|
+
readonly bigint: number;
|
|
364
381
|
};
|
|
365
382
|
|
|
366
383
|
readonly dbMode: {
|
|
@@ -376,6 +393,17 @@ export interface MDBX_Param {
|
|
|
376
393
|
readonly del: number;
|
|
377
394
|
};
|
|
378
395
|
|
|
396
|
+
readonly putFlag: {
|
|
397
|
+
readonly noOverwrite: number;
|
|
398
|
+
readonly noDupData: number;
|
|
399
|
+
readonly current: number;
|
|
400
|
+
readonly allDups: number;
|
|
401
|
+
readonly reserve: number;
|
|
402
|
+
readonly append: number;
|
|
403
|
+
readonly appendDup: number;
|
|
404
|
+
readonly multiple: number;
|
|
405
|
+
};
|
|
406
|
+
|
|
379
407
|
readonly cursorMode: {
|
|
380
408
|
readonly first: number;
|
|
381
409
|
readonly last: number;
|
package/package.json
CHANGED
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/node": "^22.10.2",
|
|
53
|
+
"msgpackr": "^1.11.9",
|
|
53
54
|
"typescript": "^5.6.3"
|
|
54
55
|
},
|
|
55
56
|
"scripts": {
|
|
@@ -58,6 +59,9 @@
|
|
|
58
59
|
"e4": "node ./test/e4.js",
|
|
59
60
|
"e4async": "node ./test/e4async.mjs",
|
|
60
61
|
"e5": "node ./test/e5.js",
|
|
62
|
+
"e7": "node ./test/e7.js",
|
|
63
|
+
"e8": "node ./test/e8.js",
|
|
64
|
+
"e9": "node ./test/e9.js",
|
|
61
65
|
"test:types": "node ./test/types/run.mjs",
|
|
62
66
|
"build": "node build.js",
|
|
63
67
|
"build-dev": "node build-dev.js",
|
|
@@ -65,7 +69,7 @@
|
|
|
65
69
|
},
|
|
66
70
|
"gypfile": true,
|
|
67
71
|
"name": "mdbxmou",
|
|
68
|
-
"version": "0.3.
|
|
72
|
+
"version": "0.3.12",
|
|
69
73
|
"description": "Node bindings for mdbx",
|
|
70
74
|
"repository": {
|
|
71
75
|
"type": "git",
|
|
@@ -1,10 +1,53 @@
|
|
|
1
1
|
#include "envmou_keys.hpp"
|
|
2
2
|
#include "envmou.hpp"
|
|
3
|
+
#include "convmou.hpp"
|
|
3
4
|
#include "dbimou.hpp"
|
|
4
|
-
#include "
|
|
5
|
+
#include "valuemou.hpp"
|
|
5
6
|
|
|
6
7
|
namespace mdbxmou {
|
|
7
8
|
|
|
9
|
+
namespace {
|
|
10
|
+
|
|
11
|
+
template<bool Ordinal>
|
|
12
|
+
void scan_keys_from(mdbx::cursor_managed& cursor, keys_line& arg0,
|
|
13
|
+
keymou& from_key, mdbx::cursor::move_operation turn_mode)
|
|
14
|
+
{
|
|
15
|
+
auto& item = arg0.item;
|
|
16
|
+
auto cursor_mode = arg0.cursor_mode;
|
|
17
|
+
bool is_key_equal_mode = (cursor_mode == mdbx::cursor::move_operation::key_equal ||
|
|
18
|
+
cursor_mode == mdbx::cursor::move_operation::multi_exactkey_value_equal);
|
|
19
|
+
|
|
20
|
+
std::size_t index{};
|
|
21
|
+
cursor.scan_from([&](const mdbx::pair& f) {
|
|
22
|
+
if (index >= arg0.limit) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
keymou key{f.key};
|
|
27
|
+
if (is_key_equal_mode) {
|
|
28
|
+
if constexpr (Ordinal) {
|
|
29
|
+
if (arg0.id_buf != key.as_int64()) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
} else if (from_key != key) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async_key rc{};
|
|
38
|
+
if constexpr (Ordinal) {
|
|
39
|
+
rc.id_buf = key.as_uint64();
|
|
40
|
+
} else {
|
|
41
|
+
rc.key_buf.assign(key.char_ptr(), key.end_char_ptr());
|
|
42
|
+
}
|
|
43
|
+
item.push_back(std::move(rc));
|
|
44
|
+
++index;
|
|
45
|
+
return false;
|
|
46
|
+
}, from_key, cursor_mode, turn_mode);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
} // namespace
|
|
50
|
+
|
|
8
51
|
void async_keys::Execute()
|
|
9
52
|
{
|
|
10
53
|
try {
|
|
@@ -24,26 +67,14 @@ void async_keys::Execute()
|
|
|
24
67
|
static Napi::Value write_row(Napi::Env env, const keys_line& row)
|
|
25
68
|
{
|
|
26
69
|
auto& param = row.item;
|
|
27
|
-
|
|
28
|
-
auto key_flag = row.key_flag;
|
|
70
|
+
convmou conv{row.key_mod, {}, row.key_flag, {}};
|
|
29
71
|
auto js_arr = Napi::Array::New(env, param.size());
|
|
30
72
|
for (std::uint32_t j = 0; j < param.size(); ++j) {
|
|
31
73
|
const auto& item = param[j];
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
} else {
|
|
37
|
-
key_value = Napi::BigInt::New(env, item.id_buf);
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
if (key_flag.val & base_flag::string) {
|
|
41
|
-
key_value = Napi::String::New(env, item.key_buf.data(), item.key_buf.size());
|
|
42
|
-
} else {
|
|
43
|
-
key_value = Napi::Buffer<char>::Copy(env, item.key_buf.data(), item.key_buf.size());
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
js_arr.Set(j, key_value);
|
|
74
|
+
auto key = mdbx::is_ordinal(row.key_mod) ?
|
|
75
|
+
keymou{item.id_buf} :
|
|
76
|
+
keymou{item.key_buf};
|
|
77
|
+
js_arr.Set(j, conv.convert_key(env, key));
|
|
47
78
|
}
|
|
48
79
|
return js_arr;
|
|
49
80
|
}
|
|
@@ -140,14 +171,12 @@ void async_keys::do_keys_batch(txnmou_managed& txn,
|
|
|
140
171
|
void async_keys::do_keys_from(txnmou_managed& txn,
|
|
141
172
|
mdbx::map_handle dbi, keys_line& arg0)
|
|
142
173
|
{
|
|
143
|
-
// сыллка на массив результатов
|
|
144
|
-
auto& item = arg0.item;
|
|
145
|
-
std::size_t count = 0;
|
|
146
174
|
using move_operation = mdbx::cursor::move_operation;
|
|
175
|
+
auto is_ordinal = mdbx::is_ordinal(arg0.key_mod);
|
|
147
176
|
|
|
148
177
|
auto cursor = txn.open_cursor(dbi);
|
|
149
178
|
|
|
150
|
-
keymou from_key =
|
|
179
|
+
keymou from_key = is_ordinal ?
|
|
151
180
|
keymou{arg0.id_buf} :
|
|
152
181
|
keymou{mdbx::slice{arg0.key_buf.data(), arg0.key_buf.size()}};
|
|
153
182
|
|
|
@@ -170,50 +199,10 @@ void async_keys::do_keys_from(txnmou_managed& txn,
|
|
|
170
199
|
break;
|
|
171
200
|
}
|
|
172
201
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
std::size_t index{};
|
|
177
|
-
if (mdbx::is_ordinal(arg0.key_mod)) {
|
|
178
|
-
// Создаем ключ для позиционирования
|
|
179
|
-
cursor.scan_from([&](const mdbx::pair& f) {
|
|
180
|
-
if (index >= arg0.limit) {
|
|
181
|
-
return true; // останавливаем сканирование
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
keymou key{f.key};
|
|
185
|
-
if (is_key_equal_mode) {
|
|
186
|
-
if (arg0.id_buf != key.as_int64()) {
|
|
187
|
-
return true; // останавливаем сканирование
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
async_key rc{};
|
|
192
|
-
rc.id_buf = key.as_uint64();
|
|
193
|
-
item.push_back(std::move(rc));
|
|
194
|
-
index++;
|
|
195
|
-
return false; // продолжаем сканирование
|
|
196
|
-
}, from_key, arg0.cursor_mode, turn_mode);
|
|
202
|
+
if (is_ordinal) {
|
|
203
|
+
scan_keys_from<true>(cursor, arg0, from_key, turn_mode);
|
|
197
204
|
} else {
|
|
198
|
-
|
|
199
|
-
cursor.scan_from([&](const mdbx::pair& f) {
|
|
200
|
-
if (index >= arg0.limit) {
|
|
201
|
-
return true; // останавливаем сканирование
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
keymou key{f.key};
|
|
205
|
-
if (is_key_equal_mode) {
|
|
206
|
-
if (from_key != key) {
|
|
207
|
-
return true; // останавливаем сканирование
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
async_key rc{};
|
|
212
|
-
rc.id_buf = key.as_uint64();
|
|
213
|
-
item.push_back(std::move(rc));
|
|
214
|
-
index++;
|
|
215
|
-
return false; // продолжаем сканирование
|
|
216
|
-
}, from_key, arg0.cursor_mode, turn_mode);
|
|
205
|
+
scan_keys_from<false>(cursor, arg0, from_key, turn_mode);
|
|
217
206
|
}
|
|
218
207
|
}
|
|
219
208
|
|