Commit 37ce792b authored by Guillaume Royer's avatar Guillaume Royer

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

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