mdbxmou 0.3.11 → 0.3.13

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.
Files changed (38) hide show
  1. package/README.md +113 -11
  2. package/deps/libmdbx/ChangeLog.md +44 -0
  3. package/deps/libmdbx/SECURITY.md +18 -0
  4. package/deps/libmdbx/VERSION.json +1 -1
  5. package/deps/libmdbx/mdbx.c +121 -63
  6. package/deps/libmdbx/mdbx.c++ +2 -2
  7. package/deps/libmdbx/mdbx_chk.c +2 -2
  8. package/deps/libmdbx/mdbx_copy.c +2 -2
  9. package/deps/libmdbx/mdbx_drop.c +2 -2
  10. package/deps/libmdbx/mdbx_dump.c +5 -5
  11. package/deps/libmdbx/mdbx_load.c +24 -23
  12. package/deps/libmdbx/mdbx_stat.c +2 -3
  13. package/lib/async.d.mts +6 -4
  14. package/lib/types.d.ts +17 -2
  15. package/package.json +2 -1
  16. package/src/async/envmou_keys.cpp +1 -1
  17. package/src/async/envmou_query.cpp +14 -13
  18. package/src/convmou.cpp +17 -0
  19. package/src/convmou.hpp +4 -8
  20. package/src/cursormou.cpp +2 -1
  21. package/src/cursormou.hpp +1 -0
  22. package/src/dbimou.cpp +71 -18
  23. package/src/dbimou.hpp +3 -1
  24. package/src/modulemou.cpp +14 -0
  25. package/src/querymou.cpp +15 -15
  26. package/src/querymou.hpp +3 -1
  27. package/src/txnmou.cpp +3 -3
  28. package/src/typemou.hpp +85 -5
  29. package/src/valuemou.hpp +62 -83
  30. package/deps/libmdbx/.github/workflows/ci-android.yml +0 -38
  31. package/deps/libmdbx/.github/workflows/ci-mingw.yml +0 -40
  32. package/deps/libmdbx/.github/workflows/ci-posix.yml +0 -34
  33. package/deps/libmdbx/.github/workflows/ci-wincxx.yml +0 -45
  34. package/deps/libmdbx/.github/workflows/ci-windows.yml +0 -32
  35. package/deps/libmdbx/ci.sh +0 -86
  36. package/deps/libmdbx/packages/archlinux/.SRCINFO +0 -16
  37. package/deps/libmdbx/packages/archlinux/PKGBUILD +0 -38
  38. package/deps/libmdbx/packages/buildroot/0001-package-libmdbx.patch +0 -75
@@ -18,7 +18,7 @@
18
18
  /// \copyright SPDX-License-Identifier: Apache-2.0
19
19
  /// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2026
20
20
 
21
- #define MDBX_BUILD_SOURCERY 90c8567c0f319539000cf161230c67f127fd9cbcb5d35ad5b3b076b78b5dc48d_v0_13_11_0_gb862eb08
21
+ #define MDBX_BUILD_SOURCERY a575a490fc080ca11e89ff6db9f0bd38aa830959905998cac0e45274b9e6bb0e_v0_13_12_0_gf619d43d
22
22
 
23
23
  #define LIBMDBX_INTERNALS
24
24
  #define MDBX_DEPRECATED
@@ -1499,7 +1499,7 @@ MDBX_INTERNAL int osal_lockfile(mdbx_filehandle_t fd, bool wait);
1499
1499
  #define MMAP_OPTION_SEMAPHORE 2
1500
1500
  MDBX_INTERNAL int osal_mmap(const int flags, osal_mmap_t *map, size_t size, const size_t limit, const unsigned options,
1501
1501
  const pathchar_t *pathname4logging);
1502
- MDBX_INTERNAL int osal_munmap(osal_mmap_t *map);
1502
+ MDBX_INTERNAL void osal_munmap(osal_mmap_t *map);
1503
1503
  #define MDBX_MRESIZE_MAY_MOVE 0x00000100
1504
1504
  #define MDBX_MRESIZE_MAY_UNMAP 0x00000200
1505
1505
  MDBX_INTERNAL int osal_mresize(const int flags, osal_mmap_t *map, size_t size, size_t limit);
@@ -3516,7 +3516,6 @@ int main(int argc, char *argv[]) {
3516
3516
  signal(SIGTERM, signal_handler);
3517
3517
  #endif /* !WINDOWS */
3518
3518
 
3519
- envname = argv[optind];
3520
3519
  envname = argv[optind];
3521
3520
  if (!quiet) {
3522
3521
  printf("mdbx_stat %s (%s, T-%s)\nRunning for %s...\n", mdbx_version.git.describe, mdbx_version.git.datetime,
package/lib/async.d.mts CHANGED
@@ -1,4 +1,6 @@
1
- import type { MDBXDbiStat, MDBXEnvOpenOptions, MDBXKey, MDBXValue } from "./types.js";
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: MDBXValue, flags?: number): Promise<boolean>;
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: MDBXValue, index: number) => void): Promise<void>;
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: MDBXValue }>, flags?: number): Promise<MDBXAsyncPutBatchResultItem[]>;
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
@@ -202,7 +202,7 @@ export interface MDBX_Dbi<K extends MDBXKey = MDBXKey, V extends MDBXValue = MDB
202
202
  readonly keyFlag: number;
203
203
  readonly valueFlag: number;
204
204
 
205
- put(txn: MDBX_Txn, key: K, value: MDBXValue): void;
205
+ put(txn: MDBX_Txn, key: K, value: MDBXValue, flags?: number): void;
206
206
  get(txn: MDBX_Txn, key: K): V | undefined;
207
207
  del(txn: MDBX_Txn, key: K): boolean;
208
208
  has(txn: MDBX_Txn, key: K): boolean;
@@ -224,6 +224,7 @@ export interface MDBX_Dbi<K extends MDBXKey = MDBXKey, V extends MDBXValue = MDB
224
224
  keys(txn: MDBX_Txn): K[];
225
225
  keysFrom(txn: MDBX_Txn, fromKey: K, limit?: number, cursorMode?: MDBXCursorMode): K[];
226
226
  getRange(txn: MDBX_Txn, options?: MDBXRangeOptions<K>): MDBXCursorResult<K, V>[];
227
+ getCount(txn: MDBX_Txn, options?: MDBXRangeOptions<K>): number;
227
228
  keysRange(txn: MDBX_Txn, options?: MDBXRangeOptions<K>): K[];
228
229
  valuesRange(txn: MDBX_Txn, options?: MDBXRangeOptions<K>): V[];
229
230
  drop(txn: MDBX_Txn, deleteDb?: boolean): void;
@@ -264,6 +265,7 @@ export interface MDBXQueryRequest {
264
265
  dbi: MDBX_Dbi;
265
266
  mode?: number;
266
267
  queryMode?: number;
268
+ putFlag?: number;
267
269
  item: MDBXQueryItem[];
268
270
  }
269
271
 
@@ -374,6 +376,8 @@ export interface MDBX_Param {
374
376
 
375
377
  readonly valueFlag: {
376
378
  readonly string: number;
379
+ readonly number: number;
380
+ readonly bigint: number;
377
381
  };
378
382
 
379
383
  readonly dbMode: {
@@ -389,6 +393,17 @@ export interface MDBX_Param {
389
393
  readonly del: number;
390
394
  };
391
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
+
392
407
  readonly cursorMode: {
393
408
  readonly first: number;
394
409
  readonly last: number;
package/package.json CHANGED
@@ -61,6 +61,7 @@
61
61
  "e5": "node ./test/e5.js",
62
62
  "e7": "node ./test/e7.js",
63
63
  "e8": "node ./test/e8.js",
64
+ "e9": "node ./test/e9.js",
64
65
  "test:types": "node ./test/types/run.mjs",
65
66
  "build": "node build.js",
66
67
  "build-dev": "node build-dev.js",
@@ -68,7 +69,7 @@
68
69
  },
69
70
  "gypfile": true,
70
71
  "name": "mdbxmou",
71
- "version": "0.3.11",
72
+ "version": "0.3.13",
72
73
  "description": "Node bindings for mdbx",
73
74
  "repository": {
74
75
  "type": "git",
@@ -67,7 +67,7 @@ void async_keys::Execute()
67
67
  static Napi::Value write_row(Napi::Env env, const keys_line& row)
68
68
  {
69
69
  auto& param = row.item;
70
- convmou conv{row.key_mod, row.key_flag};
70
+ convmou conv{row.key_mod, {}, row.key_flag, {}};
71
71
  auto js_arr = Napi::Array::New(env, param.size());
72
72
  for (std::uint32_t j = 0; j < param.size(); ++j) {
73
73
  const auto& item = param[j];
@@ -13,9 +13,9 @@ void async_query::Execute()
13
13
  {
14
14
  mdbx::map_handle dbi{req.id};
15
15
  auto mode = req.mode;
16
- if (mode.val & query_mode::get) {
16
+ if (mode.is_get()) {
17
17
  do_get(txn, dbi, req);
18
- } else if (mode.val & query_mode::del) {
18
+ } else if (mode.is_del()) {
19
19
  do_del(txn, dbi, req);
20
20
  } else {
21
21
  do_put(txn, dbi, req);
@@ -33,7 +33,7 @@ static Napi::Value write_row(Napi::Env env, const query_line& row)
33
33
  {
34
34
  auto& param = row.item;
35
35
  auto mode = row.mode;
36
- convmou conv{row.key_mod, row.key_flag, row.value_flag};
36
+ convmou conv{row.key_mod, row.val_mod, row.key_flag, row.value_flag};
37
37
  auto js_arr = Napi::Array::New(env, param.size());
38
38
  for (std::size_t j = 0; j < param.size(); ++j) {
39
39
  const auto& item = param[j];
@@ -43,13 +43,11 @@ static Napi::Value write_row(Napi::Env env, const query_line& row)
43
43
  keymou{item.key_buf};
44
44
  js_item.Set("key", conv.convert_key(env, key));
45
45
 
46
- // все методы которые должны показать value в результате
47
- const auto mask{query_mode::get|query_mode::upsert|
48
- query_mode::update|query_mode::insert_unique};
49
- if (mode.val & mask)
50
- {
46
+ if (mode.is_get() || mode.is_write()) {
51
47
  auto& val_buf = item.val_buf;
52
- if (val_buf.empty()) {
48
+ if (is_ordinal(row.val_mod) && mode.is_write() && val_buf.empty()) {
49
+ js_item.Set("value", conv.convert_value(env, valuemou{item.val_num}));
50
+ } else if (val_buf.empty()) {
53
51
  js_item.Set("value", env.Null());
54
52
  } else {
55
53
  js_item.Set("value",
@@ -58,7 +56,7 @@ static Napi::Value write_row(Napi::Env env, const query_line& row)
58
56
  }
59
57
 
60
58
  // выдадим флаги удаления и успешности
61
- if (mode.val & query_mode::del) {
59
+ if (mode.is_del()) {
62
60
  js_item.Set("found", Napi::Boolean::New(env, item.found));
63
61
  }
64
62
  js_arr.Set(static_cast<uint32_t>(j), js_item);
@@ -133,15 +131,18 @@ void async_query::do_get(const txnmou_managed& txn,
133
131
  void async_query::do_put(txnmou_managed& txn,
134
132
  mdbx::map_handle dbi, query_line& arg0)
135
133
  {
136
- auto mode = arg0.mode;
134
+ auto flags = static_cast<MDBX_put_flags_t>(
135
+ arg0.mode.write_flags() | arg0.put_flags.val);
137
136
  // очищаем put флаги
138
137
  auto key_mode = arg0.key_mod;
139
138
  for (auto& q : arg0.item)
140
139
  {
141
140
  auto key = mdbx::is_ordinal(key_mode) ?
142
141
  keymou{q.id_buf} : keymou{q.key_buf};
143
- mdbx::slice val{q.val_buf.data(), q.val_buf.size()};
144
- txn.put(dbi, key, val, mode);
142
+ valuemou val = is_ordinal(arg0.val_mod) ?
143
+ valuemou{q.val_num} :
144
+ valuemou{q.val_buf};
145
+ mdbx::error::success_or_throw(txn.put(dbi, key, &val, flags));
145
146
  }
146
147
  }
147
148
 
package/src/convmou.cpp CHANGED
@@ -1,7 +1,18 @@
1
1
  #include "convmou.hpp"
2
+ #include "dbimou.hpp"
2
3
 
3
4
  namespace mdbxmou {
4
5
 
6
+ convmou convmou::for_dbi(const dbimou& dbi) noexcept
7
+ {
8
+ return {
9
+ dbi.get_key_mode(),
10
+ dbi.get_value_mode(),
11
+ dbi.get_key_flag(),
12
+ dbi.get_value_flag()
13
+ };
14
+ }
15
+
5
16
  Napi::Value convmou::convert_key(const Napi::Env& env, const keymou& key) const
6
17
  {
7
18
  if (mdbx::is_ordinal(key_mode_)) {
@@ -17,6 +28,12 @@ Napi::Value convmou::convert_key(const Napi::Env& env, const keymou& key) const
17
28
 
18
29
  Napi::Value convmou::convert_value(const Napi::Env& env, const valuemou& val) const
19
30
  {
31
+ if (is_ordinal(value_mode_)) {
32
+ return (value_flag_ & base_flag::bigint) ?
33
+ val.to_bigint(env) :
34
+ val.to_number(env);
35
+ }
36
+
20
37
  return (value_flag_ & base_flag::string) ?
21
38
  val.to_string(env) :
22
39
  val.to_buffer(env);
package/src/convmou.hpp CHANGED
@@ -4,20 +4,16 @@
4
4
 
5
5
  namespace mdbxmou {
6
6
 
7
+ class dbimou;
8
+
7
9
  struct convmou
8
10
  {
9
11
  key_mode key_mode_{};
12
+ value_mode value_mode_{};
10
13
  base_flag key_flag_{};
11
14
  base_flag value_flag_{};
12
15
 
13
- convmou() = default;
14
-
15
- convmou(key_mode key_mode, base_flag key_flag,
16
- base_flag value_flag = {}) noexcept
17
- : key_mode_{key_mode}
18
- , key_flag_{key_flag}
19
- , value_flag_{value_flag}
20
- { }
16
+ static convmou for_dbi(const dbimou& dbi) noexcept;
21
17
 
22
18
  Napi::Value convert_key(const Napi::Env& env, const keymou& key) const;
23
19
 
package/src/cursormou.cpp CHANGED
@@ -230,7 +230,8 @@ namespace mdbxmou
230
230
  keymou::from(info[0], env, key_num_) :
231
231
  keymou::from(info[0], env, key_buf_);
232
232
 
233
- valuemou val = valuemou::from(info[1], env, val_buf_);
233
+ valuemou val = valuemou::from(info[1], env, val_buf_, val_num_,
234
+ is_ordinal(dbi_->get_value_mode()));
234
235
 
235
236
  // Опциональный флаг put_mode (по умолчанию MDBX_UPSERT)
236
237
  MDBX_put_flags_t flags = MDBX_UPSERT;
package/src/cursormou.hpp CHANGED
@@ -20,6 +20,7 @@ private:
20
20
  buffer_type key_buf_{};
21
21
  buffer_type val_buf_{};
22
22
  std::uint64_t key_num_{};
23
+ std::uint64_t val_num_{};
23
24
 
24
25
  // Внутренний хелпер для навигации
25
26
  Napi::Value move(const Napi::Env& env, MDBX_cursor_op op);
package/src/dbimou.cpp CHANGED
@@ -165,14 +165,13 @@ MDBX_cursor_op range_turn_op(const range_options& options)
165
165
  return options.reverse ? MDBX_PREV : MDBX_NEXT;
166
166
  }
167
167
 
168
- Napi::Array collect_range(const Napi::Env& env, dbimou& self, txnmou& txn, const range_options& options, range_output output)
168
+ template<class Fn>
169
+ std::size_t scan_range(dbimou& self, txnmou& txn, const range_options& options, Fn&& fn)
169
170
  {
170
- Napi::Array result = Napi::Array::New(env);
171
171
  if (options.limit == 0) {
172
- return result;
172
+ return 0;
173
173
  }
174
174
 
175
- auto conv = self.get_convmou();
176
175
  auto cursor = self.open_cursor(txn);
177
176
  mdbx::slice key{};
178
177
  mdbx::slice value{};
@@ -186,7 +185,7 @@ Napi::Array collect_range(const Napi::Env& env, dbimou& self, txnmou& txn, const
186
185
  }
187
186
 
188
187
  if (!cursor_get(cursor, range_start_op(options), key, value)) {
189
- return result;
188
+ return 0;
190
189
  }
191
190
 
192
191
  std::size_t skipped{};
@@ -201,17 +200,8 @@ Napi::Array collect_range(const Napi::Env& env, dbimou& self, txnmou& txn, const
201
200
  if (skipped < options.offset) {
202
201
  ++skipped;
203
202
  } else {
204
- switch (output) {
205
- case range_output::items: {
206
- result.Set(index, conv.make_result(env, keymou{key}, valuemou{value}));
207
- break;
208
- }
209
- case range_output::keys:
210
- result.Set(index, conv.convert_key(env, keymou{key}));
211
- break;
212
- case range_output::values:
213
- result.Set(index, conv.convert_value(env, valuemou{value}));
214
- break;
203
+ if (fn(keymou{key}, valuemou{value}, index)) {
204
+ break;
215
205
  }
216
206
 
217
207
  ++index;
@@ -225,9 +215,39 @@ Napi::Array collect_range(const Napi::Env& env, dbimou& self, txnmou& txn, const
225
215
  }
226
216
  }
227
217
 
218
+ return index;
219
+ }
220
+
221
+ Napi::Array collect_range(const Napi::Env& env, dbimou& self, txnmou& txn, const range_options& options, range_output output)
222
+ {
223
+ Napi::Array result = Napi::Array::New(env);
224
+ auto conv = self.get_convmou();
225
+ scan_range(self, txn, options, [&](const keymou& key, const valuemou& value, std::size_t index) {
226
+ switch (output) {
227
+ case range_output::items:
228
+ result.Set(index, conv.make_result(env, key, value));
229
+ break;
230
+ case range_output::keys:
231
+ result.Set(index, conv.convert_key(env, key));
232
+ break;
233
+ case range_output::values:
234
+ result.Set(index, conv.convert_value(env, value));
235
+ break;
236
+ }
237
+ return false;
238
+ });
228
239
  return result;
229
240
  }
230
241
 
242
+ std::size_t count_range(dbimou& self, txnmou& txn, range_options options)
243
+ {
244
+ options.offset = 0;
245
+ options.limit = std::numeric_limits<std::size_t>::max();
246
+ return scan_range(self, txn, options, [](const keymou&, const valuemou&, std::size_t) {
247
+ return false;
248
+ });
249
+ }
250
+
231
251
  Napi::Value run_range_query(const Napi::CallbackInfo& info, dbimou& self, const char* method_name, range_output output)
232
252
  {
233
253
  Napi::Env env = info.Env();
@@ -247,6 +267,26 @@ Napi::Value run_range_query(const Napi::CallbackInfo& info, dbimou& self, const
247
267
  }
248
268
  }
249
269
 
270
+ Napi::Value run_range_count(const Napi::CallbackInfo& info, dbimou& self, const char* method_name)
271
+ {
272
+ Napi::Env env = info.Env();
273
+ if (info.Length() < 1) {
274
+ throw Napi::TypeError::New(env, std::string(method_name) + ": txnmou required");
275
+ }
276
+
277
+ auto txn = txnmou::unwrap_checked(env, info[0], method_name);
278
+
279
+ try {
280
+ auto options = info.Length() > 1 ?
281
+ parse_range_options(env, info[1], self) :
282
+ range_options{};
283
+ auto count = count_range(self, *txn, options);
284
+ return Napi::Number::New(env, static_cast<double>(count));
285
+ } catch (const std::exception& e) {
286
+ throw Napi::Error::New(env, std::string(method_name) + ": " + e.what());
287
+ }
288
+ }
289
+
250
290
  } // namespace
251
291
 
252
292
  Napi::FunctionReference dbimou::ctor{};
@@ -263,6 +303,7 @@ void dbimou::init(const char *class_name, Napi::Env env)
263
303
  InstanceMethod("keys", &dbimou::keys),
264
304
  InstanceMethod("keysFrom", &dbimou::keys_from),
265
305
  InstanceMethod("getRange", &dbimou::get_range),
306
+ InstanceMethod("getCount", &dbimou::get_count),
266
307
  InstanceMethod("keysRange", &dbimou::keys_range),
267
308
  InstanceMethod("valuesRange", &dbimou::values_range),
268
309
  InstanceMethod("drop", &dbimou::drop),
@@ -294,8 +335,15 @@ Napi::Value dbimou::put(const Napi::CallbackInfo& info)
294
335
  keymou::from(info[1], env, t) :
295
336
  keymou::from(info[1], env, key_buf_);
296
337
 
297
- auto val = valuemou::from(info[2], env, val_buf_);
298
- dbi::put(*txn, key, val, *this);
338
+ auto val = valuemou::from(info[2], env, val_buf_, val_num_, is_ordinal(value_mode_));
339
+ MDBX_put_flags_t flags = MDBX_UPSERT;
340
+ if (arg_len > 3 && !info[3].IsUndefined() && !info[3].IsNull()) {
341
+ if (!info[3].IsNumber()) {
342
+ throw Napi::TypeError::New(env, "put: flags must be a number");
343
+ }
344
+ flags = put_flag::parse(info[3]);
345
+ }
346
+ dbi::put(*txn, key, val, flags);
299
347
  } catch (const std::exception& e) {
300
348
  throw Napi::Error::New(env, std::string("put: ") + e.what());
301
349
  }
@@ -709,6 +757,11 @@ Napi::Value dbimou::get_range(const Napi::CallbackInfo& info)
709
757
  return run_range_query(info, *this, "getRange", range_output::items);
710
758
  }
711
759
 
760
+ Napi::Value dbimou::get_count(const Napi::CallbackInfo& info)
761
+ {
762
+ return run_range_count(info, *this, "getCount");
763
+ }
764
+
712
765
  Napi::Value dbimou::keys_range(const Napi::CallbackInfo& info)
713
766
  {
714
767
  return run_range_query(info, *this, "keysRange", range_output::keys);
package/src/dbimou.hpp CHANGED
@@ -25,6 +25,7 @@ class dbimou final
25
25
 
26
26
  buffer_type key_buf_{};
27
27
  buffer_type val_buf_{};
28
+ std::uint64_t val_num_{};
28
29
 
29
30
  public:
30
31
  static Napi::FunctionReference ctor;
@@ -73,6 +74,7 @@ public:
73
74
  Napi::Value keys(const Napi::CallbackInfo&);
74
75
  Napi::Value keys_from(const Napi::CallbackInfo&);
75
76
  Napi::Value get_range(const Napi::CallbackInfo&);
77
+ Napi::Value get_count(const Napi::CallbackInfo&);
76
78
  Napi::Value keys_range(const Napi::CallbackInfo&);
77
79
  Napi::Value values_range(const Napi::CallbackInfo&);
78
80
  Napi::Value drop(const Napi::CallbackInfo&);
@@ -124,7 +126,7 @@ public:
124
126
  }
125
127
 
126
128
  convmou get_convmou() const noexcept {
127
- return {key_mode_, key_flag_, value_flag_};
129
+ return convmou::for_dbi(*this);
128
130
  }
129
131
  };
130
132
 
package/src/modulemou.cpp CHANGED
@@ -80,6 +80,8 @@ Napi::Object Init(Napi::Env env, Napi::Object exports)
80
80
 
81
81
  Napi::Object value_flag = Napi::Object::New(env);
82
82
  MDBXMOU_DECLARE_FLAG_NAME(value_flag, "string", base_flag::string);
83
+ MDBXMOU_DECLARE_FLAG_NAME(value_flag, "number", base_flag::number);
84
+ MDBXMOU_DECLARE_FLAG_NAME(value_flag, "bigint", base_flag::bigint);
83
85
  mdbx_mou.Set("valueFlag", value_flag);
84
86
 
85
87
  using mdbxmou::db_mode;
@@ -97,6 +99,18 @@ Napi::Object Init(Napi::Env env, Napi::Object exports)
97
99
  MDBXMOU_DECLARE_FLAG_NAME(queryMode, "del", query_mode::del);
98
100
  mdbx_mou.Set("queryMode", queryMode);
99
101
 
102
+ using mdbxmou::put_flag;
103
+ Napi::Object putFlag = Napi::Object::New(env);
104
+ MDBXMOU_DECLARE_FLAG_NAME(putFlag, "noOverwrite", put_flag::no_overwrite);
105
+ MDBXMOU_DECLARE_FLAG_NAME(putFlag, "noDupData", put_flag::no_dup_data);
106
+ MDBXMOU_DECLARE_FLAG_NAME(putFlag, "current", put_flag::current);
107
+ MDBXMOU_DECLARE_FLAG_NAME(putFlag, "allDups", put_flag::all_dups);
108
+ MDBXMOU_DECLARE_FLAG_NAME(putFlag, "reserve", put_flag::reserve);
109
+ MDBXMOU_DECLARE_FLAG_NAME(putFlag, "append", put_flag::append);
110
+ MDBXMOU_DECLARE_FLAG_NAME(putFlag, "appendDup", put_flag::append_dup);
111
+ MDBXMOU_DECLARE_FLAG_NAME(putFlag, "multiple", put_flag::multiple);
112
+ mdbx_mou.Set("putFlag", putFlag);
113
+
100
114
  using move_operation = mdbx::cursor::move_operation;
101
115
  Napi::Object cursor_mode = Napi::Object::New(env);
102
116
  MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "first", move_operation::first);
package/src/querymou.cpp CHANGED
@@ -23,20 +23,11 @@ dbimou* async_common::parse(const Napi::Object& arg0)
23
23
 
24
24
  void async_key::parse(const async_common& common, const Napi::Value& item)
25
25
  {
26
- // утснавлиаем общие параметры
27
- auto key_flag = common.key_flag;
28
-
29
26
  keymou key{};
30
27
  if (mdbx::is_ordinal(common.key_mod)) {
31
- if (item.IsBigInt()) {
32
- key = keymou{item.As<Napi::BigInt>(), id_buf};
33
- } else if (item.IsNumber()) {
34
- key = keymou{item.As<Napi::Number>(), id_buf};
35
- }
28
+ key = keymou::from(item, item.Env(), id_buf);
36
29
  } else {
37
- key = (key_flag & base_flag::string) ?
38
- keymou{item.As<Napi::String>(), item.Env(), key_buf} :
39
- keymou{item.As<Napi::Buffer<char>>(), key_buf};
30
+ key = keymou::from(item, item.Env(), key_buf);
40
31
  }
41
32
  }
42
33
 
@@ -44,12 +35,14 @@ void async_keyval::parse(const query_line& common, const Napi::Object& item)
44
35
  {
45
36
  async_key::parse(common, item);
46
37
  // проверяем надо ли что-то писать
47
- if (common.mode.val & query_mode::write_mask) {
38
+ if (common.mode.is_write()) {
48
39
  valuemou val{};
49
40
  auto item_val = item.Get("value");
50
- val = (common.value_flag & base_flag::string) ?
51
- valuemou{item_val.As<Napi::String>(), item_val.Env(), val_buf} :
52
- valuemou{item_val.As<Napi::Buffer<char>>(), val_buf};
41
+ val = is_ordinal(common.val_mod) ?
42
+ valuemou::from(item_val, item_val.Env(), val_num) :
43
+ (common.value_flag & base_flag::string) ?
44
+ valuemou{item_val.As<Napi::String>(), item_val.Env(), val_buf} :
45
+ valuemou{item_val.As<Napi::Buffer<char>>(), val_buf};
53
46
  }
54
47
  }
55
48
 
@@ -63,6 +56,13 @@ void query_line::parse(txn_mode txn, const Napi::Object& arg0)
63
56
  } else if (arg0.Has("queryMode")) {
64
57
  mode = query_mode::parse(txn, arg0.Get("queryMode").As<Napi::Number>());
65
58
  }
59
+ if (arg0.Has("putFlag")) {
60
+ put_flags = put_flag::parse_query(arg0.Get("putFlag"));
61
+ if (!mode.is_write()) {
62
+ throw Napi::TypeError::New(arg0.Env(),
63
+ "query putFlag requires write queryMode");
64
+ }
65
+ }
66
66
  auto items_array = arg0.Get("item").As<Napi::Array>();
67
67
  auto item_len = items_array.Length();
68
68
  if (item_len > 0) {
package/src/querymou.hpp CHANGED
@@ -39,6 +39,7 @@ struct async_keyval
39
39
  : async_key
40
40
  {
41
41
  buffer_type val_buf{};
42
+ std::uint64_t val_num{};
42
43
  bool found{false};
43
44
 
44
45
  void parse(const query_line& line, const Napi::Object& obj);
@@ -57,6 +58,7 @@ struct query_line
57
58
  {
58
59
  base_flag value_flag{};
59
60
  query_mode mode{};
61
+ put_flag put_flags{};
60
62
  // буффер для запроса / ответа
61
63
  std::vector<async_keyval> item{};
62
64
  void parse(txn_mode txn, const Napi::Object& arg0);
@@ -83,4 +85,4 @@ struct keys_line
83
85
  using keys_request = std::vector<keys_line>;
84
86
  keys_request parse_keys(const Napi::Value& obj);
85
87
 
86
- } // namespace mdbxmou
88
+ } // namespace mdbxmou
package/src/txnmou.cpp CHANGED
@@ -159,7 +159,7 @@ Napi::Value txnmou::get_dbi(const Napi::Object& arg0, db_mode db_mode)
159
159
  if (arg0.Has("valueMode")) {
160
160
  auto value = arg0.Get("valueMode");
161
161
  if (!value.IsUndefined() && !value.IsNull()) {
162
- value_mode = value_mode::parse(value);
162
+ value_mode = parse_value_mode(value, value_flag);
163
163
  }
164
164
  }
165
165
 
@@ -189,7 +189,7 @@ Napi::Value txnmou::get_dbi(const Napi::CallbackInfo& info, db_mode db_mode)
189
189
  auto arg2 = info[2]; // value_mode
190
190
  db_name = arg0.As<Napi::String>().Utf8Value();
191
191
  key_mode = parse_key_mode(env, arg1, key_flag);
192
- value_mode = value_mode::parse(arg2);
192
+ value_mode = parse_value_mode(arg2, value_flag);
193
193
  } else if (arg_count == 2) {
194
194
  // db_name + key_mode || key_mode + value_mode
195
195
  auto arg0 = info[0];
@@ -199,7 +199,7 @@ Napi::Value txnmou::get_dbi(const Napi::CallbackInfo& info, db_mode db_mode)
199
199
  key_mode = parse_key_mode(env, arg1, key_flag);
200
200
  } else {
201
201
  key_mode = parse_key_mode(env, arg0, key_flag);
202
- value_mode = value_mode::parse(arg1);
202
+ value_mode = parse_value_mode(arg1, value_flag);
203
203
  }
204
204
  } else if (arg_count == 1) {
205
205
  // db_name || key_mode