Tripletail::DB - DBIのラッパ
$TL->startCgi( -DB => 'DB', -main => \&main, ); sub main { my $DB = $TL->getDB('DB'); $DB->setDefaultSet('R_Trans'); $DB->tx(sub{ my $sth = $DB->execute(q{SELECT a, b FROM foo WHERE a = ?}, 999); while (my $hash = $sth->fetchHash) { print $hash->{a}; } # commit is done implicitly. }); $DB->tx('W_Trans' => sub{ $DB->execute(q{UPDATE counter SET counter = counter + 1 WHERE id = ?}, 1); $DB->commit; # can commit explicitly. } }
手動で接続/切断する場合は、connect/disconnectを使う。
$db->execute(q{select * from a where mode in (??)}, ['a', 'b'])
と記述すると、
$db->execute(q{select * from a where mode in (?, ?)}, 'a', 'b')
のように解釈される。
$db->execute(q{select * from a limit ??}, ['a', \'SQL_INTEGER'])
Tripletail::DBでは、レプリケーションを利用してロードバランスすることを支援するため、 1つのDBグループの中に、複数のDBセットを定義することが可能となっている。 DBセットの中には、複数のDBコネクションを定義できる。
更新用DBセット、参照用DBセット、などの形で定義しておき、プログラム中で トランザクション単位でどのDBセットを使用するか指定することで、 更新用クエリはマスタDB、参照用クエリはスレーブDB、といった 使い分けをすることが可能となる。
DBセットには複数のDBコネクションを定義でき、複数定義した場合は プロセス単位でプロセスIDを元に1つのコネクションが選択される。 (プロセスIDを定義数で割り、その余りを使用して決定する。)
同じDBグループの中の複数のDBセットで同じDBコネクション名が使用された場合は、 実際にDBに接続されるコネクション数は1つとなる。 このため、縮退運転時に参照用DBセットのDBコネクションを更新用の ものに差し替えたり、予め将来を想定して多くのDBセットに分散 させておくことが可能となっている。
DBセットの名称はSET_XXXX(XXXXは任意の文字列)でなければならない。 DBコネクションの名称はCON_XXXX(XXXXは任意の文字列)でなければならない。
TripletailのDBクラスはDBIに対するラッパの形となっており、多くのインタフェースはDBIのものとは異なる。 ただし、いつでも $DB->getDbh() メソッドにより元のDBIオブジェクトを取得できるので、DBIのインタフェースで利用することも可能となっている。
$DB->getDbh()
DBIのインタフェースは以下のようなケースで利用できる。ただし、DBIを直接利用する場合は、TLの拡張プレースホルダやデバッグ機能、トランザクション整合性の管理などの機能は利用できない。
(例)$DB->{mysql_insertid}
DBIに対するラッパであるため、大量のSQLを実行する場合などはパフォーマンス上のデメリットがある。
DBIでのSELECTは、以下のように置き換えられる。
# DBI my $sth = $DB->prepare(q{SELECT * FROM test WHERE id = ?}); $sth->execute($id); while(my $data = $sth->fetchrow_hashref) { } # TL my $sth = $DB->execute(q{SELECT * FROM test WHERE id = ?}, $id); while(my $data = $sth->fetchHash) { }
TLではprepare/executeは一括で行い、prepared statement は利用できない。
INSERT・UPDATEは、以下のように置き換えられる。
# DBI my $sth = $DB->prepare(q{INSERT INTO test VALUES (?, ?)}); my $ret = $sth->execute($id, $data); # TL my $sth = $DB->execute(q{INSERT INTO test VALUES (?, ?)}, $id, $data); my $ret = $sth->ret;
prepare/executeを一括で行うのは同様であるが、executeの戻り値は$sthオブジェクトであり、影響した行数を取得するためには $sth->ret メソッドを呼ぶ必要がある。
$sth->ret
プレースホルダの型指定は以下のように行う。
# DBI my $sth = $DB->prepare(q{SELECT * FROM test LIMIT ?}); $sth->bind_param(1, $limit, { TYPE => SQL_INTEGER }); $sth->execute; # TL my $sth = $DB->execute(q{SELECT * FROM test LIMIT ??}, [$limit, \'SQL_INTEGER']);
TLの拡張プレースホルダ(??で表記される)を利用し、配列のリファレンスの最後に型をスカラのリファレンスの形で渡す。 拡張プレースホルダでは、複数の値を渡すことも可能である。
# DBI my $sth = $DB->prepare(q{SELECT * FROM test LIMIT ?, ?}); $sth->bind_param(1, $limit, { TYPE => SQL_INTEGER }); $sth->bind_param(2, $offset, { TYPE => SQL_INTEGER }); $sth->execute; # TL my $sth = $DB->execute(q{SELECT * FROM test LIMIT ??}, [$limit, $offset, \'SQL_INTEGER']);
最後にINSERTした行のAUTO_INCREMENT値の取得などは、拡張ラッパでは制御できないので、DBIのハンドラを直接利用する。
# DBI my $id = $DB->{mysql_insertid}; # TL my $id = $DB->getDbh()->{mysql_insertid};
トランザクションには $DB->tx(sub{...}) メソッドを用いる。 DBセットを指定する時には $DB->tx(dbset_name=>sub{...}) となる。 渡したコードをトランザクション内で実行する。 die なしにコードを抜けた時に自動的にコミットされる。 途中で die した場合にはトランザクションはロールバックされる。
$DB->tx(sub{...})
$DB->tx(dbset_name=>sub{...})
# DBI $DB->do(q{BEGIN WORK}); # do something. $DB->commit; # TL $DB->tx(sub{ # do something. });
begin() メソッドも実装はされているがその使用は非推奨である。 また、 $DB->execute(q{BEGIN WORK}); は無効にされている。
begin()
$DB->execute(q{BEGIN WORK});
"execute" に渡されるSQL文には、通常のプレースホルダの他に、 拡張プレースホルダ "??" を埋め込む事が出来る。 拡張プレースホルダの置かれた場所には、パラメータとして通常のスカラー値でなく、 配列へのリファレンスを与えなければならない。配列が複数の値を持っている場合には、 それらが通常のプレースホルダをカンマで繋げたものに展開される。
例: 以下の二文は等価
$DB->execute( q{SELECT * FROM a WHERE a IN (??) AND b = ?}, ['AAA', 'BBB', 'CCC'], 800); $DB->execute( q{SELECT * FROM a WHERE a IN (?, ?, ?) AND b = ?}, 'AAA', 'BBB', 'CCC', 800);
パラメータとしての配列の最後の項目が文字列へのリファレンスである時、その文字列は SQL型名として扱われる。配列が複数の値を持つ時には、その全ての要素に対して 型指定が適用される。型名はDBI.pmで定義される。
例:
$DB->execute(q{SELECT * FROM a LIMIT ??}, [20, \'SQL_INTEGER']); ==> SELECT * FROM a LIMIT 20 $DB->execute(q{SELECT * FROM a LIMIT ??}, [20, 5, \'SQL_INTEGER']); ==> SELECT * FROM a LIMIT 20, 5
配列内の要素を更に2要素の配列とし、二番目の要素を文字列へのリファレンスと する事で、要素の型を個別に指定出来る。
$DB->execute( q{SELECT * FROM a WHERE a IN (??) AND b = ?}, [[100, \'SQL_INTEGER'], 'foo', \'SQL_VARCHAR'], 800); ==> SELECT * FROM a WHERE a IN (100, 'foo') AND b = '800'
Tripletail::DB
$TL->getDB
$DB = $TL->getDB $DB = $TL->getDB($inigroup)
Tripletail::DB オブジェクトを取得。 引数にはIniで設定したグループ名を渡す。 引数省略時は 'DB' グループが使用される。
$TL->startCgi / $TL->trapError の関数内でDBオブジェクトを取得する場合に使用する。
$TL->newDB
$DB = $TL->newDB $DB = $TL->newDB($inigroup)
新しく Tripletail::DB オブジェクト作成。 引数にはIniで設定したグループ名を渡す。 引数省略時は 'DB' グループが使用される。
動的にコネクションを作成したい場合などに使用する。 この方法で Tripletail::DB オブジェクトを取得した場合、"connect" / "disconnect" を呼び出し、接続の制御を行う必要がある。
connect
DBに接続する。
$TL->startCgi / $TL->trapError の関数内でDBオブジェクトを取得する場合には自動的に接続が管理されるため、このメソッドを呼び出してはならない。
$TL->newDB で作成した Tripletail::DB オブジェクトに関しては、このメソッドを呼び出し、DBへ接続する必要がある。
connect時には、AutoCommit 及び RaiseError オプションは 1 が指定され、PrintError オプションは 0 が指定される。
disconnect
DBから切断する。
$TL->newDB で作成した Tripletail::DB オブジェクトに関しては、このメソッドを呼び出し、DBへの接続を切断する必要がある。
tx
$DB->tx(sub{...}) $DB->tx('SET_W_Trans' => sub{...})
指定されたDBセット名でトランザクションを開始し、その中でコードを 実行する。トランザクション名(DBセット名) はiniで定義されていな ければならない。名前を省略した場合は、デフォルトのDBセットが使われるが、 setDefaultSetによってデフォルトが選ばれていない場合には例外を発生させる。
コードを die なしに終了した時にトランザクションは暗黙にコミットされる。 die した場合にはロールバックされる。 コードの中で明示的にコミット若しくはロールバックを行うこともできる。 明示的にコミット若しくはロールバックをした後は、 tx を抜けるまで DB 操作は禁止される。 この間の DB 操作は例外を発生させる。
rollback
$DB->rollback
現在実行中のトランザクションを取り消す。
commit
$DB->commit
現在実行中のトランザクションを確定する。
inTx
$DB->inTx() and die "double transaction"; $DB->inTx('SET_W_Trans') or die "transaction required";
既にトランザクション中であるかを確認する。 既にトランザクション中であれば真を、 他にトランザクションが走っていなければ偽を返す。 トランザクションの指定も可能。 異なるDBセット名のトランザクションが実行中だった場合には 例外を発生させる。
begin
$DB->begin $DB->begin('SET_W_Trans')
非推奨。"tx" を使用のこと。
指定されたDBセット名でトランザクションを開始する。トランザクション名 (DBセット名) はiniで定義されていなければならない。 名前を省略した場合は、デフォルトのDBセットが使われるが、 setDefaultSetによってデフォルトが選ばれていない場合には例外を発生させる。
CGIの中でトランザクションを開始し、終了せずにMain関数を抜けた場合は、自動的に rollbackされる。
トランザクション実行中にこのメソッドを呼んだ場合には、例外を発生させる。 1度に開始出来るトランザクションは、1つのDBグループにつき1つだけとなる。
setDefaultSet
$DB->setDefaultSet('SET_W_Trans')
デフォルトのDBセットを選択する。ここで設定されたDBセットは、引数無しのbegin() や、beginせずに行ったexecuteの際に使われる。このメソッドは Main関数 の先頭で呼ばれる事を想定している。
execute
$DB->execute($sql, $param...) $DB->execute(\'SET_W_Trans' => $sql, $param...)
SELECT/UPDATE/DELETEなどのSQL文を実行する。 第1引数にSQL、第2引数以降にプレースホルダの引数を渡す。 ただし、第1引数にリファレンスでDBセットを渡すことにより、 トランザクション外での実行時にDBセットを指定することが可能。
第2引数以降の引数では、拡張プレースホルダが使用できる。 "拡張プレースホルダ詳細" を参照。
既にトランザクションが実行されていれば、そのトランザクションの DBセットでSQLが実行される。
トランザクションが開始されておらず、かつ "lock" により テーブルがロックされていれば、ロックをかけているDBセットでSQLが実行される。
いずれの場合でもない場合は、"setDefaultSet" で指定された トランザクションが使用される。 "setDefaultSet" による設定がされていない場合は、例外を発生させる。
このメソッドを使用して、LOCK/UNLOCK/BEGIN/COMMITといったSQL文を 実行してはならない。実行しようとした場合は例外を発生させる。 代わりに専用のメソッドを使用する事。
selectAllHash
$DB->selectAllHash($sql, $param...) $DB->selectAllHash(\'SET_W_Trans' => $sql, $param...)
SELECT結果をハッシュの配列へのリファレンスで返す。 データがない場合は [] が返る。
my $arrayofhash = $DB->selectAllHash($sql, $param...); foreach my $hash (@$arrayofhash){ $TL->log(DBDATA => "name of id $hash->{id} is $hash->{name}"); }
selectAllArray
$DB->selectAllArray($sql, $param...) $DB->selectAllArray(\'SET_W_Trans' => $sql, $param...)
SELECT結果を配列の配列へのリファレンスで返す。 データがない場合は [] が返る。
my $arrayofarray = $DB->selectAllArray($sql, $param...); foreach my $array (@$arrayofarray){ $TL->log(DBDATA => $array->[0]); }
selectRowHash
$DB->selectRowHash($sql, $param...) $DB->selectRowHash(\'SET_W_Trans' => $sql, $param...)
SELECT結果の最初の1行をハッシュへのリファレンスで返す。 実行後、内部でfinishする。 データがない場合は undef が返る。
my $hash = $DB->selectRowHash($sql, $param...); $TL->log(DBDATA => "name of id $hash->{id} is $hash->{name}");
selectRowArray
$DB->selectRowArray($sql, $param...) $DB->selectRowArray(\'SET_W_Trans' => $sql, $param...)
SELECT結果の最初の1行を配列へのリファレンスで返す。 実行後、内部でfinishする。 データがない場合は undef が返る。
my $array = $DB->selectRowArray($sql, $param...); $TL->log(DBDATA => $array->[0]);
lock
$DB->lock(set => 'SET_W_Trans', read => ['A', 'B'], write => 'C')
指定されたDBセットに対してLOCK TABLESを実行する。setが省略された場合はデフォルト のDBセットが選ばれる。CGIの中でロックした場合は、 Main関数 を抜けた時点で自動的にunlockされる。
ロック実行中にこのメソッドを呼んだ場合には、例外を発生させる。 1度に開始出来るロックは、1つのDBグループにつき1つだけとなる。
unlock
$DB->unlock
UNLOCK TABLES を実行する。 ロックがかかっていない場合は例外を発生させる。
setBufferSize
$DB->setBufferSize($kbytes)
バッファサイズをKB単位でセットする。行を1行読み込んだ結果 このサイズを上回る場合、dieする。 0 または undef をセットすると、制限が解除される。
die
0
undef
symquote
$DB->symquote($sym)
文字列を識別子としてクォートする。
mysqlの場合は `a b c` となり、それ以外の場合は "a b c" となる。
`a b c`
"a b c"
$DB->getType;
DBのタイプを返す。(mysql, pgsql, ...)
(mysql, pgsql, ...)
$dbh = $DB->getDbh $dbh = $DB->getDbh('SET_W_Trans')
DBセット内のDBハンドルを返す。 返されるオブジェクトは DBI ネイティブのdbhである。
ネイティブのDBハンドルを使用してクエリを発行した場合、デバッグ機能(プロファイリング等)の機能は使用できません。 また、トランザクションやロック状態の管理もフレームワークで行えなくなるため、注意して使用する必要があります。
$id = $DB->getLastInsertId()
セッション内の最後の自動採番の値を取得.
Tripletail::DB::STH
fetchHash
$sth->fetchHash
ハッシュへのリファレンスで1行取り出す。
fetchArray
$sth->fetchArray
配列へのリファレンスで1行取り出す。
ret
最後に実行した execute の戻り値を返す。
rows
$sth->rows
DBIと同様。
finish
$sth->finish
nameArray
$sth->nameArray
$sth->{NAME_lc} を返す。
$sth->{NAME_lc}
nameHash
$sth->nameHash
$sth->{NAME_lc_hash} を返す。
$sth->{NAME_lc_hash}
DBグループのパラメータのうち、半角小文字英数字のみで構成された パラメータは予約済みで、DBグループの動作設定に使用する。 DBセットは、予約済みではない名前であれば任意の名称が使用でき、 値としてDBコネクションのINIグループ名をカンマ区切りで指定する。
[DB] namequery=1 type=mysql defaultset=SET_R_Trans SET_W_Trans=CON_DBW1 SET_R_Trans=CON_DBR1,CON_DBR2 [CON_DBW1] dbname=test user=daemon host=192.168.0.100 [CON_DBR1] dbname=test user=daemon host=192.168.0.110 [CON_DBR2] dbname=test user=daemon host=192.168.0.111
以下は特別なパラメータ:
namequery
namequery = 1
これを1にすると、実行しようとしたクエリのコマンド名の直後に /* foo.pl:111 [DB.R_Transaction1.DBR1] */ のようなコメントを挿入する。 デフォルトは0。
/* foo.pl:111 [DB.R_Transaction1.DBR1] */
type
type = mysql
DBの種類を選択する。 mysql, pgsql, oracle, sqlite, mssql が使用可能。 必須項目。
defaultset
defaultset = SET_W_Trans
デフォルトのDBセットを設定する。 ここで設定されたDBセットは、引数無しのbegin()や、beginせずに行ったexecuteの際に使われる。
dbname
dbname = test
DB名を設定する。
host
host = localhost
DBのアドレスを設定する。 デフォルトはlocalhost。
user
user = www
DBに接続する際のユーザー名を設定する。
password
password = PASS
DBに接続する際のパスワードを設定する。 省略可能。
試験的に SQL Server との接続が実装されています. DBD::ODBC と, Linux であれば unixODBC + freetds で, Windows であれば 組み込みの ODBC マネージャで動作します.
設定例:
# <tl.ini> [DB] type=mssql defaultset=SET_W_Trans SET_W_Trans=CON_RW [CON_RW] # dbname に ODBC-dsn を設定. dbname=test user=test password=test # freetds経由の時は, そちらのServernameも指定. tdsname=tds_test
freetdsでの接続文字コードの設定は freetds.conf で 設定します.
;; <freetds.conf> [tds_test] host = 10.0.0.1 ;;port = 1433 tds version = 7.0 client charset = UTF-8
Tripletail
Copyright 2006 YMIRLINK Inc. All Rights Reserved.
This framework is free software; you can redistribute it and/or modify it under the same terms as Perl itself
このフレームワークはフリーソフトウェアです。あなたは Perl と同じライセンスの 元で再配布及び変更を行うことが出来ます。
Address bug reports and comments to: tl@tripletail.jp
HP : http://tripletail.jp/
To install Tripletail, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Tripletail
CPAN shell
perl -MCPAN -e shell install Tripletail
For more information on module installation, please visit the detailed CPAN module installation guide.