Skip to content
This repository was archived by the owner on Dec 2, 2024. It is now read-only.

Commit 9a04b3b

Browse files
authored
Support clear() (#182)
* Support clear() * Optimize clear() and fix IE & Edge
1 parent f207ae6 commit 9a04b3b

File tree

7 files changed

+119
-23
lines changed

7 files changed

+119
-23
lines changed

index.js

+29
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ var serialize = require('./util/serialize')
1111
var deserialize = require('./util/deserialize')
1212
var setImmediate = require('./util/immediate')
1313
var support = require('./util/support')
14+
var clear = require('./util/clear')
15+
var createKeyRange = require('./util/key-range')
1416

1517
var DEFAULT_PREFIX = 'level-js-'
1618

@@ -181,6 +183,33 @@ Level.prototype._batch = function (operations, options, callback) {
181183
loop()
182184
}
183185

186+
Level.prototype._clear = function (options, callback) {
187+
try {
188+
var keyRange = createKeyRange(options)
189+
} catch (e) {
190+
// The lower key is greater than the upper key.
191+
// IndexedDB throws an error, but we'll just do nothing.
192+
return setImmediate(callback)
193+
}
194+
195+
if (options.limit >= 0) {
196+
// IDBObjectStore#delete(range) doesn't have such an option.
197+
// Fall back to cursor-based implementation.
198+
return clear(this, this.location, keyRange, options, callback)
199+
}
200+
201+
try {
202+
var store = this.store('readwrite')
203+
var req = keyRange ? store.delete(keyRange) : store.clear()
204+
} catch (err) {
205+
return setImmediate(function () {
206+
callback(err)
207+
})
208+
}
209+
210+
this.await(req, callback)
211+
}
212+
184213
Level.prototype._close = function (callback) {
185214
this.db.close()
186215
setImmediate(callback)

iterator.js

+2-21
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
/* global IDBKeyRange */
2-
31
'use strict'
42

53
var inherits = require('inherits')
64
var AbstractIterator = require('abstract-leveldown').AbstractIterator
7-
var ltgt = require('ltgt')
5+
var createKeyRange = require('./util/key-range')
86
var deserialize = require('./util/deserialize')
97
var setImmediate = require('./util/immediate')
108
var noop = function () {}
@@ -34,7 +32,7 @@ function Iterator (db, location, options) {
3432
}
3533

3634
try {
37-
var keyRange = this.createKeyRange(options)
35+
var keyRange = createKeyRange(options)
3836
} catch (e) {
3937
// The lower key is greater than the upper key.
4038
// IndexedDB throws an error, but we'll just return 0 results.
@@ -47,23 +45,6 @@ function Iterator (db, location, options) {
4745

4846
inherits(Iterator, AbstractIterator)
4947

50-
Iterator.prototype.createKeyRange = function (options) {
51-
var lower = ltgt.lowerBound(options)
52-
var upper = ltgt.upperBound(options)
53-
var lowerOpen = ltgt.lowerBoundExclusive(options)
54-
var upperOpen = ltgt.upperBoundExclusive(options)
55-
56-
if (lower !== undefined && upper !== undefined) {
57-
return IDBKeyRange.bound(lower, upper, lowerOpen, upperOpen)
58-
} else if (lower !== undefined) {
59-
return IDBKeyRange.lowerBound(lower, lowerOpen)
60-
} else if (upper !== undefined) {
61-
return IDBKeyRange.upperBound(upper, upperOpen)
62-
} else {
63-
return null
64-
}
65-
}
66-
6748
Iterator.prototype.createIterator = function (location, keyRange, reverse) {
6849
var self = this
6950
var transaction = this.db.db.transaction([location], 'readonly')

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"./util/immediate.js": "./util/immediate-browser.js"
2727
},
2828
"dependencies": {
29-
"abstract-leveldown": "~6.0.1",
29+
"abstract-leveldown": "~6.1.1",
3030
"immediate": "~3.2.3",
3131
"inherits": "^2.0.3",
3232
"ltgt": "^2.1.2"

test/custom-test.js

+24
Original file line numberDiff line numberDiff line change
@@ -296,5 +296,29 @@ module.exports = function (leveljs, test, testCommon) {
296296
})
297297
})
298298

299+
// TODO: move to abstract-leveldown test suite (and add to iterator tests too)
300+
test('clear() with lower key greater than upper key', function (t) {
301+
var db = testCommon.factory()
302+
303+
db.open(function (err) {
304+
t.ifError(err, 'no open error')
305+
306+
db.put('a', 'a', function (err) {
307+
t.ifError(err, 'no put error')
308+
309+
db.clear({ gt: 'b', lt: 'a' }, function (err) {
310+
t.ifError(err, 'no clear error')
311+
312+
db.get('a', { asBuffer: false }, function (err, value) {
313+
t.ifError(err, 'no get error')
314+
t.is(value, 'a')
315+
316+
db.close(t.end.bind(t))
317+
})
318+
})
319+
})
320+
})
321+
})
322+
299323
test('teardown', testCommon.tearDown)
300324
}

test/index.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ var testCommon = suite.common({
2020
seek: false,
2121

2222
// Support of buffer keys depends on environment
23-
bufferKeys: leveljs(uuid()).supports.bufferKeys
23+
bufferKeys: leveljs(uuid()).supports.bufferKeys,
24+
25+
// Opt-in to new clear() tests
26+
clear: true
2427
})
2528

2629
// Test abstract-leveldown compliance

util/clear.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict'
2+
3+
var setImmediate = require('./immediate')
4+
5+
module.exports = function clear (db, location, keyRange, options, callback) {
6+
if (options.limit === 0) return setImmediate(callback)
7+
8+
var transaction = db.db.transaction([location], 'readwrite')
9+
var store = transaction.objectStore(location)
10+
var count = 0
11+
12+
transaction.oncomplete = function () {
13+
callback()
14+
}
15+
16+
transaction.onabort = function () {
17+
callback(transaction.error || new Error('aborted by user'))
18+
}
19+
20+
// A key cursor is faster (skips reading values) but not supported by IE
21+
var method = store.openKeyCursor ? 'openKeyCursor' : 'openCursor'
22+
var direction = options.reverse ? 'prev' : 'next'
23+
24+
store[method](keyRange, direction).onsuccess = function (ev) {
25+
var cursor = ev.target.result
26+
27+
if (cursor) {
28+
// Wait for a request to complete before continuing, saving CPU.
29+
store.delete(cursor.key).onsuccess = function () {
30+
if (options.limit <= 0 || ++count < options.limit) {
31+
cursor.continue()
32+
}
33+
}
34+
}
35+
}
36+
}

util/key-range.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* global IDBKeyRange */
2+
3+
'use strict'
4+
5+
var ltgt = require('ltgt')
6+
var NONE = {}
7+
8+
module.exports = function createKeyRange (options) {
9+
var lower = ltgt.lowerBound(options, NONE)
10+
var upper = ltgt.upperBound(options, NONE)
11+
var lowerOpen = ltgt.lowerBoundExclusive(options, NONE)
12+
var upperOpen = ltgt.upperBoundExclusive(options, NONE)
13+
14+
if (lower !== NONE && upper !== NONE) {
15+
return IDBKeyRange.bound(lower, upper, lowerOpen, upperOpen)
16+
} else if (lower !== NONE) {
17+
return IDBKeyRange.lowerBound(lower, lowerOpen)
18+
} else if (upper !== NONE) {
19+
return IDBKeyRange.upperBound(upper, upperOpen)
20+
} else {
21+
return null
22+
}
23+
}

0 commit comments

Comments
 (0)