ryu1
9/9/2013 - 9:10 AM

1-Initial schema.js

// created by Max Aller <nanodeath@gmail.com>
function Migrator(db){
  var migrations = [];
  this.migration = function(number, func){
    migrations[number] = func;
  };
  var doMigration = function(number){
    if(migrations[number]){
      db.changeVersion(db.version, String(number), function(t){
        migrations[number](t);
      }, function(err){
        if(console.error) console.error("Error!: %o", err);
      }, function(){
        doMigration(number+1);
      });
    }
  };
  this.doIt = function(){
    var initialVersion = parseInt(db.version) || 0;
    try {
      doMigration(initialVersion+1);
    } catch(e) {
      if(console.error) console.error(e);
    }
  }
}
var db = openDatabase("example_db", "", "Example Database", 100000);

var M = new Migrator(db);
M.migration(1, function(t){
  t.executeSql("create table foo...");
});
M.migration(2, function(t){
  t.executeSql("alter table foo...");
});
M.migration(3, function(t){
  t.executeSql("create table foo2...");
});

M.doIt();

// db.version is now "3".  Migrations will be executed in numerical order until a "blank" is hit.  You /can/ define migrations 1, 2, and 4, if you want, but only 1 and 2 will be executed.  More error handling could be introduced to counter this, if one wanted (validating either on the #migration method or the #doIt method.
var db = openDatabase("example_db", "", "Example Database", 100000);

if(db.version == ""){
  db.changeVersion("", "1", function(t){
    t.executeSql("create table foo...");
  }, null /* error callback */, function(){
    // success callback
    db.changeVersion("1", "2", function(t){
      t.executeSql("alter table foo...");
    });    
  });
}

if(db.version == "1"){
  db.changeVersion("1", "2", function(t){
    t.executeSql("alter table foo...");
  });
}

// Or... Migrations v3

function migration1(t){ t.executeSql("create table foo...") }
function migration2(t){ t.executeSql("alter table foo...") }
function migration3(t){ t.executeSql("create table foo2...") }

if(db.version == ""){
  db.changeVersion("", "1", migration1, null, function(){
    db.changeVersion("1", "2", migration2, null, function(){
      db.changeVersion("2", "3", migration3);
    });
  });
}

if(db.version == "1"){
  db.changeVersion("1", "2", migration2, null, function(){
    db.changeVersion("2", "3", migration3);
  });
}

if(db.version == "2"){
  db.changeVersion("2", "3", migration3);
}
var db = openDatabase("example_db", "", "Example Database", 100000);

if(db.version == ""){
  db.changeVersion("", "1", function(t){
    t.executeSql("create table ...");
  });
}

if(db.version == "1"){
  db.changeVersion("1", "2", function(t){
    t.executeSql("alter table ...");
  });
}
var db = openDatabase("example_db", "", "Example Database", 100000);
// empty version string means "I don't care what version the db is"

if(db.version == ""){
  db.changeVersion("", "1", function(t){
    t.executeSql("create table ...");
  });
}
var db = openDatabase("example_db", "", "Example Database", 100000);
// openDatabase(db name, required version (blank string for n/a), human-readable database name, expected size in bytes)

db.changeVersion("", "1", function(t){
  t.executeSql("create table ...");
});

/* Note:
openDatabase actually takes one more (optional) argument -- a callback in case the database was /just/ created, for you to call changeVersion and provide an initial schema.  However, since this post is more interested in migrations, and because I don't want the initial migration to be a "special case", I'm pretending like it doesn't exist.  It's there if you want it, of course.
*/