| 簡易データベース |
サンプルプログラムでは氏名、性別、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>
|