Showing 6 changed files with 152 additions and 105 deletions
+2
Changes
... ...
@@ -5,6 +5,8 @@
5 5
   renamed tag_processors to tags. tag_prosessors is available, but deprecated.
6 6
   improved error message
7 7
   build all clause if param is undefined.
8
+  each_column callback receive self as first argument.
9
+  removed experimental txn_scope
8 10
 0.1636
9 11
   added tests and cleanup
10 12
 0.1635
+1 -27
lib/DBIx/Custom.pm
... ...
@@ -437,7 +437,7 @@ sub each_column {
437 437
         my $sth_columns = $self->dbh->column_info(undef, undef, $table, '%');
438 438
         while (my $column_info = $sth_columns->fetchrow_hashref) {
439 439
             my $column = $column_info->{COLUMN_NAME};
440
-            $cb->($table, $column, $column_info);
440
+            $self->$cb($table, $column, $column_info);
441 441
         }
442 442
     }
443 443
 }
... ...
@@ -590,17 +590,6 @@ sub table {
590 590
     return $self->{_tables}{$name};
591 591
 }
592 592
 
593
-sub txn_scope {
594
-    my $self = shift;
595
-    
596
-    require DBIx::TransactionManager;
597
-    
598
-    $self->{_transaction_manager}
599
-      ||= DBIx::TransactionManager->new($self->dbh);
600
-    
601
-    return $self->{_transaction_manager}->txn_scope;
602
-}
603
-
604 593
 our %VALID_UPDATE_ARGS
605 594
   = map { $_ => 1 } qw/table param
606 595
                        where append filter allow_update_all query/;
... ...
@@ -1255,21 +1244,6 @@ default to 0. This is experimental.
1255 1244
 This is overwrites C<default_bind_filter>.
1256 1245
 Return value of C<update()> is the count of affected rows.
1257 1246
 
1258
-=head2 C<(experimental) txn_scope>
1259
-
1260
-    {
1261
-        my $txn = $dbi->txn_scope;
1262
-        $dbi->insert(table => 'book', param => {title => 'Perl'});
1263
-        $dbi->insert(table => 'book', param => {title => 'Good days'});
1264
-        $txn->commit;
1265
-    }
1266
-
1267
-Create transaction scope. If you escape scope(that is { .. }) and commited,
1268
-Rollback is automatically done.
1269
-
1270
-Note that this is feature of L<DBIx::TransactionManager>
1271
-L<DBIx::TransactionManager> is required.
1272
-
1273 1247
 =head2 C<(experimental) table>
1274 1248
 
1275 1249
     $dbi->table('book',
+2 -5
lib/DBIx/Custom/Guide.pod
... ...
@@ -462,12 +462,9 @@ You can change Result class if you need.
462 462
     my $dbi = DBIx::Custom->connect(...);
463 463
     $dbi->result_class('Your::Result');
464 464
 
465
-=head3 Register tag processor
465
+=head3 Register tag
466 466
 
467
-You can custamize query builder object
468
-
469
-    my $dbi = DBIx::Custom->connect(...);
470
-    $dbi->register_tag_processor(
467
+    $dbi->register_tag(
471 468
         name => sub {
472 469
            ...
473 470
         }
+146 -20
lib/DBIx/Custom/Guide/Ja.pod
... ...
@@ -350,6 +350,40 @@ SQL文の末尾に文字列を追加したい場合は<append>を使用します
350 350
 またC<append>は、C<select>だけでなくC<insert()>、C<update()>、C<update_all()>
351 351
 C<delete()>、C<delete_all()>、C<select()>で使用することもできます。
352 352
 
353
+=head4 execute
354
+
355
+任意のSQLを実行するにはexecuteメソッドを使用します。
356
+
357
+    $dbi->execute("select * from book;");
358
+
359
+C<execute()>はL<DBIx::Custom>の根幹のメソッドでありタグを展開します。
360
+
361
+    $dbi->execute(
362
+        "select * from book {= title} and {= author};"
363
+        param => {title => 'Perl', author => 'Ken'}
364
+    );
365
+
366
+上記のタグを含んだSQLは次のように展開されます。
367
+
368
+    select * from book title = ? and author = ?;
369
+
370
+SQLが実行されるときにプレースホルダ(?)に対応する位置にtitleとauthor
371
+の値がが自動的に埋め込まれます。
372
+
373
+タグについてはL<5. タグ/"5. タグ">で詳しく解説しますが、
374
+ひとつの注意点があります。
375
+タグを展開するためにC<{>とC<}>は予約語になっています。
376
+もし利用したい場合は直前に\をおいてエスケープを行う必要があります。
377
+
378
+    $dbi->execute("... \\{ ... \\} ...");
379
+
380
+\自体がPerlのエスケープ文字ですので、二つ必要になるという点に注意してください。
381
+
382
+またexecuteのキュートな機能として、SQLの最後にセミコロンをおかなくても
383
+かまいません。
384
+
385
+    $dbi->execute('select * from book');
386
+
353 387
 =head2 3. 行のフェッチ
354 388
 
355 389
 C<select()>メソッドの戻り値はL<DBIx::Custom::Result>オブジェクトです。
... ...
@@ -551,19 +585,109 @@ C<delete_all()>、C<select()>で有効になります。
551 585
 このような自動的に実行されるフィルタを登録できることがL<DBIx::Custom>の
552 586
 特徴のひとつです。
553 587
 
554
-=head3 個別にフィルタを適用する
588
+=head3 個別のフィルタの適用
555 589
 
556 590
 C<apply_filter()>を使って最初にすべてのテーブルの列について
557
-フィルタを定義しておくこともできますが、
558
-さらに個別にフィルタを適用することもできます。
591
+フィルタを定義することもできますが、
592
+個別にフィルタを適用することもできます。
559 593
 個別のフィルタはC<apply_filter()>で適用したフィルタを上書きます。
594
+個別のフィルタはSQLのasを使って、列の別名を作成する必要がある場合に活躍します。
595
+
596
+データベースに送信する場合に、個別のフィルタを適用するには、各メソッドの
597
+C<filter>オプションを使用します。個別のフィルタは、C<insert()>、C<update()>、
598
+C<update_all()>、C<delete()>、C<delete_all()>、C<select()>、C<execute()>
599
+で使用することができます。
600
+
601
+C<insert()>の例を示します。
560 602
 
561
-行をフェッチするときに個別にフィルタを適用するには、
603
+    $dbi->insert(
604
+        table => 'book',
605
+        param => {issue_date => $tp, first_issue_date => $tp},
606
+        filter => {issue_date => 'tp_to_date', first_issue_date => 'tp_to_date'}
607
+    );
608
+
609
+C<execute()>の例を示します。
610
+
611
+my $sql = <<"EOS";
612
+select YEAR(issue_date) as issue_year
613
+from book
614
+where YEAR(issue_date) = {? issue_year}
615
+EOS
616
+   
617
+    my $result = $dbi->execute(
618
+        $sql,
619
+        param => {issue_year => '2010'},
620
+        filter => {issue_year => 'tp_to_year'}
621
+    );
622
+
623
+これはC<filter>を使う良くある例です。issue_dateの変換についてはC<apply_filter()>
624
+で登録してあるのですが、新しく作成した列であるissue_yearについては、
625
+何の変換も登録されていません。ですので、個別にフィルタを設定しています。
626
+
627
+また反対に行をフェッチするときにも個別のフィルタを適用することができます。
628
+フィルタを適用するには、
562 629
 C<DBIx::Custom::Result>クラスのC<filter>メソッドを使用します。
563 630
 
564
-    $result->filter(issue_date => 'date_to_tp', first_issue_date => 'date_to_tp');
631
+    $result->filter(issue_year => 'year_to_tp');
565 632
 
566
-これは、C<apply_filter()>のフィルタルールのinで定義されたフィルタを上書きます。
633
+頻繁に利用するのであれば、個別に登録するよりもC<apply_filter()>で登録
634
+しておいたほうが便利でしょう。C<apply_filter()>は存在しない列に対しても
635
+フィルタを適用できるからです。
636
+
637
+    $dbi->apply_filter('book',
638
+        'issue_year' => {out => 'tp_to_year', in => 'year_to_tp'}
639
+    );
640
+
641
+C<DBIx::Custom::Result>ではさらに最後にもう一度、フィルタを追加で
642
+登録することができます。たとえばHTMLに出力したい場合に、Time::Piece
643
+オブジェクトから読みやすい記述に変換することができます。
644
+最後のフィルタを登録するには、C<end_filter()>を使用します。
645
+
646
+    $result->end_filter(issue_date => sub {
647
+        my $tp = shift;
648
+        
649
+        return '' unless $tp;
650
+        return $tp->strftime('%Y/%m/%d %h:%m:%s (%a)');
651
+    });
652
+
653
+日付を見やすい形にフォーマットすることができます。
654
+
655
+フィルタはフェッチを行う前に登録しておく必要があることに
656
+注意してください。
657
+
658
+    $result->filter(...);
659
+    $result->end_filter(...);
660
+    my $row = $result->fetch_hash_first;
661
+
662
+=head3 列の情報を元にフィルタを適用する
663
+
664
+日付型の列は手動で設定しなくても、自動的に設定できると便利です。
665
+このためにデータベースのテーブルの列のすべての情報を
666
+順番に処理するためのC<each_column()>があります。
667
+
668
+    $dbi->each_column(
669
+        sub {
670
+            my ($self, $table, $column, $info) = @_;
671
+            
672
+            my $type = $info->{TYPE_NAME};
673
+            
674
+            my $filter = $type eq 'DATE'     ? {out => 'tp_to_date', in => 'date_to_tp'}
675
+                       : $type eq 'DATETIME' ? {out => 'tp_to_datetime', in => 'datetime_to_tp'}
676
+                                             : undef;
677
+            
678
+            $self->apply_filter($table, $column, $filter)
679
+              if $filter;
680
+        }
681
+    );
682
+
683
+each_columnはコールバックを受け取ります。コールバックの引数は
684
+順番にL<DBIx::Custom>オブジェクト、テーブル名、列名、列の情報です。
685
+列の型名の情報をもとに自動的に、フィルタを適用しています。
686
+
687
+ひとつの注意点としてコールバックの中から、コールバックの外側
688
+の変数を参照しないように注意してください。each_columnは
689
+高々1回だけ実行されるだけなので、ほとんどの場合問題ありませんが、
690
+循環参照によるメモリリークが発生してしまう可能性を持っているからです。
567 691
 
568 692
 =head2 5. タグ
569 693
 
... ...
@@ -630,7 +754,21 @@ C<{>とC<}>は予約語です。これらの文字を使いたい場合は
630 754
 
631 755
     'select * from book \\{ something statement \\}'
632 756
 
633
-=head2 6. パフォーマンスの改善
757
+=head3 L<DBIx::Custom::QueryBuilder>の機能の拡張
758
+
759
+新しいタグが欲しい場合はL<DBIx::Custom::QueryBuilder>の機能を拡張
760
+することができます。
761
+
762
+    my $dbi = DBIx::Custom->connect(...);
763
+    $dbi->register_tag(
764
+        name => sub {
765
+           ...
766
+        }
767
+    );
768
+
769
+=head2 6. Where句の動的な生成
770
+
771
+=head2 7. パフォーマンスの改善
634 772
 
635 773
 =head3 シュガーメソッドを使わない
636 774
 
... ...
@@ -670,7 +808,7 @@ C<insert()>メソッドは、SQL文とステートメントハンドルを
670 808
 C<execute>メソッドの第一引数にクエリオブジェトを渡すことができます。
671 809
 これはC<insert()>メソッドよりも高速です。
672 810
 
673
-=head2 7. その他の機能
811
+=head2 8. その他の機能
674 812
 
675 813
 =head3 トランザクション
676 814
 
... ...
@@ -711,18 +849,6 @@ fc
711 849
     my $dbi = DBIx::Custom->connect(...);
712 850
     $dbi->result_class('Your::Result');
713 851
 
714
-=head3 L<DBIx::Custom::QueryBuilder>の機能の拡張
715
-
716
-新しいタグが欲しい場合はL<DBIx::Custom::QueryBuilder>の機能を拡張
717
-することができます。
718
-
719
-    my $dbi = DBIx::Custom->connect(...);
720
-    $dbi->query_builder->register_tag_processor(
721
-        name => sub {
722
-           ...
723
-        }
724
-    );
725
-
726 852
 =head3 ヘルパーメソッドの登録
727 853
 
728 854
 ヘルパーメソッドを登録することができます。
+1 -1
t/dbix-custom-core-sqlite.t
... ...
@@ -650,7 +650,7 @@ $dbi->execute($CREATE_TABLE->{3});
650 650
 
651 651
 $infos = [];
652 652
 $dbi->each_column(sub {
653
-    my ($table, $column, $cinfo) = @_;
653
+    my ($self, $table, $column, $cinfo) = @_;
654 654
     
655 655
     if ($table =~ /^table/) {
656 656
          my $info = [$table, $column, $cinfo->{COLUMN_NAME}];
-52
t/dbix-custom-transaction-manager.t
... ...
@@ -1,52 +0,0 @@
1
-use Test::More;
2
-
3
-eval {require DBIx::TransactionManager; 1}
4
-  or plan skip_all => 'required DBIx::TransactionManager';
5
-
6
-plan 'no_plan';
7
-
8
-use DBIx::Custom;
9
-
10
-# Function for test name
11
-sub test { "# $_[0]\n" }
12
-
13
-# Constant varialbes for test
14
-my $CREATE_TABLE = {
15
-    0 => 'create table table1 (key1 char(255), key2 char(255));',
16
-};
17
-
18
-my $NEW_ARGS = {
19
-    0 => {data_source => 'dbi:SQLite:dbname=:memory:'}
20
-};
21
-
22
-# Variables
23
-my $dbi;
24
-my $result;
25
-my $txn;
26
-
27
-test 'transaction';
28
-$dbi = DBIx::Custom->connect($NEW_ARGS->{0});
29
-$dbi->execute($CREATE_TABLE->{0});
30
-{
31
-    my $txn = $dbi->txn_scope;
32
-    $dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2});
33
-    $dbi->insert(table => 'table1', param => {key1 => 2, key2 => 3});
34
-    $txn->commit;
35
-}
36
-$result = $dbi->select(table => 'table1');
37
-is_deeply(scalar $result->fetch_hash_all, [{key1 => 1, key2 => 2}, {key1 => 2, key2 => 3}],
38
-          "commit");
39
-
40
-$dbi = DBIx::Custom->connect($NEW_ARGS->{0});
41
-$dbi->execute($CREATE_TABLE->{0});
42
-
43
-{
44
-    local $SIG{__WARN__} = sub {};
45
-    {
46
-        my $txn = $dbi->txn_scope;
47
-        $dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2});
48
-    }
49
-}
50
-$result = $dbi->select(table => 'table1');
51
-ok(! $result->fetch_first, "rollback");
52
-