Skip to content

Commit

Permalink
Add clear() method to delete all entries or a range (#669)
Browse files Browse the repository at this point in the history
* Add clear() method to delete all entries or a range
* Upgrade deferred-leveldown from ~5.1.0 to ~5.2.0
* Upgrade encoding-down devDependency from ^6.0.0 to ^6.2.0
* Add link to Level/community#79
  • Loading branch information
vweevers authored Sep 8, 2019
1 parent 1dbc5fe commit 45e73a9
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 2 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ db.put('name', 'levelup', function (err) {
- <a href="#createKeyStream"><code>db.<b>createKeyStream()</b></code></a>
- <a href="#createValueStream"><code>db.<b>createValueStream()</b></code></a>
- <a href="#iterator"><code>db.<b>iterator()</b></code></a>
- <a href="#clear"><code>db.<b>clear()</b></code></a>

### Special Notes

Expand Down Expand Up @@ -391,6 +392,23 @@ db.createReadStream({ keys: false, values: true })

Returns an [`abstract-leveldown` iterator](https://github.com/Level/abstract-leveldown/#abstractleveldown_iteratoroptions), which is what powers the readable streams above. Options are the same as the range options of <a href="#createReadStream"><code>createReadStream</code></a> and are passed to the underlying store.

<a name="clear"></a>

### `db.clear([options][, callback])`

**This method is experimental. Not all underlying stores support it yet. Consult [Level/community#79](https://github.com/Level/community/issues/79) to find out if your (combination of) dependencies support `db.clear()`.**

Delete all entries or a range. Not guaranteed to be atomic. Accepts the following range options (with the same rules as on iterators):

- `gt` (greater than), `gte` (greater than or equal) define the lower bound of the range to be deleted. Only entries where the key is greater than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the entries deleted will be the same.
- `lt` (less than), `lte` (less than or equal) define the higher bound of the range to be deleted. Only entries where the key is less than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the entries deleted will be the same.
- `reverse` _(boolean, default: `false`)_: delete entries in reverse order. Only effective in combination with `limit`, to remove the last N records.
- `limit` _(number, default: `-1`)_: limit the number of entries to be deleted. This number represents a _maximum_ number of entries and may not be reached if you get to the end of the range first. A value of `-1` means there is no limit. When `reverse=true` the entries with the highest keys will be deleted instead of the lowest keys.

If no options are provided, all entries will be deleted. The `callback` function will be called with no arguments if the operation was successful or with an `WriteError` if it failed for any reason.

If no callback is passed, a promise is returned.

<a name="writeStreams"></a>

#### What happened to `db.createWriteStream`?
Expand Down Expand Up @@ -446,6 +464,7 @@ const main = async () => {
| `put` | Key has been updated | `key, value` (any) |
| `del` | Key has been deleted | `key` (any) |
| `batch` | Batch has executed | `operations` (array) |
| `clear` | Entries were deleted | `options` (object) |
| `opening` | Underlying store is opening | - |
| `open` | Store has opened | - |
| `ready` | Alias of `open` | - |
Expand Down
27 changes: 27 additions & 0 deletions lib/levelup.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,33 @@ LevelUP.prototype.iterator = function (options) {
return this.db.iterator(options)
}

LevelUP.prototype.clear = function (options, callback) {
var self = this
var promise

callback = getCallback(options, callback)
options = getOptions(options)

if (!callback) {
callback = promisify()
promise = callback.promise
}

if (maybeError(this, callback)) {
return promise
}

this.db.clear(options, function (err) {
if (err) {
return callback(new WriteError(err))
}
self.emit('clear', options)
callback()
})

return promise
}

LevelUP.prototype.readStream =
LevelUP.prototype.createReadStream = function (options) {
options = extend({ keys: true, values: true }, options)
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"prepublishOnly": "npm run dependency-check"
},
"dependencies": {
"deferred-leveldown": "~5.1.0",
"deferred-leveldown": "~5.2.0",
"level-errors": "~2.0.0",
"level-iterator-stream": "~4.0.0",
"xtend": "~4.0.0"
Expand All @@ -30,9 +30,10 @@
"coveralls": "^3.0.2",
"delayed": "^2.0.0",
"dependency-check": "^3.3.0",
"encoding-down": "^6.0.0",
"encoding-down": "^6.2.0",
"hallmark": "^2.0.0",
"level-community": "^3.0.0",
"level-concat-iterator": "^2.0.1",
"memdown": "^5.0.0",
"nyc": "^14.0.0",
"pinkie": "^2.0.4",
Expand Down
83 changes: 83 additions & 0 deletions test/clear-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
var test = require('tape')
var memdown = require('memdown')
var encode = require('encoding-down')
var concat = require('level-concat-iterator')
var levelup = require('../lib/levelup')

test('clear()', function (t) {
function makeTest (name, fn) {
t.test(name, function (t) {
var mem = memdown()

mem.open(function (err) {
t.ifError(err, 'no open error')

mem.batch([
{ type: 'put', key: '"a"', value: 'a' },
{ type: 'put', key: '"b"', value: 'b' }
], function (err) {
t.ifError(err, 'no batch error')

mem.close(function (err) {
t.ifError(err, 'no close error')
fn(t, mem)
})
})
})
})
}

function verify (t, db, expectedKey) {
concat(db.iterator({ keyAsBuffer: false }), function (err, entries) {
t.ifError(err, 'no concat error')
t.same(entries.map(function (e) { return e.key }), [expectedKey], 'got expected keys')
db.close(t.end.bind(t))
})
}

makeTest('clear() without encoding, without deferred-open', function (t, mem) {
var db = levelup(mem)

db.open(function (err) {
t.ifError(err)

db.clear({ gte: '"b"' }, function (err) {
t.ifError(err, 'no clear error')
verify(t, db, '"a"')
})
})
})

makeTest('clear() without encoding, with deferred-open', function (t, mem) {
var db = levelup(mem)

db.clear({ gte: '"b"' }, function (err) {
t.ifError(err, 'no clear error')
verify(t, db, '"a"')
})
})

makeTest('clear() with encoding, with deferred-open', function (t, mem) {
var db = levelup(encode(mem, { keyEncoding: 'json' }))

db.clear({ gte: 'b' }, function (err) {
t.ifError(err, 'no clear error')
verify(t, db, 'a')
})
})

makeTest('clear() with encoding, without deferred-open', function (t, mem) {
var db = levelup(encode(mem, { keyEncoding: 'json' }))

db.open(function (err) {
t.ifError(err)

db.clear({ gte: 'b' }, function (err) {
t.ifError(err, 'no clear error')
verify(t, db, 'a')
})
})
})

t.end()
})
1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ if (process.browser && typeof Promise !== 'function') {
require('./argument-checking-test')
require('./batch-test')
require('./binary-test')
require('./clear-test')
require('./deferred-open-test')
require('./get-put-del-test')
require('./idempotent-test')
Expand Down

0 comments on commit 45e73a9

Please sign in to comment.