From 136aa9a08cdb503aa69c5d3683a5f817b9d372e6 Mon Sep 17 00:00:00 2001 From: Nino Paolo Date: Wed, 31 Jul 2013 00:34:57 +0800 Subject: [PATCH 1/6] Fixed an issue on webkit-sqlite key. See http://stackoverflow.com/questions/17868221/why-does-lawnchairs-webkit-sqlite-adapter-converts-key-to-string/17951999#17951999 --- src/adapters/webkit-sqlite.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/adapters/webkit-sqlite.js b/src/adapters/webkit-sqlite.js index 3bf50ef1..37b1ffb2 100644 --- a/src/adapters/webkit-sqlite.js +++ b/src/adapters/webkit-sqlite.js @@ -2,6 +2,12 @@ Lawnchair.adapter('webkit-sqlite', (function () { // private methods var fail = function (e, i) { console.error('error in sqlite adaptor!', e, i) } , now = function () { return new Date() } // FIXME need to use better date fn + , convertInt2String = function(args) { + // converts array's integer value to string + return args.map(function(value, index, arr){ + return '' + value + }); + } // not entirely sure if this is needed... if (!Function.prototype.bind) { Function.prototype.bind = function( obj ) { @@ -63,7 +69,6 @@ Lawnchair.adapter('webkit-sqlite', (function () { save: function (obj, callback, error) { var that = this , objs = (this.isArray(obj) ? obj : [obj]).map(function(o){if(!o.key) { o.key = that.uuid()} return o}) - , ins = "INSERT OR REPLACE INTO " + this.record + " (value, timestamp, id) VALUES (?,?,?)" , win = function () { if (callback) { that.lambda(callback).call(that, that.isArray(obj)?objs:objs[0]) }} , error= error || function() {} , insvals = [] @@ -78,10 +83,16 @@ Lawnchair.adapter('webkit-sqlite', (function () { throw e; } - that.db.transaction(function(t) { - for (var i = 0, l = objs.length; i < l; i++) - t.executeSql(ins, insvals[i]) - }, function(e,i){fail(e,i)}, win) + that.db.transaction(function(t) { + for (var i = 0, l = objs.length; i < l; i++) { + // Fixed the issue on id field. + // Numeric id will now save as Integer. Otherwise, it will be saved as String. + ins = "INSERT OR REPLACE INTO " + that.record + " (value, timestamp, id) VALUES (?,?,"; + ins += /\D/.test(insvals[i][2]) ? "'" + insvals[i][2] + "'" : insvals[i][2]; + ins += ")"; + t.executeSql(ins, [insvals[i][0], insvals[i][1]]) + } + }, function(e,i){fail(e,i)}, win) return this }, From 64754ed66b147496f4f23fdbbacaf46ae958a07a Mon Sep 17 00:00:00 2001 From: Nino Paolo Date: Wed, 31 Jul 2013 01:59:25 +0800 Subject: [PATCH 2/6] forgot to add convertInt2String method. --- src/adapters/webkit-sqlite.js | 190 ++++++++++++++++++---------------- 1 file changed, 99 insertions(+), 91 deletions(-) diff --git a/src/adapters/webkit-sqlite.js b/src/adapters/webkit-sqlite.js index 37b1ffb2..2875eeb5 100644 --- a/src/adapters/webkit-sqlite.js +++ b/src/adapters/webkit-sqlite.js @@ -103,96 +103,104 @@ Lawnchair.adapter('webkit-sqlite', (function () { }, get: function (keyOrArray, cb) { - var that = this - , sql = '' - , args = this.isArray(keyOrArray) ? keyOrArray : [keyOrArray]; - // batch selects support - sql = 'SELECT id, value FROM ' + this.record + " WHERE id IN (" + - args.map(function(){return '?'}).join(",") + ")" - // FIXME - // will always loop the results but cleans it up if not a batch return at the end.. - // in other words, this could be faster - var win = function (xxx, results) { - var o - , r - , lookup = {} - // map from results to keys - for (var i = 0, l = results.rows.length; i < l; i++) { - o = JSON.parse(results.rows.item(i).value) - o.key = results.rows.item(i).id - lookup[o.key] = o; - } - r = args.map(function(key) { return lookup[key]; }); - if (!that.isArray(keyOrArray)) r = r.length ? r[0] : null - if (cb) that.lambda(cb).call(that, r) + var that = this + , sql = '' + , args = this.isArray(keyOrArray) ? keyOrArray : [keyOrArray]; + // batch selects support + sql = 'SELECT id, value FROM ' + this.record + " WHERE id IN (" + + args.map(function(){return '?'}).join(",") + ")" + + // converts integer value to string + args = convertInt2String(args); + + // FIXME + // will always loop the results but cleans it up if not a batch return at the end.. + // in other words, this could be faster + var win = function (xxx, results) { + var o + , r + , lookup = {} + // map from results to keys + for (var i = 0, l = results.rows.length; i < l; i++) { + o = JSON.parse(results.rows.item(i).value) + o.key = results.rows.item(i).id + lookup[o.key] = o; } - this.db.readTransaction(function(t){ t.executeSql(sql, args, win, fail) }) - return this - }, - - exists: function (key, cb) { - var is = "SELECT * FROM " + this.record + " WHERE id = ?" - , that = this - , win = function(xxx, results) { if (cb) that.fn('exists', cb).call(that, (results.rows.length > 0)) } - this.db.readTransaction(function(t){ t.executeSql(is, [key], win, fail) }) - return this - }, - - all: function (callback) { - var that = this - , all = "SELECT * FROM " + this.record - , r = [] - , cb = this.fn(this.name, callback) || undefined - , win = function (xxx, results) { - if (results.rows.length != 0) { - for (var i = 0, l = results.rows.length; i < l; i++) { - var obj = JSON.parse(results.rows.item(i).value) - obj.key = results.rows.item(i).id - r.push(obj) - } - } - if (cb) cb.call(that, r) - } - - this.db.readTransaction(function (t) { - t.executeSql(all, [], win, fail) - }) - return this - }, - - remove: function (keyOrArray, cb) { - var that = this - , args - , sql = "DELETE FROM " + this.record + " WHERE id " - , win = function () { if (cb) that.lambda(cb).call(that) } - if (!this.isArray(keyOrArray)) { - sql += '= ?'; - args = [keyOrArray]; - } else { - args = keyOrArray; - sql += "IN (" + - args.map(function(){return '?'}).join(',') + - ")"; - } - args = args.map(function(obj) { - return obj.key ? obj.key : obj; - }); - - this.db.transaction( function (t) { - t.executeSql(sql, args, win, fail); - }); - - return this; - }, - - nuke: function (cb) { - var nuke = "DELETE FROM " + this.record - , that = this - , win = cb ? function() { that.lambda(cb).call(that) } : function(){} - this.db.transaction(function (t) { - t.executeSql(nuke, [], win, fail) - }) - return this - } + r = args.map(function(key) { return lookup[key]; }); + if (!that.isArray(keyOrArray)) r = r.length ? r[0] : null + if (cb) that.lambda(cb).call(that, r) + } + + this.db.readTransaction(function(t){ t.executeSql(sql, args, win, fail) }) + return this + }, + + exists: function (key, cb) { + var is = "SELECT * FROM " + this.record + " WHERE id = ?" + , that = this + , win = function(xxx, results) { if (cb) that.fn('exists', cb).call(that, (results.rows.length > 0)) } + this.db.readTransaction(function(t){ t.executeSql(is, [''+key], win, fail) }) + return this + }, + + all: function (callback) { + var that = this + , all = "SELECT * FROM " + this.record + , r = [] + , cb = this.fn(this.name, callback) || undefined + , win = function (xxx, results) { + if (results.rows.length != 0) { + for (var i = 0, l = results.rows.length; i < l; i++) { + var obj = JSON.parse(results.rows.item(i).value) + obj.key = results.rows.item(i).id + r.push(obj) + } + } + if (cb) cb.call(that, r) + } + + this.db.readTransaction(function (t) { + t.executeSql(all, [], win, fail) + }) + return this + }, + + remove: function (keyOrArray, cb) { + var that = this + , args = this.isArray(keyOrArray) ? keyOrArray : [keyOrArray] + , sql = "DELETE FROM " + this.record + " WHERE id " + , win = function () { if (cb) that.lambda(cb).call(that) } + + if (!this.isArray(keyOrArray)) { + sql += '= ?'; + } else { + sql += "IN (" + + args.map(function(){return '?'}).join(',') + + ")"; + } + + args = args.map(function(obj) { + return obj.key ? obj.key : obj; + }); + + // converts integer value to string + args = convertInt2String(args); + + this.db.transaction( function (t) { + t.executeSql(sql, args, win, fail); + }); + + return this; + }, + + nuke: function (cb) { + var nuke = "DELETE FROM " + this.record + , that = this + , win = cb ? function() { that.lambda(cb).call(that) } : function(){} + this.db.transaction(function (t) { + t.executeSql(nuke, [], win, fail) + }) + return this + } ////// -}})()); +}})()) From d5575cd357e94fbfdabcd19937f0669f363f5f8c Mon Sep 17 00:00:00 2001 From: Nino Paolo Date: Thu, 1 Aug 2013 19:04:16 +0800 Subject: [PATCH 3/6] A fix for indexed-db adapter. This will allow multiple records or object_stores by adding a list value on option.records = []. example: `var options = {adapter:'indexed-db', name:'db_name', record:'objectStore1', records:['objectStore1', 'objectStore2', 'objectStoreN']}` --- src/adapters/indexed-db.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/adapters/indexed-db.js b/src/adapters/indexed-db.js index e0b0d842..3156770e 100644 --- a/src/adapters/indexed-db.js +++ b/src/adapters/indexed-db.js @@ -62,6 +62,7 @@ Lawnchair.adapter('indexed-db', (function(){ }; var upgrade = function(from, to) { + console.log('options: ', options) // don't try to migrate dbs, just recreate try { self.db.deleteObjectStore('teststore'); // old adapter @@ -73,7 +74,16 @@ Lawnchair.adapter('indexed-db', (function(){ // ok, create object store. var params = {}; if (self.useAutoIncrement) { params.autoIncrement = true; } - self.db.createObjectStore(self.record, params); + + if ( options.records ) { + // create multiple records or objectStores + for ( i = options.records.length; i--; ) { + self.db.createObjectStore(options.records[i], params); + } + } else { + // single records + self.db.createObjectStore(self.record, params); + } self.store = true; }; request.onupgradeneeded = function(event) { From 103b9bc8767841d9c7cd46800efdb12ae9053939 Mon Sep 17 00:00:00 2001 From: Nino Paolo Date: Thu, 1 Aug 2013 19:04:16 +0800 Subject: [PATCH 4/6] A fix for indexed-db adapter. This will allow multiple records or object_stores by adding a list value on option.records = []. example: `var options = {adapter:'indexed-db', name:'db_name', record:'objectStore1', records:['objectStore1', 'objectStore2', 'objectStoreN']}` --- src/adapters/indexed-db.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/adapters/indexed-db.js b/src/adapters/indexed-db.js index e0b0d842..694c1fa3 100644 --- a/src/adapters/indexed-db.js +++ b/src/adapters/indexed-db.js @@ -62,6 +62,7 @@ Lawnchair.adapter('indexed-db', (function(){ }; var upgrade = function(from, to) { + console.log('options: ', options) // don't try to migrate dbs, just recreate try { self.db.deleteObjectStore('teststore'); // old adapter @@ -73,7 +74,16 @@ Lawnchair.adapter('indexed-db', (function(){ // ok, create object store. var params = {}; if (self.useAutoIncrement) { params.autoIncrement = true; } - self.db.createObjectStore(self.record, params); + + if ( options.records ) { + // create multiple records or objectStores + for ( i = options.records.length; i--; ) { + self.db.createObjectStore(options.records[i], params); + } + } else { + // single record + self.db.createObjectStore(self.record, params); + } self.store = true; }; request.onupgradeneeded = function(event) { From dbab6196df33d0d55cda1e90248f0423a58309c3 Mon Sep 17 00:00:00 2001 From: Nino Paolo Date: Thu, 1 Aug 2013 19:43:30 +0800 Subject: [PATCH 5/6] remove console.log --- src/adapters/indexed-db.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/adapters/indexed-db.js b/src/adapters/indexed-db.js index 694c1fa3..dd9c0324 100644 --- a/src/adapters/indexed-db.js +++ b/src/adapters/indexed-db.js @@ -62,7 +62,6 @@ Lawnchair.adapter('indexed-db', (function(){ }; var upgrade = function(from, to) { - console.log('options: ', options) // don't try to migrate dbs, just recreate try { self.db.deleteObjectStore('teststore'); // old adapter From 6dac596b456d75a89847d364a57ff1ea3f494491 Mon Sep 17 00:00:00 2001 From: Nino Paolo Date: Thu, 1 Aug 2013 19:52:28 +0800 Subject: [PATCH 6/6] indexed-db multiple records --- src/adapters/indexed-db.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/adapters/indexed-db.js b/src/adapters/indexed-db.js index dd9c0324..a9674bd6 100644 --- a/src/adapters/indexed-db.js +++ b/src/adapters/indexed-db.js @@ -76,7 +76,8 @@ Lawnchair.adapter('indexed-db', (function(){ if ( options.records ) { // create multiple records or objectStores - for ( i = options.records.length; i--; ) { + // option object = {..., records:['objectStore1', 'objectStore2']} + for ( i=options.records.length; i--; ) { self.db.createObjectStore(options.records[i], params); } } else {