@@ -1306,6 +1306,75 @@ NAPI_METHOD(db_get) {
1306
1306
return promise;
1307
1307
}
1308
1308
1309
+ /* *
1310
+ * Worker class for db.has().
1311
+ */
1312
+ struct HasWorker final : public PriorityWorker {
1313
+ HasWorker (
1314
+ napi_env env,
1315
+ Database* database,
1316
+ napi_deferred deferred,
1317
+ leveldb::Slice key,
1318
+ const bool fillCache
1319
+ ) : PriorityWorker(env, database, deferred, " classic_level.db.has" ),
1320
+ key_ (key) {
1321
+ options_.fill_cache = fillCache;
1322
+ options_.snapshot = database->NewSnapshot ();
1323
+ }
1324
+
1325
+ ~HasWorker () {
1326
+ DisposeSliceBuffer (key_);
1327
+ }
1328
+
1329
+ void DoExecute () override {
1330
+ // LevelDB (and our wrapper) has no Has() method
1331
+ std::string value;
1332
+ leveldb::Status status = database_->Get (options_, key_, value);
1333
+
1334
+ if (status.ok ()) {
1335
+ result_ = true ;
1336
+ SetStatus (status);
1337
+ } else if (status.IsNotFound ()) {
1338
+ result_ = false ;
1339
+ SetStatus (leveldb::Status::OK ());
1340
+ } else {
1341
+ SetStatus (status);
1342
+ }
1343
+
1344
+ database_->ReleaseSnapshot (options_.snapshot );
1345
+ }
1346
+
1347
+ void HandleOKCallback (napi_env env, napi_deferred deferred) override {
1348
+ napi_value resultBoolean;
1349
+ napi_get_boolean (env, result_, &resultBoolean);
1350
+ napi_resolve_deferred (env, deferred, resultBoolean);
1351
+ }
1352
+
1353
+ private:
1354
+ leveldb::ReadOptions options_;
1355
+ leveldb::Slice key_;
1356
+ bool result_;
1357
+ };
1358
+
1359
+ /* *
1360
+ * Check if the database has an entry with the given key.
1361
+ */
1362
+ NAPI_METHOD (db_has) {
1363
+ NAPI_ARGV (3 );
1364
+ NAPI_DB_CONTEXT ();
1365
+ NAPI_PROMISE ();
1366
+
1367
+ leveldb::Slice key = ToSlice (env, argv[1 ]);
1368
+ const bool fillCache = BooleanValue (env, argv[2 ], true );
1369
+
1370
+ HasWorker* worker = new HasWorker (
1371
+ env, database, deferred, key, fillCache
1372
+ );
1373
+
1374
+ worker->Queue (env);
1375
+ return promise;
1376
+ }
1377
+
1309
1378
/* *
1310
1379
* Worker class for getting many values.
1311
1380
*/
@@ -1391,6 +1460,86 @@ NAPI_METHOD(db_get_many) {
1391
1460
return promise;
1392
1461
}
1393
1462
1463
+ /* *
1464
+ * Worker class for db.hasMany().
1465
+ */
1466
+ struct HasManyWorker final : public PriorityWorker {
1467
+ HasManyWorker (
1468
+ napi_env env,
1469
+ Database* database,
1470
+ std::vector<std::string> keys,
1471
+ napi_deferred deferred,
1472
+ const bool fillCache
1473
+ ) : PriorityWorker(env, database, deferred, " classic_level.has.many" ),
1474
+ keys_ (std::move(keys)) {
1475
+ options_.fill_cache = fillCache;
1476
+ options_.snapshot = database->NewSnapshot ();
1477
+ }
1478
+
1479
+ void DoExecute () override {
1480
+ cache_.reserve (keys_.size ());
1481
+
1482
+ for (const std::string& key: keys_) {
1483
+ std::string value;
1484
+ leveldb::Status status = database_->Get (options_, key, value);
1485
+
1486
+ if (status.ok ()) {
1487
+ cache_.push_back (true );
1488
+ } else if (status.IsNotFound ()) {
1489
+ cache_.push_back (false );
1490
+ } else {
1491
+ SetStatus (status);
1492
+ break ;
1493
+ }
1494
+ }
1495
+
1496
+ database_->ReleaseSnapshot (options_.snapshot );
1497
+ }
1498
+
1499
+ void HandleOKCallback (napi_env env, napi_deferred deferred) override {
1500
+ size_t size = cache_.size ();
1501
+
1502
+ napi_value array;
1503
+ napi_value booleanTrue;
1504
+ napi_value booleanFalse;
1505
+
1506
+ napi_create_array_with_length (env, size, &array);
1507
+ napi_get_boolean (env, true , &booleanTrue);
1508
+ napi_get_boolean (env, false , &booleanFalse);
1509
+
1510
+ for (size_t i = 0 ; i < size; i++) {
1511
+ auto value = cache_[i] ? booleanTrue : booleanFalse;
1512
+ napi_set_element (env, array, static_cast <uint32_t >(i), value);
1513
+ }
1514
+
1515
+ napi_resolve_deferred (env, deferred, array);
1516
+ }
1517
+
1518
+ private:
1519
+ leveldb::ReadOptions options_;
1520
+ const std::vector<std::string> keys_;
1521
+ std::vector<bool > cache_;
1522
+ };
1523
+
1524
+ /* *
1525
+ * Check if the database has entries with the given keys.
1526
+ */
1527
+ NAPI_METHOD (db_has_many) {
1528
+ NAPI_ARGV (3 );
1529
+ NAPI_DB_CONTEXT ();
1530
+ NAPI_PROMISE ();
1531
+
1532
+ const auto keys = KeyArray (env, argv[1 ]);
1533
+ const bool fillCache = BooleanValue (env, argv[2 ], true );
1534
+
1535
+ HasManyWorker* worker = new HasManyWorker (
1536
+ env, database, keys, deferred, fillCache
1537
+ );
1538
+
1539
+ worker->Queue (env);
1540
+ return promise;
1541
+ }
1542
+
1394
1543
/* *
1395
1544
* Worker class for deleting a value from a database.
1396
1545
*/
@@ -2182,6 +2331,8 @@ NAPI_INIT() {
2182
2331
NAPI_EXPORT_FUNCTION (db_put);
2183
2332
NAPI_EXPORT_FUNCTION (db_get);
2184
2333
NAPI_EXPORT_FUNCTION (db_get_many);
2334
+ NAPI_EXPORT_FUNCTION (db_has);
2335
+ NAPI_EXPORT_FUNCTION (db_has_many);
2185
2336
NAPI_EXPORT_FUNCTION (db_del);
2186
2337
NAPI_EXPORT_FUNCTION (db_clear);
2187
2338
NAPI_EXPORT_FUNCTION (db_approximate_size);
0 commit comments