Database Events (5)

処理速度はともかく、Database Events は、field の value 属性に実際のデータを保存します。用語辞書を見ると value 属性は値に anything と記述されています。SQLite は、バージョン 3 になって一応型が定義されています。本当に何でも value に設定できるのか試してみます。

ここまでで文字列と数値(実数、整数)がそのまま保存できるのは分かっています。前回、特に断っていなかったのですが、AppleScript の date も保存できています。value 属性を読み込むと date 型の値が返ってきます。

では、他のものではどうなるでしょうか。ということで以下のスクリプト。

Script Editor で開く

read file ((path to pictures folder as Unicode text) & "Safari.tiff") as data

AppleScript のいろんなデータを保存してみました。結論から言うと、上記スクリプトの中で保存、再読み込みが可能なのは date クラスと真偽値だけです(エラーにならないのですが、返ってくる値が一律 false になります)。alias 参照は、保存できますが読み込んだときにスラッシュ区切りの POSIX path に変換されてしまいます。

AppleScript の参照も保存できません。ということは、ある field の value に他のデータベースの field の参照をいれておくこともできません。その field を参照すると他のデータベースの field にアクセスするというようなことは無理ですね(というか、それは無茶)。

文字列で保存できるならほとんどの状況でどんなデータも保存できるので困ることもないと思います。それでも、リストやレコードなんかは内部で変換でもして保存して欲しい気もします。まぁ、多くの場合、画像を as data で保存することなんてないでしょうし、画像ファイルのパス文字列が保存できればそれでいいでしょう。リストもレコードも保存方法を考えると解決できるものです。ハンドラやスクリプトオブジェクトをそのまま保存できるなら、ハンドラデータベースが構築できると思ったのですが、これも文字列にしておけばいいですね。

そんなわけでデータベースに保存しておくのは文字列と数値にしておくのが無難です。

データベースの名前ですが、これは日本語も使えます。

Script Editor で開く

set manList to {{"山本", "浩二"}, {"金本", "雅次"}, {"園山", "香織"}, {"井上", "雅子"}}

tell application "Database Events"
    make new database with properties {name:"交友録"}
    tell database "交友録"
        repeat with i from 1 to count manList
            set recordValue to item i of manList as Unicode text
            set theRecord to make new record with properties {name:recordValue}
            tell theRecord
                make new field with properties {name:"姓", value:item 1 of (item i of manList)}
                make new field with properties {name:"名", value:item 2 of (item i of manList)}
            end tell
        end repeat
        save
    end tell
end tell

このようにして field にも日本語を利用することができます。もちろん以下のように取得も可能です。

Script Editor で開く

set theFolder to path to documents folder as Unicode text
set databaseFile to POSIX path of (theFolder & "データベース:交友録")

tell application "Database Events"

    tell database databaseFile
        name of records
        -- {"山本浩二", "金本雅次", "園山香織", "井上雅子"}
        value of field "姓" of records
        -- {"山本", "金本", "園山", "井上"}
        value of fields of (records whose value of field "名" of it contains "子")
        -- {"井上雅子", "井上", "雅子"}
    end tell
end tell

Database Events は、できたてのアプリケーションでまだまだ不安定なのか、よく反応が返ってこないことがあります。そんなときは、一度終了するともとに戻ります(System Events もですが...)。

Script Editor で開く

tell application "Database Events" to quit

また、単に処理に手間取ってなかなか結果が返ってこないこともあるので with timeout でタイムアウトも設定しておく方がいいかもしれません。

これまで長々と見てきましたが、Database Events は AppleScript で SQLite の全機能が利用できるということではなく、単純な行と列だけで表現する簡易データベースという感じです。機能的には新しい行の追加と削除ぐらいしかできないようで、行の並べ替えなんかは無理です(以前、例として載せたようなソートではなく、record をそのまま並べ替えることです)。並べ替えは実際にデータを表示するときに行えばいいのでそれほど問題はないですが、それだけコードが長くなるので、できれば実装して欲しいところです。

また、Database Events は、その用意されている用語からも分かるようにデータベースの中に複数の table を作ることもできません。プライマリーキーを設定してリレーショナルデータベースというのも(確証はないのですが、おそらく)できないでしょう。もちろん、SQLite でなら可能です。あれ? テーブルを指定できないということは、CoreData アプリケーションが保存した SQL フォーマットのデータベースも読むことができない、ということですね? ...できませんでした。。。てっきり、連携できると思っていたのですが。この辺りのことに期待していた人には悪い知らせです。すいません。

Terminal から sqlite3 コマンドを使うと分かるのですが、Database Events で作成したデータベースは、ZFIELD、ZRECORD、Z_METADATA、Z_PRIMARYKEY と 4 つのテーブルを持っています(midore さんに情報をいただきました。ありがとうございました)。ZFIELD で field が、ZRECORD で record が管理されているようです。Database Events は、これらのテーブルの内容を解析してデータを返しているようです。一方、CoreData アプリケーションが保存した SQL フォーマットのファイルもいくつかテーブルが作成されています。Developer Tools の CoreData のサンプルアプリケーション、OutlineEdit は次のようなテーブルを持っていました。ZNOTE、ZPRIORITY、Z_METADATA、Z_PRIMARYKEY。メタデータとプライマリーキーのテーブルは共通しています。こういうデータベースの作られ方というのは、CoreData を利用するときに特有のものなのでしょね(CoreData の資料にいい加減目を通さないと...)。

実際のところ、Database Events でデータベースを利用するためには、Database Events で利用できるデータ構成でないと駄目なのでしょう。sqlite3 を使えばどのアプリケーションが保存したデータベースも操作できるのですが、CoreData アプリケーションのデータベースを Database Events で利用することはできないということですね。

最後に。掲示板の方で Perl のハッシュのような使い方ができれば...とありました(TUNA さん。ありがとうございます)。ハッシュって連想配列ですよね? Perl 特有のデータ型の。Objective-C でいうところの辞書(NSDictionary)ですね。AppleScript で言えばレコード。あれは、Perl らしい使い方がいろいろと用意されていて便利ですね。Database Events で代用しようと思えば...、単純に record の name 属性をキーにして field をひとつ追加してその中にデータを入れておけばいいのでは? たとえば、次のような感じです。

Script Editor で開く

--すでに Hash.dbev というデータベースがある
set theFolder to path to documents folder as Unicode text
set databaseFile to POSIX path of (theFolder & "データベース:Hash.dbev")

--データの追加
my addRecord(databaseFile, "整数", 10)
my addRecord(databaseFile, "実数", pi)
my addRecord(databaseFile, "文字列", "我が輩は猫である")
my addRecord(databaseFile, "日付", current date)
--データの取得
getData(databaseFile, "整数")
--データの変更
setData(databaseFile, "文字列", "気は優しくて力持ち")
--キーの一覧を取得
keys(databaseFile)
--キーとデータをリストで取得
each(databaseFile)

on addRecord(databaseFile, keyStr, theData)
    tell application "Database Events"
        tell database databaseFile
            set theRecord to make new record with properties {name:keyStr}
            tell theRecord
                make new field with properties {name:"value", value:theData}
            end tell
            save
        end tell
    end tell
end addRecord

on setData(databaseFile, keyStr, newData)
    tell application "Database Events"
        tell database databaseFile
            set value of field "value" of record keyStr to newData
            save
        end tell
    end tell
end setData

on getData(databaseFile, keyStr)
    tell application "Database Events"
        tell database databaseFile
            set theResult to value of field "value" of record keyStr
        end tell
    end tell

    return theResult
end getData

on keys(databaseFile)
    tell application "Database Events"
        tell database databaseFile
            set theResult to name of records
        end tell
    end tell

    return theResult
end keys

on values(databaseFile)
    tell application "Database Events"
        tell database databaseFile
            set theResult to value of field "value" of records
        end tell
    end tell

    return theResult
end values

on each(databaseFile)
    tell application "Database Events"
        set theResult to {}
        tell database databaseFile
            set end of theResult to name of records
            set end of theResult to value of field "value" of records
        end tell
    end tell

    return theResult
end each

これでは使えるデータが文字列と数値のみですが。リストやレコードに対応すればもう少し便利に使えるかも。

0 件のコメント :

コメントを投稿