Skip to content

Commit

Permalink
Complete use of range in FDBCursor._iterate
Browse files Browse the repository at this point in the history
  • Loading branch information
dumbmatter committed Apr 19, 2017
1 parent 2e224bd commit fc9f9d9
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 34 deletions.
8 changes: 3 additions & 5 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
# v2 stuff:

abstract data functions
- FDBCursor._iterate
- don't start searching at record 0 if we know there is a lower bound. same with upper bound, can stop after passing it
- store lower bound to start iterator (don't worry about making it precise, including value and gt/gte), and upper bound to stop, based on various inputs

binary search tree

TypeScript
- tslint

Run on real W3C tests

Expand All @@ -21,6 +17,8 @@ addDomStringListMethods - make it a class

add lib.js for 1.x compatability, and test

make sure it works in node 4

---

test that IDBObjectStore.index returns the same or different IDBIndex depending on situation http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBObjectStore-index-IDBIndex-DOMString-name
Expand Down
73 changes: 46 additions & 27 deletions src/FDBCursor.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,35 @@ const getEffectiveObjectStore = (cursor) => {
return cursor.source;
};

const makeKeyRange = (lower, upper) => {
// This takes a key range, a list of lower bounds, and a list of upper bounds and combines them all into a single key
// range. It does not handle gt/gte distinctions, because it doesn't really matter much anyway, since for next/prev
// cursor iteration it'd also have to look at values to be precise, which would be complicated. This should get us 99%
// of the way there.
const makeKeyRange = (range, lowers, uppers) => {
// Start with bounds from range
let lower = range !== undefined ? range.lower : undefined;
let upper = range !== undefined ? range.upper : undefined;

// Augment with values from lowers and uppers
for (const lowerTemp of lowers) {
if (lowerTemp === undefined) {
continue;
}

if (lower === undefined || cmp(lower, lowerTemp) === 1) {
lower = lowerTemp;
}
}
for (const upperTemp of uppers) {
if (upperTemp === undefined) {
continue;
}

if (upper === undefined || cmp(upper, upperTemp) === -1) {
upper = upperTemp;
}
}

if (lower !== undefined && upper !== undefined) {
return FDBKeyRange.bound(lower, upper);
}
Expand Down Expand Up @@ -61,7 +89,8 @@ class FDBCursor {

let foundRecord;
if (this.direction === "next") {
for (const record of records.values()) {
const range = makeKeyRange(this._range, [key, this._position], []);
for (const record of records.values(range)) {
if (key !== undefined) {
if (cmp(record.key, key) === -1) {
continue;
Expand Down Expand Up @@ -90,29 +119,10 @@ class FDBCursor {
break;
}
} else if (this.direction === "nextunique") {
let lower;
let upper;
if (key !== undefined) {
lower = key;
}
if (this._position !== undefined) {
if (lower === undefined || cmp(lower, this._position) === 1) {
lower = this._position;
}
}
if (this._range !== undefined) {
if (this._range.lower !== undefined && (lower === undefined || cmp(lower, this._range.lower) === 1)) {
lower = this._range.lower;
}
if (this._range.upper !== undefined) {
upper = this._range.upper;
}
}
const range = makeKeyRange(lower, upper);

// This could be done without iterating, if the range was defined slightly better (to handle gt/gte cases).
// But the performance difference should be small, and that wouldn't work anyway for directions where the
// value needs to be used (like next and prev).
const range = makeKeyRange(this._range, [key, this._position], []);
for (const record of records.values(range)) {
if (key !== undefined) {
if (cmp(record.key, key) === -1) {
Expand All @@ -133,7 +143,8 @@ class FDBCursor {
break;
}
} else if (this.direction === "prev") {
for (const record of records.values(undefined, 'prev')) {
const range = makeKeyRange(this._range, [], [key, this._position]);
for (const record of records.values(range, 'prev')) {
if (key !== undefined) {
if (cmp(record.key, key) === 1) {
continue;
Expand Down Expand Up @@ -163,7 +174,8 @@ class FDBCursor {
}
} else if (this.direction === "prevunique") {
let tempRecord;
for (const record of records.values(undefined, 'prev')) {
const range = makeKeyRange(this._range, [], [key, this._position]);
for (const record of records.values(range, 'prev')) {
if (key !== undefined) {
if (cmp(record.key, key) === 1) {
continue;
Expand Down Expand Up @@ -192,17 +204,24 @@ class FDBCursor {
if (!foundRecord) {
this._key = undefined;
if (!sourceIsObjectStore) { this._objectStorePosition = undefined; }
this.value = undefined;
if (this.constructor.name === 'FDBCursorWithValue') {
this.value = undefined;
}
result = null;
} else {
this._position = foundRecord.key;
if (!sourceIsObjectStore) { this._objectStorePosition = foundRecord.value; }
this._key = foundRecord.key;
if (sourceIsObjectStore) {
this.value = structuredClone(foundRecord.value);
this._primaryKey = structuredClone(foundRecord.key);
if (this.constructor.name === 'FDBCursorWithValue') {
this.value = structuredClone(foundRecord.value);
}
} else {
this.value = structuredClone(this.source.objectStore._rawObjectStore.getValue(foundRecord.value));
this._primaryKey = structuredClone(foundRecord.value);
if (this.constructor.name === 'FDBCursorWithValue') {
this.value = structuredClone(this.source.objectStore._rawObjectStore.getValue(foundRecord.value));
}
}
this._gotValue = true;
result = this;
Expand Down
16 changes: 14 additions & 2 deletions src/lib/RecordStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,12 @@ class RecordStore {
}
}
} else {
i = this._records.length;
i = this._records.length - 1;
if (range !== undefined && range.upper !== undefined) {
while (this._records[i] !== undefined && cmp(this._records[i].key, range.upper) === 1) {
i -= 1;
}
}
}

return {
Expand All @@ -120,9 +125,16 @@ class RecordStore {
}
}
} else {
i -= 1;
value = this._records[i];
done = i < 0;
i -= 1;

if (!done && range !== undefined && range.lower !== undefined) {
done = cmp(value.key, range.lower) === -1;
if (done) {
value = undefined;
}
}
}

return {
Expand Down

0 comments on commit fc9f9d9

Please sign in to comment.