Showing 6 changed files with 136 additions and 14 deletions
+11
Changes
... ...
@@ -1,3 +1,14 @@
1
+0.2107
2
+  - removed EXPERIMENTAL status from the following methods and functinalities.
3
+      DBIx::Custom::Result::value method
4
+      DBIx::Custom::Result::column method
5
+      DBIx::Custom::insert method "bulk_insert" option
6
+      DBIx::Custom::insert method "multiplue insert functinality"
7
+      DBIx::Custom::select method "first argument is received as column option"
8
+      DBIx::Custom::Model::created_at attribute
9
+      DBIx::Custom::Model::updated_at attribute
10
+  - added EXPERIMENTAL DBIx::Custom::execute method "prepare_attr" option
11
+  - added EXPERIMETNAL DBIx::Custom::execute method "statement" option
1 12
 0.2106
2 13
   - renamed DBIx::Custom::Result::fetch_hash_first to fethc_hash_one
3 14
     because first is misleading name. fethc_hash_first is DEPRECATED!
+24 -9
lib/DBIx/Custom.pm
... ...
@@ -354,6 +354,7 @@ sub execute {
354 354
   # Merge second parameter
355 355
   my @cleanup;
356 356
   my $saved_param;
357
+  $opt{statement} ||= '';
357 358
   if (($opt{statement} || '') ne 'insert' && ref $params eq 'ARRAY') {
358 359
     my $params2 = $params->[1];
359 360
     $params = $params->[0];
... ...
@@ -395,7 +396,8 @@ sub execute {
395 396
             unless $column =~ /^[$c\.]+$/;
396 397
         }
397 398
       }
398
-      $query = $self->_create_query($sql,$opt{after_build_sql} || $opt{sqlfilter});
399
+      $query = $self->_create_query($sql,
400
+        $opt{after_build_sql} || $opt{sqlfilter}, $opt{prepare_attr});
399 401
     }
400 402
     $query->{statement} = $opt{statement} || '';
401 403
     $opt{reuse}->{$sql} = $query if $opt{reuse};
... ...
@@ -554,7 +556,7 @@ sub execute {
554 556
   }
555 557
   
556 558
   # Not select statement
557
-  return $affected unless $sth->{NUM_OF_FIELDS};
559
+  return $affected if !$sth->{NUM_OF_FIELDS} && $opt{statement} ne 'select';
558 560
 
559 561
   # Filter(DEPRECATED!)
560 562
   my $infilter = {};
... ...
@@ -1269,7 +1271,9 @@ sub where { DBIx::Custom::Where->new(dbi => shift, @_) }
1269 1271
 
1270 1272
 sub _create_query {
1271 1273
   
1272
-  my ($self, $source, $after_build_sql) = @_;
1274
+  my ($self, $source, $after_build_sql, $prepare_attr) = @_;
1275
+  
1276
+  $prepare_attr ||= {};
1273 1277
   
1274 1278
   # Cache
1275 1279
   my $cache = $self->{cache};
... ...
@@ -1344,7 +1348,7 @@ sub _create_query {
1344 1348
   
1345 1349
   # Prepare statement handle
1346 1350
   my $sth;
1347
-  eval { $sth = $self->dbh->prepare($query->{sql}) };
1351
+  eval { $sth = $self->dbh->prepare($query->{sql}, $prepare_attr) };
1348 1352
   
1349 1353
   if ($@) {
1350 1354
     $self->_croak($@, qq{. Following SQL is executed.\n}
... ...
@@ -2631,6 +2635,13 @@ The following SQL is executed.
2631 2635
 
2632 2636
 Append some statement after SQL.
2633 2637
 
2638
+=item C<prepare_attr> EXPERIMENTAL
2639
+
2640
+  prepare_attr => {async => 1}
2641
+
2642
+Statemend handle attributes,
2643
+this is L<DBI>'s C<prepare> method second argument.
2644
+
2634 2645
 =item C<bind_type>
2635 2646
 
2636 2647
 Specify database bind data type.
... ...
@@ -2694,6 +2705,12 @@ because generally creating query object is slow.
2694 2705
 
2695 2706
 Priamry key. This is used for C<id> option.
2696 2707
 
2708
+=item C<statement> EXPERIMETAL
2709
+
2710
+  statement => 'select'
2711
+
2712
+If you set statement to C<select>, return value is always L<DBIx::Custom::Result> object.
2713
+
2697 2714
 =item C<table>
2698 2715
   
2699 2716
   table => 'author'
... ...
@@ -2790,7 +2807,6 @@ as parameter value.
2790 2807
   {date => \"NOW()"}
2791 2808
 
2792 2809
 You can pass multiple parameters, this is very fast.
2793
-This is EXPERIMETNAL.
2794 2810
 
2795 2811
   $dbi->insert(
2796 2812
     [
... ...
@@ -2801,7 +2817,7 @@ This is EXPERIMETNAL.
2801 2817
   );
2802 2818
 
2803 2819
 In multiple insert, you can't use C<id> option.
2804
-and only first parameter is used by creating sql.
2820
+and only first parameter is used to create sql.
2805 2821
 
2806 2822
 B<options>
2807 2823
 
... ...
@@ -2809,8 +2825,8 @@ C<insert> method use all of C<execute> method's options,
2809 2825
 and use the following new ones.
2810 2826
 
2811 2827
 =over 4
2812
-b
2813
-=item C<bulk_insert> EXPERIMENTAL
2828
+
2829
+=item C<bulk_insert>
2814 2830
 
2815 2831
   bulk_insert => 1
2816 2832
 
... ...
@@ -3030,7 +3046,6 @@ Register filters, used by C<filter> option of many methods.
3030 3046
 Execute select statement.
3031 3047
 
3032 3048
 You can pass odd number arguments. first argument is C<column>.
3033
-This is EXPERIMENTAL.
3034 3049
 
3035 3050
   my $result = $dbi->select(['author', 'title'], table => 'book');
3036 3051
 
+2 -2
lib/DBIx/Custom/Model.pm
... ...
@@ -185,7 +185,7 @@ my $model = DBIx::Custom::Model->new(table => 'books');
185 185
 
186 186
 L<DBIx::Custom> object.
187 187
 
188
-=head2 C<created_at EXPERIMENTAL>
188
+=head2 C<created_at>
189 189
 
190 190
   my $created_at = $model->created_at;
191 191
   $model = $model->created_at('created_datatime');
... ...
@@ -225,7 +225,7 @@ Database data type, this is used as type optioon of C<insert>,
225 225
 C<update>, C<update_all>, C<delete>, C<delete_all>,
226 226
 and C<select> method
227 227
 
228
-=head2 C<updated_at EXPERIMENTAL>
228
+=head2 C<updated_at>
229 229
 
230 230
   my $updated_at = $model->updated_at;
231 231
   $model = $model->updated_at('updated_datatime');
+3 -3
lib/DBIx/Custom/Result.pm
... ...
@@ -327,7 +327,7 @@ sub _cache {
327 327
   $self->{_type_map} = {};
328 328
   $self->{_pos} = {};
329 329
   $self->{_columns} = {};
330
-  for (my $i = 0; $i < @{$self->{sth}->{NAME}}; $i++) {
330
+  for (my $i = 0; $i < @{$self->{sth}->{NAME} || []}; $i++) {
331 331
     my $type = lc $self->{sth}{TYPE}[$i];
332 332
     my $name = $self->{sth}{NAME}[$i];
333 333
     $self->{_type_map}{$type} ||= [];
... ...
@@ -496,7 +496,7 @@ and implements the following new ones.
496 496
 
497 497
 Same as C<fetch_hash_all>.
498 498
 
499
-=head2 C<column> EXPERIMENTAL
499
+=head2 C<column>
500 500
 
501 501
   my $column = $result->column;
502 502
 
... ...
@@ -645,7 +645,7 @@ By default, type rule is on.
645 645
 Turn C<from2> type rule on.
646 646
 By default, type rule is on.
647 647
 
648
-=head2 C<value> EXPERIMENTAL
648
+=head2 C<value>
649 649
 
650 650
   my $value = $result->value;
651 651
 
t/_run/mysql-async.run
No changes.
+96
t/mysql-async.t
... ...
@@ -0,0 +1,96 @@
1
+use Test::More;
2
+use strict;
3
+use warnings;
4
+use utf8;
5
+
6
+use FindBin;
7
+use DBIx::Custom;
8
+
9
+my $dbi;
10
+my $dsn;
11
+my $args;
12
+my $user = 'dbix_custom';
13
+my $password = 'dbix_custom';
14
+my $database = 'dbix_custom';
15
+
16
+$dsn = "dbi:mysql:database=$database";
17
+$args = {dsn => $dsn, user => $user, password => $password,};
18
+
19
+plan skip_all => 'mysql private test' unless -f "$FindBin::Bin/run/mysql-async.run"
20
+  && eval { $dbi = DBIx::Custom->connect($args); 1 };
21
+plan 'no_plan';
22
+
23
+$SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /DEPRECATED/};
24
+
25
+# Function for test name
26
+sub test { print "# $_[0]\n" }
27
+
28
+# Varialbes for tests
29
+my $dbname;
30
+my $row;
31
+my $rows;
32
+my $result;
33
+my $result2;
34
+my $model;
35
+my $dbi2;
36
+
37
+test 'connect';
38
+eval {
39
+  $dbi = DBIx::Custom->connect(
40
+    dsn => "dbi:mysql:database=$database;host=localhost;port=10000",
41
+    user => $user,
42
+    password => $password
43
+  );
44
+};
45
+ok(!$@);
46
+
47
+eval { $dbi->do('drop table table1') };
48
+$dbi->do('create table table1 (key1 varchar(255), key2 varchar(255)) engine=InnoDB');
49
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
50
+
51
+test 'async test';
52
+
53
+use AnyEvent;
54
+use DBI;
55
+my $cond = AnyEvent->condvar;
56
+$result = $dbi->execute('SELECT SLEEP(1), 3', undef,
57
+  prepare_attr => {async => 1}, statement => 'select');
58
+
59
+$dbi2 = DBIx::Custom->connect(
60
+  dsn => "dbi:mysql:database=$database;host=localhost;port=10000",
61
+  user => $user,
62
+  password => $password
63
+);
64
+$result2 = $dbi2->select('key1', table => 'table1', prepare_attr => {async => 1});
65
+
66
+my $timer = AnyEvent->timer(
67
+  interval => 1,
68
+  cb => sub {
69
+    1;
70
+  }
71
+);
72
+
73
+my $count = 0;
74
+
75
+my $mysql_watcher = AnyEvent->io(
76
+  fh   => $dbi->dbh->mysql_fd,
77
+  poll => 'r',
78
+  cb   => sub {
79
+    my $row = $result->fetch_one;
80
+    is($row->[1], 3, 'before');
81
+    $cond->send if ++$count == 2;
82
+    undef $result;
83
+  }
84
+);
85
+
86
+my $mysql_watcher2= AnyEvent->io(
87
+  fh   => $dbi2->dbh->mysql_fd,
88
+  poll => 'r',
89
+  cb   => sub {
90
+    my $row = $result2->fetch_one;
91
+    is($row->[0], 1, 'after');
92
+    $cond->send if ++$count == 2;
93
+    undef $result2;
94
+  }
95
+);
96
+$cond->recv;