DBD::Sprite (0.19)(日本語チョー訳)

by Hippo2000(2001/7/10)

PurePerlなDBDにしてデータベース、DBD::Spriteなのです。Oracleをエミュレートできるってほんまかいな...。

なおこのドキュメントはDBD::SpriteのPODををhtml化し日本語に訳そうとしたものです。わかりにくい部分は本物を見てください。(^^;;

原本の著作権はJim Turner氏がお持ちです。Jim Turnerさんにメールで了解をいただきました。

なお内容等が間違っていたら修正します。ご連絡ください。



名前

     DBD::Sprite - DBIのためのPerl拡張、フラット・ファイルを通してデータベース・エミュレーションを提供。

作者(AUTHOR)

(原文のまま)

    This module is Copyright (C) 2000 by

           Jim Turner
                
        Email: jim.turner@lmco.com

    All rights reserved.

    You may distribute this module under the terms of either the GNU General
    Public License or the Artistic License, as specified in the Perl README
    file.

   JSprite.pm is a derived work by Jim Turner from Sprite.pm, a module 
        written and copyrighted (c) 1995-1998, by Shishir Gurdavaram 
        (shishir@ora.com).


概要

     use DBI;
     $dbh = DBI->connect("DBI:Sprite:spritedb",'user','password')
         or die "Cannot connect: " . $DBI::errstr;
     $sth = $dbh->prepare("CREATE TABLE a (id INTEGER, name CHAR(10))")
         or die "Cannot prepare: " . $dbh->errstr();
     $sth->execute() or die "Cannot execute: " . $sth->errstr();
     $sth->finish();
     $dbh->disconnect();


説明

DBD::SpriteはPerlのデータベース独立インターフェース(DBI)にフラットファイルを介してデータベース・エミュレーションを加えるためのDBI拡張モジュールです。ほかのDBDモジュールと違い、データベースを購入したり、取得したりする必要はありません。PerlとDBIを使うデータベース独立アプリケーションをプロトタイプするために必要なものはすべて、ここに含まれています。しかし、おそらくはあなたの製品やより大きなデータの必要性のために、"mysql"のような本当のデータベースを取得したいと思うかもしれません。というのもこれはデータベースとSQLをテキストファイルでエミュレートすることは、あなたの"データーベース"がありきたりの大きさ(各テーブルごとに20、30件(a few dozen)程度のレコード)ではなくなるになるに従って、とても遅くなります。

DBD::SpriteはShishir Gurdavaramによって書かれた"Sprite"という古いPerlモジュールの上に構築されてました。このコードは開始点として使われました。それは完全に補正され、多くの新しい機能が追加され、"JSprite.pm"(Jim Turner's Sprite)と呼ばれるモジュールを作成しました。これはDBD::DBDと統合され、今あなたがインストールするもの(DBD::Sprite)を作成しています。JSpriteはこのモジュールに別のファイルとして入っており、必要となります。

Gurdavaramに感謝します。

DBD::Spriteの最大の利点は個人的なマシン(もしくはOracleライセンスやほかの"主流の"データベースを持たないマシン)でプロトタイプ・アプリケーションを、"本当の"データベースを持っている"製品"マシンにリリースする前に開発しテストできることです。これはPerlコードを最小限の変更あるいは変更なしで行うことができます。

DBD::Spriteのもう一つの利点はデータを検索するためにPerlの正規表現を使うことができることです。おそらくいつかは、より多くの"本当の"データベースもこの機能を持つことでしょう!

DBD::Spriteはフラットファイルを通して、基本的なデ−タベーステーブルとSQL呼び出しをエミュレートする能力を提供します。想定している基礎的な使い方は、Oracleライセンスを購入する余裕がないWebサイトの開発者に自分自身の道具で、後でOracleが使われているより大きい顧客のサイトでホスティングするためのプロトタイプやPerlアプリケーションの開発を可能とさせることです。 :-)

DBD::Spriteはできるだけデータベースに依存しない方法でことを行おうとしますが、違いがあるとJSpriteはOracleを最も近くエミュレートします。例えば"シーケンス/自動番号付け"。JSpriteは"シーケンスファイル"(.seq)という小さな1行のテキストファイルと自動的に番号がふられるフィールドに挿入するための"seq_file_name.NEXTVAL"関数を使います。これは作者がOracleショップで働いていて、Oracleライセンスを取得するのに時には時間がかかったために、このモジュールは彼自身に彼のPCとOracleを持っていないマシンでコードを動かすために書かれたためです。

DBD::SpriteはDBD::CSVと似ていますが、以下の点で異なります。

   1) ユーザIDとパスワードを持った本当の"データベース"を作成し、動作します。
        2) データベースの作者はフィールド・デリミタ、レコード・デリミタ、ユーザ、パスワード、
        テーブル・ファイル・パスそして書くデータベースの拡張子を指定します。
        3) トランザクション(コミットとロールバック)が完全にサポートされています!
        4) 自動採番とユーザ定義関数がサポートされています。
        5) ほかのモジュールやデータベースを必要としません。(Perl5とDBIモジュールを除いて
        必要条件はありません!
        6) データの周りにクォートは使われません
        7) SQLのときには"$dbh->quote()"メソッドを呼び出す必要はありません。
        8) NULL は空文字列として扱われます。
        9) SQLで使うために独自のデータ変換関数を"登録"することができます。下記
        の"fn_register"メソッドをご覧ください。

 


インストール方法

    このモジュール(そして事前に必要なもの)をインストールのはとても簡単です。アーカイブを取得し、以下のようにして解凍します。
        gzip -cd DBD-Sprite-0.1000.tar.gz | tar xf -
    (これはUnixユーザ用です。WindowsユーザーはWinZipまたは同様のものを好むでしょう)そして以下のように入力します:
        cd DBD-Sprite-#.###
        perl Makefile.PL
        make
        make test
    もしテストが失敗したら教えてください。そうでなければ以下のようにして進んでください。
        make install

    注意 おそらくはrootまたは管理者権限が必要です。それを持っていなければ、自分のディレクトリにインストールするための詳細
    についてExtUtils::MakeMaker manページを見てください。
   注意: "makesdb.pl"を/usr/local/binまたはどこかパスの通っているところにコピーする必要があるかもしれません。


はじめに

   1) データベースを格納したいところへcdします
        2) データベースを作成するためにmakesdb.plを実行します。つまり
        
           Database name: mydb
                Database user: me
                User password: mypassword
                Database path: .
                Table file extension (default .stb): 
                Record delimiter (default \n): 
                Field delimiter (default ::): 

           これは新しいデータベース・テキストファイル(mydb.sdb)をカレント・ディレクトリに作成します。
                このASCIIファイルには上記で入力した情報が入ります。追加のユーザ空間を追加するには、データベー
                ス名として"mydb"をつけてmakesdb.plを再実行します。そして追加のユーザ(name,password,pasu,extension
                そしてdelimiters)を入力します。例は"make test"を実行したあとに"test.sdb"ファイルをご覧下さい。
           Spriteデータベースに接続するとき、Spriteはカレント・ディレクトリを見て、もし指定されていれば
                SPRITE_HOME環境変数に指定されたパスを見に行きます。
           データベース名(database name)、ユーザー(user)そしてパスワード(password)は下記で説明する
                "db->connect()"メソッドで使われます。 "database path"はテーブルが作られ、置かれるところです。
                テーブルはASCIIテキストファイルで、デフォルトでは拡張子".stb"(Sprite table)を持ちます。
                デフォルトでは、各レコードは1つの行に書かれます(\nで区切られて -- Windowsユーザはたぶん"\r\n"を
                使うでしょう。)各フィールド項目はクォートなしに"フィールド・デリミタ(デフォルト:二重のコロン)"
                で区切られます。テーブルファイルの先頭行はフィールド名、等号(=)記号、それがキーフィールドであれば
                アスタリスク、そしてデータ型と大きさから構成されます。この情報は各フィールド用に入り、フィールド・
                セパレータによって分けられます。例については"make test"実行後の、ファイル"testtable.stb"をご覧下さい。
   3) DBIを使うスクリプトを書きます。つまり
        
           #!/usr/bin/perl
                use DBI;
                
           $dbh = DBI->connect('DBI:Sprite:mydb','me','mypassword') || 
                                die "Could not connect (".$DBI->err.':'.$DBI->errstr.")!";
                ...
                #テーブルを作り、レコードを挿入し、楽しんでください!
                
   4) アプリケーションを動かします。
        
   5) "製品"マシンにアプリケーションを移動し、"Sprite"を"本当の"データベースのためのDBIドライバに
        変更します!

テーブルの作成と削除

    You can create and drop tables with commands like the following:

        $dbh->do("CREATE TABLE $table (id INTEGER, name CHAR(64))");
        $dbh->do("DROP TABLE $table");

    Note that currently only the column names will be stored and no other
    data. Thus all other information including column type (INTEGER or
    CHAR(x), for example), column attributes (NOT NULL, PRIMARY KEY, ...)
    will silently be discarded. This may change in a later release.

    A drop just removes the file without any warning.

    See the DBI(3) manpage for more details.

    Table names cannot be arbitrary, due to restrictions of the SQL syntax.
    I recommend that table names are valid SQL identifiers: The first
    character is alphabetic, followed by an arbitrary number of alphanumeric
    characters. If you want to use other files, the file names must start
    with '/', './' or '../' and they must not contain white space.


データの挿入、取り出しそして更新

    以下の例はテーブルにデータを挿入し、それを取り出します:
    最初すべてのデータは文字列にあります:
        $dbh->do("INSERT INTO $table VALUES (1, 'foobar')");
    単語'foobar'をエスケープするためのquoteメソッドの使い方に注意してください。バイナリ
    データが入っていなくても、すべての文字列がエスケープされます。
    次の例ではパラメータを使っています:
        $dbh->do("INSERT INTO $table VALUES (?, ?)", undef,
                 2, "It's a string!");
    データを取り出すには以下のようにできます:
        my($query) = "SELECT * FROM $table WHERE id > 1 ORDER BY id";
        my($sth) = $dbh->prepare($query);
        $sth->execute();
        while (my $row = $sth->fetchrow_hashref) {
            print("Found result row: id = ", $row->{'id'},
                  ", name = ", $row->{'name'});
        }
        $sth->finish();
    再び、カラムバイディングも機能します:同じ例を再び行います:
        my($query) = "SELECT * FROM $table WHERE id > 1 ORDER BY id";
        my($sth) = $dbh->prepare($query);
        $sth->execute();
        my($id, $name);
        $sth->bind_columns(undef, \$id, \$name);
        while ($sth->fetch) {
            print("Found result row: id = $id, name = $name\n");
        }
        $sth->finish();
    もちろん入力パラメータを使うことさえもできます。以下に3度目の例をあげます:
        my($query) = "SELECT * FROM $table WHERE id = ?";
        my($sth) = $dbh->prepare($query);
        $sth->bind_columns(undef, \$id, \$name);
        for (my($i) = 1;  $i <= 2;   $i++) {
            $sth->execute($id);
            if ($sth->fetch) {
                print("Found result row: id = $id, name = $name\n");
            }
            $sth->finish();
        }
    これらのメソッドの詳細についてはDBI(3)のmanページをご覧下さい。WHERE節についての詳細はSQL::Statement(3) 
    manページをご覧下さい。
    データ行はUPDATEステートメントで変更されます:
        $dbh->do("UPDATE $table SET id = 3 WHERE id = 1");
    同様にDELETEステートメントで行を削除します:
        $dbh->do("DELETE FROM $table WHERE id > 1");

fn_register

このメソッドは2つの引数を取ります:関数名とオプションのパッケージ名(デフォルトは"main")を取ります。

           $dbh->fn_register ('myfn','mypackage');

-または-

           use JSprite;
                JSprite::fn_register ('myfn',__PACKAGE__);

そしてSQLで以下のようにします:

   insert into mytable values (myfn(?))
        

そして値を"?"にバインドします、それは"myfn"に渡され、返された値がデータベースに登録されます。バインドなしに呼び出すこともできます。:

   insert into mytable values (myfn('mystring'))
        

-または (関数が数値を取るのであればi)-

   select field1, field2 from mytable where field3 = myfn(123) 
        

戻り値

   なし


エラーの取り扱い

    上記の例では戻り値をまったく注意していません。もちろんこれはお勧めできることではありません。代わりに
    以下のように書きます(例えば):
        my($query) = "SELECT * FROM $table WHERE id = ?";
        my($sth) = $dbh->prepare($query)
            or die "prepare: " . $dbh->errstr();
        $sth->bind_columns(undef, \$id, \$name)
            or die "bind_columns: " . $dbh->errstr();
        for (my($i) = 1;  $i <= 2;   $i++) {
            $sth->execute($id)
                or die "execute: " . $dbh->errstr();
            if ($sth->fetch) {
                print("Found result row: id = $id, name = $name\n");
            }
        }
        $sth->finish($id)
            or die "finish: " . $dbh->errstr();

    明らかにこれは面白くありません。幸いなことに我々にはDBIの*RaiseError*属性があります:

        $dbh->{'RaiseError'} = 1;
        $@ = '';
        eval {
            my($query) = "SELECT * FROM $table WHERE id = ?";
            my($sth) = $dbh->prepare($query);
            $sth->bind_columns(undef, \$id, \$name);
            for (my($i) = 1;  $i <= 2;   $i++) {
                $sth->execute($id);
                if ($sth->fetch) {
                    print("Found result row: id = $id, name = $name\n");
                }
            }
            $sth->finish($id);
        };
        if ($@) { die "SQL database error: $@"; }
    これは短いだけでなく、サブルーチンの中でDBIメソッドを使っているときにも機能します。


メタデータ

    以下の属性はDBD::Fileではなく、DBI自身により扱われます。そのため
    期待通りに動くでしょう:私は以下の最後の3つしか使ったことがありません。
        Active
        ActiveKids
        CachedKids
        CompatMode             (Not used)
        InactiveDestroy
        Kids
        PrintError
        RaiseError
        Warn

    以下のDBI属性はDBd::Spriteによって扱われます:
    AutoCommit
        機能します
    ChopBlanks
        機能するはず
    NUM_OF_FIELDS
        '$sth->execute'の後、有効
    NUM_OF_PARAMS
        '$sth->prepare'の後、有効
    NAME
        '$sth->execute'の後、有効; 非SELECTステートメントではundef。
    NULLABLE
        本当には機能しません。DBD::Spriteが常にNULLを許す(空文字列として
        扱われます)ので常にその配列リファレンスを返します。
        '$sth->execute'の後、有効。
    PRECISION
                機能します
    SCALE
                機能します
    LongReadLen
                Should work
    LongTruncOk
                機能します
    これらの属性とメソッドはサポートされていません:
        bind_param_inout
        CursorName
    DBI属性に加えて、以下のdbh属性を使うことができます。
    これらの属性は"connect"の後、読み込みのみです。
    sprite_dbdir
                データベースのテーブルのためのパス
   sprite_dbext
                データベースでのテーブル・ファイルで使われるファイル拡張子。
   sprite_dbuser
                現在のデーターベース・ユーザ。
                
   sprite_dbfdelim
                データーベースのために使われるフィールド・デリミタ文字列。
                
   sprite_dbrdelim
                データベースで使われるレコード・デリミタ。

   以下の環境変数はSpriteによって特別に解釈されます。

   SPRITE_HOME
                Spriteデータベース(*.sdb)ファイルを検索するためのパスを指定する環境変数
   以下のSprite特有のオプションは接続のときに設定できます。
   sprite_CaseTableNames
                デフォルトでは、テーブル名は大文字、小文字は無視されます(Oracleでのように)。
                大文字、小文字を区別するように(MySqlでのように)して、"test"と"TEST"を
                2つの異なるテーブルだとするには、このオプションを1にしてください。
   sprite_StrictCharComp  (NEW!)
                CHAR フィールドはつねに右側にフィールドいっぱいに空白が埋められます。
                昔 (5.17以前) Sprite の動きは"where"節での等価チェックは埋められた
                空白もリテラルに入ることを必要としていました。
                私はDBIx-Recordsetをテストしているとき、Oracleと他のいくつかのデーターベースが
                これを必要としていないことを発見しました。そこでSpriteは等価のチェックのとき
                自動的に右側の埋められたリテラルを埋めるようにしました。
                これを止めさせ、昔の動きを強制させるためには、このオプションを1にします。

ドライバ独自のメソッド

    DBI->data_sources()
        'data_sources' メソッドはカレント・ディレクトリともし指定されていれば
        SPRITE_HOME環境変数で指定されたパスで見つかった"データーベース"(.sdbファイル)
        のリストを返します。
    $dbh->tables()
        このメソッドは現在のデータベースで定義されたテーブルのリストを返します。
        例:
            my($dbh) = DBI->connect("DBI:Sprite:mydatabase",'me','mypswd');
            my(@list) = $dbh->func('list_tables');
    JSprite::fn_register ('myfn',__PACKAGE__);
                このメソッドはSQLコマンドの中でユーザが定義したデータ変換関数の名前を取ります。
                関数は引数をオプションで取ることができます。しかし1つの数または文字列を返さなければなりません。
                パッケージ"main"で定義されていなければ、パッケージ名も指定するか、現在のパッケージのための
                "__PACKAGE__"を指定しなければなりません。例については上記の"INSERTING, FETCHING AND MODIFYING DATA"
                またはJSprite(3)をご覧下さい。

サポートしている他のユーティリティ

   makesdb.pl
                このユーティリティは新しいSpriteデータベースを構築させ、それに後から追加の
                ユーザ空間を加えさせます。単にデータベースを作りたい/変更したいディレクトリへ
                cdし、実行します。それは以下のようなプロンプトを出します:
           Database name: Enter a 1-word name for your database.
                Database user: Enter a 1-word user-name.
                User password: Enter a 1-word password for this user.
                Database path: Enter a path (no trailing backslash) to store tables.
                Table file extension (default .stb): 
                Record delimiter (default \n): 
                Field delimiter (default ::): 
           最後から6つのプロンプトは1つのデータベースに複数のユーザを設定することを
                可能とするため、他のユーザ名をいれなくなるまで繰り返します。各"ユーザー"は
                異なるパス、ファイル拡張子、パスワードそしてデリミタを指定することにより
                独自の別のテーブルを持つことができます!既にあるデータベースに"makesdb.pl"を
                呼び出すことによりユーザを追加することができます。ユーザを削除するために
                viで編集することもできます。そのユーザのためのパスから始まる5行を削除して
                ください。ファイルはパスワードを除いてすべてテキストです。それは保護のため
                暗号化されています!

制約

   DBD::Sprite は以下のデータ型をサポートしています:
                NUMBER FLOAT DOUBLE INT INTEGER NUM CHAR VARCHAR VARCHAR2 
                DATE LONG BLOB そして MEMO。しかし本当は基本的な3つのデータ型しかありません
                (NUMBER, CHAR, そして VARCHAR)。 これはPerlがすべてのものを単純な文字列として 
                扱うためです。最初の5つはPerlによってソートのさいに"数値"として扱われます。
                残りは文字列として扱われます。つまりNUMERICタイプは1,5,10,40,200のようにソートし、
                STRING型では1,10,200,40,5のようになります。CHARフィールドは格納されたときに
                右側に空白が埋められます。LONG型フィールドは"LongReadLen"属性値により切り捨て
                られることに関連します。
   もし"Sprite => 1"行が"%CAN_BIND"と"%CAN_BINDSELECT"ハッシュに加えられるとDBD::Spriteは
                tieDBIモジュールとともに機能します。これは必須ではなりませんが、私がやったtきに発見しました。

DBD::Spriteの拡張でするべきこと

    結合
        このモジュールの現在のバージョンは単独のテーブルのSELECTのみ機能します。これは元になっている
        JSpriteでのstatementオブジェクトが1つのファイルに結び付けられているための現象です。
        私にはアイデアがありこれについてまじめに見始めています。お見逃しなく!
   追加のOracle的な組込関数。現在のところサポートされているのは "SYSTIME", "NUM", そして"NULL"。"NUM"は何もせず、
        "NULL"は空文字列を返す。最初のは"TO_DATE"でしょう。 
   Gurdavaram氏が追加したいと思いそうなもののすべて
        

既知のバグ

このモジュールは内部的にはflock()を使っています。しかしこの関数はプラットホームによっては使えません。MacOSとWindows95ではflock()を使うことができません。ロックはなにもありません(どのみち1つのユーザー用なので、多分これらのオペレーティングシステムではあまり重要ではないでしょう。)


参考資料

   JSprite(3), DBI(3), perl(1)

DBD::Sprite - Perl extension for DBI, providing database emmulation via flat files.


ホーム Perlの小技

ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。