2010年9月10日金曜日

Safariのtransaction

SafariのopenDatabase」の項目に引き続いて、以下のURLにあるSafariのデータベースの解説を見ていきたいと思います。

Safari Client-Side Storage and Offline Applications Programming Guide: Introduction
http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Introduction/Introduction.html

Safariのデータベースで面倒なのが"Listing4-2 CreatingaSQLtable"にあるようなトランザクション処理の関数です。"Listing4-2 CreatingaSQLtable"にある最初のトランザクションは「SafariのopenDatabase」の項目にあるように他の関数に移し、すでにデータがある場合の処理は別にしたとして、データベースに初期データを入れる部分を抜き書きして、さらに初期データを一つだけにすると以下のようになります。

function createTables()
{
 db.transaction(
  function (transaction) {
   transaction.executeSql('insert into people 
    (name, shirt) VALUES ("Joe", "Green");',
    [], nullDataHandler, errorHandler);
  }
 );
}

関数内の最初の二行で、データベースのオブジェクト db のメソッドである transaction に関数を渡しています。渡した関数の引数がオブジェクトになっていて、そのオブジェクトのメソッドである executeSql でSQL命令を発効しています。
これだけでもチョット面倒ですが、さらに面倒なことに executeSql メソッドの引数が四つあって、その内の二つが関数で、その二つの関数がくせ者です(苦笑)

そのくせ者の前に注意しなくてはならないのが transaction です。 db.transaction とその後の transaction は別物です。 function(transaction)transaction.executeSqltransaction は同じ変数で、その名前は transaction である必要はなく、 myTransaction などの他の変数名でも動作します。ここで同じ名前を使用しなくてはならない理由が私には思い付かず、サンプルコードとしては誤解を招きやすい解説だと思います。私は実際のコードを書く場合でも、後から調べることを考えて別名にしています。

閑話休題、もとの「くせ者」の話に戻しましょう。この二つの関数は一方通行で、行ったまま戻ってきませんし、引数を渡すこともできません。呼び出される関数の引数は二つのオブジェクトと決まっています。マウスなどのイベントを処理するメソッド addEventListener に近い感じです。また、話しを脱線させると・・・個人的な経験を元にした推測にしか過ぎませんが、おそらくトランザクション処理をするために非同期コールを組み込む必要が出てこのような面倒なことをしているのではないか?と思っています。

さて、 executeSql メソッドの第一引数と第二引数はC言語の printf 関数のようなイメージで使用しますが、変数が多くなると高い確率で間違います・・・つまり、私は間違いました(笑)また、初期化に限らず似たような処理を繰り返し実行することは良くあります。そこで私は「SafariのopenDatabase」の項目にあるSQL文の書き方にもう少し手を加えた方法を利用しています。一つの参考としてご紹介します。

function createTables()
{
 var nameShirt = {    
  "Joe": "Green",
  "Mark": "Blue",
  "Phil": "Orange",
  "jdoe": "Purple"
 }
 db.transaction(
  function (trans) {
   for(var index in nameShirt) {
    var mySQL = 'insert into people (name, shirt) VALUES ("' +
     index +
     '", "' +
     nameShirt[index] +
     '");';
    trans.executeSql(mySQL, [], nullDataHandler, errorHandler);
   }
  }
 );
}

上記の方法をさらに手を加えると、複数のテーブルを扱う時に便利になります。私は、object literalとArrayオブジェクトを組み合わせて、データベースの構造を宣言して、SQL文のテーブルの宣言部分を書いています。

以上のように関数の中に関数が多重で入っており書きにくく、読みにくく、間違いやすい構文になっています。このために、"Listing 4-5 SQL insert query example"にあるような書き方は、面白いとは思いますが・・・関わりになるのは避けたいです(苦笑)

0 件のコメント: