Commit c3ce93e6 authored by preetwinder's avatar preetwinder

add include_docs and repair

parent 05bea40b
...@@ -38,18 +38,67 @@ ...@@ -38,18 +38,67 @@
this._sub_storage = jIO.createJIO(description.sub_storage); this._sub_storage = jIO.createJIO(description.sub_storage);
this._database_name = "jio:" + description.database; this._database_name = "jio:" + description.database;
this._index_keys = description.index_keys || []; this._index_keys = description.index_keys || [];
this._use_sub_storage_query = description.use_sub_storage_query || false;
this._use_sub_storage_query_partial = true;
if (description.use_sub_storage_query_partial !== undefined) {
this._use_sub_storage_query_partial =
description.use_sub_storage_query_partial;
}
this._version = description.version || undefined; this._version = description.version || undefined;
} }
function convertToObject(list, key) {
var i, obj = {};
for (i = 0; i < list.length; i += 1) {
obj[list[i][key]] = list[i];
}
return obj;
}
function keyCount(obj) {
return Object.keys(obj).length;
}
function union(list) {
var result, i, j;
if (list.length === 0) {
return [];
}
result = convertToObject(list[0], 'id');
for (i = 1; i < list.length; i += 1) {
for (j = 0; j < list[i].length; j += 1) {
if (result[list[i][j].id]) {
if (keyCount(result[list[i][j].id].doc) <
keyCount(list[i][j].doc)) {
result[list[i][j].id] = list[i][j];
}
} else {
result[list[i][j].id] = list[i][j];
}
}
}
return Object.values(result);
}
function intersect(list) {
var result, temp = {}, i, j;
if (list.length === 0) {
return [];
}
result = convertToObject(list[0], 'id');
for (i = 1; i < list.length; i += 1) {
for (j = 0; j < list[i].length; j += 1) {
if (result[list[i][j].id]) {
if (keyCount(result[list[i][j].id].doc) <
keyCount(list[i][j].doc)) {
temp[list[i][j].id] = list[i][j];
} else {
temp[list[i][j].id] = result[list[i][j].id];
}
}
}
result = temp;
temp = {};
}
return Object.values(result);
}
IndexStorage2.prototype.hasCapacity = function (name) { IndexStorage2.prototype.hasCapacity = function (name) {
var this_storage_capacity_list = ["limit", var this_storage_capacity_list = ["select",
"select",
"list", "list",
"query", "query",
"sort", "sort",
...@@ -60,27 +109,6 @@ ...@@ -60,27 +109,6 @@
} }
}; };
function compareSortOn(value1, value2, sort_on) {
var current_compare = sort_on.slice(0, 1)[0],
remaining_compare = sort_on.slice(1);
if (value1[current_compare[0]] === value2[current_compare[0]]) {
if (remaining_compare.length === 0) {
return 0;
}
return compareSortOn(value1, value2, remaining_compare);
}
if (value1[current_compare[0]] > value2[current_compare[0]]) {
if (current_compare[1] === 'ascending') {
return 1;
}
return -1;
}
if (current_compare[1] === 'descending') {
return 1;
}
return -1;
}
function handleUpgradeNeeded(evt, index_keys) { function handleUpgradeNeeded(evt, index_keys) {
var db = evt.target.result, store, i, current_indices; var db = evt.target.result, store, i, current_indices;
...@@ -93,6 +121,17 @@ ...@@ -93,6 +121,17 @@
store = evt.target.transaction.objectStore('index-store'); store = evt.target.transaction.objectStore('index-store');
} }
current_indices = new Set(store.indexNames); current_indices = new Set(store.indexNames);
for (i = 0; i < index_keys.length; i += 1) {
if (!(current_indices.has(index_keys[i]))) {
db.deleteObjectStore("index-store");
store = db.createObjectStore("index-store", {
keyPath: "id",
autoIncrement: false
});
current_indices = new Set();
break;
}
}
for (i = 0; i < index_keys.length; i += 1) { for (i = 0; i < index_keys.length; i += 1) {
if (!(current_indices.has('Index-' + index_keys[i]))) { if (!(current_indices.has('Index-' + index_keys[i]))) {
store.createIndex('Index-' + index_keys[i], store.createIndex('Index-' + index_keys[i],
...@@ -134,7 +173,8 @@ ...@@ -134,7 +173,8 @@
reject("Connection to: " + db_name + " timeout"); reject("Connection to: " + db_name + " timeout");
}; };
// request.onblocked = function () { // request.onblocked = function (evt) {
// console.log("evt", evt);
// request.result.close(); // request.result.close();
// reject("Connection to: " + db_name + " was blocked"); // reject("Connection to: " + db_name + " was blocked");
// }; // };
...@@ -215,55 +255,52 @@ ...@@ -215,55 +255,52 @@
function filterDocValues(doc, keys) { function filterDocValues(doc, keys) {
var filtered_doc = {}, i; var filtered_doc = {}, i;
if (keys) {
for (i = 0; i < keys.length; i += 1) { for (i = 0; i < keys.length; i += 1) {
if (doc[keys[i]]) {
filtered_doc[keys[i]] = doc[keys[i]]; filtered_doc[keys[i]] = doc[keys[i]];
} else {
throw new jIO.util.jIOError(
"Index key '" + keys[i] + "' not found in document",
404
);
}
} }
return filtered_doc; return filtered_doc;
} }
return doc;
}
IndexStorage2.prototype._runQuery = function (index, value, limit, sort_on) { IndexStorage2.prototype.forceIncludeDocs = function (result) {
var context = this; var i, get_list = {}, context = this;
return new RSVP.Queue() return RSVP.Queue()
.push(function () { .push(function () {
if ((context._index_keys.indexOf(index) === -1)) { for (i = 0; i < result.length; i += 1) {
if (context._use_sub_storage_query_partial) { if (!(result[i].include)) {
try { get_list[result[i].id] = context._sub_storage.get(result[i].id);
context._sub_storage.hasCapacity("query");
} catch (error) {
if (error instanceof jIO.util.jIOError &&
error.status_code === 501) {
throw new jIO.util.jIOError("No index for '" + index +
"' key and substorage doesn't support queries", 404);
}
throw error;
} }
return context._sub_storage.buildQuery(
{ "query": index + ":" + value }
);
} }
throw new jIO.util.jIOError("No index for '" + index + return RSVP.hash(get_list);
"' key and checking the substorage for partial queries is not set", })
404); .push(function (get_result) {
var keys;
result = convertToObject(result, 'id');
keys = Object.keys(get_result);
for (i = 0; i < keys.length; i += 1) {
result[keys[i]].doc = get_result[keys[i]];
} }
result = Object.values(result);
return result;
})
.push(function () {
return result;
});
};
IndexStorage2.prototype._runQuery = function (index, value) {
var context = this;
return new RSVP.Queue()
.push(function () {
return waitForOpenIndexedDB(context._database_name, context._version, return waitForOpenIndexedDB(context._database_name, context._version,
context._index_keys, function (db) { context._index_keys, function (db) {
return waitForTransaction(db, ["index-store"], "readonly", return waitForTransaction(db, ["index-store"], "readonly",
function (tx) { function (tx) {
return waitForIDBRequest(tx.objectStore("index-store") return waitForIDBRequest(tx.objectStore("index-store")
.index("Index-" + index).getAll(value, limit)) .index("Index-" + index).getAll(value))
.then(function (evt) { .then(function (evt) {
if (sort_on) {
evt.target.result.sort(function (v1, v2) {
return compareSortOn(v1.doc, v2.doc, sort_on);
});
}
return evt.target.result; return evt.target.result;
}); });
}); });
...@@ -271,114 +308,70 @@ ...@@ -271,114 +308,70 @@
}); });
}; };
IndexStorage2.prototype._processQueryObject = function (object, limit, IndexStorage2.prototype._processQueryObject = function (object,
sort_on) { include_docs) {
var promise_list = [], context = this, i, j, query_result = new Set(); var promise_list = [], context = this, i;
include_docs = include_docs || false;
return RSVP.Queue() return RSVP.Queue()
.push(function () { .push(function () {
if (object.type === "simple") { if (object.type === "simple") {
return context._runQuery(object.key, object.value, limit, sort_on); if ((context._index_keys.indexOf(object.key) === -1)) {
return context._sub_storage.allDocs({
"query": object.key + ":" + object.value,
"include_docs": include_docs
})
.push(function (result) {
if (include_docs) {
result.data.rows.map(function (v) {
v.include = true;
});
}
return result.data.rows;
});
}
return context._runQuery(object.key, object.value);
} }
if (object.type === "complex") { if (object.type === "complex") {
for (i = 0; i < object.query_list.length; i += 1) { for (i = 0; i < object.query_list.length; i += 1) {
promise_list.push(context promise_list.push(context
._processQueryObject(object.query_list[i])); ._processQueryObject(object.query_list[i], include_docs));
} }
return RSVP.all(promise_list) return RSVP.all(promise_list)
.then(function (result) { .then(function (result) {
if (object.operator === "OR") { if (object.operator === "OR") {
for (i = 0; i < result.length; i += 1) { return union(result);
for (j = 0; j < result[i].length; j += 1) {
query_result.add(result[i][j]);
}
}
return Array.from(query_result);
} }
if (object.operator === "AND") { if (object.operator === "AND") {
var temp_set = new Set(); return intersect(result);
for (i = 0; i < result[0].length; i += 1) {
query_result.add(result[0][i].id);
}
for (i = 1; i < result.length; i += 1) {
for (j = 0; j < result[i].length; j += 1) {
if (query_result.has(result[i][j].id)) {
temp_set.add(result[i][j]);
}
}
query_result = temp_set;
temp_set = new Set();
}
return Array.from(query_result);
} }
}); });
} }
}); })
}; };
IndexStorage2.prototype.buildQuery = function (options) { IndexStorage2.prototype.buildQuery = function (options) {
var context = this, substorage = this._sub_storage; var context = this;
try {
if (substorage.hasCapacity("list") &&
((options.query === undefined) ||
(context._use_sub_storage_query &&
substorage.hasCapacity("query"))) &&
((options.sort_on === undefined) ||
(substorage.hasCapacity("sort"))) &&
((options.select_list === undefined) ||
(substorage.hasCapacity("select"))) &&
((options.limit === undefined) ||
(substorage.hasCapacity("limit"))) &&
((options.include_docs === undefined ||
(substorage.hasCapacity("include"))))) {
return substorage.buildQuery(options);
}
} catch (error) {
if (!((error instanceof jIO.util.jIOError) &&
(error.status_code === 501))) {
throw error;
}
}
if (options.query) { if (options.query) {
return this._processQueryObject(parseStringToObject(options.query), return this._processQueryObject(parseStringToObject(options.query),
options.limit, options.sort_on) options.include_docs)
.push(function (result) { .push(function (result) {
if (options.include_docs) { if (options.include_docs) {
options.select_list = context._index_keys; result = context.forceIncludeDocs(result);
options.select_list = undefined;
} else {
options.select_list = options.select_list || [];
} }
return result;
})
.push(function (result) {
return result.map(function (value) { return result.map(function (value) {
return { return {
"id": value.id, "id": value.id,
"value": filterDocValues(value.doc, "value": filterDocValues(value.doc, options.select_list)
options.select_list || [])
}; };
}); });
}); });
} }
return waitForOpenIndexedDB(context._database_name, context._version,
context._index_keys, function (db) {
return waitForTransaction(db, ["index-store"], "readonly",
function (tx) {
return waitForIDBRequest(tx.objectStore("index-store")
.getAll(undefined, options.limit))
.then(function (evt) {
if (options.sort_on) {
evt.target.result.sort(function (v1, v2) {
return compareSortOn(v1.doc, v2.doc, options.sort_on);
});
}
if (options.include_docs) {
options.select_list = context._index_keys;
}
return evt.target.result.map(function (value) {
return {
"id": value.id,
"value": filterDocValues(value.doc,
options.select_list || [])
};
});
});
});
});
}; };
IndexStorage2.prototype.get = function () { IndexStorage2.prototype.get = function () {
...@@ -411,7 +404,7 @@ ...@@ -411,7 +404,7 @@
var context = this; var context = this;
return context._sub_storage.post(value) return context._sub_storage.post(value)
.push(function (id) { .push(function (id) {
context._put(id, value); return context._put(id, value);
}); });
}; };
...@@ -443,5 +436,17 @@ ...@@ -443,5 +436,17 @@
arguments); arguments);
}; };
IndexStorage2.prototype.repair = function () {
var context = this, promise_list = [], i;
return context._sub_storage.allDocs()
.push(function (result) {
for (i = 0; i < result.data.total_rows; i += 1) {
promise_list.push(context.put(result.data.rows[i].id,
filterDocValues(result.data.rows[i].value, context._index_keys)));
}
return RSVP.all(promise_list);
});
};
jIO.addStorage("index2", IndexStorage2); jIO.addStorage("index2", IndexStorage2);
}(indexedDB, jIO, RSVP, IDBOpenDBRequest, DOMError, parseStringToObject)); }(indexedDB, jIO, RSVP, IDBOpenDBRequest, DOMError, parseStringToObject));
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment