Skip to content

Instantly share code, notes, and snippets.

@anzfactory
Last active December 4, 2015 17:43
Show Gist options
  • Save anzfactory/8b06414037df9ed1bf62 to your computer and use it in GitHub Desktop.
Save anzfactory/8b06414037df9ed1bf62 to your computer and use it in GitHub Desktop.
SQLite差分アップデート(SQLiteUnityKit版)
/*********************************
SQLiteのdbを差分アップデートする奴
2015-12-04
*********************************/
using System.Collections.Generic;
using UnityEngine;
public class SqliteMigration
{
private SqliteDatabase dbInstance;
private string dbPath;
public SqliteMigration(SqliteDatabase db, string path)
{
this.dbInstance = db;
this.dbPath = path;
}
public void Migrate()
{
// 現在のDBバージョンを読み込む
int currentVersion = GetCurrentVersion();
Debug.Log("current db version:" + currentVersion);
// 差分アップデート用のファイルがあるかサーチ
var sqlList = SearchMigrateSql(currentVersion);
if (sqlList.Count == 0) {
// アップデート必要なし
Debug.Log("cancel migrate");
return;
}
Debug.Log("do migrate files:" + sqlList.Count);
// version 順に適用していかないと矛盾が生じる可能性があるので昇順ソート
var versions = new List<int>(sqlList.Keys);
versions.Sort();
// バックアップをとっておく
string backupPath = Backup();
Debug.Log("backup path:" + backupPath);
try {
string sql = "";
foreach (int ver in versions) {
sql = sqlList[ver];
this.dbInstance.ExecuteScript(sql);
}
// 最後にバージョンアップ(最終バージョンに)
sql = string.Format("update `version_info` set `version` = {0}", Last<int>(versions.ToArray()));
this.dbInstance.ExecuteNonQuery(sql);
} catch (System.Exception e) {
// リストア
Restore(backupPath);
// 失敗したら普通にアプリ実行させたところでアカンので終了
// TODO なんかアラートとかだしたいけど...
// throw e; 例外スローしてもアプリおちないので....
Application.Quit(); // 自分でおとす
}
}
private int GetCurrentVersion()
{
string sql = "select `version` from `version_info`";
var dt = this.dbInstance.ExecuteQuery(sql);
if (dt == null || dt.Rows.Count == 0) {
throw new SqliteMigrationException("DBにバージョン情報が存在しないようです");
}
return int.Parse(dt.Rows[0]["version"].ToString());
}
private Dictionary<int, string> SearchMigrateSql(int currentVersion)
{
Dictionary<int, string> sqlList = new Dictionary<int, string>();
int searchVersion = currentVersion;
searchVersion++;
string sql = "";
// .sqlファイル検索する
while (ReadFile(searchVersion, out sql)) {
sqlList.Add(searchVersion, sql);
searchVersion++;
}
return sqlList;
}
private string Backup()
{
string tempPath = System.IO.Path.Combine(Application.temporaryCachePath, "backup.db");
if (this.dbPath.Contains("://") || tempPath.Contains("://")) {
WWW www = new WWW(this.dbPath);
while (!www.isDone) {
// 待機
}
System.IO.File.WriteAllBytes(tempPath, www.bytes);
} else {
System.IO.File.Copy(this.dbPath, tempPath, true); // 第3引数は上書可能かどうか
}
return tempPath;
}
private void Restore(string backupPath)
{
if (this.dbPath.Contains("://") || backupPath.Contains("://")) {
WWW www = new WWW(backupPath);
while (!www.isDone) {
// 待機
}
System.IO.File.WriteAllBytes(this.dbPath, www.bytes);
} else {
// バックアップファイルから上書き
System.IO.File.Copy(backupPath, this.dbPath, true); // 第3引数は上書可能かどうか
}
}
private bool ReadFile(int searchVersion, out string sql)
{
string path = System.IO.Path.Combine(
Application.streamingAssetsPath,
searchVersion.ToString() + ".sql"
);
Debug.Log(path);
if (path.Contains("://")) {
// Android だと System.IOでよみこめないのでwww使うみたい
// http://answers.unity3d.com/questions/210909/android-streamingassets-file-access.html
sql = ReadFileByWWW(path);
} else {
sql = ReadFileByIO(path);
}
return !string.IsNullOrEmpty(sql);
}
private string ReadFileByWWW(string path)
{
WWW www = new WWW(path);
while (!www.isDone) {
// 読み込みが終わるまで待機
}
string text = "";
if (string.IsNullOrEmpty(www.error)) {
text = www.text;
} else {
Debug.Log(www.error);
}
return text;
}
private string ReadFileByIO(string path)
{
string text = "";
if (System.IO.File.Exists(path)) {
text = System.IO.File.ReadAllText(path);
}
return text;
}
private T Last<T>(T[] arr)
{
if (arr == null || arr.Length == 0) {
return default(T);
}
return arr[arr.Length - 1];
}
}
public class SqliteMigrationException : System.Exception
{
public SqliteMigrationException (string message) : base(message)
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment