2014-06-23 17:09:02 +00:00
|
|
|
var FILE_SYSTEM_NAME = require('../constants.js').FILE_SYSTEM_NAME;
|
|
|
|
var FILE_STORE_NAME = require('../constants.js').FILE_STORE_NAME;
|
|
|
|
var WSQL_VERSION = require('../constants.js').WSQL_VERSION;
|
|
|
|
var WSQL_SIZE = require('../constants.js').WSQL_SIZE;
|
|
|
|
var WSQL_DESC = require('../constants.js').WSQL_DESC;
|
|
|
|
var Errors = require('../errors.js');
|
2014-08-16 20:22:41 +00:00
|
|
|
var FilerBuffer = require('../buffer.js');
|
|
|
|
var base64ArrayBuffer = require('base64-arraybuffer');
|
2013-11-27 21:52:52 +00:00
|
|
|
|
2014-06-23 17:09:02 +00:00
|
|
|
function WebSQLContext(db, isReadOnly) {
|
|
|
|
var that = this;
|
|
|
|
this.getTransaction = function(callback) {
|
|
|
|
if(that.transaction) {
|
|
|
|
callback(that.transaction);
|
|
|
|
return;
|
2013-11-29 15:29:04 +00:00
|
|
|
}
|
2014-06-23 17:09:02 +00:00
|
|
|
// Either do readTransaction() (read-only) or transaction() (read/write)
|
|
|
|
db[isReadOnly ? 'readTransaction' : 'transaction'](function(transaction) {
|
|
|
|
that.transaction = transaction;
|
|
|
|
callback(transaction);
|
2013-11-27 21:52:52 +00:00
|
|
|
});
|
|
|
|
};
|
2014-06-23 17:09:02 +00:00
|
|
|
}
|
2014-08-16 20:22:41 +00:00
|
|
|
|
2014-06-23 17:09:02 +00:00
|
|
|
WebSQLContext.prototype.clear = function(callback) {
|
|
|
|
function onError(transaction, error) {
|
|
|
|
callback(error);
|
|
|
|
}
|
|
|
|
function onSuccess(transaction, result) {
|
|
|
|
callback(null);
|
|
|
|
}
|
|
|
|
this.getTransaction(function(transaction) {
|
|
|
|
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME + ";",
|
|
|
|
[], onSuccess, onError);
|
|
|
|
});
|
|
|
|
};
|
2014-08-16 20:22:41 +00:00
|
|
|
|
|
|
|
function _get(getTransaction, key, callback) {
|
2014-06-23 17:09:02 +00:00
|
|
|
function onSuccess(transaction, result) {
|
|
|
|
// If the key isn't found, return null
|
|
|
|
var value = result.rows.length === 0 ? null : result.rows.item(0).data;
|
2014-08-16 20:22:41 +00:00
|
|
|
callback(null, value);
|
2014-06-23 17:09:02 +00:00
|
|
|
}
|
|
|
|
function onError(transaction, error) {
|
|
|
|
callback(error);
|
|
|
|
}
|
2014-08-16 20:22:41 +00:00
|
|
|
getTransaction(function(transaction) {
|
|
|
|
transaction.executeSql("SELECT data FROM " + FILE_STORE_NAME + " WHERE id = ? LIMIT 1;",
|
2014-06-23 17:09:02 +00:00
|
|
|
[key], onSuccess, onError);
|
|
|
|
});
|
2014-08-16 20:22:41 +00:00
|
|
|
}
|
|
|
|
WebSQLContext.prototype.getObject = function(key, callback) {
|
|
|
|
_get(this.getTransaction, key, function(err, result) {
|
|
|
|
if(err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
if(result) {
|
|
|
|
result = JSON.parse(result);
|
|
|
|
}
|
|
|
|
} catch(e) {
|
|
|
|
return callback(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
callback(null, result);
|
|
|
|
});
|
2014-06-23 17:09:02 +00:00
|
|
|
};
|
2014-08-16 20:22:41 +00:00
|
|
|
WebSQLContext.prototype.getBuffer = function(key, callback) {
|
|
|
|
_get(this.getTransaction, key, function(err, result) {
|
|
|
|
if(err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
2014-08-16 21:02:18 +00:00
|
|
|
// Deal with zero-length ArrayBuffers, which will be encoded as ''
|
|
|
|
if(result || result === '') {
|
2014-08-16 20:22:41 +00:00
|
|
|
var arrayBuffer = base64ArrayBuffer.decode(result);
|
|
|
|
result = new FilerBuffer(arrayBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
callback(null, result);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
function _put(getTransaction, key, value, callback) {
|
2014-06-23 17:09:02 +00:00
|
|
|
function onSuccess(transaction, result) {
|
|
|
|
callback(null);
|
|
|
|
}
|
|
|
|
function onError(transaction, error) {
|
|
|
|
callback(error);
|
|
|
|
}
|
2014-08-16 20:22:41 +00:00
|
|
|
getTransaction(function(transaction) {
|
2014-06-23 17:09:02 +00:00
|
|
|
transaction.executeSql("INSERT OR REPLACE INTO " + FILE_STORE_NAME + " (id, data) VALUES (?, ?);",
|
|
|
|
[key, value], onSuccess, onError);
|
|
|
|
});
|
2014-08-16 20:22:41 +00:00
|
|
|
}
|
|
|
|
WebSQLContext.prototype.putObject = function(key, value, callback) {
|
|
|
|
var json = JSON.stringify(value);
|
|
|
|
_put(this.getTransaction, key, json, callback);
|
|
|
|
};
|
|
|
|
WebSQLContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback) {
|
|
|
|
var base64 = base64ArrayBuffer.encode(uint8BackedBuffer.buffer);
|
|
|
|
_put(this.getTransaction, key, base64, callback);
|
2014-06-23 17:09:02 +00:00
|
|
|
};
|
2014-08-16 20:22:41 +00:00
|
|
|
|
2014-06-23 17:09:02 +00:00
|
|
|
WebSQLContext.prototype.delete = function(key, callback) {
|
|
|
|
function onSuccess(transaction, result) {
|
|
|
|
callback(null);
|
|
|
|
}
|
|
|
|
function onError(transaction, error) {
|
|
|
|
callback(error);
|
|
|
|
}
|
|
|
|
this.getTransaction(function(transaction) {
|
|
|
|
transaction.executeSql("DELETE FROM " + FILE_STORE_NAME + " WHERE id = ?;",
|
|
|
|
[key], onSuccess, onError);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-11-27 21:52:52 +00:00
|
|
|
|
2014-06-23 17:09:02 +00:00
|
|
|
function WebSQL(name) {
|
|
|
|
this.name = name || FILE_SYSTEM_NAME;
|
|
|
|
this.db = null;
|
|
|
|
}
|
|
|
|
WebSQL.isSupported = function() {
|
|
|
|
return !!global.openDatabase;
|
|
|
|
};
|
2013-11-27 21:52:52 +00:00
|
|
|
|
2014-06-23 17:09:02 +00:00
|
|
|
WebSQL.prototype.open = function(callback) {
|
|
|
|
var that = this;
|
|
|
|
|
|
|
|
// Bail if we already have a db open
|
|
|
|
if(that.db) {
|
2014-08-21 00:53:01 +00:00
|
|
|
return callback();
|
2013-11-27 21:52:52 +00:00
|
|
|
}
|
|
|
|
|
2014-06-23 17:09:02 +00:00
|
|
|
var db = global.openDatabase(that.name, WSQL_VERSION, WSQL_DESC, WSQL_SIZE);
|
|
|
|
if(!db) {
|
|
|
|
callback("[WebSQL] Unable to open database.");
|
|
|
|
return;
|
|
|
|
}
|
2013-11-27 21:52:52 +00:00
|
|
|
|
2014-06-23 17:09:02 +00:00
|
|
|
function onError(transaction, error) {
|
|
|
|
if (error.code === 5) {
|
|
|
|
callback(new Errors.EINVAL('WebSQL cannot be accessed. If private browsing is enabled, disable it.'));
|
2013-11-27 21:52:52 +00:00
|
|
|
}
|
2014-06-23 17:09:02 +00:00
|
|
|
callback(error);
|
|
|
|
}
|
|
|
|
function onSuccess(transaction, result) {
|
|
|
|
that.db = db;
|
2014-08-21 00:53:01 +00:00
|
|
|
callback();
|
2014-06-23 17:09:02 +00:00
|
|
|
}
|
2013-11-29 15:29:04 +00:00
|
|
|
|
2014-06-23 17:09:02 +00:00
|
|
|
// Create the table and index we'll need to store the fs data.
|
|
|
|
db.transaction(function(transaction) {
|
|
|
|
function createIndex(transaction) {
|
|
|
|
transaction.executeSql("CREATE INDEX IF NOT EXISTS idx_" + FILE_STORE_NAME + "_id" +
|
|
|
|
" on " + FILE_STORE_NAME + " (id);",
|
|
|
|
[], onSuccess, onError);
|
2013-11-27 21:52:52 +00:00
|
|
|
}
|
2014-06-23 17:09:02 +00:00
|
|
|
transaction.executeSql("CREATE TABLE IF NOT EXISTS " + FILE_STORE_NAME + " (id unique, data TEXT);",
|
|
|
|
[], createIndex, onError);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
WebSQL.prototype.getReadOnlyContext = function() {
|
|
|
|
return new WebSQLContext(this.db, true);
|
|
|
|
};
|
|
|
|
WebSQL.prototype.getReadWriteContext = function() {
|
|
|
|
return new WebSQLContext(this.db, false);
|
|
|
|
};
|
2013-11-27 21:52:52 +00:00
|
|
|
|
2014-06-23 17:09:02 +00:00
|
|
|
module.exports = WebSQL;
|