| ... | ... | @@ -1,23 +0,0 @@ | 
| 1 | -use strict; | |
| 2 | -use warnings; | |
| 3 | -use Module::Build; | |
| 4 | - | |
| 5 | -my $builder = Module::Build->new( | |
| 6 | - module_name => 'DBIx::Custom', | |
| 7 | - license => 'perl', | |
| 8 | - dist_author => 'Yuki Kimoto <kimoto.yuki@gmail.com>', | |
| 9 | - dist_version_from => 'lib/DBIx/Custom.pm', | |
| 10 | -    build_requires => { | |
| 11 | - 'Test::More' => 0, | |
| 12 | - }, | |
| 13 | -    requires => { | |
| 14 | - 'Object::Simple' => 3.0201, | |
| 15 | - 'DBI' => 1.605, | |
| 16 | - 'DBD::SQLite' => 1.25, | |
| 17 | - 'Time::Piece' => 1.15 | |
| 18 | - }, | |
| 19 | - add_to_cleanup => [ 'DBIx-Custom-*' ], | |
| 20 | - create_makefile_pl => 'traditional', | |
| 21 | -); | |
| 22 | - | |
| 23 | -$builder->create_build_script(); | 
| ... | ... | @@ -1,3 +1,6 @@ | 
| 1 | +0.1619 | |
| 2 | + updated document | |
| 3 | + added experimental expand method | |
| 1 | 4 | 0.1618 | 
| 2 | 5 | added helper method | 
| 3 | 6 | added begin_work, commit, and rollback method | 
| ... | ... | @@ -1,6 +1,6 @@ | 
| 1 | 1 | DBIx-Custom | 
| 2 | 2 |  | 
| 3 | -Custamizable DBI | |
| 3 | +DBI interface, having hash parameter binding and filtering system | |
| 4 | 4 |  | 
| 5 | 5 | INSTALLATION | 
| 6 | 6 |  | 
| ... | ... | @@ -1,6 +1,6 @@ | 
| 1 | 1 | package DBIx::Custom; | 
| 2 | 2 |  | 
| 3 | -our $VERSION = '0.1618'; | |
| 3 | +our $VERSION = '0.1619'; | |
| 4 | 4 |  | 
| 5 | 5 | use 5.008001; | 
| 6 | 6 | use strict; | 
| ... | ... | @@ -256,6 +256,21 @@ sub execute{ | 
| 256 | 256 | return $affected; | 
| 257 | 257 | } | 
| 258 | 258 |  | 
| 259 | +sub expand { | |
| 260 | + my $self = shift; | |
| 261 | +    my $source = ref $_[0] eq 'HASH' ? $_[0] : {@_}; | |
| 262 | + my $table = (keys %$source)[0]; | |
| 263 | +    my $param = $source->{$table}; | |
| 264 | + | |
| 265 | + # Expand table name | |
| 266 | +    my $expand = {}; | |
| 267 | +    foreach my $column (keys %$param) { | |
| 268 | +        $expand->{"$table.$column"} = $param->{$column}; | |
| 269 | + } | |
| 270 | + | |
| 271 | + return %$expand; | |
| 272 | +} | |
| 273 | + | |
| 259 | 274 |  our %VALID_INSERT_ARGS = map { $_ => 1 } qw/table param append filter/; | 
| 260 | 275 |  | 
| 261 | 276 |  sub insert { | 
| ... | ... | @@ -646,7 +661,7 @@ so you have to execute raw SQL in the end. | 
| 646 | 661 |  | 
| 647 | 662 | L<DBIx::Custom> is middle area between L<DBI> and O/R mapper. | 
| 648 | 663 | L<DBIx::Custom> provide flexible hash parameter binding and filtering system, | 
| 649 | -and suger methods, such as C<select()>, C<update()>, C<delete()>, C<select()> | |
| 664 | +and suger methods, such as C<insert()>, C<update()>, C<delete()>, C<select()> | |
| 650 | 665 | to execute SQL easily. | 
| 651 | 666 |  | 
| 652 | 667 | L<DBIx::Custom> respects SQL. SQL is very complex and not beautiful, | 
| ... | ... | @@ -838,6 +853,22 @@ B<Example:> | 
| 838 | 853 | my $title = $row->[1]; | 
| 839 | 854 | } | 
| 840 | 855 |  | 
| 856 | +=head2 C<(experimental) expand> | |
| 857 | + | |
| 858 | + my %expand = $dbi->expand($source); | |
| 859 | + | |
| 860 | +The following hash | |
| 861 | + | |
| 862 | +    {books => {title => 'Perl', author => 'Ken'}} | |
| 863 | + | |
| 864 | +is expanded to | |
| 865 | + | |
| 866 | +    ('books.title' => 'Perl', 'books.author' => 'Ken') | |
| 867 | + | |
| 868 | +This is used in C<select()> | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 841 | 872 | =head2 C<delete> | 
| 842 | 873 |  | 
| 843 | 874 | $dbi->delete(table => $table, | 
| ... | ... | @@ -0,0 +1,594 @@ | 
| 1 | +=encoding utf8 | |
| 2 | + | |
| 3 | +=head1 名前 | |
| 4 | + | |
| 5 | +DBIx::Custom::Guides::Ja - DBIx::Customの日本語のガイド | |
| 6 | + | |
| 7 | +=head1 ガイド | |
| 8 | + | |
| 9 | +L<DBIx::Custom>はデータベースへのクエリの発行を簡単に行うための | |
| 10 | +クラスです。L<DBIx::Class>やL<DBIx::Simple>と同じように | |
| 11 | +L<DBI>のラッパクラスになっています。 | |
| 12 | + | |
| 13 | +L<DBIx::Custom>はO/Rマッパーではありません。O/Rマッパーは | |
| 14 | +便利ですが、O/Rマッパのたくさんの文法を覚える必要があります。 | |
| 15 | +また、O/Rマッパによって生成されたSQLは非効率なことがあり、 | |
| 16 | +生のSQLを発行しなければならないこともあります。 | |
| 17 | + | |
| 18 | +L<DBIx::Custom>はO/RマッパとL<DBI>の中間に位置するモジュールです。 | |
| 19 | +L<DBIx::Custom>は柔軟なハッシュパラメータバインディングとフィルタリング | |
| 20 | +のシステムを提供します。またSQLを簡単に実行するための、 | |
| 21 | +C<insert()>, C<update()>, C<delete()>,C<select()>などの | |
| 22 | +シュガーメソッドも提供します。 | |
| 23 | + | |
| 24 | +L<DBIx::Custom>はSQLを尊重します。SQLはとても複雑で、美しくはありません。 | |
| 25 | +けれども、SQLはデファクトスタンダードな技術です。 | |
| 26 | +ですので、データベースを学ぶすべての人はSQLを知っています。 | |
| 27 | +あなたがすでにSQLを知っているなら、L<DBIx::Custom>を使って | |
| 28 | +何かを行うために覚えることはとても少ないです。 | |
| 29 | + | |
| 30 | +では使い方を解説します。 | |
| 31 | + | |
| 32 | +=head2 1. データベースへの接続 | |
| 33 | + | |
| 34 | +L<DBIx::Custom>オブジェクトを生成し、データベースに接続するには | |
| 35 | +C<connect()>メソッドを使用します。 | |
| 36 | + | |
| 37 | + use DBIx::Custom; | |
| 38 | + my $dbi = DBIx::Custom->connect(data_source => "dbi:mysql:database=dbname", | |
| 39 | + user => 'ken', password => '!LFKD%$&'); | |
| 40 | + | |
| 41 | +データベースがSQLiteであれば、代わりにL<DBIx::Custom::SQLite>を使うと | |
| 42 | +データベースへの接続が簡単です。 | |
| 43 | + | |
| 44 | + use DBIx::Custom::SQLite; | |
| 45 | + my $dbi = DBIx::Custom::SQLite->connect(database => 'dbname'); | |
| 46 | + | |
| 47 | +データベースがMySQLであれば、代わりにL<DBIx::Custom::MySQL>を使うと | |
| 48 | +データベースへの接続が簡単です。 | |
| 49 | + | |
| 50 | + use DBIx::Custom::MySQL; | |
| 51 | + my $dbi = DBIx::Custom::MySQL->connect( | |
| 52 | + database => 'dbname', | |
| 53 | + user => 'ken', | |
| 54 | + password => '!LFKD%$&' | |
| 55 | + ); | |
| 56 | + | |
| 57 | +L<DBIx::Custom>はL<DBI>のラッパです。 | |
| 58 | +L<DBI>オブジェクトはC<dbh>で取得することができます。 | |
| 59 | + | |
| 60 | + my $dbh = $dbi->dbh; | |
| 61 | + | |
| 62 | +データベースハンドル属性にはデフォルトで次のものが設定されます。 | |
| 63 | + | |
| 64 | +    $dbi->dbh->{RaiseError} = 1; | |
| 65 | +    $dbi->dbh->{PrintError} = 0; | |
| 66 | +    $dbi->dbh->{AutoCommit} = 1; | |
| 67 | + | |
| 68 | +この設定を行っているので、致命的なエラーが起こると、 | |
| 69 | +例外が発生しプログラムは終了します。 | |
| 70 | +またクエリが発行されると自動的にコミットされます。 | |
| 71 | + | |
| 72 | +=head2 2. シュガーメソッド | |
| 73 | + | |
| 74 | +L<DBIx::Custom>は、 | |
| 75 | +C<insert()>、C<update()>、C<delete()>、C<select()> | |
| 76 | +のようなシュガーメソッドを持っています。 | |
| 77 | +小さなことを行うのであれば、SQL文を | |
| 78 | +作成する必要はありません。 | |
| 79 | + | |
| 80 | +=head3 C<insert()> | |
| 81 | + | |
| 82 | +C<insert>メソッドです。データベースにデータを挿入します。 | |
| 83 | + | |
| 84 | + $dbi->insert(table => 'books', | |
| 85 | +                 param  => {title => 'Perl', author => 'Ken'}); | |
| 86 | + | |
| 87 | +これは次のL<DBI>の操作と同じです。 | |
| 88 | + | |
| 89 | +    my $sth = $dbh->prepare('insert into (title, author) values (?, ?);'); | |
| 90 | +    $sth->execute('Perl', 'Ken'); | |
| 91 | + | |
| 92 | +=head3 C<update()> | |
| 93 | + | |
| 94 | +C<update>メソッドです。データベースのデータを更新します。 | |
| 95 | + | |
| 96 | + $dbi->update(table => 'books', | |
| 97 | +                 param  => {title => 'Perl', author => 'Ken'},  | |
| 98 | +                 where  => {id => 5}); | |
| 99 | + | |
| 100 | +これは次のL<DBI>の操作と同じです。 | |
| 101 | + | |
| 102 | + my $sth = $dbh->prepare( | |
| 103 | + 'update books set title = ?, author = ? where id = ?;'); | |
| 104 | +    $sth->execute('Perl', 'Ken', 5); | |
| 105 | + | |
| 106 | +C<update>メソッドは安全のため | |
| 107 | +where句のないSQLを発行することを許可していません。 | |
| 108 | +もしすべての行を更新したい場合は | |
| 109 | +C<update_all()>メソッドを使用してください。 | |
| 110 | + | |
| 111 | + $dbi->update_all(table => 'books', | |
| 112 | +                     param  => {title => 'Perl', author => 'Ken'}); | |
| 113 | + | |
| 114 | +=head3 C<delete()> | |
| 115 | + | |
| 116 | +C<delete>メソッドです。データベースのデータを削除します。 | |
| 117 | + | |
| 118 | + $dbi->delete(table => 'books', | |
| 119 | +                 where  => {author => 'Ken'}); | |
| 120 | + | |
| 121 | +これは次のL<DBI>の操作と同じです。 | |
| 122 | + | |
| 123 | +    my $sth = $dbh->prepare('delete from books where id = ?;'); | |
| 124 | +    $sth->execute('Ken'); | |
| 125 | + | |
| 126 | +C<delete>メソッドは安全のため | |
| 127 | +where句のないSQLを発行することを許可していません。 | |
| 128 | +もしすべての行を削除したい場合は | |
| 129 | +C<delete_all()>メソッドを使用してください。 | |
| 130 | + | |
| 131 | + $dbi->delete_all(table => 'books'); | |
| 132 | + | |
| 133 | +=head3 C<select()> | |
| 134 | + | |
| 135 | +C<select>メソッドです。テーブル名だけを指定しています。 | |
| 136 | + | |
| 137 | + my $result = $dbi->select(table => 'books'); | |
| 138 | + | |
| 139 | +これは次のL<DBI>の操作と同じです。 | |
| 140 | + | |
| 141 | +    my $sth = $dbh->prepare('select * from books;); | |
| 142 | + $sth->execute; | |
| 143 | + | |
| 144 | +C<select()>メソッドの戻り値はL<DBIx::Custom::Result> | |
| 145 | +オブジェクトです。C<fetch>メソッドを使用して | |
| 146 | +行をフェッチすることができます。 | |
| 147 | + | |
| 148 | +    while (my $row = $result->fetch) { | |
| 149 | + my $title = $row->[0]; | |
| 150 | + my $author = $row->[1]; | |
| 151 | + } | |
| 152 | + | |
| 153 | +次のC<select>は行の名前とwhere句を指定したものです。 | |
| 154 | + | |
| 155 | + my $result = $dbi->select( | |
| 156 | + table => 'books', | |
| 157 | + column => [qw/author title/], | |
| 158 | +        where  => {author => 'Ken'} | |
| 159 | + ); | |
| 160 | + | |
| 161 | +次のL<DBI>の操作と同じです。 | |
| 162 | + | |
| 163 | + my $sth = $dbh->prepare( | |
| 164 | + 'select author, title from books where author = ?;'); | |
| 165 | +    $sht->execute('Ken'); | |
| 166 | + | |
| 167 | +テーブルをjoinしたい場合はC<relation>を使用します。 | |
| 168 | + | |
| 169 | + my $result = $dbi->select( | |
| 170 | + table => ['books', 'rental'], | |
| 171 | + column => ['books.name as book_name'] | |
| 172 | +        relation => {'books.id' => 'rental.book_id'} | |
| 173 | + ); | |
| 174 | + | |
| 175 | +次のL<DBI>の操作と同じです。 | |
| 176 | + | |
| 177 | + my $sth = $dbh->prepare( | |
| 178 | + 'select books.name as book_name from books, rental' . | |
| 179 | + 'where books.id = rental.book_id;'); | |
| 180 | + $sth->execute; | |
| 181 | + | |
| 182 | +=head3 C<append>オプション | |
| 183 | + | |
| 184 | +SQL文の末尾に文字列を追加したい場合は<append>オプションを使用します。 | |
| 185 | + | |
| 186 | + my $result = $dbi->select( | |
| 187 | + table => 'books', | |
| 188 | +        where  => {author => 'Ken'}, | |
| 189 | + append => 'order by price limit 5', | |
| 190 | + ); | |
| 191 | + | |
| 192 | +次のL<DBI>の操作と同じです。 | |
| 193 | + | |
| 194 | + my $sth = $dbh->prepare( | |
| 195 | + 'select * books where author = ? order by price limit 5;'); | |
| 196 | + $sth->execute; | |
| 197 | + | |
| 198 | +C<append>オプションは、C<insert()>、C<update()>、C<update_all()> | |
| 199 | +C<delete()>、C<select>メソッドで使用することが | |
| 200 | +できます。 | |
| 201 | + | |
| 202 | +=head3 C<filter>オプション | |
| 203 | + | |
| 204 | +この後のフィルタリングの解説で詳しく扱いますが、値をフィルタリングしたい | |
| 205 | +場合はC<filter>オプションを使用することができます。 | |
| 206 | + | |
| 207 | + $dbi->insert(table => 'books', | |
| 208 | +                 param  => {title => 'Perl', author => 'Ken'}); | |
| 209 | +                 filter => {title  => 'encode_utf8', | |
| 210 | + author => 'encode_utf8'}); | |
| 211 | + | |
| 212 | +C<filter>オプションは、C<insert()>、C<update()>、C<update_all()> | |
| 213 | +C<delete()>、C<select>メソッドで使用することが | |
| 214 | +できます。 | |
| 215 | + | |
| 216 | +=head2 3. 行のフェッチ | |
| 217 | + | |
| 218 | +C<select()>メソッドの戻り値であるL<DBIx::Custom::Result> | |
| 219 | +には行をフェッチするためのさまざまなメソッドが | |
| 220 | +用意されています。 | |
| 221 | +(このセクションの解説では「配列」は「配列のリファレンス」を | |
| 222 | +「ハッシュ」は「ハッシュのリファレンス」を意味しますので | |
| 223 | +注意してください。) | |
| 224 | + | |
| 225 | +=head3 C<fetch> | |
| 226 | + | |
| 227 | +一行フェッチして配列に格納します。 | |
| 228 | + | |
| 229 | +    while (my $row = $result->fetch) { | |
| 230 | + my $author = $row->[0]; | |
| 231 | + my $title = $row->[1]; | |
| 232 | + } | |
| 233 | + | |
| 234 | +=head3 C<fetch_first> | |
| 235 | + | |
| 236 | +一行だけフェッチして配列に格納します。 | |
| 237 | + | |
| 238 | + my $row = $result->fetch_first; | |
| 239 | + | |
| 240 | +フェッチが終わった後は、ステートメントハンドルからC<finish()> | |
| 241 | +メソッドが呼び出されてそれ以上フェッチできなくなります。 | |
| 242 | + | |
| 243 | +=head3 C<fetch_multi> | |
| 244 | + | |
| 245 | +複数行をフェッチして配列の配列に格納します。 | |
| 246 | + | |
| 247 | +    while (my $rows = $result->fetch_multi(5)) { | |
| 248 | + my $first_author = $rows->[0][0]; | |
| 249 | + my $first_title = $rows->[0][1]; | |
| 250 | + my $second_author = $rows->[1][0]; | |
| 251 | + my $second_value = $rows->[1][1]; | |
| 252 | + } | |
| 253 | + | |
| 254 | +=head3 C<fetch_all> | |
| 255 | + | |
| 256 | +すべての行をフェッチして配列の配列に格納します。 | |
| 257 | + | |
| 258 | + my $rows = $result->fetch_all; | |
| 259 | + | |
| 260 | +=head3 C<fetch_hash> | |
| 261 | + | |
| 262 | +一行フェッチしてハッシュに格納します。 | |
| 263 | + | |
| 264 | +    while (my $row = $result->fetch_hash) { | |
| 265 | +        my $title  = $row->{title}; | |
| 266 | +        my $author = $row->{author}; | |
| 267 | + } | |
| 268 | + | |
| 269 | +=head3 C<fetch_hash_first> | |
| 270 | + | |
| 271 | +一行だけフェッチしてハッシュに格納します。 | |
| 272 | + | |
| 273 | + my $row = $result->fetch_hash_first; | |
| 274 | + | |
| 275 | +フェッチが終わった後は、ステートメントハンドルからC<finish()> | |
| 276 | +メソッドが呼び出されてそれ以上フェッチできなくなります。 | |
| 277 | + | |
| 278 | +=head3 C<fetch_hash_multi> | |
| 279 | + | |
| 280 | +複数行をフェッチしてハッシュの配列に格納します。 | |
| 281 | + | |
| 282 | +    while (my $rows = $result->fetch_hash_multi(5)) { | |
| 283 | +        my $first_title   = $rows->[0]{title}; | |
| 284 | +        my $first_author  = $rows->[0]{author}; | |
| 285 | +        my $second_title  = $rows->[1]{title}; | |
| 286 | +        my $second_author = $rows->[1]{author}; | |
| 287 | + } | |
| 288 | + | |
| 289 | +=head3 C<fetch_all> | |
| 290 | + | |
| 291 | +すべての行をフェッチしてハッシュの配列に格納します。 | |
| 292 | + | |
| 293 | + my $rows = $result->fetch_hash_all; | |
| 294 | + | |
| 295 | +=head3 C<sth> | |
| 296 | + | |
| 297 | +L<DBI>のステートメントハンドルにアクセスしたい場合は | |
| 298 | +<sth>を使用します。 | |
| 299 | + | |
| 300 | + my $sth = $result->sth; | |
| 301 | + | |
| 302 | +=head2 4. Hash parameter binding | |
| 303 | + | |
| 304 | +L<DBIx::Custom> provides hash parameter binding. | |
| 305 | + | |
| 306 | +At frist, I show normal parameter binding. | |
| 307 | + | |
| 308 | + use DBI; | |
| 309 | + my $dbh = DBI->connect(...); | |
| 310 | + my $sth = $dbh->prepare( | |
| 311 | + "select * from books where author = ? and title like ?;" | |
| 312 | + ); | |
| 313 | +    $sth->execute('Ken', '%Perl%'); | |
| 314 | + | |
| 315 | +This is very good way because database system can enable SQL caching, | |
| 316 | +and parameter is quoted automatically. this is secure. | |
| 317 | + | |
| 318 | +L<DBIx::Custom> hash parameter binding system improve | |
| 319 | +normal parameter binding to use hash parameter. | |
| 320 | + | |
| 321 | + my $result = $dbi->execute( | |
| 322 | +        "select * from books where {= author} and {like title};" | |
| 323 | +        param => {author => 'Ken', title => '%Perl%'} | |
| 324 | + ); | |
| 325 | + | |
| 326 | +This is same as the normal way, execpt that the parameter is hash. | |
| 327 | +{= author} and {like title} is called C<tag>. | |
| 328 | +tag is expand to placeholder string internally. | |
| 329 | + | |
| 330 | +    select * from books where {= author} and {like title} | |
| 331 | + -> select * from books where author = ? and title like ?; | |
| 332 | + | |
| 333 | +The following tags is available. | |
| 334 | + | |
| 335 | + [TAG] [REPLACED] | |
| 336 | +    {? NAME}               ->   ? | |
| 337 | +    {= NAME}               ->   NAME = ? | |
| 338 | +    {<> NAME}              ->   NAME <> ? | |
| 339 | + | |
| 340 | +    {< NAME}               ->   NAME < ? | |
| 341 | +    {> NAME}               ->   NAME > ? | |
| 342 | +    {>= NAME}              ->   NAME >= ? | |
| 343 | +    {<= NAME}              ->   NAME <= ? | |
| 344 | + | |
| 345 | +    {like NAME}            ->   NAME like ? | |
| 346 | +    {in NAME COUNT}        ->   NAME in [?, ?, ..] | |
| 347 | + | |
| 348 | +    {insert_param NAME1 NAME2}   ->   (NAME1, NAME2) values (?, ?) | |
| 349 | +    {update_param NAME1 NAME2}   ->   set NAME1 = ?, NAME2 = ? | |
| 350 | + | |
| 351 | +See also L<DBIx::Custom::QueryBuilder>. | |
| 352 | + | |
| 353 | +C<{> and C<}> is reserved. If you use these charactors, | |
| 354 | +you must escape them using '\'. Note that '\' is | |
| 355 | +already perl escaped charactor, so you must write '\\'. | |
| 356 | + | |
| 357 | +    'select * from books \\{ something statement \\}' | |
| 358 | + | |
| 359 | +=head2 5. Filtering | |
| 360 | + | |
| 361 | +Usually, Perl string is kept as internal string. | |
| 362 | +If you want to save the string to database, You must encode the string. | |
| 363 | +Filtering system help you to convert a data to another data | |
| 364 | +when you save to the data and get the data form database. | |
| 365 | + | |
| 366 | +If you want to register filter, use C<register_filter()> method. | |
| 367 | + | |
| 368 | + $dbi->register_filter( | |
| 369 | +        to_upper_case => sub { | |
| 370 | + my $value = shift; | |
| 371 | + return uc $value; | |
| 372 | + } | |
| 373 | + ); | |
| 374 | + | |
| 375 | +C<encode_utf8> and C<decode_utf8> filter is registerd by default. | |
| 376 | + | |
| 377 | +You can specify these filters to C<filter> argument of C<execute()> method. | |
| 378 | + | |
| 379 | + my $result = $dbi->execute( | |
| 380 | +        "select * from books where {= author} and {like title};" | |
| 381 | +        param  => {author => 'Ken', title => '%Perl%'}, | |
| 382 | +        filter => {author => 'to_upper_case, title => 'encode_utf8'} | |
| 383 | + ); | |
| 384 | + | |
| 385 | +C<filter> argument can be specified to suger methods, such as | |
| 386 | +C<insert()>, C<update()>, C<update_all()>, | |
| 387 | +C<delete()>, C<delete_all()>, C<select()>. | |
| 388 | + | |
| 389 | + # insert(), having filter argument | |
| 390 | + $dbi->insert(table => 'books', | |
| 391 | +                 param  => {title => 'Perl', author => 'Ken'}, | |
| 392 | +                 filter => {title => 'encode_utf8'}); | |
| 393 | + | |
| 394 | + # select(), having filter argument | |
| 395 | + my $result = $dbi->select( | |
| 396 | + table => 'books', | |
| 397 | + column => [qw/author title/], | |
| 398 | +        where  => {author => 'Ken'}, | |
| 399 | + append => 'order by id limit 1', | |
| 400 | +        filter => {title => 'encode_utf8'} | |
| 401 | + ); | |
| 402 | + | |
| 403 | +Filter works each parmeter, but you prepare default filter for all parameters. | |
| 404 | + | |
| 405 | +    $dbi->default_bind_filter('encode_utf8'); | |
| 406 | + | |
| 407 | +C<filter()> argument overwrites this default filter. | |
| 408 | + | |
| 409 | +    $dbi->default_bind_filter('encode_utf8'); | |
| 410 | + $dbi->insert( | |
| 411 | + table => 'books', | |
| 412 | +        param  => {title => 'Perl', author => 'Ken', price => 1000}, | |
| 413 | +        filter => {author => 'to_upper_case', price => undef} | |
| 414 | + ); | |
| 415 | + | |
| 416 | +This is same as the following example. | |
| 417 | + | |
| 418 | + $dbi->insert( | |
| 419 | + table => 'books', | |
| 420 | +        param  => {title => 'Perl', author => 'Ken', price => 1000}, | |
| 421 | +        filter => {title => 'encode_uft8' author => 'to_upper_case'} | |
| 422 | + ); | |
| 423 | + | |
| 424 | +You can also specify filter when the row is fetched. This is reverse of bind filter. | |
| 425 | + | |
| 426 | + my $result = $dbi->select(table => 'books'); | |
| 427 | +    $result->filter({title => 'decode_utf8', author => 'to_upper_case'}); | |
| 428 | + | |
| 429 | +Filter works each column value, but you prepare a default filter | |
| 430 | +for all clumn value. | |
| 431 | + | |
| 432 | +    $dbi->default_fetch_filter('decode_utf8'); | |
| 433 | + | |
| 434 | +C<filter()> method of L<DBIx::Custom::Result> | |
| 435 | +overwrites this default filter. | |
| 436 | + | |
| 437 | +    $dbi->default_fetch_filter('decode_utf8'); | |
| 438 | + my $result = $dbi->select( | |
| 439 | + table => 'books', | |
| 440 | + columns => ['title', 'author', 'price'] | |
| 441 | + ); | |
| 442 | +    $result->filter({author => 'to_upper_case', price => undef}); | |
| 443 | + | |
| 444 | +This is same as the following one. | |
| 445 | + | |
| 446 | + my $result = $dbi->select( | |
| 447 | + table => 'books', | |
| 448 | + columns => ['title', 'author', 'price'] | |
| 449 | + ); | |
| 450 | +    $result->filter({title => 'decode_utf8', author => 'to_upper_case'}); | |
| 451 | + | |
| 452 | +Note that in fetch filter, column names must be lower case | |
| 453 | +even if the column name conatains upper case charactors. | |
| 454 | +This is requirment not to depend database systems. | |
| 455 | + | |
| 456 | +=head2 6. Get high performance | |
| 457 | + | |
| 458 | +=head3 Disable filter checking | |
| 459 | + | |
| 460 | +Filter checking is executed by default. | |
| 461 | +This is done to check right filter name is specified, | |
| 462 | +but sometimes damage performance. | |
| 463 | + | |
| 464 | +If you disable this filter checking, | |
| 465 | +Set C<filter_check> attribute to 0. | |
| 466 | + | |
| 467 | + $dbi->filter_check(0); | |
| 468 | + | |
| 469 | +=head3 Use execute() method instead suger methods | |
| 470 | + | |
| 471 | +If you execute insert statement by C<insert()> method, | |
| 472 | +you sometimes can't get required performance. | |
| 473 | + | |
| 474 | +C<insert()> method is a little slow because SQL statement and statement handle | |
| 475 | +is created every time. | |
| 476 | + | |
| 477 | +In that case, you can prepare a query by C<create_query()> method. | |
| 478 | + | |
| 479 | + my $query = $dbi->create_query( | |
| 480 | +        "insert into books {insert_param title author};" | |
| 481 | + ); | |
| 482 | + | |
| 483 | +Return value of C<create_query()> is L<DBIx::Custom::Query> object. | |
| 484 | +This keep the information of SQL and column names. | |
| 485 | + | |
| 486 | +    { | |
| 487 | + sql => 'insert into books (title, author) values (?, ?);', | |
| 488 | + columns => ['title', 'author'] | |
| 489 | + } | |
| 490 | + | |
| 491 | +Execute query repeatedly. | |
| 492 | + | |
| 493 | + my $inputs = [ | |
| 494 | +        {title => 'Perl',      author => 'Ken'}, | |
| 495 | +        {title => 'Good days', author => 'Mike'} | |
| 496 | + ]; | |
| 497 | + | |
| 498 | +    foreach my $input (@$inputs) { | |
| 499 | + $dbi->execute($query, $input); | |
| 500 | + } | |
| 501 | + | |
| 502 | +This is faster than C<insert()> method. | |
| 503 | + | |
| 504 | +=head3 caching | |
| 505 | + | |
| 506 | +C<execute()> method caches the parsed result of the source of SQL. | |
| 507 | +Default to 1 | |
| 508 | + | |
| 509 | + $dbi->cache(1); | |
| 510 | + | |
| 511 | +Caching is on memory, but you can change this by C<cache_method()>. | |
| 512 | +First argument is L<DBIx::Custom> object. | |
| 513 | +Second argument is a source of SQL, | |
| 514 | +such as "select * from books where {= title} and {= author};"; | |
| 515 | +Third argument is parsed result, such as | |
| 516 | +{sql => "select * from books where title = ? and author = ?", | |
| 517 | + columns => ['title', 'author']}, this is hash reference. | |
| 518 | +If arguments is more than two, this method is called to set cache. | |
| 519 | +If not, this method is called to get cache. | |
| 520 | + | |
| 521 | +    $dbi->cache_method(sub { | |
| 522 | +        sub { | |
| 523 | + my $self = shift; | |
| 524 | + | |
| 525 | +            $self->{_cached} ||= {}; | |
| 526 | + | |
| 527 | + # Set cache | |
| 528 | +            if (@_ > 1) { | |
| 529 | +                $self->{_cached}{$_[0]} = $_[1]  | |
| 530 | + } | |
| 531 | + | |
| 532 | + # Get cache | |
| 533 | +            else { | |
| 534 | +                return $self->{_cached}{$_[0]} | |
| 535 | + } | |
| 536 | + } | |
| 537 | + }); | |
| 538 | + | |
| 539 | +=head2 7. More features | |
| 540 | + | |
| 541 | +=head3 トランザクション | |
| 542 | + | |
| 543 | + | |
| 544 | +=head3 Change Result class | |
| 545 | + | |
| 546 | +You can change Result class if you need. | |
| 547 | + | |
| 548 | + package Your::Result; | |
| 549 | + use base 'DBIx::Custom::Result'; | |
| 550 | + | |
| 551 | +    sub some_method { ... } | |
| 552 | + | |
| 553 | + 1; | |
| 554 | + | |
| 555 | + package main; | |
| 556 | + | |
| 557 | + use Your::Result; | |
| 558 | + | |
| 559 | + my $dbi = DBIx::Custom->connect(...); | |
| 560 | +    $dbi->result_class('Your::Result'); | |
| 561 | + | |
| 562 | +=head3 Custamize SQL builder object | |
| 563 | + | |
| 564 | +You can custamize SQL builder object | |
| 565 | + | |
| 566 | + my $dbi = DBIx::Custom->connect(...); | |
| 567 | + $dbi->query_builder->register_tag_processor( | |
| 568 | +        name => sub { | |
| 569 | + ... | |
| 570 | + } | |
| 571 | + ); | |
| 572 | + | |
| 573 | +=head3 Resister helper method | |
| 574 | + | |
| 575 | +You can resiter helper method. | |
| 576 | + | |
| 577 | + $dbi->helper( | |
| 578 | +        update_or_insert => sub { | |
| 579 | + my $self = shift; | |
| 580 | + # do something | |
| 581 | + }, | |
| 582 | +        find_or_create   => sub { | |
| 583 | + my $self = shift; | |
| 584 | + # do something | |
| 585 | + } | |
| 586 | + ); | |
| 587 | + | |
| 588 | +Register helper methods. | |
| 589 | +These method can be called from L<DBIx::Custom> object directory. | |
| 590 | + | |
| 591 | + $dbi->update_or_insert; | |
| 592 | + $dbi->find_or_create; | |
| 593 | + | |
| 594 | +=cut | 
| ... | ... | @@ -1,4 +1,4 @@ | 
| 1 | -use Test::More 'no_plan'; | |
| 1 | +use Test::More tests => 15; | |
| 2 | 2 | use strict; | 
| 3 | 3 | use warnings; | 
| 4 | 4 |  | 
| ... | ... | @@ -101,3 +101,17 @@ $dbi->register_filter({b => sub {2}}); | 
| 101 | 101 |  is($dbi->filters->{b}->(), 2, $test); | 
| 102 | 102 |  | 
| 103 | 103 |  | 
| 104 | +test 'expand'; | |
| 105 | +{ | |
| 106 | + $dbi = DBIx::Custom->new; | |
| 107 | +    my $source = {books => {title => 'Perl', author => 'Ken'}}; | |
| 108 | +    is_deeply({$dbi->expand($source)},  | |
| 109 | +              {'books.title' => 'Perl', 'books.author' => 'Ken'}); | |
| 110 | +} | |
| 111 | +{ | |
| 112 | + $dbi = DBIx::Custom->new; | |
| 113 | +    my %source = (books => {title => 'Perl', author => 'Ken'}); | |
| 114 | +    is_deeply({$dbi->expand(%source)},  | |
| 115 | +              {'books.title' => 'Perl', 'books.author' => 'Ken'}); | |
| 116 | +} | |
| 117 | + |