DBD::Informixモジュール(日本語チョー訳)

by Hippo2000(1999/11/25)

DBD::Informixモジュールのなのです。

なおこのドキュメントではCPANで公開されているDBD::Informixのドキュメントを日本語化したものです。わかりにくい部分は本物を見てください。(^^;;なによりInformixの用語(特にデータベースのタイプとか)については、まったくわかっていませんので、おかしなところががありましたら是非、教えてください。
#他のもそうなんですけどねぇf(^^)

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

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


目次


名前

DBD::Informix - Informixデータベースへのアクセス


概要

  use DBI;

説明

このドキュメントはDBD::Informix バージョン0.61について説明しています。

このドキュメントはそこで書かれていることを適用しているので、DBIドキュメントも読まなければなりません。このドキュメントはDBI 0.85仕様のために、最後に更新されていますが、コードはDBI 0.89リリースからの機能を必要としていることに注意してください。DBIの仕様は現時点(1997年中ば)では、特に変更されやすくなっており、DBIの新しいバージョンをDBD::Informixのこのバージョンと一緒に使うと問題が起こるかもしれません(あってはならないことですが)

このドキュメントはDBIとDBD::Informixの使い方について、まだ偏った見方をしています。DBIとDBD::Informixのほとんどの部分をカバーしています。始めにDBIドキュメントは同等以下の状態でしたが、DBIの各リリースで改良されていき、そしてDBIについてのDBIドキュメントのコメントがこのドキュメントでのコメントよりも先に進んでいます(しかしこのドキュメントのほうが、DBD::Informixの実際の動きをよりよく反映しているかもしれません)

Informixソフトウェアの異なるバージョンやInformixデータベースの異なるタイプの違いによって、このドキュメントの説明が複雑になっていることに、ときどき注意してください。

鍵となる要素はDBD::Informixを構築するときのESQL/Cのバージョンです。基本的に気にしなければならないバージョン2つのグループがあります。バージョンの5.0xファミリー(現在は5.00.UC1 〜 5.08.UD1 )、そしてバージョンの6.0x以降のファミリー(現時点では6.00.UE1 〜7.23.UC1)です。すべてのバージョン・ファミリーは、場合によって特別なバージョンを取得します。

DBD::InformixはESQL/Cの4.1x以前では機能しないことに注意してください。これはDBD::InformixがSQL記述子(descriptor)とカーソル名とステートメント名のための文字列の両方を使い、これらの機能はESQL/Cバージョン5.00以前では使えないからです。

DBD::Informixと一緒に配布される、Informixソフトウェアについての情報のために、Informix.Licence ファイルも読むべきです。


DBD::Informixの使い方


DBD::Informixのロード

DBD::Informixソフトウェアを使うために、DBIソフトウェアをロードする必要があります。

    use DBI;

通常の環境では、セクション"データベースへの接続"での書き方を使ってデータベースに接続します、それはDBI->connect()を呼びます。いくつかのDBD::Informixテストコードは通常の環境を扱わず、このためセクション"ドライバ属性とメソッド"での優先されないテクニックを使っていることに注意してください。


ドライバ属性とメソッド

どうしてもそうしたければ、明示的にInformixドライバを使用するデータベースに接続することとは独立して以下のようにインストールすることができます:

    $drh = DBI->install_driver('Informix');

これはドライバへのリファレンス、いわゆるドライバ・ハンドルを与えてくれます。ロードが失敗すると、プログラムはすぐに止まってしまいます(おそらく、ステートメントをevalしていなければ)

ドライバ・ハンドルを手に入れれば、ドライバにいくつかの基本的な情報を質問することが出来ます:

    print "Driver Information\n";
    # Type は常に'dr'。
    print "    Type:                  $drh->{Type}\n";
    # Name は常に 'Informix'。
    print "    Name:                  $drh->{Name}\n";
    # Version はDBD::Informix (例えば 0.51)のバージョン
    print "    Version:               $drh->{Version}\n";
    # Attributionは、おのソフトウェアをあなたに提供した
    # 犯人をしめします。
    print "    Attribution:           $drh->{Attribution}\n";
    # ProductNameはESQL/Cのバージョン;これは"esql -V"の出力の
    # 最初の行に対応します。
    print "    Product:               $drh->{ix_ProductName}\n";
    # ProductVersionは整数のバージョン番号。ESQL/C バージョン 
    # 7.21.UC1は721となります。
    print "    Product Version:       $drh->{ix_ProductVersion}\n";
    # MultipleConnectionsはドライバが複数の接続を
    # サポートしている(1)あるいは、していない(0)ことを示します。
    print "    Multiple Connections:  $drh->{ix_MultipleConnections}\n";
    # ActiveConnectionsはオープンされている接続の数を示します。
    print "    Active Connections:      $drh->{ix_ActiveConnections}\n";
    # CurrentConnectionは現在の接続を示します。
    print "    Current Connections:     $drh->{ix_CurrentConnection}\n";

一度ドライバをロードすると、データベースに接続したり、データベースへのすべての接続をdisconnect_allで切断することが出来ます。

    $drh->disconnect_all;

以下の関数を使って利用できるデータベースを見つけることが出来ます:

    @dbnames = DBI->data_sources('Informix');

他の書き方を使って、まだ他のデータベースに接続する事ができるかもしれないということに注意してください。(例えば、"server"がsqlhostsファイルにあり、データベース"dbase"がそのserverで起動しており、さらにそのサーバとそのサーバ上のデータベースを使えるのであれば、"dbase@server"に多分、接続できるでしょうなど)。同様にデータベースへの接続許可が与えられていなければ、リストに現れたデータベースのそれぞれに接続できないかもしれません。しかしDBI->data_sourcesメソッドによって与えられたリストは確かに存在し、それらに接続しようとするのは適切なことです.

これが機能するかどうかは以下のようにして確かめることができます:

    if (defined @dbnames) { ...process array... }
    else                  { ...process error... }

テスト・ファイル"t/dblist.t"もご覧下さい。


データベースへの接続

データベースに接続するために、connect関数を使うことが出来ます。それは成功すれば、正しいリファレンスまたはデータベース・ハンドルを与えます。ドライバそのものがロードできなければ(上で説明したDBI->install_driver() メソッドによって)、DBI スクリプトを中断(abort)します。(そして、それが正常にロードされないために、DBD::Informixはそれについて何もすることが出来ません)

    $dbh = DBI->connect("dbi:Informix:$database");
    $dbh = DBI->connect("dbi:Informix:$database", $user, $pass);
    $dbh = DBI->connect("dbi:Informix:$database", $user, $pass, %attr);

DBI connect メソッドは最初の引数から頭の'dbi'をを取り除き、次の文字列(この場合はInformix)で示されるDBDモジュールをロードします。2番目のコロンの後ろの文字列はすべてDBD::Informixコードに渡されます。

このフォーマットでは、ユーザ名やパスワードを指定する必要はありません。もしユーザ名を指定してもパスワードを指定しなければ、DBD::Informixは黙ってユーザ名を無視することに注意してください。connect呼び出しの時、属性を指定することも出来ます。以下のものがあります:

        AutoCommit
        PrintError
        RaiseError

このリストにChopBlanksが指定できないことに注意してください。ix_AutoErrorReport(下記を参照)がconnect呼び出しでは理解されないことを除けば、、PrintError属性はix_AutoErrorReportと同じでした。しかし、ix_AutoErrorReportは今や削除され、それを使っているコードはすべて、代りにPrintErrorを使うようにアップグレードしなければなりません(というのもPrintErrorはDBI標準の名前であり、ix_AutoErrorReportはそうではないからです)。新しいスタイルのconnectを使うと、データベースをAutoCommitモードで操作しないように、しかしエラーは自動的に報告されるよう以下のように指定することが出来ます。:

        $dbh = DBI->connect("dbi:Informix:$database", '', '',
                                                { AutoCommit => 0, PrintError => 1 });

このスタイルの接続を使うと、AutoCommitのデフォルトの値はOn(または1)です;これは昔のスタイルがOff(または0)であったのとは対照的です。同様にDBD::Informix 0.56リリースから、ログなし(UnLogged)データベースに接続したときにAutoCommitをOffに設定しようとしたときに警告を受けるかもしれないという点を除いて、接続するInformixデータベースのタイプによって動きが影響を受けないという点にも注意してください。このドキュメントの「トランザクション管理」での大量の注意もご覧下さい。


"廃れてしまった接続メソッド"

接続の古いスタイルは、最初の引数の頭に"dbi:Informix"という文字列を使いません。あるテストがこれをつかっているという事実にもかかわらず、このスタイルを使うことは強く反対されます。

    $dbh = DBI->connect($database, $username, $password, 'Informix');

4番目の引数('Informix')を省略すると、DBIはそのルールにしたがって、あるドライバをロードするかもしれません-- 実際にロードされたドライバはDBD::Informixによって制御されません。4番目の引数を省略すると、そうしたければ$passwordと$username引数も省略することが出来ます。4番目の引数を指定したならば、$passwordと$username引数を空のままにすることによって、無視されます。

    $dbh = DBI->connect($database, $username, $password);
    $dbh = DBI->connect($database, $username);
    $dbh = DBI->connect($database);

"Informix接続での意味論"

ESQL/Cの5.0バージョンを使っているならば、DBD::Informixはユーザ名とパスワードのデータを無視し、ステートメントは"EXEC SQL DATABASE :database;"と同値になります。 ESQL/Cの6.0以降のバージョンを使っているならば、DBD::Informixはユーザ名とパスワードの両方が与えられたときにだけ使いますが、それは以下のものと同値になります:

    EXEC SQL CONNECT TO :database AS :connection
        USER :username USING :password
        WITH CONCURRENT TRANSACTIONS

connectionはDBD::Informixによって与えられる名前です。

DBD::Informixにとって、データベース名はDATABASEまたはCONNECTステートメントに適した形式た名前です。

以下に例をあげます:

    dbase               # 'ローカル' データベース
    //machine1/dbase    # リモート・マシン上のデータベース
    dbase@server1       # (リモートの)サーバ(sqlhostsで定義された)上のデータベース
    @server1            # (リモートの)サーバへの接続、ただしデータベース無し
    /some/where/dbase   # ローカルのSEデータベースに接続

(DBD:::InformixTestでのテストコードではテストデータベースの名前を暗黙のうちに与えてはいますが)データベース名はDBD::Informixによって暗黙のうちには何も与えられません。もしあれば何がデフォルトとして与えられるかについては、DBIドライバのドキュメントをお読みください(例えば、DBI_DRIVERとDBI_DSN環境変数のチェック)。

DBD::Informixは空文字列を見つけたら、ESQL/C 5.0xではどのデータベースにも接続しません、そしてESQL/C 6.00以降ではデフォルト接続をします。追加の文字列".DEFAULT."があります。これはデータベース名として明示的に指定することが出来、デフォルト接続を要求するように解釈されます。これは適切なInformixデータベースではありません、そのため混乱は無いということに注意してください。

一度データベース・ハンドルを手に入れれば、データベースなどについて、いくつかの基本的な情報を質問することが出来ます:

     print "Database Information\n";
     # Type は常に'db'
     print "    Type:                    $dbh->{Type}\n";
     # Nameは接続のさいに指定された名前
     print "    Original Database Name:  $dbh->{Name}\n";
     # ix_DatabaseNameは現在のデータベースの名前
     print "    Current Database Name:   $dbh->{ix_DatabaseName}\n";
     # AutoCommitはデータベースが各ステートメントをコミットするならば1(true) 
     print "    AutoCommit:              $dbh->{AutoCommit}\n";
     # ix_InformixOnLineは、ハンドルがInformix-OnLineサーバに
     # 接続されていれば、1(true)
     print "    Informix-OnLine:         $dbh->{ix_InformixOnLine}\n";
     # ix_LoggedDatabaseはデータベースがトランザクションを持って
     # いれば、1(true)
     print "    Logged Database:         $dbh->{ix_LoggedDatabase}\n";
     # ix_ModeAnsiDatabaseはデータベースがMODE_ANSIならば、1(true)
     print "    Mode ANSI Database:      $dbh->{ix_ModeAnsiDatabase}\n";
     # ix_AutoErrorReportはエラーが検出されたとき報告されるなrば1 (true) 
     # これは廃れてしまっています。-- $dbh->{PrintError}を使ってください。
     print "    AutoErrorReport:         $dbh->{PrintError}\n";
     # ix_InTransactionはデータベースがトランザクション中であれば1 (true) 
     print "    Transaction Active:      $dbh->{ix_InTransaction}\n";
     # ix_ConnectionNameはESQL/Cのconnectionの名前
     # 主にInformix-ESQL/C 6.00以降に適用できます。
     print "    Connection Name:         $dbh->{ix_ConnectionName}\n";

$dbh->{PrintError} がtrueならば、DBIは検出すると、各エラーを自動的にSTDERRに報告します。エラーはパッケージ変数$DBI::errstrと$DBI::errを介して利用することが出来ます。$DBI::errstrにはSQLエラー番号と、もしあればISAMエラー番号が入り、改行で終わることに注意してください。 メッセージは複数の行になるかも、ならないかもしれません。そして通常は80カラムで適切に表示されるように整形されます。メッセージの最後の文字は改行です。$dbh->{PrintError} がfalseならば、DBIはそれらを検出したときに報告しません;エラーが発生したこと知らせ、それらは報告用に上げられます。

DBI->connect() メソッドを使って接続すると、またドライバを忘れてしまったとき、それを以下のようにして再び見つけることが出来ます:

    $drh = $dbh->{Driver};

これにより、前に説明したドライバ・メソッドや属性ににアクセスすることができます。

バージョン0.60から、DATABASE、CLOSE DATABASE、 CREATE DATABASE、 ROLLFORWARD DATABASE そして START DATABASEステートメントが使われるとき、データベースの名前は正確に追跡されます。CONNECTステートメントをprepareできないこと、そのため追跡される必要が無いことに注意してください。


メタデータ

DBI func()を使って、Informixメタデータを比較的簡単に取り出すために、呼び出せる2つのメソッドがあります:

        @list = $dbh->func('_tables');
        @list = $dbh->func('user', '_tables');
        @list = $dbh->func('base', '_tables');
        @list = $dbh->func('user', 'base', '_tables');
        @list = $dbh->func('system', '_tables');
        @list = $dbh->func('view', '_tables');
        @list = $dbh->func('synonym', '_tables');

テーブルのリストはすべて「所有者.テーブル名」('owner'.tablename)のように修飾されます。そしてデータベースにそのテーブルが無いという恐れなしにSQLステートメントで使えます(あなたの後ろでだれかがそれを削除しなければ)。前の引数は返される名前のリストを修飾します。プライベート・シノニムは現在のユーザのためにだけ報告されます。

        @list = $dbh->func('_columns');
        @list = $dbh->func(@tables, '_columns');

listはそれぞれ所有者名、テーブル名、カラム番号、カラム名、基本データ型(ix_ColType値−下記参照)、データ長(ix_ColLength−下記参照)に対応する値の配列へのリファレンスです。何のテーブルもリストになければ、データベースにあるすべてのカラムがリストされます。これは適切にUNION処理を必要とするシノニムを扱っているためにとても遅いことがあります。

さらに'_tables'メソッドはリモート・シノニムの名前を報告しても、'_columns'メソッドはそれらを拡張しません(主に適切にそれを行うのはとても難しいからです)。どのようにこれらを使うことが出来るかは、t/metadata.tの例をご覧ください。練習のために:元の参照されたサイトがさらに3番目のサイトへの名前に転送している再配置されたリモート・シノニムも含めて、リモート・シノニムのカラムについて報告できるように'_columns'を拡張してみてください!


データベースからの切断

以下のようにすればデータベースから切断することも出来ます:

    $dbh->disconnect;

これはコミットされていないすべての作業をロールバックします。これはデータベース・ハンドルを破壊しないことに注意してください。ハンドルを破壊するためには明示的に'undef $dbh'することが必要です。このハンドルを使ってprepareされたすべてのステートメントはfinishされ(下記参照)、再び使うことは出来ません。ステートメントに結び付けられていたすべての空間は解放されます。

$drh{ProductVErsion}>=600であるInformixドライバを使っているならば、複数の並行接続を持つことができます。これは$drh->connectを複数回呼び出すことが、1つあるいは複数の独立した接続を与えることを意味します。

$drh{ProductVErsion}<600であるInformixドライバを使っているならば、複数の並行接続を持つことはできません。もし複数回$drh->connectをすれば、1つの行で複数のdatabaseステートメントを実行しているのと同じ効果を実現することになります。これは一般的にデータベースを正常に切り替えます、しかし以前にprepareされたステートメントをすべて無効にするかもしれません。もし現在のデータベースがローカルでなかったり、アクティブなトランザクションがあったりなどする場合には失敗するかもしれません。


簡単なステートメント

所与のデータベース接続で、何種類もの簡単なステートメントをいくつかの異なる呼び出して実行することができます:

    $dbh->commit;
    $dbh->rollback;

これら2つの操作は現在のトランザクションをコミットあるいはロールバックします。もしデータベースがログなしであれば、これらはなにもしません。

もしAutoCommitが1に設定されていれば、何も有効なことはしません。AutoCommitが0に設定されれば、新しいトランザクションが開始されます(MODE ANSIであるデータベースにとっては暗黙のうちに、MODE ANSIでないデータベースには明示的に)。

たいていのprepare可能なパラメータ無しのステートメントは以下のようにして実行することが出来ます:

    $dbh->do($stmt);

ステートメントにはSELECT(SELECT ... INTO TEMPを除く)やデータを返すプロシージャのEXECUTE PROCEDUREのどちらも指定することができません。

パラメータを持った任意のステートメントを以下のようにして実行することが出来ます:

    $dbh->do($stmt, undef, @parameters);
    $dbh->do($stmt, undef, $param1, $param2);

'undef'はDBIの仕様でドキュメントになっている属性のハッシュへのリファレンス(\%attr)が未定義であることを示します。このドキュメントの0.56エディションはこの引数を省略しており、混乱を招きました。再び、ステートメントはSELECTやデータを返すプロシージャのEXECUTE PROCEDUREのどちらも指定することができません。@parametersの値(または分割された値)はステートメント文字列のクエスチョンマークに結び付けられます。

    $sth = $dbh->prepare($stmt);
    $sth->execute(@parameters);

DBD::Informix バージョン0.26 〜0.55は'do'操作をもっぱら自分自身のために扱ったコードを使い、EXECUTE IMMEDIATEステートメントを出来る限り使ってきました。0.26の前のリリースと0.56からのリリースはDBIパッケージからのコードを使い、EXECUTE IMMEDIATEを使っていません。IMMEDIATE.

ステートメント中にクォーテーション・マークの入った任意の文字列を正しく扱われるように以下のように呼び出すことによって埋め込むことが出来ます:

    $dbh->quote($string);

このメソッドはDBIパッケージの実装によって提供され、DBD::Informixパッケージによって継承されています。文字列はシングル・クォートで囲まれ、SQL-92標準に適合するように、埋め込まれたシングル・クォートは二重化されます。これは典型的には以下のような文脈で使われます:

    $value = "Doesn't work unless quotes (\"'\" and '\"') are handled";
    $stmt = "INSERT INTO SomeTable(SomeColumn) " .
            "VALUES(" . $dbh->quote($value) . ")";

これにより、$valuesに入っているデータが、$valueのなかにどのようなクォートが入っているかにかかわらず(改行文字が入っているのでなければ)正しく解釈されることを保証します。以下のような他の代入はうまく動きません!

    $stmt = "INSERT INTO SomeTable(SomeColumn) VALUES($dbh->quote($value))";

ステートメントの生成

複数回使用するためにステートメントをprepareすることもできます。そしてこれを値を返さない非カーソル・ステートメントと同様に、SELECTや値を返すEXECUTE PROCEDUREステートメント(カーソル・ステートメント)にもすることができます。ステートメント・ハンドル(他のリファレンス)を以下のようにして作成することが出来ます:

    $sth = $dbh->prepare($stmt);

もしステートメントが(SELECT...INTO TEMPでない)データを返すSELECTや値を返すプロシージャのためのEXECUTE PROCEDURE であれば、カーソルがprepareされたステートメントに宣言されます。

DBIの仕様にしたがって、prepare呼び出しはハッシュへのリファレンスであるオプションの属性パラメータを受け取ります。そのとき、パラメータはなにも理解されません。それは追加するのに適正で、例えばで宣言されると指定します。{ix_CursorWithHold => 1}は、 カーソルはWITH HOLDで宣言されると指定します。同様にステートメント毎のblob位置付けをサポートするように{ix_BlobLocation => 'InFile'} を、スクロール・カーソルをサポートするように{ix_ScrollCursor => 1}を追加することが出来ます。

注意:DBD::Informix 0.25より前のバージョンでは、ステートメントをprepareすることも非カーソル・ステートメントを実行し、カーソル・ステートメントのためのカーソルを開いています。これはもはや発生しません。

さらに典型的には、エラー・チェックをする必要があり、これは以下のようにして成し遂げることが出来ます:

    die "Failed to prepare '$stmt'\n"
        unless ($sth = $dbh->prepare($stmt));

バグ:ステートメントが実行可能なだけであるか、カーソル(取り出すことが出来る)ステートメントであるかを知らせる方法はありません。あなたが知っているものと仮定されます。{ix_IsCursory}のような属性を追加し、情報のキーのかけらを提供することはできます。これはInformix特有のことではありません。

一度ステートメントがprepareされると、それを実行することができます:

    $sth->execute;

非カーソル・ステートメントにとって、これは単にそのステートメントを実行します。ステートメトが正常に実行されれば、影響を受けた行の数が返されます。エラーが発生すれば、返される値はundefです。ステートメントが何の行にも影響を与えなければ、文字列"0E0"が返されます。これはtrueに解釈されますが、同時に0でもあります。

カーソル・ステートメントにとっては、これはカーソルをオープンします。カーソルが正常にオープンされれば、"0E0"の値が返されます。これはtrueに解釈されますが、同時に0でもあります。もしエラーが発生すれば、返される値はundefです。

DBI 0.85 仕様はこのことについて何も言っていませんが、利用するためにステートメントに入力パラメータを指定することもできます。

    $sth->execute(@parameters);

最初のパラメータは最初のプレース・ホルダであるクエスチョン・マークのための値として与えられます、2番目のパラメータは2番目のプレース・ホルダのなどなど。

論点:そのとき、いくつの入力パラメータが与えられ、いくつが必要なのかはDBD::Informixによってはチェックされません。InformixエンジンはINSERTステートメントのVALUES節にあるものを除いては入力パラメータの数の判定のサポートを与えていません。これは解決に必要です。

論点: InformixエンジンはINSERTステートメントのVALUES節にあるものを除いては入力パラメータの型の判定のサポートをしていません。これはDBD::InformixがUPDATEステートメントのSET節でblobを扱うことが出来ないことを意味します。これを扱うための分かっている唯一の方法は、SELECTを使って昔のデータを取り出し、DELETEでそれを削除し、INSERTで変更されたデータで置きかえることです。よくはありませんが、機能します。

警告:最近のDBIのバージョンはステートメントのための入力パラメータをPerl変数に結びつけるためのメソッドを指定しています。このため、これは変更のための他の領域の題材です。

カーソル・ステートメントでは、返されるカラム名、型、NULLにできるかどうかなどをわかることができます。以下のようにしてできます:

    @name = @{$sth->{NAME}};        # カラム名
    @null = @{$sth->{NULLABLE}};    # True => NULLを受け入れる
    @type = @{$sth->{TYPE}};        # ODBC データ型番号
    @prec = @{$sth->{PRECISION}};   # ODBC PRECISION数値(桁数)(またはundef)
    @scal = @{$sth->{SCALE}};       # ODBC SCALE 数値(小数点以下桁数) (または undef)
    # ネイティブな(Informix) 型と同等
    @tnam = @{$sth->{ix_NativeTypeName}};# 型名
    @tnum = @{$sth->{ix_ColType}};       # SysColumns.ColTypeからのType番号
    @tlen = @{$sth->{ix_ColLength}};     # SysColumns.ColLengthからのType長

注意: Informix は $sth->{NAME} の中で、SELECTリストの中でエイリアスされていない計算された値やストアド・プロシージャからの戻り値を記述したりなどのために'(式)' を使います。これは有効に改良されるでしょう。返される名前がユニークであることも保証しません。例えば"SELECT A.Column, B.Column FROM Table1 A, Table1 B WHERE ..."では、返されるカラムは両方とも'column'と記述されます。

ステートメントがカーソル・ステートメントであれば、DBI仕様で記述された、いろんな方法でデータを取り出すことができます。

        $ref = $sth->fetchrow_arrayref;
    $ref = $sth->fetch;                                 # 他の書き方...
    @row = @{$ref};
    @row = @{$sth->fetchrow_arrayref};  # 上記を短くした書き方...
    @row = $sth->fetchrow_array;
    $ref = $sth->fetchall_arrayref;

通常は、これが動くかどうかを心配する必要があります。このため通常は以下のようにします:

    while ($ref = $sth->fetch)
    {
        # ここでなんらかのデータがとれたことがわかります
        ...
    }
    # エラーが発生したか、SELECTが単にもう返すものがなくなったのかを
    # 調べます
    if ($sth->{sqlcode} < 0)
    {
        # エラーの処理...
    }

返されたblobが入ったデータは文字列に対応付けられます。バイトblobはASCII NULL '\0'が入っているかもしれないことに注意してください。Perlは文字列の長さを知っており、バイトblobの真中にNULを残しています。しかしこの文字列の扱い方を決めるには注意が必要です。

blobをどのように扱いたいのかを指定するための準備があります。以下のように属性を設定することができます:

    $sth->{ix_BlobLocation} = 'InMemory';      # デフォルト
    $sth->{ix_BlobLocation} = 'InFile';        # 名前のついたファイルの中
    $sth->{ix_BlobLocation} = 'DummyValue';    # ダミーの値を返す
    $sth->{ix_BlobLocation} = 'NullValue';     # 未定義値を返す

InFileモードは取り出された配列の中にファイルの名前を返します。そのファイルはPerlの通常のファイル・アクセス・メソッドを使ってアクセスすることができます。DummyValueモードはテキストblobには"<<TEXT VALUE>>"を、バイト(バイナリ)blobには"<<BYTE VALUE>>"を返します。NullValueモードは未定義値(つまりPerlの"defined"演算子がfalseを返す)を返します。これら2つのオプションが必然的にサーバにアプリケーションへデータを返すことを妨げるわけではないのですが、ユーザはデータを見るために取り出さないということに注意してください--これはSQL記述子との合同でのESQL/C FETCH操作の実装に依存します。

これを置きかえるために、ステートメントレベルでデータベースにix_BlobLocation 属性を設定することができます。

バグ: ix_BlobLocation は適切に扱われません。

必要なだけ行を取り出したら、使っているカーソルを以下のようにして閉じます:

    $sth->finish;

もしデータを取り出すのに失敗した取出しを実行したならば、明示的にカーソルをfinishする必要がありません。

$sth->finishをすることは単にカーソルを閉じます。カーソルやステートメントを解放しません。それはステートメント・ハンドルを破壊(undef)したときに行われます:

    undef $sth;

単に同じ変数を再び使うことによって、暗黙のうちに新しいステートメントにステートメント・ハンドルを再設定することもできます。 これによってメモリ・リークを発生することはありません。

ix_StatementText 属性を使ってステートメントのテキストを(再)取得することができます。

        $txt = $sth->{ix_StatementText};

更新のためのカーソル

DBD::Informix v0.51以降では、カーソルの名前を取り出すために$sth->{CursorName} 属性を使うことができます。$sthのためのステートメントが実際にSELECTで、カーソルがMODE ANSIデータベースであるか、'FOR UPDATE [OF col, ...'タグ付きで宣言されたならば、カーソル名を'DELETE...WHERE CURRENT OF'や'UPDATE...WHERE CURRENT OF'ステートメントのなかで使うことができます。

    $st1 = $dbh->prepare("SELECT * FROM SomeTable FOR UPDATE");
    $wc = "WHERE CURRENT OF $st1->{CursorName}";
    $st2 = $dbh->prepare("UPDATE SomeTable SET SomeColumn = ? $wc");
    $st3 = $dbh->prepare("DELETE FROM SomeTable $wc");
    $st1->execute;
    $row = $st1->fetch;
    $st2->execute("New Value");
    $row = $st1->fetch;
    $st3->execute();

SQLCAレコードへのアクセス

データベース・ハンドルやステートメント・ハンドルを介してSQLCA レコードにアクセスすることができます。

    $sqlcode = $sth->{ix_sqlcode};
    $sqlerrm = $sth->{ix_sqlerrm};
    $sqlerrp = $sth->{ix_sqlerrp};
    @sqlerrd = $sth->{ix_sqlerrd};
    @sqlwarn = $sth->{ix_sqlwarn};

警告情報が(Informix-ESQL/Cのように)一連の分割されたフィールドではなく、(Informix-4GLのように)配列で扱われることに注意してください。これらの使い方についてのさらなるアイデアについてはInformixTestpmでのprint_sqlca()関数のコードを調べてください。sqlcaレコードを設定することはできません。


トランザクション管理

DBI仕様が変更されたために、トンラザクション管理はDBD::Informix 0.56リリースで一部変更されました。このセクションを注意して読んでください。ドキュメントに書かれていることと実際に発生していることとに逸脱を見つけたならば、それを報告してください。問題はドキュメントかコード(あるいは両方)にあるかもしれません。

以前は、InformixデータベースのタイプがデフォルトのAutoCommit属性に影響を与えていました。今やAutoCommit属性(DBI->connect()呼び出しで設定することができます)だけが、AutoCommitの動きを制御します。


AutoCommitとInformixデータベースとの相互関係

Informixデータベースには考慮すべき3つのタイプがあります:MODE ANSI、ログあり(Logged)、ログなし(UnLogged)です。MODE ANSI データベースもトランザクション・ログを持っていますが、ログありデータベースのカテゴリは特にMODE ANSIデータベースを除外しています。OnLineでは、これはWITH LOGまたはWITH BUFFERED LOGで作成されたデータベースを参照します。SETではWITH LOG IN "/some/file/name"で作成されたデータベースです。

AutoCommitには考慮すべき2つモードOn、Offがあります。

2つの可能なトランザクション状態があります:In-TX (トランザクションの中)、No-TX (トランザクションの外)

考慮すべき少なくとも13のステートメントのタイプがあります(4つのグループと9つのサブグループ):

    $drh->connect('xyz');                   # Group 1A
    $dbh->do('DATABASE xyz');               # Group 1B
    $dbh->do('CREATE DATABASE xyz');        # Group 1B
    $dbh->do('ROLLFORWARD DATABASE xyz');   # Group 1B
    $dbh->do('START DATABASE xyz');         # Group 1B
    $dbh->disconnect();                     # Group 2A
    $dbh->do('CLOSE DATABASE');             # Group 2B
    $dbh->commit();                         # Group 3A
    $dbh->rollback();                       # Group 3A
    $dbh->do('BEGIN WORK');                 # Group 3B
    $dbh->do('ROLLBACK WORK');              # Group 3C
    $dbh->do('COMMIT WORK');                # Group 3C
    $dbh->prepare('SELECT ...');            # Group 4A
    $dbh->prepare('UPDATE ...');            # Group 4B

Group 1 ステートメントはデータベースへの接続を確立します。接続するデータベースのタイプはAutoCommitモードに影響を与えません。Group 1A はデータベース接続の主な方法です;Group 1B ステートメントは現在のデータベースを変更することができます。Group 1B ステートメントは、ESQL/C 6.00以降を使っているならば、".DEFAULT"接続を除いては実行することができません。

データベースの全てのタイプにとって、デフォルトのAutoCommitモードはOnです。MODE ANSIまたはログありデータベースでは、AutoCOmmitの値はOffに設定することができます、これは自動的にトランザクションを開始します(もしデータベースがログありであれば明示的に、MODE ANSIであれば暗黙のうちに)。

ログなし(UnLogged)データベースでは、AutoCommitモードは変更することが出来ません。ログなしデータベースでAutoCommitモードをOffに変更しようとすると、致命的でない警告が発生します。

Group 2ステートメントはデータベースへの接続を切断します。Group 2Aステートメントはデータベース・ハンドルを使えなくします;'undefまたは新しい接続の再代入を除いては、なにも操作することが出来ません。Group 2Bステートメントは、Group1Bや'DROP DATABASE'以外の操作がそのハンドルに許されないことを意味します。Group 1Bであれば、Group 2Bステートメントは".DEFAULT"接続にしか使うことが出来ません。

データベースが閉じた後、AutoCommitの値は不適切ですが、DBD::Informixによって変更されません。

Group 3 と 4 ステートメントは多くの複雑な方法で相互に関係し合いますが、新しい操作スタイルは相当に相互作用を感田にします。変更の副作用の1つはBEGIN WORKは完全に限界すれすれにされ、そして一般的にエラーを発生します。UPDATEがGroup 4Bに引用されていますが、これはSELECT以外のステートメントすべてを表します。

プログラムには何もデータを返さないために、'SELECT...INTO TEMP'はGroup 4B ステートメントであることに注意してください。'EXECUTE PROCEDURE'ステートメントはデータを返すのであればGroup 4A、データを返さなければGroup 4Bです。そしてステートメントがprepareされるまでは2つのどちらのグループが適用されるかはわかりません。


MODE ANSIデータベース

以前は、MODE ANSI データベースはすべての時点でトランザクションがあることだと考えられていましたが、これらのデータベースが働く方法を見る唯一の方法ではありません。しかしながら、データベースがオープンされた直後の状態や、COMMIT WORKやROLLBACK WORK処理の直後にNo-Tx状態にあることを考えることはより満足させます。

切断ステートメント(Group 2)やコミットやロールバック(Groups 3A または 3C)以外のステートメントは、データベースをIn-TX状態に します。

MODE ANSIデータベースでは、BEGIN WORKを正常に実行することができます。しかし、AutoCommitがOnならば、トランザクションはすぐにコミットされ、そのためよくはありません。AutoCommitをOnに変更するならば、うまくいきます。コミットされるGroup 4Bステートメントがアクティブなカーソルを閉じないように、すべてのカーソルはWITH HOLDで宣言される必要があります。Group 4Bステートメントが実行されるときはいつも、ステートメントはコミットされる必要があります。OnLineでは(そして理論できにはSEでも)、もしステートメントが失敗しても、ロールバックをする必要がありません--いずれにせよ失敗したステートメントはロールバックされるのです。上記のため、実際には必要でなくても切断の前にコードがROLLBACK WORKします。


ログありデータベース(Logged Database)

以前は、ログあり(Logged)とMODE ANSIデータベースにはいくつか大きな違いがありました。大きな1つの変化の進歩は、今や基本的にこの2つに違いがないことです。

BEGIN WORKを実行することは何の役にも立たないことに注意してください;有効な結果を得るためには、AutoCommitモードを明示的に切り替える必要があります。


ログなしデータベース(Unlogged Database)

トランザクション状態はNo-TXで、AutoCommit はOn、そしてこれを変更することはできません。AutoCommitをOffに設定しようとすると、致命的でない警告を発生しますが、プログラムは継続します;Onに設定することは警告もエラーも発生しません。$dbh->commit と$dbh->rollbackの両方が成功しますが何もしません。Group 3Bまたは3Cのいずれかのステートメントを実行するとエラーが発生します。

AutoCommitがOffでログなし(Unlogged)データベースに接続しようとするならば、接続失敗となるのが理想的です。障害発生時のDBI 0.85の動き方のために、これは実装上、問題があります。そのため実際には実装されていません。


属性名の変更

以前のリリースでは、Informix特有の属性は'ix_'から始まる名前を持っていませんでした。リリース0.57から、古いものが見つかると、(DBIによって)エラーメッセージが発生します。

Note that {ix_AutoErrorReport}は{PrintError}になることに注意してください;2つの名前はいくつかのバージョンではおなじになっており、{ix_AutoErrorReport} はなくなります。他のいくつかのInformix特有の属性もDBI仕様に合わせられる(多分名前の変更とともに)であろうことに注意してください。これらも削除される前に、最初は公式のDBI名と同じように扱われます。属性の名前変更を追いかけている人たちにとっては、新しい削除サイクルは5リリースよりも短いことでしょう。

'ix_'で始まる理解されない属性は、警告メッセージを発生します。


ESQL/CとDBD::INFORMIXの対応

DBD::InformixとESQL/C同値との対応のおおざっぱな形式で以下に示します--とても正確とはいえないところ(例えばAutoCommitの影響)がたくさんありますが、ほとんどの目的には十分に正確でしょう。

        DBI->connect            => DATABASE (5.0x)
        $dbh->disconnect        => CLOSE DATABASE (5.0x)
        DBI->connect            => CONNECT (6.0x 以降)
        $dbh->disconnect        => DISCONNECT (6.0x以降)
        $dbh->commit            => COMMIT WORK (+BEGIN WORK)
        $dbh->rollback          => ROLLBACK WORK (+BEGIN WORK)
        $dbh->do                => EXECUTE IMMEDIATE
        $dbh->prepare           => PREPARE, DESCRIBE (DECLARE)
        $sth->execute           => EXECUTE または OPEN
        $sth->fetch             => FETCH
        $sth->fetchrow          => FETCH
        $sth->finish            => CLOSE
        undef $sth              => FREE cursor, FREE statement, など

既知の制限


作者

いろいろな時期がありました:


参考資料

perl(1), perldoc for DBI.


ホーム Perlの小技

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