@@ -1376,6 +1376,89 @@ NAPI_METHOD(db_get) {
13761376 return promise;
13771377}
13781378
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+
13791462/* *
13801463 * Worker class for getting many values.
13811464 */
@@ -1481,6 +1564,100 @@ NAPI_METHOD(db_get_many) {
14811564 return promise;
14821565}
14831566
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+
14841661/* *
14851662 * Worker class for deleting a value from a database.
14861663 */
@@ -2280,6 +2457,8 @@ NAPI_INIT() {
22802457 NAPI_EXPORT_FUNCTION (db_put);
22812458 NAPI_EXPORT_FUNCTION (db_get);
22822459 NAPI_EXPORT_FUNCTION (db_get_many);
2460+ NAPI_EXPORT_FUNCTION (db_has);
2461+ NAPI_EXPORT_FUNCTION (db_has_many);
22832462 NAPI_EXPORT_FUNCTION (db_del);
22842463 NAPI_EXPORT_FUNCTION (db_clear);
22852464 NAPI_EXPORT_FUNCTION (db_approximate_size);
0 commit comments