node-webkit中數據庫升級機制

寫了個模塊,本模塊中應用了sqllite3數據庫,升級原理是檢查數據庫的version版本表中版本值,把版本值加一以後去讀取對應的sql文件,執行sql語句,而後依次循環說取下一個文件直到完成。sql

模塊中全部sql文件放在/sql/文件夾下,如:contact_create.sql,contact_update_1.sql,contact_update_2.sql,等等,使用時執行 updateUserDB()方法就行。數據庫

var _=require("underscore");
var sqlite3 = require('sqlite3').verbose();
var fs = require('fs');
var async = require("async");
var path=require("path");

EnvironmentDAO = function(){
var DB={},dbNames=["contact","groups","message"];//for example 
//初始化
var init = function(){
    _.each(dbNames,function(name){
	DB[name]=new sqlite3.Database(path.join("/main/db",name+'.db'), sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE)
    });
};
init();
// 檢查數據庫是否爲空
this.checkDB = function(db,callback){			
	db.get("SELECT count(*) as exist FROM sqlite_master WHERE type='table' AND name='version'",function(err,result){
		if(err){
			console.error("checkDB error",err);
			callback(null,false);
		}else{
			if(result.exist == 1){
				callback(null,true);
			}else{
				callback(null,false);
			}
		}					
	});					
};	
// 通用初始化數據庫
this.initDbCommon = function(db,dbName,callback){
	var self=this;
	var sql = fs.readFileSync('/sql/'+dbName+"_create.sql", 'utf8');			
	db.exec(sql,function(err,result){
		if(err){
			console.error("create DB error",dbName,err)
		}
		callback&&callback(err,result)
	});
};
// 通用獲取數據庫版本
this.getDbVersionCommon = function(db,callback){			
	db.get("SELECT version from version where key = 'db_version'",function(err,result){
		if(err){
			console.error("getDbVersion err",err);
		}
		callback&&callback(err,result);
	})				
};		
// 通用升級數據庫
this.updateDbCommon = function(db,dbName,callback){  			
	var self = this;
	var doUpdate = function(cb){
		self.getDbVersionCommon(db,function(err,dbv){
			if(err||!dbv){
				console.error("getDbVersion err ",dbName,dbv,err);
				//沒有表或表名錯誤時從新建立表--容錯機制
				if(err.code == "SQLITE_ERROR"){
					self.initDbCommon(db,dbName,function(err){
					if(!err){
						self.updateDbCommon(db,dbName,function(err){
	        				if(err){
	        					console.error("second time Init and UPdate DB error",dbName,err);
	        				}
	        				cb(true);				        				
	        			});
					}	
	    			})
				}else{
				//其它錯誤忽略
					cb(false)
				}						
			}else{
				var v = dbv.version;
				v++;
	        	if(fs.existsSync('/sql/'+dbName+"_update_"+v+'.sql')){
					var sql = fs.readFileSync('/sql/'+dbName+"_update_"+v+'.sql', 'utf8');
	    			db.exec(sql,function(err){
	    				if(err){
	    					console.error("updateDbCommon err:",dbName,sql,err);
	    					cb(false);
	    				}else{
	    					cb(true);
	    				}
	    			});
	        	}else{
	        		cb(false);
	        	}
			}					
		});
	}
	doUpdate(function(tryAgain){
		if(tryAgain){
			doUpdate.apply(this,[arguments.callee]);
		}else{
			if(typeof callback =="function") callback();
		}
	});			
};
// 升級全部用戶數據庫
this.updateUserDB=function(callback){			
	var self = this;
	async.forEach(
	  dbNames, 
	  function(dbname,cb){
	  	self.checkDB(DB[dbname],function(err,isExist){
	  		if(isExist){
	        		self.updateDbCommon(DB[dbname],dbname,cb);
	    		}else{
	    			self.initDbCommon(DB[dbname],dbname,function(){
	        			self.updateDbCommon(DB[dbname],dbname,cb);
	    			})
	    		}
	  	})
	  }, 
	  function(err){
	    if(err){
	      logger.error("updateUserDB Error:",err);
	    }
      	if(typeof callback =="function") {
			callback(err);	
		}
	  }
	);
};
}

exports = module.exports = new EnvironmentDAO();
相關文章
相關標籤/搜索