@@ -1376,6 +1376,89 @@ NAPI_METHOD(db_get) {
1376
1376
return promise;
1377
1377
}
1378
1378
1379
+ /* *
1380
+ * Worker class for db.has().
1381
+ */
1382
+ struct HasWorker final : public PriorityWorker {
1383
+ HasWorker (
1384
+ napi_env env,
1385
+ Database* database,
1386
+ napi_deferred deferred,
1387
+ leveldb::Slice key,
1388
+ const bool fillCache,
1389
+ ExplicitSnapshot* snapshot
1390
+ ) : PriorityWorker(env, database, deferred, " classic_level.db.has" ),
1391
+ key_ (key) {
1392
+ options_.fill_cache = fillCache;
1393
+
1394
+ if (snapshot == NULL ) {
1395
+ implicitSnapshot_ = database->NewSnapshot ();
1396
+ options_.snapshot = implicitSnapshot_;
1397
+ } else {
1398
+ implicitSnapshot_ = NULL ;
1399
+ options_.snapshot = snapshot->nut ;
1400
+ }
1401
+ }
1402
+
1403
+ ~HasWorker () {
1404
+ DisposeSliceBuffer (key_);
1405
+ }
1406
+
1407
+ void DoExecute () override {
1408
+ // LevelDB (and our wrapper) has no Has() method
1409
+ std::string value;
1410
+ leveldb::Status status = database_->Get (options_, key_, value);
1411
+
1412
+ if (status.ok ()) {
1413
+ result_ = true ;
1414
+ SetStatus (status);
1415
+ } else if (status.IsNotFound ()) {
1416
+ result_ = false ;
1417
+ SetStatus (leveldb::Status::OK ());
1418
+ } else {
1419
+ SetStatus (status);
1420
+ }
1421
+
1422
+ if (implicitSnapshot_) {
1423
+ database_->ReleaseSnapshot (implicitSnapshot_);
1424
+ }
1425
+ }
1426
+
1427
+ void HandleOKCallback (napi_env env, napi_deferred deferred) override {
1428
+ napi_value resultBoolean;
1429
+ napi_get_boolean (env, result_, &resultBoolean);
1430
+ napi_resolve_deferred (env, deferred, resultBoolean);
1431
+ }
1432
+
1433
+ private:
1434
+ leveldb::ReadOptions options_;
1435
+ leveldb::Slice key_;
1436
+ bool result_;
1437
+ const leveldb::Snapshot* implicitSnapshot_;
1438
+ };
1439
+
1440
+ /* *
1441
+ * Check if the database has an entry with the given key.
1442
+ */
1443
+ NAPI_METHOD (db_has) {
1444
+ NAPI_ARGV (4 );
1445
+ NAPI_DB_CONTEXT ();
1446
+ NAPI_PROMISE ();
1447
+
1448
+ leveldb::Slice key = ToSlice (env, argv[1 ]);
1449
+ const bool fillCache = BooleanValue (env, argv[2 ], true );
1450
+
1451
+ ExplicitSnapshot* snapshot = NULL ;
1452
+ napi_get_value_external (env, argv[3 ], (void **)&snapshot);
1453
+
1454
+ HasWorker* worker = new HasWorker (
1455
+ env, database, deferred, key, fillCache, snapshot
1456
+ );
1457
+
1458
+ worker->Queue (env);
1459
+ return promise;
1460
+ }
1461
+
1379
1462
/* *
1380
1463
* Worker class for getting many values.
1381
1464
*/
@@ -1481,6 +1564,100 @@ NAPI_METHOD(db_get_many) {
1481
1564
return promise;
1482
1565
}
1483
1566
1567
+ /* *
1568
+ * Worker class for db.hasMany().
1569
+ */
1570
+ struct HasManyWorker final : public PriorityWorker {
1571
+ HasManyWorker (
1572
+ napi_env env,
1573
+ Database* database,
1574
+ std::vector<std::string> keys,
1575
+ napi_deferred deferred,
1576
+ const bool fillCache,
1577
+ ExplicitSnapshot* snapshot
1578
+ ) : PriorityWorker(env, database, deferred, " classic_level.has.many" ),
1579
+ keys_ (std::move(keys)) {
1580
+ options_.fill_cache = fillCache;
1581
+
1582
+ if (snapshot == NULL ) {
1583
+ implicitSnapshot_ = database->NewSnapshot ();
1584
+ options_.snapshot = implicitSnapshot_;
1585
+ } else {
1586
+ implicitSnapshot_ = NULL ;
1587
+ options_.snapshot = snapshot->nut ;
1588
+ }
1589
+ }
1590
+
1591
+ void DoExecute () override {
1592
+ cache_.reserve (keys_.size ());
1593
+
1594
+ for (const std::string& key: keys_) {
1595
+ std::string value;
1596
+ leveldb::Status status = database_->Get (options_, key, value);
1597
+
1598
+ if (status.ok ()) {
1599
+ cache_.push_back (true );
1600
+ } else if (status.IsNotFound ()) {
1601
+ cache_.push_back (false );
1602
+ } else {
1603
+ SetStatus (status);
1604
+ break ;
1605
+ }
1606
+ }
1607
+
1608
+ if (implicitSnapshot_) {
1609
+ database_->ReleaseSnapshot (implicitSnapshot_);
1610
+ }
1611
+ }
1612
+
1613
+ void HandleOKCallback (napi_env env, napi_deferred deferred) override {
1614
+ size_t size = cache_.size ();
1615
+
1616
+ napi_value array;
1617
+ napi_value booleanTrue;
1618
+ napi_value booleanFalse;
1619
+
1620
+ napi_create_array_with_length (env, size, &array);
1621
+ napi_get_boolean (env, true , &booleanTrue);
1622
+ napi_get_boolean (env, false , &booleanFalse);
1623
+
1624
+ for (size_t i = 0 ; i < size; i++) {
1625
+ auto value = cache_[i] ? booleanTrue : booleanFalse;
1626
+ napi_set_element (env, array, static_cast <uint32_t >(i), value);
1627
+ }
1628
+
1629
+ napi_resolve_deferred (env, deferred, array);
1630
+ }
1631
+
1632
+ private:
1633
+ leveldb::ReadOptions options_;
1634
+ const std::vector<std::string> keys_;
1635
+ std::vector<bool > cache_;
1636
+ const leveldb::Snapshot* implicitSnapshot_;
1637
+ };
1638
+
1639
+ /* *
1640
+ * Check if the database has entries with the given keys.
1641
+ */
1642
+ NAPI_METHOD (db_has_many) {
1643
+ NAPI_ARGV (4 );
1644
+ NAPI_DB_CONTEXT ();
1645
+ NAPI_PROMISE ();
1646
+
1647
+ const auto keys = KeyArray (env, argv[1 ]);
1648
+ const bool fillCache = BooleanValue (env, argv[2 ], true );
1649
+
1650
+ ExplicitSnapshot* snapshot = NULL ;
1651
+ napi_get_value_external (env, argv[3 ], (void **)&snapshot);
1652
+
1653
+ HasManyWorker* worker = new HasManyWorker (
1654
+ env, database, keys, deferred, fillCache, snapshot
1655
+ );
1656
+
1657
+ worker->Queue (env);
1658
+ return promise;
1659
+ }
1660
+
1484
1661
/* *
1485
1662
* Worker class for deleting a value from a database.
1486
1663
*/
@@ -2280,6 +2457,8 @@ NAPI_INIT() {
2280
2457
NAPI_EXPORT_FUNCTION (db_put);
2281
2458
NAPI_EXPORT_FUNCTION (db_get);
2282
2459
NAPI_EXPORT_FUNCTION (db_get_many);
2460
+ NAPI_EXPORT_FUNCTION (db_has);
2461
+ NAPI_EXPORT_FUNCTION (db_has_many);
2283
2462
NAPI_EXPORT_FUNCTION (db_del);
2284
2463
NAPI_EXPORT_FUNCTION (db_clear);
2285
2464
NAPI_EXPORT_FUNCTION (db_approximate_size);
0 commit comments