簡易データベース |
サンプルプログラムでは氏名、性別、E-Mailアドレス、電話番号のデータベースを作成します。レコード中の各フィールドの区切り文字は、カンマ , としています。E-Mailアドレスは重複することがないとして、キーはE-Mailアドレスとします。データベースをオープンする(dbmopen)と連想配列(ハッシュ)を経由してデータを得ることができます。処理が終了したらデータベースをクローズ(dbmclose)します。
ファイルを新規作成する際にはモード(パーミッション)を指定する必要があります。このモードはUNIXで用いられているもので、実際のオープンはこのモードにumaskでマスクされたモードで作成されます。umask
は現時点ではWindows/Macには実装されていませんが、パーミッションのどのビットをオフ(無効)にするかを設定するものです。
ファイルをオープンする際に、ファイルが存在しない場合は作成したくない場合は、モードにundefを指定します。ファイルを新規作成するときだけモードを指定するとおぼえておくと良いでしょう。データベースファイルは、指定したファイル名.dirとファイル名.pagの2つが生成されます。
パーミッションモードは次のような規則です。数値は8進数(頭に0)です。rwx-
はそれぞれRead、Write、eXecute、なし、の意味でUNIXの ls -l コマンドで表示されるものです。ただし、こちらの表現はdbmopenには用いることはできません。実は、UNIXではもう一つモードがあり先頭の-がそれなのですが、dbmopenでは関係ありませんから説明は省きます。
数値表現 | 文字表現 | 内容 |
0400 | -r-------- | ファイルのオーナーのリード権 |
0200 | --w------- | ファイルのオーナーのライト権 |
0100 | ---x------ | ファイルのオーナーと実行権 |
0040 | ----r----- | ファイルのオーナーと同一グループのユーザのリード権 |
0020 | -----w---- | ファイルのオーナーと同一グループのユーザのライト権 |
0010 | ------x--- | ファイルのオーナーと同一グループのユーザの実行権 |
0004 | -------r-- | その他のユーザのリード権 |
0002 | --------w- | その他のユーザのライト権 |
0001 | ---------x | その他のユーザの実行権 |
例えばオーナーにリード/ライト/実行権、オーナーと同一グループのユーザにリード権、その他のユーザはどの権限もなしの場合、
0400
0200
0100
0040
----
0740 -rwxr-----
のように、それぞれの数値を足しあわせた値となります。
入力画面
表示画面
[サンプルプログラムの実行]
#!/usr/bin/perl # # simpledb.cgi # # (C)1999 Kaoru Fujita # use lib './lib'; require 'util.pl'; # # 定数 # $Title = '簡易データベースのサンプル'; $Location = './tmp'; $dbfile = $Location.'/mydb'; $delim = ','; $Encoding = 'sjis'; $CharSet = 'Shift_JIS'; @Fields = ('LastName', 'FirstName', 'Sex', 'E-Mail', 'Telephone'); parseInput($Encoding); if ($in{'Action'} eq 'Add') { addData(); } else { viewData(); } exit(0); # # # sub viewData { dbmopen(%DB, $dbfile, undef) or exitError("データベース $dbfile がオープンできません。"); print "Content-Type: text/html\n\n"; print "<HTML>\n"; print "<HEAD>\n"; print "<META HTTP-EQUIV=Content-Type CONTENT=text/html; charset=$CharSet>\n"; print "<TITLE>$Title</TITLE>\n"; print "</HEAD>\n"; print "<BODY>\n"; print "<TABLE>\n"; print "<TR>\n"; for ($i=0; $i < scalar(@Fields); $i++) { print "<TH>$Fields[$i]</TH>\n"; } print "</TR>\n"; foreach (sort values %DB) { print "<TR>\n"; @data = split(/$delim/); for ($i=0; $i < scalar(@Fields); $i++) { print '<TD BGCOLOR="#F0F0F0">',$data[$i],"</TD>\n"; } print "</TR>\n"; } print "</TABLE>\n"; dbmclose(DB); print "</BODY>\n"; print "</HTML>\n"; } # # # sub addData { dbmopen(%DB, $dbfile, 0600) or exitError("データベース $dbfile がオープンできません。"); $key = $in{'E-Mail'}; if ($DB{$key}) { exitError("すでに同じE-Mailアドレス $key があります。"); } foreach (@Fields) { $rec = $rec.$in{$_}.$delim; } chomp($rec); $DB{$key} = $rec; dbmclose(DB); print << "END_OF_HTML"; Content-Type: text/html <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$CharSet"> <TITLE>$Title</TITLE> </HEAD> <BODY> 登録しました。 </BODY> </HTML> END_OF_HTML } #--End of simpledb.cgi |
<HTML> <HEAD> <TITLE>簡易データベース サンプル</TITLE> <SCRIPT language="JavaScript"> <!-- function doIt(act) { document.Form.Action.value = act; document.Form.submit(); } //--> </SCRIPT> </HEAD> <BODY> <FORM ACTION="/cgi-bin/simpledb.cgi" NAME="Form"> <INPUT TYPE="hidden" NAME="Action"> 氏名: <INPUT TYPE="text" NAME="LastName" SIZE="8"> <INPUT TYPE="text" NAME="FirstName" SIZE="8"><BR> 性別: <SELECT NAME="Sex"> <OPTION VALUE="Male" selected>男 <OPTION VALUE="Female">女 </SELECT><BR> E-Mailアドレス: <INPUT TYPE="text" NAME="E-Mail" SIZE="32"><BR> 電話番号: <INPUT TYPE="test" NAME="Telephone" SIZE="32"><BR> <INPUT TYPE="button" NAME="View" VALUE="表示" onClick=doIt('View')> <INPUT TYPE="button" NAME="Add" VALUE="登録" onClick=doIt('Add')> </FORM> </BODY> </HTML> |
実は、dbmopenはPerl4の古い時代からのインターフェースで、Perl5ではtieでハッシュとDBMパケージクラスとを結び付けることができます。関連付けが必要なくなったときには、untieで解除します。dbmopenと違うところはFcntlモジュールで定義されているファイルオープンフラグを指定することです。
フラグ | 内容 |
O_CREAT | ファイルが存在しない場合は新規作成する。 |
O_RDWR | リード/ライトモードでオープンする。 |
O_RDONLY | リード専用でオープンする。 |
O_WRONLY | ライト専用でオープンする。 |
O_EXCL | O_CREATが指定されていて、ファイルが存在する場合にエラーを返す。 |
O_TRUNC | ファイルを切り詰めてオープンする。 |
tileを用いて上記サンプルを書き換えると次のようになります。DBMモジュールには、NDBM_File、SDBM_File、GDBM_File、ODBM_File、DB_File、AnyDBM_Fileがありますが、ここでは標準でバンドルされているSDBM_Fileを利用します。
HTMLは呼び出すCGIを変更するだけです。
[サンプルプログラムの実行]
#!/usr/bin/perl # # simpledb2.cgi # # (C)1999 Kaoru Fujita # use lib './lib'; require 'util.pl'; use Fcntl; use SDBM_File; # # 定数 # $Title = '簡易データベースのサンプル(2)'; $Location = './tmp'; $dbfile = $Location.'/mydb'; $delim = ','; $Encoding = 'sjis'; $CharSet = 'Shift_JIS'; @Fields = ('LastName', 'FirstName', 'Sex', 'E-Mail', 'Telephone'); parseInput($Encoding); if ($in{'Action'} eq 'Add') { addData(); } else { viewData(); } exit(0); # # # sub viewData { tie(%DB, SDBM_File, $dbfile, O_RDONLY, undef) or exitError("データベース $dbfile がオープンできません。"); print "Content-Type: text/html\n\n"; print "<HTML>\n"; print "<HEAD>\n"; print "<META HTTP-EQUIV=Content-Type CONTENT=text/html; charset=$CharSet>\n"; print "<TITLE>$Title</TITLE>\n"; print "</HEAD>\n"; print "<BODY>\n"; print "<TABLE>\n"; print "<TR>\n"; for ($i=0; $i < scalar(@Fields); $i++) { print "<TH>$Fields[$i]</TH>\n"; } print "</TR>\n"; foreach (sort values %DB) { print "<TR>\n"; @data = split(/$delim/); for ($i=0; $i < scalar(@Fields); $i++) { print '<TD BGCOLOR="#F0F0F0">',$data[$i],"</TD>\n"; } print "</TR>\n"; } print "</TABLE>\n"; print "</BODY>\n"; print "</HTML>\n"; untie(%DB); } # # # sub addData { tie(%DB, SDBM_File, $dbfile, O_CREAT|O_RDWR, 0600) or exitError("データベース $dbfile がオープンできません。"); $key = $in{'E-Mail'}; if ($DB{$key}) { exitError("すでに同じE-Mailアドレス $key があります。"); } foreach (@Fields) { $rec = $rec.$in{$_}.$delim; } chomp($rec); $DB{$key} = $rec; untie(%DB); print << "END_OF_HTML"; Content-Type: text/html <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$CharSet"> <TITLE>$Title</TITLE> </HEAD> <BODY> 登録しました。 </BODY> </HTML> END_OF_HTML } #--End of simpledb2.cgi |
<HTML> <HEAD> <TITLE>簡易データベース サンプル(2)</TITLE> <SCRIPT language="JavaScript"> <!-- function doIt(act) { document.Form.Action.value = act; document.Form.submit(); } //--> </SCRIPT> </HEAD> <BODY> <FORM ACTION="/cgi-bin/simpledb2.cgi" NAME="Form"> <INPUT TYPE="hidden" NAME="Action"> 氏名: <INPUT TYPE="text" NAME="LastName" SIZE="8"> <INPUT TYPE="text" NAME="FirstName" SIZE="8"><BR> 性別: <SELECT NAME="Sex"> <OPTION VALUE="Male" selected>男 <OPTION VALUE="Female">女 </SELECT><BR> E-Mailアドレス: <INPUT TYPE="text" NAME="E-Mail" SIZE="32"><BR> 電話番号: <INPUT TYPE="test" NAME="Telephone" SIZE="32"><BR> <INPUT TYPE="button" NAME="View" VALUE="表示" onClick=doIt('View')> <INPUT TYPE="button" NAME="Add" VALUE="登録" onClick=doIt('Add')> </FORM> </BODY> </HTML> |