My First NSBasic


4. 思ったより簡単にデータベースが使えたから、沖まで船を出そう

Palm 上のファイルは、パーソナル コンピュータ上のファイルとは、扱い方が違います。データは「データベース」に記録されます。この『データベース』っていう言葉が誤解を招くんですよね。

それじゃ SQL でクエリを書けばいいのかって?違うってば。

多分、汎用機のデータ レコードみたいな感じでしょう。Palm のデータベースについては NSBasic のハンドブックに書かれていますので、それを参考にされるとよいと思います。データベースはアプリケーションと同じクリエータ ID を持つ、*.pdb ファイルです。アプリケーションは *.prc として Palm のラウンチャでアイコンが表示されますが、*.pdb は表示されないので、一般ユーザなどは知らないかもしれません。
データベースのデータはバイトの並びでしかなく、例えば、お小遣い帳みたいなアプリケーションで扱うデータとして「日付」と「ナンバー」と「金額」をそれぞれ変数に定義して

  Time + Integer + Double

という形のデータを考えたとすると、これは実際にデータベースに格納される時に

  8 byte + 4 byte + 8 byte

という、トータル 20 byte のレコード サイズを持つデータになるわけですね。

NSBasic で *.pdb ファイルを扱う時には、ふたつのアクセスの仕方があります。

  1) キーを使わない読み書き
  2) キーを使う読み書き

キーを使わない方法だと、目的のレコードを読み出す時にはレコードを一つ一つ調べなくてはなりません。CodeWarrior ってこの方法しかないんですよね。ああ、面倒だ。これに対してキーを使う場合は、それぞれのフィールドにユニークな ID としてキーを割り当てて読み書きをするため、上記の「ナンバー」フィールドをキーに使うと、データベースのレコード全てを調べる必要はなく、「ナンバー」フィールドにある目的のキーを取り出すだけです。とりあえずサンプルを参考にしながらやってみましょう。

NSBasic の IDE を立ち上げます。



このように画面を作ってみました。メモ帳ではなく「一言コメント帳」ですね。まず、キーとなるナンバーを入れるフィールドを「key field」と、タイトルを入れるフィールドを「title field」。そしてコメントを入れる「body field」を作成します。ラベルもつけました。下には、テストのためにボタンを 3 つ作ります。

    OPEN = データベースを開くボタン
    Add = データを追加する書き込みボタン
    Find = キーでデータを検索するボタン

う〜ん、余り役に立ちそうにもないけど、まっ、いいか。
ここではこのアプリケーションのクリエータ ID を「skyF」にしました(Skyfisher からつけました。関係ないけど密かに Skyfisherman's Wharf 計画が進行しています)。

「プロジェクト」メニューから「Startup code」を選択し、アプリケーションの Startup Code に次のようにグローバル変数を定義します。

Sub main()

  Global DBF as Database   1
  Global KEY as Integer    2
  Global TITLE as String    3
  Global BODY as String    4
  Global RES as Integer     5

End Sub

1 データベースとして「DBF」を定義
2 キーを格納するグローバル変数「KEY」を整数型として定義
3 タイトル格納するグローバル変数「TITLE」を文字型として定義
4 内容を格納するグローバル変数「BODY」を文字型として定義
5 データベース関数の戻り値を格納するためのグローバル変数「RES」を整数型として定義(これはデータベースのオープンや、データの挿入、検索などの結果として返された数値を格納して、その数値によってその後の身の振り方を考えます)

これらをグローバル変数として定義しておけば、アプリケーションのどこからでも利用できます。
さて次はそれぞれのボタンのコードです。これらは NSBasic に添付されているサンプル プロジェクトを参考にして作りました。NSBasic はハンドブックが割と簡単なので、実際にどうすればいいのか悩んだ時はサンプルを探すと見つかります。

●「OPEN」ボタンのコード

Sub object1016()

  RES = dbopen(DBF,"datafile",0)
  If RES = 0 Then
    Exit Sub
  End If

  MsgBox str(RES) + ":DBfile not found."
  If RES = 519 Then
    RES = dbcreate(DBF,"datafile",0,"skyF")
    If RES = 0 Then
      RES = dbopen(DBF,"datafile",0)
      If RES = 0 Then
      MsgBox "DBfile create and open."
      End If
    End If
    MsgBox "Error:" + str(RES)
  End If
  MsgBox "Error:" + str(RES)

End Sub

○「OPEN」ボタンのコードについて

Sub object1016()

  RES = dbopen(DBF,"datafile",0)
' 「datafile」という名前のデータベースをオープンしています
' 「DBF」は Startup code で定義してあるので、すぐに使えます
' カッコの中の最後の「0」は『本体内のカード』を意味します
' データベースをオープンした結果を「RES」に格納しています

  If RES = 0 Then
    Exit Sub
  End If

' 結果が「0」の場合、「dbopen」関数はオープンに成功していますので
' そのままボタンのコードは終わらせても構いません

' オープンできなかった場合

  MsgBox str(RES) + ":DBfile not found."
' 一応「dbopen」の返り値をメッセージボックスで表示して
' エラーを連絡するようにしてあります
' 「RES」は整数型なので、表示するために文字型に変換しています

  If RES = 519 Then

' 「519」が戻ってきた時は「データベースが見つからない」場合です
' 最初にこのアプリケーションを立ち上げた時は、当然データベースは
' 存在しないのでこれが返ってきて当たり前ですが・・・

    RES = dbcreate(DBF,"datafile",0,"skyF")

' データベースを「skyF」というクリエータ ID で作成しています
' その結果がどうだったのかを「RES」に格納しています
' dbopen 同様に「0」は成功です

    If RES = 0 Then
      RES = dbopen(DBF,"datafile",0)

' データベースが作成されたで開きます

      If RES = 0 Then
      MsgBox "DBfile create and open."
      End If
    End If
    MsgBox "Error:" + str(RES)

' 確認のための結果の表示です
' 「0」であれば OK です
' 開けない時は、なんで開けなかったのか数値で返します

  End If
  MsgBox "Error:" + str(RES)

' 作成できなかった時は、なんで作成できなかったのか数値で戻します

End Sub

とはいうものの、ここまではデータベースを開いただけで、まだ何にもしていません。実際に使うアプリケーションならば Startup code の中でここまでやってしまってもいいと思いますが、これは試しに確認しながら作ったアプリケーションなので、全て手作業で行うようにしてあります。

次にフィールドに文字などを書き込みます。一番上にあるキーのフィールドには数値を書き込みます。フリーウェアなどで公開する場合は、このフィールドに数値以外書き込めないようにきちんとチェックする必要がありますが、今回はテストなのでいい加減なままにしておきます。タイトルは文字、内容も文字で入力します。おっと、このままでは日本語になっているのかどうか分かりませんね。シフト インジケータをつけましょう。



ツールの一番下にある、上向きの矢印アイコンをクリックしてカーソルが変わったことを確認して、フォームの上でクリックするとシフト インジケータが表示されます。これで日本語と英語の状態が分かります。さてデータベースにデータを書き込みます。

●「Add」ボタンのコード

Sub object1013()

  KEY = val(key_field.text)
  TITLE = title_field.text
  BODY = body_field.text

  If KEY = 0 Then
    MsgBox "Cannot assign 0 to key."
    Exit Sub
  End If

  RES = dbinsert(DBF,KEY,TITLE,BODY)
  If RES = 0 Then
    MsgBox "Add data successfuly."
    Exit Sub
  End If
  MsgBox "Error:" + str(RES)

End Sub

○「Add」ボタンのコードについて

Sub object1013()

  KEY = val(key_field.text)
  TITLE = title_field.text
  BODY = body_field.text

' キーフィールドのテキストを数値に変換して格納しています
' 他はそのまま変数に格納しています

  If KEY = 0 Then
    MsgBox "Cannot assign 0 to key."
    Exit Sub
  End If

' キーが「0」だと登録できません

  RES = dbinsert(DBF,KEY,TITLE,BODY)

' それ以外の場合はデータベースにそれぞれのフィールドを書き込んでいます
' このテストではキーが同じ場合、上書きします
' 本来ならばキーがユニークであるかどうか、一旦データベースをチェックして
' 大丈夫なら書き込んで、存在していればアラートを出さなければだめですね

  If RES = 0 Then
    MsgBox "Add data successfuly."
    Exit Sub

' 他の関数と同じく「0」が返ってくれば成功です

  End If
  MsgBox "Error:" + str(RES)

' 確認のための結果の表示です
' 「0」であれば OK です

End Sub

キーのダブりチェックをしていないので、簡単なコードです。チェックをかけると、コードの行数は、この倍以上に膨れ上がるでしょう。そこが結構大変だったりしますが、まあみんなそれを経験して大人になったのだから、一度はやっておかないとね。とか言いながら今回はパスします。

次はデータベースの検索と読み出しです。ここでキーが生きてきます。キーフィールドにデータのナンバーを書き込み、それに該当するデータを読み出してきて、タイトルと内容を表示します。

●「Find」ボタンのコード

Sub object1014()

  KEY = val(key_field.text)
  RES = dbfind(DBF,KEY)

  If RES = 0 Then
    MsgBox "Record found."

  RES = dbread(DBF,KEY,TITLE,BODY)
  If RES <> 0 Then
    MsgBox "Error:" + str(RES)
    Exit Sub
  End If

  key_field.text = str(KEY)
  title_field.text = TITLE
  body_field.text = BODY

  End If
End Sub

○「Find」ボタンのコードについて

Sub object1014()

  KEY = val(key_field.text)
  RES = dbfind(DBF,KEY)

' キーフィールドの数値を整数型に変換して「KEY」に格納しています
' そのキーに該当するデータを検索して、その結果を「RES」に格納しています

  If RES = 0 Then
    MsgBox "Record found."

' 例によって成功した場合は「0」が返されます

  RES = dbread(DBF,KEY,TITLE,BODY)

' そのキーに対応するデータを読み出します

  If RES <> 0 Then
    MsgBox "Error:" + str(RES)
    Exit Sub
  End If

' 読み出しに失敗した場合は、その数値を返します

  key_field.text = str(KEY)
  title_field.text = TITLE
  body_field.text = BODY

' 読み出されたデータを、それぞれのフィールドに格納します
' 「KEY」の場合は整数型ですから、文字に変換して格納します

  End If
End Sub


コンパイルして動作をチェックします。とりあえず書き込むデータは次のものを使いました。

キー:タイトル:内容
 1:cw   :CodeWarrior を使うなら、必ず見ておく講座です。
 2:nsb  :NSBasic 講座ではなくて、いい加減なコラムです。
 3:prc  :FreeBSD で Palmware を開発しましょう。
 4:nsb_ami:本当の NSBasic 講座です。

使い方:
・まずアプリケーションを立ち上げて「OPEN」ボタンでデータベースを開きます。初めてですから生成してくれます。

データベースが見つからないのは当たり前

「OK」をタップしたら作成してくれる

「0」だから成功している(エラーではない)

・次にそれぞれのデータをフィールドに入力して、「Add」ボタンをタップします。するとデータが書き込まれます。

最初のデータをフィールドに書き込む

「Add」をタップすると書き込む











・4 つ書き込んだら、どれかナンバーをキーフィールドに入力して、「Find」ボタンをタップします。まあ当然「2」でしょうね。

最後のデータは表示されたままなので、キーのナンバーを「2」に書き換える

・するとデータベースから、そのキーに該当するデータが読み出されます。

「Find」をタップするとキーのデータを発見

「OK」をタップするとそのデータを表示する

割と簡単ですね。これを拡張して自分なりのデータを格納するアプリケーションや、データを活用したクイズみたいなものも考えられます。またグラフィックと組み合わせてページをめくっていくような、絵本みたいなものもあるでしょう。さらに標準のメモやアドレスなど他の *.pdb ファイルの読み書きもできますし、今関さんの CSubLocalSend を使ってみるのもいいと思います。

終わりに

実はこの講座、mizuno-ami さんに「My NSBasic」を書いていただけることになったので、3 月末にはこの回をリリースして終了し、その後を mizuno-ami さんにお願いするつもりでした。ところが PalmSource や 4 月 1 日の対応で追われまくりまして、とうとう 4 月半ばになってしまいまして、間が悪いったらありゃしない。というところで「My First NSBasic」は一旦終了させていただきます。ありがとうございました。



copyright(C)2002 Hacker Dude-san all rights reserved.