SQLiteデータベースのバージョンを変更する

iPhone アプリで利用している SQLite のスキーマを変更する必要に迫られ開発中に予期せぬ出来事があった。具体的にはテーブルに一列追加する changeVersion という関数を利用する際に必ずバージョンがマッチしないというエラーを出力するというものだ。

success callback である第五引数内でもoj.versionがoldVersionを返すのが気になります、、、。リロードするとようやくnewVersionに変わるんですけれど、これで良いのかなぁ。

引用元: JavaScript++かも日記: 【iPhone】iPhone用 JavaScriptデータベースプログラミング入門 (6).

Safari の JavaScript のデバッガでこの問題を確認し回避策を模索していたところ、Apple の文書に次のような回答を見つけた。

Unfortunately, the only way for your code to see the new version number is by closing the browser window. If you get an error code 2 (see “Error Codes”) and the database version you passed in for the old version matches the version in db.version, you should either assume that the version change already happened or display an alert instructing the user to close and reopen the browser window.

引用元: Safari Dev Center: Safari Client-Side Storage and Offline Applications Programming Guide: Using the JavaScript Database.

結局のところ挙動は問題ないのだけど、ブラウザを閉じるか再読み込みしないと利用者に反映されないということで、次のようなコードにして iPhone の UIWebView 用に移植する前段階として一旦作業を終えることにした。

try {
  if (window.openDatabase) {
  // db = openDatabase("BackgammonPositionsDB", "1.0", "Backgammon Positions DB", 200000); /* 現行バージョンの記述 */
  db = openDatabase("BackgammonPositionsDB", "2.0", "Backgammon Positions DB", 200000);2.0バージョンは開けずエラーをキャッチするので通常の処理は省略)
} catch(e) {
  if (e.code == DOMException.INVALID_STATE_ERR) { // Version number mismatch.
    var prevdb = openDatabase("BackgammonPositionsDB", "1.0", "Backgammon Positions DB", 200000);
    prevdb.changeVersion("1.0","2.0", 
      function(tx){
        tx.executeSql('ALTER TABLE BGPositions ADD COLUMN crawford INTEGER default 0;VACUUM;');}, 
        function(error){ /* SQLエラー処理 */ }, 
        function(){ /* 成功後初期化処理 */ });
    return;
  }
  alert("Unknown error " + e + ".");
}

またこの検証作業に関して SQLite のバージョンを戻す(1.0 に下げる)必要があり、前述した Apple の文書にもある ~/Library/Safari/Databases/ にあるファイルを削除して Safari を再起動するという若干面倒な手続きを取るしか方法がないので、Rails のような管理手法を Automator や AppleScript で作ることが望ましい気がした。

実際の iPhone 上の UIWevView ではどのような挙動になるのか、悩ましいことになるようであれば追って報告しようと思う。

投稿者: hkitago

個人事業主でウェブと iOS, Android アプリの開発者で一児の父親兼ポケモンGOトレーナー。JavaScript, ActionScript, AppleScript, PHP, SQL, ObjC, Swift, Java の読書実行試験運用管理を生業とし、Bind, Postfix, Apache を MacOS で使い、エディタは Vi, mi, Kod, Smultron, TextWrangler を経て Coda, Xcode, Android Studio といった IDE と CotEditor を重用しています。トレーナーコード: 249158576842