Showing 6 changed files with 395 additions and 377 deletions
+2
t/common-mysql.t
... ...
@@ -19,6 +19,8 @@ use DBIx::Custom;
19 19
     sub create_table1_2 {'create table table1 (key1 varchar(255), key2 varchar(255), '
20 20
      . 'key3 varchar(255), key4 varchar(255), key5 varchar(255)) engine=InnoDB;' }
21 21
     sub create_table1_type { 'create table table1 (key1 Date, key2 datetime) engine=InnoDB;;' }
22
+    sub create_table1_highperformance { "create table table1 (ab varchar(255), bc varchar(255), "
23
+      . "ik varchar(255), hi varchar(255), ui varchar(255), pq varchar(255), dc varchar(255)) engine=InnoDB;" }
22 24
     sub create_table2 { 'create table table2 (key1 varchar(255), key3 varchar(255)) engine=InnoDB;' }
23 25
     sub create_table2_2 { "create table table2 (key1 varchar(255), key2 varchar(255), key3 varchar(255)) engine=InnoDB" }
24 26
     sub create_table3 { "create table table3 (key1 varchar(255), key2 varchar(255), key3 varchar(255)) engine=InnoDB" }
+2
t/common-postgresql.t
... ...
@@ -18,6 +18,8 @@ use DBIx::Custom;
18 18
     sub create_table1_2 {'create table table1 (key1 varchar(255), key2 varchar(255), '
19 19
      . 'key3 varchar(255), key4 varchar(255), key5 varchar(255));' }
20 20
     sub create_table1_type { 'create table table1 (key1 Date, key2 varchar(255));' }
21
+    sub create_table1_highperformance { "create table table1 (ab varchar(255), bc varchar(255), "
22
+      . "ik varchar(255), hi varchar(255), ui varchar(255), pq varchar(255), dc varchar(255));" }
21 23
     sub create_table2 { 'create table table2 (key1 varchar(255), key3 varchar(255));' }
22 24
     sub create_table2_2 { "create table table2 (key1 varchar(255), key2 varchar(255), key3 varchar(255))" }
23 25
     sub create_table3 { "create table table3 (key1 varchar(255), key2 varchar(255), key3 varchar(255))" }
+1
t/common-sqlite-quote.t
... ...
@@ -13,6 +13,7 @@ use DBIx::Custom;
13 13
     sub create_table1 { 'create table table1 (key1, key2);' }
14 14
     sub create_table1_2 {'create table table1 (key1, key2, key3, key4, key5);' }
15 15
     sub create_table1_type { 'create table table1 (key1 Date, key2 datetime);' }
16
+    sub create_table1_highperformance { "create table table1 (ab, bc, ik, hi, ui, pq, dc);" }
16 17
     sub create_table2 { 'create table table2 (key1, key3);' }
17 18
     sub create_table2_2 { "create table table2 (key1, key2, key3)" }
18 19
     sub create_table3 { "create table table3 (key1, key2, key3)" }
+3
t/common-sqlite.t
... ...
@@ -12,6 +12,9 @@ use DBIx::Custom;
12 12
     sub create_table1 { 'create table table1 (key1, key2);' }
13 13
     sub create_table1_2 {'create table table1 (key1, key2, key3, key4, key5);' }
14 14
     sub create_table1_type { 'create table table1 (key1 Date, key2 datetime);' }
15
+    
16
+    sub create_table1_highperformance { "create table table1 (ab, bc, ik, hi, ui, pq, dc);" }
17
+    
15 18
     sub create_table2 { 'create table table2 (key1, key3);' }
16 19
     sub create_table2_2 { "create table table2 (key1, key2, key3)" }
17 20
     sub create_table3 { "create table table3 (key1, key2, key3)" }
+322
t/common.t
... ...
@@ -146,6 +146,7 @@ sub test { print "# $_[0]\n" }
146 146
 my $create_table1 = $dbi->create_table1;
147 147
 my $create_table1_2 = $dbi->create_table1_2;
148 148
 my $create_table1_type = $dbi->create_table1_type;
149
+my $create_table1_highperformance = $dbi->create_table1_highperformance;
149 150
 my $create_table2 = $dbi->create_table2;
150 151
 my $create_table2_2 = $dbi->create_table2_2;
151 152
 my $create_table3 = $dbi->create_table3;
... ...
@@ -2671,4 +2672,325 @@ $param = $dbi->map_param(
2671 2672
 );
2672 2673
 is_deeply($param, {'book.price' => '%a'});
2673 2674
 
2675
+test 'order';
2676
+$dbi = DBIx::Custom->connect;
2677
+eval { $dbi->execute('drop table table1') };
2678
+$dbi->execute($create_table1);
2679
+$dbi->insert({key1 => 1, key2 => 1}, table => 'table1');
2680
+$dbi->insert({key1 => 1, key2 => 3}, table => 'table1');
2681
+$dbi->insert({key1 => 2, key2 => 2}, table => 'table1');
2682
+$dbi->insert({key1 => 2, key2 => 4}, table => 'table1');
2683
+my $order = $dbi->order;
2684
+$order->prepend('key1', 'key2 desc');
2685
+$result = $dbi->select(table => 'table1', append => "$order");
2686
+is_deeply($result->all, [{key1 => 1, key2 => 3}, {key1 => 1, key2 => 1},
2687
+  {key1 => 2, key2 => 4}, {key1 => 2, key2 => 2}]);
2688
+$order->prepend('key1 desc');
2689
+$result = $dbi->select(table => 'table1', append => "$order");
2690
+is_deeply($result->all, [{key1 => 2, key2 => 4}, {key1 => 2, key2 => 2},
2691
+  {key1 => 1, key2 => 3}, {key1 => 1, key2 => 1}]);
2692
+
2693
+$order = $dbi->order;
2694
+$order->prepend(['table1-key1'], [qw/table1-key2 desc/]);
2695
+$result = $dbi->select(table => 'table1',
2696
+  column => [[key1 => 'table1-key1'], [key2 => 'table1-key2']],
2697
+  append => "$order");
2698
+is_deeply($result->all, [{'table1-key1' => 1, 'table1-key2' => 3},
2699
+  {'table1-key1' => 1, 'table1-key2' => 1},
2700
+  {'table1-key1' => 2, 'table1-key2' => 4},
2701
+  {'table1-key1' => 2, 'table1-key2' => 2}]);
2702
+
2703
+test 'tag_parse';
2704
+$dbi = DBIx::Custom->connect;
2705
+$dbi->tag_parse(0);
2706
+eval { $dbi->execute('drop table table1') };
2707
+$dbi->execute($create_table1);
2708
+$dbi->insert({key1 => 1, key2 => 1}, table => 'table1');
2709
+eval {$dbi->execute("select * from table1 where {= key1}", {key1 => 1})};
2710
+ok($@);
2711
+
2712
+test 'last_sql';
2713
+$dbi = DBIx::Custom->connect;
2714
+eval { $dbi->execute('drop table table1') };
2715
+$dbi->execute($create_table1);
2716
+$dbi->execute('select * from table1');
2717
+is($dbi->last_sql, 'select * from table1;');
2718
+
2719
+eval{$dbi->execute("aaa")};
2720
+is($dbi->last_sql, 'aaa;');
2721
+
2722
+test 'DBIx::Custom header';
2723
+$dbi = DBIx::Custom->connect;
2724
+eval { $dbi->execute('drop table table1') };
2725
+$dbi->execute($create_table1);
2726
+$result = $dbi->execute('select key1 as h1, key2 as h2 from table1');
2727
+is_deeply($result->header, [qw/h1 h2/]);
2728
+
2729
+test 'Named placeholder :name(operater) syntax';
2730
+$dbi->execute('drop table table1');
2731
+$dbi->execute($create_table1_2);
2732
+$dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5});
2733
+$dbi->insert(table => 'table1', param => {key1 => 6, key2 => 7, key3 => 8, key4 => 9, key5 => 10});
2734
+
2735
+$source = "select * from table1 where :key1{=} and :key2{=}";
2736
+$result = $dbi->execute($source, param => {key1 => 1, key2 => 2});
2737
+$rows = $result->all;
2738
+is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}]);
2739
+
2740
+$source = "select * from table1 where :key1{ = } and :key2{=}";
2741
+$result = $dbi->execute($source, param => {key1 => 1, key2 => 2});
2742
+$rows = $result->all;
2743
+is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}]);
2744
+
2745
+$source = "select * from table1 where :key1{<} and :key2{=}";
2746
+$result = $dbi->execute($source, param => {key1 => 5, key2 => 2});
2747
+$rows = $result->all;
2748
+is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}]);
2749
+
2750
+$source = "select * from table1 where :table1.key1{=} and :table1.key2{=}";
2751
+$result = $dbi->execute(
2752
+    $source,
2753
+    param => {'table1.key1' => 1, 'table1.key2' => 1},
2754
+    filter => {'table1.key2' => sub { $_[0] * 2 }}
2755
+);
2756
+$rows = $result->all;
2757
+is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}]);
2758
+
2759
+test 'high perfomance way';
2760
+$dbi->execute('drop table table1');
2761
+$dbi->execute($create_table1_highperformance);
2762
+$rows = [
2763
+    {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 7},
2764
+    {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 8},
2765
+];
2766
+{
2767
+    my $query;
2768
+    foreach my $row (@$rows) {
2769
+      $query ||= $dbi->insert($row, table => 'table1', query => 1);
2770
+      $dbi->execute($query, $row, filter => {ab => sub { $_[0] * 2 }});
2771
+    }
2772
+    is_deeply($dbi->select(table => 'table1')->all,
2773
+      [
2774
+          {ab => 2, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 7},
2775
+          {ab => 2, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 8},
2776
+      ]
2777
+    );
2778
+}
2779
+
2780
+$dbi->execute('drop table table1');
2781
+$dbi->execute($create_table1_highperformance);
2782
+$rows = [
2783
+    {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 7},
2784
+    {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 8},
2785
+];
2786
+{
2787
+    my $query;
2788
+    my $sth;
2789
+    foreach my $row (@$rows) {
2790
+      $query ||= $dbi->insert($row, table => 'table1', query => 1);
2791
+      $sth ||= $query->sth;
2792
+      $sth->execute(map { $row->{$_} } sort keys %$row);
2793
+    }
2794
+    is_deeply($dbi->select(table => 'table1')->all,
2795
+      [
2796
+          {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 7},
2797
+          {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 8},
2798
+      ]
2799
+    );
2800
+}
2801
+
2802
+test 'result';
2803
+$dbi = DBIx::Custom->connect;
2804
+eval { $dbi->execute('drop table table1') };
2805
+$dbi->execute($create_table1);
2806
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
2807
+$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
2808
+
2809
+$result = $dbi->select(table => 'table1');
2810
+@rows = ();
2811
+while (my $row = $result->fetch) {
2812
+    push @rows, [@$row];
2813
+}
2814
+is_deeply(\@rows, [[1, 2], [3, 4]]);
2815
+
2816
+$result = $dbi->select(table => 'table1');
2817
+@rows = ();
2818
+while (my $row = $result->fetch_hash) {
2819
+    push @rows, {%$row};
2820
+}
2821
+is_deeply(\@rows, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
2822
+
2823
+$dbi = DBIx::Custom->connect;
2824
+eval { $dbi->execute('drop table table1') };
2825
+$dbi->execute($create_table1);
2826
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
2827
+$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
2828
+
2829
+test 'fetch_all';
2830
+$result = $dbi->select(table => 'table1');
2831
+$rows = $result->fetch_all;
2832
+is_deeply($rows, [[1, 2], [3, 4]]);
2833
+
2834
+$result = $dbi->select(table => 'table1');
2835
+$rows = $result->fetch_hash_all;
2836
+is_deeply($rows, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
2837
+
2838
+$result = $dbi->select(table => 'table1');
2839
+$result->dbi->filters({three_times => sub { $_[0] * 3}});
2840
+$result->filter({key1 => 'three_times'});
2841
+
2842
+$rows = $result->fetch_all;
2843
+is_deeply($rows, [[3, 2], [9, 4]], "array");
2844
+
2845
+$result = $dbi->select(table => 'table1');
2846
+$result->dbi->filters({three_times => sub { $_[0] * 3}});
2847
+$result->filter({key1 => 'three_times'});
2848
+$rows = $result->fetch_hash_all;
2849
+is_deeply($rows, [{key1 => 3, key2 => 2}, {key1 => 9, key2 => 4}], "hash");
2850
+
2851
+test "query_builder";
2852
+$datas = [
2853
+    # Basic tests
2854
+    {   name            => 'placeholder basic',
2855
+        source            => "a {?  k1} b {=  k2} {<> k3} {>  k4} {<  k5} {>= k6} {<= k7} {like k8}", ,
2856
+        sql_expected    => "a ? b k2 = ? k3 <> ? k4 > ? k5 < ? k6 >= ? k7 <= ? k8 like ?;",
2857
+        columns_expected   => [qw/k1 k2 k3 k4 k5 k6 k7 k8/]
2858
+    },
2859
+    {
2860
+        name            => 'placeholder in',
2861
+        source            => "{in k1 3};",
2862
+        sql_expected    => "k1 in (?, ?, ?);",
2863
+        columns_expected   => [qw/k1 k1 k1/]
2864
+    },
2865
+    
2866
+    # Table name
2867
+    {
2868
+        name            => 'placeholder with table name',
2869
+        source            => "{= a.k1} {= a.k2}",
2870
+        sql_expected    => "a.k1 = ? a.k2 = ?;",
2871
+        columns_expected  => [qw/a.k1 a.k2/]
2872
+    },
2873
+    {   
2874
+        name            => 'placeholder in with table name',
2875
+        source            => "{in a.k1 2} {in b.k2 2}",
2876
+        sql_expected    => "a.k1 in (?, ?) b.k2 in (?, ?);",
2877
+        columns_expected  => [qw/a.k1 a.k1 b.k2 b.k2/]
2878
+    },
2879
+    {
2880
+        name            => 'not contain tag',
2881
+        source            => "aaa",
2882
+        sql_expected    => "aaa;",
2883
+        columns_expected  => [],
2884
+    }
2885
+];
2886
+
2887
+for (my $i = 0; $i < @$datas; $i++) {
2888
+    my $data = $datas->[$i];
2889
+    my $builder = DBIx::Custom->new->query_builder;
2890
+    my $query = $builder->build_query($data->{source});
2891
+    is($query->{sql}, $data->{sql_expected}, "$data->{name} : sql");
2892
+    is_deeply($query->columns, $data->{columns_expected}, "$data->{name} : columns");
2893
+}
2894
+
2895
+$builder = DBIx::Custom->new->query_builder;
2896
+$ret_val = $builder->register_tag(
2897
+    p => sub {
2898
+        my @args = @_;
2899
+        
2900
+        my $expand    = "? $args[0] $args[1]";
2901
+        my $columns = [2];
2902
+        return [$expand, $columns];
2903
+    }
2904
+);
2905
+
2906
+$query = $builder->build_query("{p a b}");
2907
+is($query->{sql}, "? a b;", "register_tag sql");
2908
+is_deeply($query->{columns}, [2], "register_tag columns");
2909
+isa_ok($ret_val, 'DBIx::Custom::QueryBuilder');
2910
+
2911
+$builder = DBIx::Custom->new->query_builder;
2912
+
2913
+eval{$builder->build_query('{? }')};
2914
+like($@, qr/\QColumn name must be specified in tag "{? }"/, "? not arguments");
2915
+
2916
+eval{$builder->build_query("{a }")};
2917
+like($@, qr/\QTag "a" is not registered/, "tag not exist");
2918
+
2919
+$builder->register_tag({
2920
+    q => 'string'
2921
+});
2922
+
2923
+eval{$builder->build_query("{q}", {})};
2924
+like($@, qr/Tag "q" must be sub reference/, "tag not code ref");
2925
+
2926
+$builder->register_tag({
2927
+   r => sub {} 
2928
+});
2929
+
2930
+eval{$builder->build_query("{r}")};
2931
+like($@, qr/\QTag "r" must return [STRING, ARRAY_REFERENCE]/, "tag return noting");
2932
+
2933
+$builder->register_tag({
2934
+   s => sub { return ["a", ""]} 
2935
+});
2936
+
2937
+eval{$builder->build_query("{s}")};
2938
+like($@, qr/\QTag "s" must return [STRING, ARRAY_REFERENCE]/, "tag return not array columns");
2939
+
2940
+$builder->register_tag(
2941
+    t => sub {return ["a", []]}
2942
+);
2943
+
2944
+
2945
+test 'General error case';
2946
+$builder = DBIx::Custom->new->query_builder;
2947
+$builder->register_tag(
2948
+    a => sub {
2949
+        return ["? ? ?", ['']];
2950
+    }
2951
+);
2952
+eval{$builder->build_query("{a}")};
2953
+like($@, qr/\QPlaceholder count/, "placeholder count is invalid");
2954
+
2955
+
2956
+test 'Default tag Error case';
2957
+eval{$builder->build_query("{= }")};
2958
+like($@, qr/Column name must be specified in tag "{= }"/, "basic '=' : key not exist");
2959
+
2960
+eval{$builder->build_query("{in }")};
2961
+like($@, qr/Column name and count of values must be specified in tag "{in }"/, "in : key not exist");
2962
+
2963
+eval{$builder->build_query("{in a}")};
2964
+like($@, qr/\QColumn name and count of values must be specified in tag "{in }"/,
2965
+     "in : key not exist");
2966
+
2967
+eval{$builder->build_query("{in a r}")};
2968
+like($@, qr/\QColumn name and count of values must be specified in tag "{in }"/,
2969
+     "in : key not exist");
2970
+
2971
+test 'variouse source';
2972
+$source = "a {= b} c \\{ \\} {= \\{} {= \\}} d;";
2973
+$query = $builder->build_query($source);
2974
+is($query->sql, 'a b = ? c { } { = ? } = ? d;', "basic : 1");
2975
+
2976
+$source = "abc;";
2977
+$query = $builder->build_query($source);
2978
+is($query->sql, 'abc;', "basic : 2");
2979
+
2980
+$source = "{= a}";
2981
+$query = $builder->build_query($source);
2982
+is($query->sql, 'a = ?;', "only tag");
2983
+
2984
+$source = "000;";
2985
+$query = $builder->build_query($source);
2986
+is($query->sql, '000;', "contain 0 value");
2987
+
2988
+$source = "a {= b} }";
2989
+eval{$builder->build_query($source)};
2990
+like($@, qr/unexpected "}"/, "error : 1");
2991
+
2992
+$source = "a {= {}";
2993
+eval{$builder->build_query($source)};
2994
+like($@, qr/unexpected "{"/, "error : 2");
2995
+
2674 2996
 1;
+65 -377
t/sqlite.t
... ...
@@ -203,383 +203,6 @@ $dbi = DBIx::Custom->connect;
203 203
 
204 204
 
205 205
 
206
-test 'order';
207
-$dbi = DBIx::Custom->connect;
208
-eval { $dbi->execute('drop table table1') };
209
-$dbi->execute("create table table1 (key1, key2)");
210
-$dbi->insert({key1 => 1, key2 => 1}, table => 'table1');
211
-$dbi->insert({key1 => 1, key2 => 3}, table => 'table1');
212
-$dbi->insert({key1 => 2, key2 => 2}, table => 'table1');
213
-$dbi->insert({key1 => 2, key2 => 4}, table => 'table1');
214
-my $order = $dbi->order;
215
-$order->prepend('key1', 'key2 desc');
216
-$result = $dbi->select(table => 'table1', append => "$order");
217
-is_deeply($result->all, [{key1 => 1, key2 => 3}, {key1 => 1, key2 => 1},
218
-  {key1 => 2, key2 => 4}, {key1 => 2, key2 => 2}]);
219
-$order->prepend('key1 desc');
220
-$result = $dbi->select(table => 'table1', append => "$order");
221
-is_deeply($result->all, [{key1 => 2, key2 => 4}, {key1 => 2, key2 => 2},
222
-  {key1 => 1, key2 => 3}, {key1 => 1, key2 => 1}]);
223
-
224
-$order = $dbi->order;
225
-$order->prepend(['table1-key1'], [qw/table1-key2 desc/]);
226
-$result = $dbi->select(table => 'table1',
227
-  column => [[key1 => 'table1-key1'], [key2 => 'table1-key2']],
228
-  append => "$order");
229
-is_deeply($result->all, [{'table1-key1' => 1, 'table1-key2' => 3},
230
-  {'table1-key1' => 1, 'table1-key2' => 1},
231
-  {'table1-key1' => 2, 'table1-key2' => 4},
232
-  {'table1-key1' => 2, 'table1-key2' => 2}]);
233
-
234
-test 'tag_parse';
235
-$dbi = DBIx::Custom->connect;
236
-$dbi->tag_parse(0);
237
-eval { $dbi->execute('drop table table1') };
238
-$dbi->execute("create table table1 (key1, key2)");
239
-$dbi->insert({key1 => 1, key2 => 1}, table => 'table1');
240
-eval {$dbi->execute("select * from table1 where {= key1}", {key1 => 1})};
241
-ok($@);
242
-
243
-test 'last_sql';
244
-$dbi = DBIx::Custom->connect;
245
-eval { $dbi->execute('drop table table1') };
246
-$dbi->execute("create table table1 (key1, key2)");
247
-$dbi->execute('select * from table1');
248
-is($dbi->last_sql, 'select * from table1;');
249
-
250
-eval{$dbi->execute("aaa")};
251
-is($dbi->last_sql, 'aaa;');
252
-
253
-test 'DBIx::Custom header';
254
-$dbi = DBIx::Custom->connect;
255
-eval { $dbi->execute('drop table table1') };
256
-$dbi->execute("create table table1 (key1, key2)");
257
-$result = $dbi->execute('select key1 as h1, key2 as h2 from table1');
258
-is_deeply($result->header, [qw/h1 h2/]);
259
-
260
-test 'Named placeholder :name(operater) syntax';
261
-$dbi->execute('drop table table1');
262
-$dbi->execute($create_table1_2);
263
-$dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5});
264
-$dbi->insert(table => 'table1', param => {key1 => 6, key2 => 7, key3 => 8, key4 => 9, key5 => 10});
265
-
266
-$source = "select * from table1 where :key1{=} and :key2{=}";
267
-$result = $dbi->execute($source, param => {key1 => 1, key2 => 2});
268
-$rows = $result->all;
269
-is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}]);
270
-
271
-$source = "select * from table1 where :key1{ = } and :key2{=}";
272
-$result = $dbi->execute($source, param => {key1 => 1, key2 => 2});
273
-$rows = $result->all;
274
-is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}]);
275
-
276
-$source = "select * from table1 where :key1{<} and :key2{=}";
277
-$result = $dbi->execute($source, param => {key1 => 5, key2 => 2});
278
-$rows = $result->all;
279
-is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}]);
280
-
281
-$source = "select * from table1 where :table1.key1{=} and :table1.key2{=}";
282
-$result = $dbi->execute(
283
-    $source,
284
-    param => {'table1.key1' => 1, 'table1.key2' => 1},
285
-    filter => {'table1.key2' => sub { $_[0] * 2 }}
286
-);
287
-$rows = $result->all;
288
-is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}]);
289
-
290
-test 'high perfomance way';
291
-$dbi->execute('drop table table1');
292
-$dbi->execute("create table table1 (ab, bc, ik, hi, ui, pq, dc);");
293
-$rows = [
294
-    {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 7},
295
-    {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 8},
296
-];
297
-{
298
-    my $query;
299
-    foreach my $row (@$rows) {
300
-      $query ||= $dbi->insert($row, table => 'table1', query => 1);
301
-      $dbi->execute($query, $row, filter => {ab => sub { $_[0] * 2 }});
302
-    }
303
-    is_deeply($dbi->select(table => 'table1')->all,
304
-      [
305
-          {ab => 2, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 7},
306
-          {ab => 2, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 8},
307
-      ]
308
-    );
309
-}
310
-
311
-$dbi->execute('drop table table1');
312
-$dbi->execute("create table table1 (ab, bc, ik, hi, ui, pq, dc);");
313
-$rows = [
314
-    {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 7},
315
-    {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 8},
316
-];
317
-{
318
-    my $query;
319
-    my $sth;
320
-    foreach my $row (@$rows) {
321
-      $query ||= $dbi->insert($row, table => 'table1', query => 1);
322
-      $sth ||= $query->sth;
323
-      $sth->execute(map { $row->{$_} } sort keys %$row);
324
-    }
325
-    is_deeply($dbi->select(table => 'table1')->all,
326
-      [
327
-          {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 7},
328
-          {ab => 1, bc => 2, ik => 3, hi => 4, ui => 5, pq => 6, dc => 8},
329
-      ]
330
-    );
331
-}
332
-
333
-test 'result';
334
-$dbi = DBIx::Custom->connect;
335
-eval { $dbi->execute('drop table table1') };
336
-$dbi->execute($create_table1);
337
-$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
338
-$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
339
-
340
-$result = $dbi->select(table => 'table1');
341
-@rows = ();
342
-while (my $row = $result->fetch) {
343
-    push @rows, [@$row];
344
-}
345
-is_deeply(\@rows, [[1, 2], [3, 4]]);
346
-
347
-$result = $dbi->select(table => 'table1');
348
-@rows = ();
349
-while (my $row = $result->fetch_hash) {
350
-    push @rows, {%$row};
351
-}
352
-is_deeply(\@rows, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
353
-
354
-$result = $dbi->select(table => 'table1');
355
-$row = $result->fetch_first;
356
-is_deeply($row, [1, 2], "row");
357
-$row = $result->fetch;
358
-ok(!$row, "finished");
359
-
360
-$result = $dbi->select(table => 'table1');
361
-$row = $result->fetch_hash_first;
362
-is_deeply($row, {key1 => 1, key2 => 2}, "row");
363
-$row = $result->fetch_hash;
364
-ok(!$row, "finished");
365
-
366
-$dbi->execute('create table table2 (key1, key2);');
367
-$result = $dbi->select(table => 'table2');
368
-$row = $result->fetch_hash_first;
369
-ok(!$row, "no row fetch");
370
-
371
-$dbi = DBIx::Custom->connect;
372
-eval { $dbi->execute('drop table table1') };
373
-$dbi->execute($create_table1);
374
-$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
375
-$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
376
-$dbi->insert({key1 => 5, key2 => 6}, table => 'table1');
377
-$dbi->insert({key1 => 7, key2 => 8}, table => 'table1');
378
-$dbi->insert({key1 => 9, key2 => 10}, table => 'table1');
379
-$result = $dbi->select(table => 'table1');
380
-$rows = $result->fetch_multi(2);
381
-is_deeply($rows, [[1, 2],
382
-                  [3, 4]], "fetch_multi first");
383
-$rows = $result->fetch_multi(2);
384
-is_deeply($rows, [[5, 6],
385
-                  [7, 8]], "fetch_multi secound");
386
-$rows = $result->fetch_multi(2);
387
-is_deeply($rows, [[9, 10]], "fetch_multi third");
388
-$rows = $result->fetch_multi(2);
389
-ok(!$rows);
390
-
391
-$result = $dbi->select(table => 'table1');
392
-eval {$result->fetch_multi};
393
-like($@, qr/Row count must be specified/, "Not specified row count");
394
-
395
-$result = $dbi->select(table => 'table1');
396
-$rows = $result->fetch_hash_multi(2);
397
-is_deeply($rows, [{key1 => 1, key2 => 2},
398
-                  {key1 => 3, key2 => 4}], "fetch_multi first");
399
-$rows = $result->fetch_hash_multi(2);
400
-is_deeply($rows, [{key1 => 5, key2 => 6},
401
-                  {key1 => 7, key2 => 8}], "fetch_multi secound");
402
-$rows = $result->fetch_hash_multi(2);
403
-is_deeply($rows, [{key1 => 9, key2 => 10}], "fetch_multi third");
404
-$rows = $result->fetch_hash_multi(2);
405
-ok(!$rows);
406
-
407
-$result = $dbi->select(table => 'table1');
408
-eval {$result->fetch_hash_multi};
409
-like($@, qr/Row count must be specified/, "Not specified row count");
410
-
411
-$dbi = DBIx::Custom->connect;
412
-eval { $dbi->execute('drop table table1') };
413
-$dbi->execute($create_table1);
414
-$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
415
-$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
416
-
417
-test 'fetch_all';
418
-$result = $dbi->select(table => 'table1');
419
-$rows = $result->fetch_all;
420
-is_deeply($rows, [[1, 2], [3, 4]]);
421
-
422
-$result = $dbi->select(table => 'table1');
423
-$rows = $result->fetch_hash_all;
424
-is_deeply($rows, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
425
-
426
-$result = $dbi->select(table => 'table1');
427
-$result->dbi->filters({three_times => sub { $_[0] * 3}});
428
-$result->filter({key1 => 'three_times'});
429
-
430
-$rows = $result->fetch_all;
431
-is_deeply($rows, [[3, 2], [9, 4]], "array");
432
-
433
-$result = $dbi->select(table => 'table1');
434
-$result->dbi->filters({three_times => sub { $_[0] * 3}});
435
-$result->filter({key1 => 'three_times'});
436
-$rows = $result->fetch_hash_all;
437
-is_deeply($rows, [{key1 => 3, key2 => 2}, {key1 => 9, key2 => 4}], "hash");
438
-
439
-test "query_builder";
440
-$datas = [
441
-    # Basic tests
442
-    {   name            => 'placeholder basic',
443
-        source            => "a {?  k1} b {=  k2} {<> k3} {>  k4} {<  k5} {>= k6} {<= k7} {like k8}", ,
444
-        sql_expected    => "a ? b k2 = ? k3 <> ? k4 > ? k5 < ? k6 >= ? k7 <= ? k8 like ?;",
445
-        columns_expected   => [qw/k1 k2 k3 k4 k5 k6 k7 k8/]
446
-    },
447
-    {
448
-        name            => 'placeholder in',
449
-        source            => "{in k1 3};",
450
-        sql_expected    => "k1 in (?, ?, ?);",
451
-        columns_expected   => [qw/k1 k1 k1/]
452
-    },
453
-    
454
-    # Table name
455
-    {
456
-        name            => 'placeholder with table name',
457
-        source            => "{= a.k1} {= a.k2}",
458
-        sql_expected    => "a.k1 = ? a.k2 = ?;",
459
-        columns_expected  => [qw/a.k1 a.k2/]
460
-    },
461
-    {   
462
-        name            => 'placeholder in with table name',
463
-        source            => "{in a.k1 2} {in b.k2 2}",
464
-        sql_expected    => "a.k1 in (?, ?) b.k2 in (?, ?);",
465
-        columns_expected  => [qw/a.k1 a.k1 b.k2 b.k2/]
466
-    },
467
-    {
468
-        name            => 'not contain tag',
469
-        source            => "aaa",
470
-        sql_expected    => "aaa;",
471
-        columns_expected  => [],
472
-    }
473
-];
474
-
475
-for (my $i = 0; $i < @$datas; $i++) {
476
-    my $data = $datas->[$i];
477
-    my $builder = DBIx::Custom->new->query_builder;
478
-    my $query = $builder->build_query($data->{source});
479
-    is($query->{sql}, $data->{sql_expected}, "$data->{name} : sql");
480
-    is_deeply($query->columns, $data->{columns_expected}, "$data->{name} : columns");
481
-}
482
-
483
-$builder = DBIx::Custom->new->query_builder;
484
-$ret_val = $builder->register_tag(
485
-    p => sub {
486
-        my @args = @_;
487
-        
488
-        my $expand    = "? $args[0] $args[1]";
489
-        my $columns = [2];
490
-        return [$expand, $columns];
491
-    }
492
-);
493
-
494
-$query = $builder->build_query("{p a b}");
495
-is($query->{sql}, "? a b;", "register_tag sql");
496
-is_deeply($query->{columns}, [2], "register_tag columns");
497
-isa_ok($ret_val, 'DBIx::Custom::QueryBuilder');
498
-
499
-$builder = DBIx::Custom->new->query_builder;
500
-
501
-eval{$builder->build_query('{? }')};
502
-like($@, qr/\QColumn name must be specified in tag "{? }"/, "? not arguments");
503
-
504
-eval{$builder->build_query("{a }")};
505
-like($@, qr/\QTag "a" is not registered/, "tag not exist");
506
-
507
-$builder->register_tag({
508
-    q => 'string'
509
-});
510
-
511
-eval{$builder->build_query("{q}", {})};
512
-like($@, qr/Tag "q" must be sub reference/, "tag not code ref");
513
-
514
-$builder->register_tag({
515
-   r => sub {} 
516
-});
517
-
518
-eval{$builder->build_query("{r}")};
519
-like($@, qr/\QTag "r" must return [STRING, ARRAY_REFERENCE]/, "tag return noting");
520
-
521
-$builder->register_tag({
522
-   s => sub { return ["a", ""]} 
523
-});
524
-
525
-eval{$builder->build_query("{s}")};
526
-like($@, qr/\QTag "s" must return [STRING, ARRAY_REFERENCE]/, "tag return not array columns");
527
-
528
-$builder->register_tag(
529
-    t => sub {return ["a", []]}
530
-);
531
-
532
-
533
-test 'General error case';
534
-$builder = DBIx::Custom->new->query_builder;
535
-$builder->register_tag(
536
-    a => sub {
537
-        return ["? ? ?", ['']];
538
-    }
539
-);
540
-eval{$builder->build_query("{a}")};
541
-like($@, qr/\QPlaceholder count/, "placeholder count is invalid");
542
-
543
-
544
-test 'Default tag Error case';
545
-eval{$builder->build_query("{= }")};
546
-like($@, qr/Column name must be specified in tag "{= }"/, "basic '=' : key not exist");
547
-
548
-eval{$builder->build_query("{in }")};
549
-like($@, qr/Column name and count of values must be specified in tag "{in }"/, "in : key not exist");
550
-
551
-eval{$builder->build_query("{in a}")};
552
-like($@, qr/\QColumn name and count of values must be specified in tag "{in }"/,
553
-     "in : key not exist");
554
-
555
-eval{$builder->build_query("{in a r}")};
556
-like($@, qr/\QColumn name and count of values must be specified in tag "{in }"/,
557
-     "in : key not exist");
558
-
559
-test 'variouse source';
560
-$source = "a {= b} c \\{ \\} {= \\{} {= \\}} d;";
561
-$query = $builder->build_query($source);
562
-is($query->sql, 'a b = ? c { } { = ? } = ? d;', "basic : 1");
563
-
564
-$source = "abc;";
565
-$query = $builder->build_query($source);
566
-is($query->sql, 'abc;', "basic : 2");
567
-
568
-$source = "{= a}";
569
-$query = $builder->build_query($source);
570
-is($query->sql, 'a = ?;', "only tag");
571
-
572
-$source = "000;";
573
-$query = $builder->build_query($source);
574
-is($query->sql, '000;', "contain 0 value");
575
-
576
-$source = "a {= b} }";
577
-eval{$builder->build_query($source)};
578
-like($@, qr/unexpected "}"/, "error : 1");
579
-
580
-$source = "a {= {}";
581
-eval{$builder->build_query($source)};
582
-like($@, qr/unexpected "{"/, "error : 2");
583 206
 
584 207
 
585 208
 
... ...
@@ -1501,6 +1124,71 @@ $result = $dbi->execute("select * from ${q}table$p");
1501 1124
 $rows   = $result->all;
1502 1125
 is_deeply($rows, [], "reserved word");
1503 1126
 
1127
+test 'finish statement handle';
1128
+$dbi = DBIx::Custom->connect;
1129
+$dbi->execute($create_table1);
1130
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
1131
+$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
1132
+
1133
+$result = $dbi->select(table => 'table1');
1134
+$row = $result->fetch_first;
1135
+is_deeply($row, [1, 2], "row");
1136
+$row = $result->fetch;
1137
+ok(!$row, "finished");
1138
+
1139
+$result = $dbi->select(table => 'table1');
1140
+$row = $result->fetch_hash_first;
1141
+is_deeply($row, {key1 => 1, key2 => 2}, "row");
1142
+$row = $result->fetch_hash;
1143
+ok(!$row, "finished");
1144
+
1145
+$dbi->execute('create table table2 (key1, key2);');
1146
+$result = $dbi->select(table => 'table2');
1147
+$row = $result->fetch_hash_first;
1148
+ok(!$row, "no row fetch");
1149
+
1150
+$dbi = DBIx::Custom->connect;
1151
+eval { $dbi->execute('drop table table1') };
1152
+$dbi->execute($create_table1);
1153
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
1154
+$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
1155
+$dbi->insert({key1 => 5, key2 => 6}, table => 'table1');
1156
+$dbi->insert({key1 => 7, key2 => 8}, table => 'table1');
1157
+$dbi->insert({key1 => 9, key2 => 10}, table => 'table1');
1158
+$result = $dbi->select(table => 'table1');
1159
+$rows = $result->fetch_multi(2);
1160
+is_deeply($rows, [[1, 2],
1161
+                  [3, 4]], "fetch_multi first");
1162
+$rows = $result->fetch_multi(2);
1163
+is_deeply($rows, [[5, 6],
1164
+                  [7, 8]], "fetch_multi secound");
1165
+$rows = $result->fetch_multi(2);
1166
+is_deeply($rows, [[9, 10]], "fetch_multi third");
1167
+$rows = $result->fetch_multi(2);
1168
+ok(!$rows);
1169
+
1170
+$result = $dbi->select(table => 'table1');
1171
+eval {$result->fetch_multi};
1172
+like($@, qr/Row count must be specified/, "Not specified row count");
1173
+
1174
+$result = $dbi->select(table => 'table1');
1175
+$rows = $result->fetch_hash_multi(2);
1176
+is_deeply($rows, [{key1 => 1, key2 => 2},
1177
+                  {key1 => 3, key2 => 4}], "fetch_multi first");
1178
+$rows = $result->fetch_hash_multi(2);
1179
+is_deeply($rows, [{key1 => 5, key2 => 6},
1180
+                  {key1 => 7, key2 => 8}], "fetch_multi secound");
1181
+$rows = $result->fetch_hash_multi(2);
1182
+is_deeply($rows, [{key1 => 9, key2 => 10}], "fetch_multi third");
1183
+$rows = $result->fetch_hash_multi(2);
1184
+ok(!$rows);
1185
+
1186
+$result = $dbi->select(table => 'table1');
1187
+eval {$result->fetch_hash_multi};
1188
+like($@, qr/Row count must be specified/, "Not specified row count");
1189
+
1190
+
1191
+
1504 1192
 
1505 1193
 
1506 1194