Commit 37ce792b by Guillaume Royer

refactor(sql storage): use jio storage to save index

1 parent 34f242f2
......@@ -7,34 +7,37 @@
* JIO Sql Storage. Type = "sql".
* sql "database" storage.
*/
/*global Blob, jIO, RSVP, SQL, localStorage*/
/*global Blob, jIO, RSVP, SQL*/
/*jslint nomen: true*/
(function (jIO, RSVP, SQL, localStorage) {
(function (Blob, jIO, RSVP, SQL) {
"use strict";
var sqlStorageKey = 'jio_sql',
sqlTable = "jiosearch";
function resetDb(indexFields) {
function initSQLDb(indexFields) {
var db = new SQL.Database(),
fields = ["id"].concat(indexFields);
db.run("CREATE TABLE " + sqlTable + " ( " + fields.join(", ") + ");");
return db;
}
function initDb(indexFields) {
var data = localStorage.getItem(sqlStorageKey);
if (data) {
return new SQL.Database(data.split(","));
}
return resetDb(indexFields);
}
function loadSQLDb(storage, indexFields) {
var db = null;
function saveDb(db) {
var data = db["export"](); // jslint throws error
localStorage.setItem(sqlStorageKey, data);
return storage
.getAttachment(sqlStorageKey, sqlStorageKey, {
format: 'array_buffer'
})
.push(function (data) {
db = new SQL.Database(data);
}, function () {
db = initSQLDb(indexFields);
})
.push(function () {
return db;
});
}
function docToParams(id, doc) {
......@@ -98,14 +101,57 @@
* @constructor
*/
function SqlStorage(spec) {
if (!spec.index_sub_storage) {
throw new TypeError(
"SQL 'index_sub_storage' must be provided."
);
}
this._index_sub_storage = jIO.createJIO(spec.index_sub_storage);
if (!this._index_sub_storage.hasCapacity('getAttachment')) {
throw new TypeError(
"SQL 'index_sub_storage' must have getAttachment capacity."
);
}
this._sub_storage = jIO.createJIO(spec.sub_storage);
this.__index_fields = spec.index_fields;
this.__db = initDb(spec.index_fields || []);
this._index_fields = spec.index_fields;
}
SqlStorage.prototype.__resetDb = function (indexFields) {
this.__index_fields = indexFields;
this.__db = resetDb(indexFields);
SqlStorage.prototype._getDb = function () {
var context = this;
if (this._db) {
return new RSVP.Queue().push(function () {
return context._db;
});
}
return loadSQLDb(
this._index_sub_storage,
this._index_fields
).push(function (db) {
context._db = db;
return context._db;
});
};
SqlStorage.prototype._resetDb = function (indexFields) {
this._index_fields = indexFields;
this._db = initSQLDb(indexFields);
};
SqlStorage.prototype._saveDb = function () {
var context = this;
return this._getDb()
.push(function (db) {
var data = db["export"](); // jslint throws error
return context._index_sub_storage.putAttachment(
sqlStorageKey,
sqlStorageKey,
new Blob([data])
);
});
};
SqlStorage.prototype.get = function () {
......@@ -117,42 +163,50 @@
};
SqlStorage.prototype.post = function (doc) {
var db = this.__db,
indexFields = this.__index_fields;
var context = this,
indexFields = this._index_fields;
return this._sub_storage.post.apply(this._sub_storage, arguments)
.push(function (id) {
db.run(
"INSERT INTO " + sqlTable + dbValues(indexFields),
docToParams(id, doc)
);
saveDb(db);
return context._getDb().push(function (db) {
db.run(
"INSERT INTO " + sqlTable + dbValues(indexFields),
docToParams(id, doc)
);
return context._saveDb();
});
});
};
SqlStorage.prototype.put = function (id, doc) {
var db = this.__db,
indexFields = this.__index_fields;
var context = this,
indexFields = this._index_fields;
return this._sub_storage.put.apply(this._sub_storage, arguments)
.push(function () {
return context._getDb();
})
.push(function (db) {
db.run(
"UPDATE " + sqlTable + dbSet(indexFields) + " WHERE id=:id",
docToParams(id, doc)
);
saveDb(db);
return context._saveDb();
});
};
SqlStorage.prototype.remove = function (id) {
var db = this.__db;
var context = this;
return this._sub_storage.remove(id)
.push(function () {
return context._getDb();
})
.push(function (db) {
db.run("DELETE FROM " + sqlTable + " WHERE id=:id", {
":id": id
});
saveDb(db);
return context._saveDb();
});
};
......@@ -195,11 +249,13 @@
}
var context = this,
db = this.__db,
parsed_query = jIO.QueryFactory.create(options.query);
return new RSVP.Queue()
.push(function () {
return context._getDb();
})
.push(function (db) {
var query = "SELECT id FROM " + sqlTable,
where = dbWhere(
parsed_query.query_list || [parsed_query],
......@@ -241,5 +297,4 @@
};
jIO.addStorage('sql', SqlStorage);
}(jIO, RSVP, SQL, localStorage));
}(Blob, jIO, RSVP, SQL));
/*jslint nomen: true */
/*global jIO, QUnit, sinon, localStorage */
(function (jIO, QUnit, sinon, localStorage) {
/*global jIO, QUnit, sinon */
(function (jIO, QUnit, sinon) {
"use strict";
var test = QUnit.test,
stop = QUnit.stop,
......@@ -66,61 +66,92 @@
jIO.addStorage('sql200', Storage200);
function Index200() {
this.attachments = {};
return this;
}
Index200.prototype.putAttachment = function (id, name, data) {
var context = this;
return new RSVP.Queue().push(function () {
context.attachments[id] = {
id: id,
name: name,
data: data
};
return context.attachments[id];
});
};
Index200.prototype.getAttachment = function (id) {
var context = this;
return new RSVP.Queue().push(function () {
if (context.attachments[id] !== undefined) {
return context.attachments[id].data;
}
throw new Error("not found");
});
};
jIO.addStorage('index200', Index200);
/////////////////////////////////////////////////////////////////
// SqlStorage.constructor
/////////////////////////////////////////////////////////////////
module("SqlStorage.constructor", {
setup: function () {
this.getItemSpy = sinon.spy(localStorage, "getItem");
this.jio = jIO.createJIO({
type: "sql",
index_fields: ["title"],
index_sub_storage: {
type: "index200"
},
sub_storage: {
type: "sql200"
}
});
},
teardown: function () {
this.getItemSpy.restore();
delete this.getItemSpy;
}
});
test("set the type", function () {
equal(this.jio.__type, "sql");
});
test("spy load from localStorage", function () {
ok(
this.getItemSpy.calledOnce,
"getItem count " + this.getItemSpy.callCount
);
stop();
this.jio.post({
title: "title 1"
})
.fail(function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// SqlStorage.hasCapacity
/////////////////////////////////////////////////////////////////
module("SqlStorage.hasCapacity");
test("can list documents", function () {
var jio = jIO.createJIO({
type: "sql",
sub_storage: {
type: "sql200"
}
});
module("SqlStorage.hasCapacity", {
setup: function () {
this.jio = jIO.createJIO({
type: "sql",
index_sub_storage: {
type: "index200"
},
sub_storage: {
type: "sql200"
}
});
}
});
ok(jio.hasCapacity("list"));
test("can list documents", function () {
ok(this.jio.hasCapacity("list"));
});
test("can query documents", function () {
var jio = jIO.createJIO({
type: "sql",
sub_storage: {
type: "sql200"
}
});
ok(jio.hasCapacity("query"));
ok(this.jio.hasCapacity("query"));
});
/////////////////////////////////////////////////////////////////
......@@ -133,23 +164,26 @@
index_fields: [
"title"
],
index_sub_storage: {
type: "index200"
},
sub_storage: {
type: "sql200"
}
});
this.jio.__storage.__resetDb([
this.jio.__storage._resetDb([
"title"
]);
this.db = this.jio.__storage.__db;
this.db = this.jio.__storage._db;
this.setItemSpy = sinon.spy(localStorage, "setItem");
this.runSpy = sinon.spy(this.db, "run");
this.saveSpy = sinon.spy(this.jio.__storage, "_saveDb");
},
teardown: function () {
this.setItemSpy.restore();
delete this.setItemSpy;
this.runSpy.restore();
delete this.runSpy;
this.saveSpy.restore();
delete this.saveSpy;
}
});
......@@ -163,8 +197,8 @@
this.jio.post(doc)
.then(function () {
ok(
context.setItemSpy.calledOnce,
"setItem count " + context.setItemSpy.callCount
context.saveSpy.calledOnce,
"save count " + context.saveSpy.callCount
);
ok(
context.runSpy.calledOnce,
......@@ -202,23 +236,26 @@
index_fields: [
"title"
],
index_sub_storage: {
type: "index200"
},
sub_storage: {
type: "sql200"
}
});
this.jio.__storage.__resetDb([
this.jio.__storage._resetDb([
"title"
]);
this.db = this.jio.__storage.__db;
this.db = this.jio.__storage._db;
this.setItemSpy = sinon.spy(localStorage, "setItem");
this.runSpy = sinon.spy(this.db, "run");
this.saveSpy = sinon.spy(this.jio.__storage, "_saveDb");
},
teardown: function () {
this.setItemSpy.restore();
delete this.setItemSpy;
this.runSpy.restore();
delete this.runSpy;
this.saveSpy.restore();
delete this.saveSpy;
}
});
......@@ -232,8 +269,8 @@
this.jio.put("1", doc)
.then(function () {
ok(
context.setItemSpy.calledOnce,
"setItem count " + context.setItemSpy.callCount
context.saveSpy.calledOnce,
"save count " + context.saveSpy.callCount
);
ok(
context.runSpy.calledOnce,
......@@ -271,23 +308,26 @@
index_fields: [
"title"
],
index_sub_storage: {
type: "index200"
},
sub_storage: {
type: "sql200"
}
});
this.jio.__storage.__resetDb([
this.jio.__storage._resetDb([
"title"
]);
this.db = this.jio.__storage.__db;
this.db = this.jio.__storage._db;
this.setItemSpy = sinon.spy(localStorage, "setItem");
this.runSpy = sinon.spy(this.db, "run");
this.saveSpy = sinon.spy(this.jio.__storage, "_saveDb");
},
teardown: function () {
this.setItemSpy.restore();
delete this.setItemSpy;
this.runSpy.restore();
delete this.runSpy;
this.saveSpy.restore();
delete this.saveSpy;
}
});
......@@ -298,8 +338,8 @@
this.jio.remove("1")
.then(function () {
ok(
context.setItemSpy.calledOnce,
"setItem count " + context.setItemSpy.callCount
context.saveSpy.calledOnce,
"save count " + context.saveSpy.callCount
);
ok(
context.runSpy.calledOnce,
......@@ -333,11 +373,14 @@
setup: function () {
this.jio = jIO.createJIO({
type: "sql",
index_sub_storage: {
type: "index200"
},
sub_storage: {
type: "sql200"
}
});
this.jio.__storage.__resetDb([
this.jio.__storage._resetDb([
"title"
]);
}
......@@ -423,7 +466,7 @@
});
test("search multiple fields", function () {
this.jio.__storage.__resetDb([
this.jio.__storage._resetDb([
"title",
"body"
]);
......@@ -468,7 +511,7 @@
});
test("limit results", function () {
this.jio.__storage.__resetDb([
this.jio.__storage._resetDb([
"title"
]);
var context = this,
......@@ -517,7 +560,7 @@
});
test("sort results", function () {
this.jio.__storage.__resetDb([
this.jio.__storage._resetDb([
"title",
"body"
]);
......@@ -566,4 +609,4 @@
start();
});
});
}(jIO, QUnit, sinon, localStorage));
}(jIO, QUnit, sinon));
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!