Skip to content

Commit

Permalink
Add a flag to NoSqlProvider to skip ordering results. This can make t…
Browse files Browse the repository at this point in the history
…h… (#67)

* Add a flag to NoSqlProvider to skip odering results. This can make the sqlite provider faster on large datasets
Keep backwards compatibility with the existing boolean
* Add more tests & bump package.json
  • Loading branch information
berickson1 authored Oct 15, 2018
1 parent da5a95a commit 5433bcb
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 56 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nosqlprovider",
"version": "0.6.20",
"version": "0.6.21",
"description": "A cross-browser/platform indexeddb-like client library",
"author": "David de Regt <[email protected]>",
"scripts": {
Expand Down
8 changes: 5 additions & 3 deletions src/FullTextSearchHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,12 @@ export abstract class DbIndexFTSFromRangeQueries implements NoSqlProvider.DbInde
});
}

abstract getAll(reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
abstract getOnly(key: KeyType, reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
abstract getAll(reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number)
: SyncTasks.Promise<ItemType[]>;
abstract getOnly(key: KeyType, reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number)
: SyncTasks.Promise<ItemType[]>;
abstract getRange(keyLowRange: KeyType, keyHighRange: KeyType, lowRangeExclusive?: boolean, highRangeExclusive?: boolean,
reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
reverseOrSortOrder?: boolean|NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
abstract countAll(): SyncTasks.Promise<number>;
abstract countOnly(key: KeyType): SyncTasks.Promise<number>;
abstract countRange(keyLowRange: KeyType, keyHighRange: KeyType, lowRangeExclusive?: boolean, highRangeExclusive?: boolean)
Expand Down
19 changes: 10 additions & 9 deletions src/InMemoryProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ class InMemoryIndex extends FullTextSearchHelpers.DbIndexFTSFromRangeQueries {
return data;
}

getAll(reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
getAll(reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
if (!this._trans.internal_isOpen()) {
return SyncTasks.Rejected('InMemoryTransaction already closed');
}
Expand All @@ -316,15 +316,16 @@ class InMemoryIndex extends FullTextSearchHelpers.DbIndexFTSFromRangeQueries {
}

const sortedKeys = _.keys(data).sort();
return this._returnResultsFromKeys(data, sortedKeys, reverse, limit, offset);
return this._returnResultsFromKeys(data, sortedKeys, reverseOrSortOrder, limit, offset);
}

getOnly(key: KeyType, reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
return this.getRange(key, key, false, false, reverse, limit, offset);
getOnly(key: KeyType, reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number)
: SyncTasks.Promise<ItemType[]> {
return this.getRange(key, key, false, false, reverseOrSortOrder, limit, offset);
}

getRange(keyLowRange: KeyType, keyHighRange: KeyType, lowRangeExclusive?: boolean, highRangeExclusive?: boolean,
reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
if (!this._trans.internal_isOpen()) {
return SyncTasks.Rejected('InMemoryTransaction already closed');
}
Expand All @@ -339,7 +340,7 @@ class InMemoryIndex extends FullTextSearchHelpers.DbIndexFTSFromRangeQueries {
return SyncTasks.Rejected(err);
}

return this._returnResultsFromKeys(data!!!, sortedKeys!!!, reverse, limit, offset);
return this._returnResultsFromKeys(data!!!, sortedKeys!!!, reverseOrSortOrder, limit, offset);
}

// Warning: This function can throw, make sure to trap.
Expand All @@ -351,9 +352,9 @@ class InMemoryIndex extends FullTextSearchHelpers.DbIndexFTSFromRangeQueries {
(key > keyLow || (key === keyLow && !lowRangeExclusive)) && (key < keyHigh || (key === keyHigh && !highRangeExclusive)));
}

private _returnResultsFromKeys(data: _.Dictionary<ItemType[]>|_.Dictionary<ItemType>, sortedKeys: string[], reverse?: boolean,
limit?: number, offset?: number) {
if (reverse) {
private _returnResultsFromKeys(data: _.Dictionary<ItemType[]> | _.Dictionary<ItemType>, sortedKeys: string[],
reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number) {
if (reverseOrSortOrder === true || reverseOrSortOrder === NoSqlProvider.QuerySortOrder.Reverse) {
sortedKeys = _.reverse(sortedKeys);
}

Expand Down
11 changes: 7 additions & 4 deletions src/IndexedDbProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -720,22 +720,24 @@ class IndexedDbIndex extends FullTextSearchHelpers.DbIndexFTSFromRangeQueries {
}
}

getAll(reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
getAll(reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
const reverse = reverseOrSortOrder === true || reverseOrSortOrder === NoSqlProvider.QuerySortOrder.Reverse;
// ************************* Don't change this null to undefined, IE chokes on it... *****************************
// ************************* Don't change this null to undefined, IE chokes on it... *****************************
// ************************* Don't change this null to undefined, IE chokes on it... *****************************
const req = this._store.openCursor(null!!!, reverse ? 'prev' : 'next');
return this._resolveCursorResult(req, limit, offset);
}

getOnly(key: KeyType, reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
getOnly(key: KeyType, reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number)
: SyncTasks.Promise<ItemType[]> {
const keyRange = _.attempt(() => {
return this._getKeyRangeForOnly(key);
});
if (_.isError(keyRange)) {
return SyncTasks.Rejected(keyRange);
}

const reverse = reverseOrSortOrder === true || reverseOrSortOrder === NoSqlProvider.QuerySortOrder.Reverse;
const req = this._store.openCursor(keyRange, reverse ? 'prev' : 'next');
return this._resolveCursorResult(req, limit, offset);
}
Expand All @@ -749,14 +751,15 @@ class IndexedDbIndex extends FullTextSearchHelpers.DbIndexFTSFromRangeQueries {
}

getRange(keyLowRange: KeyType, keyHighRange: KeyType, lowRangeExclusive?: boolean, highRangeExclusive?: boolean,
reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
const keyRange = _.attempt(() => {
return this._getKeyRangeForRange(keyLowRange, keyHighRange, lowRangeExclusive, highRangeExclusive);
});
if (_.isError(keyRange)) {
return SyncTasks.Rejected(keyRange);
}

const reverse = reverseOrSortOrder === true || reverseOrSortOrder === NoSqlProvider.QuerySortOrder.Reverse;
const req = this._store.openCursor(keyRange, reverse ? 'prev' : 'next');
return this._resolveCursorResult(req, limit, offset);
}
Expand Down
29 changes: 17 additions & 12 deletions src/NoSqlProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ import SyncTasks = require('synctasks');
export type ItemType = object;
export type KeyComponentType = string|number|Date;
export type KeyType = KeyComponentType|KeyComponentType[];
export type KeyPathType = string|string[];
export type KeyPathType = string | string[];
export enum QuerySortOrder {
None,
Forward,
Reverse
}

// Schema type describing an index for a store.
export interface IndexSchema {
Expand Down Expand Up @@ -55,10 +60,10 @@ export enum FullTextTermResolution {

// Interface type describing an index being opened for querying.
export interface DbIndex {
getAll(reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
getOnly(key: KeyType, reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
getAll(reverseOrSortOrder?: boolean|QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
getOnly(key: KeyType, reverseOrSortOrder?: boolean|QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
getRange(keyLowRange: KeyType, keyHighRange: KeyType, lowRangeExclusive?: boolean, highRangeExclusive?: boolean,
reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
reverseOrSortOrder?: boolean|QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]>;
countAll(): SyncTasks.Promise<number>;
countOnly(key: KeyType): SyncTasks.Promise<number>;
countRange(keyLowRange: KeyType, keyHighRange: KeyType, lowRangeExclusive?: boolean, highRangeExclusive?: boolean)
Expand Down Expand Up @@ -189,25 +194,25 @@ export abstract class DbProvider {
});
}

getAll(storeName: string, indexName: string|undefined, reverse?: boolean, limit?: number, offset?: number)
getAll(storeName: string, indexName: string|undefined, reverseOrSortOrder?: boolean|QuerySortOrder, limit?: number, offset?: number)
: SyncTasks.Promise<ItemType[]> {
return this._getStoreIndexTransaction(storeName, false, indexName).then(index => {
return index.getAll(reverse, limit, offset);
return index.getAll(reverseOrSortOrder, limit, offset);
});
}

getOnly(storeName: string, indexName: string|undefined, key: KeyType, reverse?: boolean, limit?: number, offset?: number)
: SyncTasks.Promise<ItemType[]> {
getOnly(storeName: string, indexName: string | undefined, key: KeyType, reverseOrSortOrder?: boolean | QuerySortOrder, limit?: number,
offset?: number): SyncTasks.Promise<ItemType[]> {
return this._getStoreIndexTransaction(storeName, false, indexName).then(index => {
return index.getOnly(key, reverse, limit, offset);
return index.getOnly(key, reverseOrSortOrder, limit, offset);
});
}

getRange(storeName: string, indexName: string|undefined, keyLowRange: KeyType, keyHighRange: KeyType,
lowRangeExclusive?: boolean, highRangeExclusive?: boolean, reverse?: boolean, limit?: number, offset?: number)
getRange(storeName: string, indexName: string | undefined, keyLowRange: KeyType, keyHighRange: KeyType, lowRangeExclusive?: boolean,
highRangeExclusive?: boolean, reverseOrSortOrder?: boolean | QuerySortOrder, limit?: number, offset?: number)
: SyncTasks.Promise<ItemType[]> {
return this._getStoreIndexTransaction(storeName, false, indexName).then(index => {
return index.getRange(keyLowRange, keyHighRange, lowRangeExclusive, highRangeExclusive, reverse, limit, offset);
return index.getRange(keyLowRange, keyHighRange, lowRangeExclusive, highRangeExclusive, reverseOrSortOrder, limit, offset);
});
}

Expand Down
23 changes: 14 additions & 9 deletions src/SqlProviderBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1118,8 +1118,13 @@ class SqlStoreIndex implements NoSqlProvider.DbIndex {
}
}

private _handleQuery(sql: string, args?: any[], reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
sql += ' ORDER BY ' + this._queryColumn + (reverse ? ' DESC' : ' ASC');
private _handleQuery(sql: string, args?: any[], reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number,
offset?: number): SyncTasks.Promise<ItemType[]> {
// Check if we must do some sort of ordering
if (reverseOrSortOrder !== NoSqlProvider.QuerySortOrder.None) {
const reverse = reverseOrSortOrder === true || reverseOrSortOrder === NoSqlProvider.QuerySortOrder.Reverse;
sql += ' ORDER BY ' + this._queryColumn + (reverse ? ' DESC' : ' ASC');
}

if (limit) {
if (limit > LimitMax) {
Expand All @@ -1138,13 +1143,13 @@ class SqlStoreIndex implements NoSqlProvider.DbIndex {
return this._trans.internal_getResultsFromQuery(sql, args);
}

getAll(reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
getAll(reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
let startTime: number;
if (this._verbose) {
startTime = Date.now();
}

let promise = this._handleQuery('SELECT nsp_data FROM ' + this._tableName, undefined, reverse, limit, offset);
let promise = this._handleQuery('SELECT nsp_data FROM ' + this._tableName, undefined, reverseOrSortOrder, limit, offset);
if (this._verbose) {
promise = promise.finally(() => {
console.log('SqlStoreIndex (' + this._rawTableName + '/' + this._indexTableName + ') getAll: (' +
Expand All @@ -1154,7 +1159,8 @@ class SqlStoreIndex implements NoSqlProvider.DbIndex {
return promise;
}

getOnly(key: KeyType, reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
getOnly(key: KeyType, reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number)
: SyncTasks.Promise<ItemType[]> {
const joinedKey = _.attempt(() => {
return NoSqlProviderUtils.serializeKeyToString(key, this._keyPath);
});
Expand All @@ -1168,8 +1174,7 @@ class SqlStoreIndex implements NoSqlProvider.DbIndex {
}

let promise = this._handleQuery('SELECT nsp_data FROM ' + this._tableName + ' WHERE ' + this._queryColumn + ' = ?',
[joinedKey],
reverse, limit, offset);
[joinedKey], reverseOrSortOrder, limit, offset);
if (this._verbose) {
promise = promise.finally(() => {
console.log('SqlStoreIndex (' + this._rawTableName + '/' + this._indexTableName + ') getOnly: (' +
Expand All @@ -1180,7 +1185,7 @@ class SqlStoreIndex implements NoSqlProvider.DbIndex {
}

getRange(keyLowRange: KeyType, keyHighRange: KeyType, lowRangeExclusive?: boolean, highRangeExclusive?: boolean,
reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ItemType[]> {
let checks: string;
let args: string[];
const err = _.attempt(() => {
Expand All @@ -1198,7 +1203,7 @@ class SqlStoreIndex implements NoSqlProvider.DbIndex {
}

let promise = this._handleQuery('SELECT nsp_data FROM ' + this._tableName + ' WHERE ' + checks!!!, args!!!,
reverse, limit, offset);
reverseOrSortOrder, limit, offset);
if (this._verbose) {
promise = promise.finally(() => {
console.log('SqlStoreIndex (' + this._rawTableName + '/' + this._indexTableName + ') getRange: (' +
Expand Down
28 changes: 14 additions & 14 deletions src/StoreHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,21 @@ export class SimpleTransactionIndexHelper<ObjectType extends ItemType, IndexKeyF
// Nothing to see here
}

getAll(reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ObjectType[]> {
let promise = this._index.getAll(reverse, limit, offset) as SyncTasks.Promise<ObjectType[]>;
getAll(reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ObjectType[]> {
let promise = this._index.getAll(reverseOrSortOrder, limit, offset) as SyncTasks.Promise<ObjectType[]>;
return ErrorCatcher ? promise.catch(ErrorCatcher) : promise;
}

getOnly(key: IndexKeyFormat, reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ObjectType[]> {
let promise = this._index.getOnly(key, reverse, limit, offset) as SyncTasks.Promise<ObjectType[]>;
getOnly(key: IndexKeyFormat, reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number)
: SyncTasks.Promise<ObjectType[]> {
let promise = this._index.getOnly(key, reverseOrSortOrder, limit, offset) as SyncTasks.Promise<ObjectType[]>;
return ErrorCatcher ? promise.catch(ErrorCatcher) : promise;
}

getRange(keyLowRange: IndexKeyFormat, keyHighRange: IndexKeyFormat,
lowRangeExclusive?: boolean, highRangeExclusive?: boolean, reverse?: boolean, limit?: number, offset?: number)
: SyncTasks.Promise<ObjectType[]> {
getRange(keyLowRange: IndexKeyFormat, keyHighRange: IndexKeyFormat, lowRangeExclusive?: boolean, highRangeExclusive?: boolean,
reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ObjectType[]> {
let promise = this._index.getRange(keyLowRange, keyHighRange, lowRangeExclusive,
highRangeExclusive, reverse, limit, offset) as SyncTasks.Promise<ObjectType[]>;
highRangeExclusive, reverseOrSortOrder, limit, offset) as SyncTasks.Promise<ObjectType[]>;
return ErrorCatcher ? promise.catch(ErrorCatcher) : promise;
}

Expand Down Expand Up @@ -84,16 +84,16 @@ export class SimpleTransactionStoreHelper<StoreName extends string, ObjectType e
return ErrorCatcher ? promise.catch(ErrorCatcher) : promise;
}

getOnly(key: KeyFormat, reverse?: boolean, limit?: number, offset?: number): SyncTasks.Promise<ObjectType[]> {
let promise = this._store.openPrimaryKey().getOnly(key, reverse, limit, offset) as SyncTasks.Promise<ObjectType[]>;
getOnly(key: KeyFormat, reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number)
: SyncTasks.Promise<ObjectType[]> {
let promise = this._store.openPrimaryKey().getOnly(key, reverseOrSortOrder, limit, offset) as SyncTasks.Promise<ObjectType[]>;
return ErrorCatcher ? promise.catch(ErrorCatcher) : promise;
}

getRange(keyLowRange: KeyFormat, keyHighRange: KeyFormat,
lowRangeExclusive?: boolean, highRangeExclusive?: boolean, reverse?: boolean, limit?: number, offset?: number)
: SyncTasks.Promise<ObjectType[]> {
getRange(keyLowRange: KeyFormat, keyHighRange: KeyFormat, lowRangeExclusive?: boolean, highRangeExclusive?: boolean,
reverseOrSortOrder?: boolean | NoSqlProvider.QuerySortOrder, limit?: number, offset?: number): SyncTasks.Promise<ObjectType[]> {
let promise = this._store.openPrimaryKey().getRange(keyLowRange, keyHighRange,
lowRangeExclusive, highRangeExclusive, reverse, limit, offset) as SyncTasks.Promise<ObjectType[]>;
lowRangeExclusive, highRangeExclusive, reverseOrSortOrder, limit, offset) as SyncTasks.Promise<ObjectType[]>;
return ErrorCatcher ? promise.catch(ErrorCatcher) : promise;
}

Expand Down
Loading

0 comments on commit 5433bcb

Please sign in to comment.