Un'interessante novità introdotta con HTML5 è la possibilità di salvare dati permanenti (fino alla prossima pulizia cache del browser) in un database locale tramite comandi SQLite. L'utilizzo diretto di quest'API risulta però piuttosto "scomodo" e ripetitivo, appesantendo quindi il codice con logiche che andrebbero invece raccolte in procedure a più basso livello. Ho quindi sviluppato una classe Javascript che semplifica le operazioni di versioning, scrittura e lettura dei record, in modo da rendere l'API Web SQL Database più fruibile.
/**
* HTML5 Web SQL Database framework
* Author: Stefano Storti
* Licence: GNU General Public License version 3.0 or later <http://www.gnu.org/licenses/gpl-3.0.html>
*/
var db = new function Database() {
this._db = null;
/**
* Open database
*/
this.open = function(name, descr, ver, size) {
if (ver == undefined)
ver = "";
this._db = window.openDatabase(name, ver, descr, size);
}
/**
* Database version
*/
this.version = function() {
return this._db.version;
}
/**
* Execute an SQL command or an array of commands
*/
this.execute = function(sql, onSuccess, onError) {
this._db.transaction(function(tx) {
if (sql.constructor == Array) {
for (i = 0; i < sql.length; i++)
tx.executeSql(sql[i]);
}
else {
tx.executeSql(sql);
}
}, onError, onSuccess);
}
/**
* Execute an SQL query
*/
this.query = function(sql, onSuccess, onError) {
this._db.transaction(function(tx) {
tx.executeSql(sql, [], onSuccess, onError);
}, onError);
}
/**
* Upgrade to new version
* sqlVers = [{ver: "1", sql: "sql command 1"}, {ver: "2.0", sql: "sql command 2.0"}, {ver: "3.1", sql: "sql command 3.1"}, ...]
*/
this.upgrade = function(sqlVers, onSuccess, onError) {
var currentVer = 0;
if (this._db.version)
currentVer = parseFloat(this._db.version);
var sqlExec = new Array();
for (i = 0; i < sqlVers.length; i++) {
var ver = parseFloat(sqlVers[i].ver);
var sql = sqlVers[i].sql;
if (ver > currentVer) {
sqlExec.push(sql);
}
}
var currentVer = this._db.version;
var lastVer = (sqlVers[sqlVers.length - 1]).ver;
if (sqlExec.length > 0) {
this.changeVersion(currentVer, lastVer, sqlExec, onSuccess, onError);
}
}
/**
* Change database version
* sql = single SQL command or array of SQL commands
*/
this.changeVersion = function(oldVer, newVer, sql, onSuccess, onError) {
this._db.changeVersion(oldVer, newVer, function (tx) {
if (sql.constructor == Array) {
for (i = 0; i < sql.length; i++)
tx.executeSql(sql[i]);
}
else {
tx.executeSql(sql);
}
}, onError, onSuccess);
}
/**
* Check whether can use HTML5 SQLite web database
*/
this.webDbImplemented = function() {
return (window.openDatabase != undefined);
}
}
Utilizzo
Creare/aprire un database:
Controllare la versione del database:
Prima creazione:
// Full database creation
var sql = [
"CREATE TABLE BRANDS (id primary key, name)"
, "CREATE TABLE CARS (id primary key, name, brand_id)"
];
// db.changeVersion(oldVer, newVer, sql, onSuccess, onError)
db.changeVersion("", "1", sql,
function() { alert("Database created!"); }, function(err) { alert("Error in database creation: "+err.message); } );
Aggiornamento struttura database:
// Upgrade database (database diff): skip SQL command if current database version >= .ver property
var sqlVers = [
{ver: "2", sql: "ALTER TABLE BRANDS ADD COLUMN country"}
, {ver: "3", sql: "ALTER TABLE CARS ADD COLUMN production_started"}
, {ver: "3", sql: "ALTER TABLE CARS ADD COLUMN production_ended"}
// future upgrades here...
];
// db.upgrade(sqlVers, onSuccess, onError)
db.upgrade(sqlVers, function() { alert("Database upgraded!"); }, function(err) { alert("Error in database upgrade: "+err.message); } );
Esegue un comando o un array di comandi SQL:
var sqlInsert = [
"INSERT INTO BRANDS(id, name, country) VALUES (1, 'Fiat', 'Italy')"
, "INSERT INTO BRANDS(id, name, country) VALUES (2, 'Alfa Romeo', 'Italy')"
, "INSERT INTO CARS(id, name, brand_id, production_started) VALUES (1, '500', 1, 2007)"
, "INSERT INTO CARS(id, name, brand_id, production_started) VALUES (2, 'MiTo', 2, 2008)"
, "INSERT INTO CARS(id, name, brand_id, production_started) VALUES (2, 'Giulietta', 2, 2010)"
];
// db.execute(sql, onSuccess, onError)
db.execute(sql, function() { alert("Database has been populated!"); }, function(err) { alert("Error in executing SQLite command: "+err.message); });
Esegue una query SQL:
// db.query(sql, onSuccess, onError)
db.query('SELECT CARS.name AS car_name, BRANDS.name AS brand_name
FROM CARS INNER JOIN BRANDS ON CARS.brand_id = BRANDS.id
ORDER BY CARS.name',
function(tx, results) {
for (i = 0; i < results.rows.length; i++)
alert('Car:'+results.rows.item(i).car_name+', brand: '+results.rows.item(i).brand_name);
}, function(tx, err) {
alert("Error in executing SQLite query: "+err.message);
}
);
Controlla se l'API Web SQL Database è disponibile:
Ed è tutto! Spero questa libreria possa tornarvi utile!