Showing 5 changed files with 156 additions and 135 deletions
+2 -5
Changes 1000644 → 1000755
... ...
@@ -1,5 +1,2 @@
1
-Revision history for DBI-Custom
2
-
3
-0.01    Date/time
4
-        First version, released on an unsuspecting world.
5
-
1
+0.0101
2
+  First release
+2 -39
README 1000644 → 1000755
... ...
@@ -1,47 +1,10 @@
1 1
 DBI-Custom
2 2
 
3
-The README is used to introduce the module and provide instructions on
4
-how to install the module, any machine dependencies it may have (for
5
-example C compilers and installed libraries) and any other information
6
-that should be provided before the module is installed.
7
-
8
-A README file is required for CPAN modules since CPAN extracts the README
9
-file from a module distribution so that people browsing the archive
10
-can use it to get an idea of the module's uses. It is usually a good idea
11
-to provide version information here so that people can decide whether
12
-fixes for the module are worth downloading.
13
-
3
+Custamizable DBI
14 4
 
15 5
 INSTALLATION
16 6
 
17
-To install this module, run the following commands:
18
-
19
-	perl Build.PL
20
-	./Build
21
-	./Build test
22
-	./Build install
23
-
24
-SUPPORT AND DOCUMENTATION
25
-
26
-After installing, you can find documentation for this module with the
27
-perldoc command.
28
-
29
-    perldoc DBI::Custom
30
-
31
-You can also look for information at:
32
-
33
-    RT, CPAN's request tracker
34
-        http://rt.cpan.org/NoAuth/Bugs.html?Dist=DBI-Custom
35
-
36
-    AnnoCPAN, Annotated CPAN documentation
37
-        http://annocpan.org/dist/DBI-Custom
38
-
39
-    CPAN Ratings
40
-        http://cpanratings.perl.org/d/DBI-Custom
41
-
42
-    Search CPAN
43
-        http://search.cpan.org/dist/DBI-Custom/
44
-
7
+cpan DBI::Custom
45 8
 
46 9
 COPYRIGHT AND LICENCE
47 10
 
+96 -87
lib/DBI/Custom.pm
... ...
@@ -5,9 +5,10 @@ our $VERSION = '0.0101';
5 5
 
6 6
 use Carp 'croak';
7 7
 use DBI;
8
-use DBI::Custom::SQL::Template;
9
-use DBI::Custom::Result;
10 8
 use DBI::Custom::Query;
9
+use DBI::Custom::Result;
10
+use DBI::Custom::SQL::Template;
11
+
11 12
 
12 13
 ### Class-Object Accessors
13 14
 sub user        : ClassObjectAttr { initialize => {clone => 'scalar'} }
... ...
@@ -65,8 +66,7 @@ sub add_filter {
65 66
 sub _auto_commit {
66 67
     my $self = shift;
67 68
     
68
-    croak("Cannot change AutoCommit becouse of not connected")
69
-      unless $self->dbh;
69
+    croak("Not yet connect to database") unless $self->dbh;
70 70
     
71 71
     if (@_) {
72 72
         $self->dbh->{AutoCommit} = $_[0];
... ...
@@ -83,7 +83,7 @@ sub connect {
83 83
     my $password    = $self->password;
84 84
     my $dbi_options  = $self->dbi_options;
85 85
     
86
-    my $dbh = DBI->connect(
86
+    my $dbh = eval{DBI->connect(
87 87
         $data_source,
88 88
         $user,
89 89
         $password,
... ...
@@ -93,7 +93,9 @@ sub connect {
93 93
             AutoCommit => 1,
94 94
             %{$dbi_options || {} }
95 95
         }
96
-    );
96
+    )};
97
+    
98
+    croak $@ if $@;
97 99
     
98 100
     $self->dbh($dbh);
99 101
     return $self;
... ...
@@ -127,74 +129,19 @@ sub reconnect {
127 129
     $self->connect;
128 130
 }
129 131
 
130
-# Run tranzaction
131
-sub run_tranzaction {
132
-    my ($self, $tranzaction) = @_;
133
-    
134
-    # Auto commit off
135
-    $self->_auto_commit(0);
136
-    
137
-    # Run tranzaction
138
-    eval {$tranzaction->()};
139
-    
140
-    # Tranzaction error
141
-    my $tranzaction_error = $@;
142
-    
143
-    # RaiseError on
144
-    my $old_raise_error = $self->dbh->{RaiseError};
145
-    $self->dbh->{RaiseError} = 1;
146
-    
147
-    # Tranzaction is failed.
148
-    if ($tranzaction_error) {
149
-        # Rollback
150
-        eval{$self->dbh->rollback};
151
-        
152
-        # Rollback error
153
-        my $rollback_error = $@;
154
-        
155
-        # Auto commit on
156
-        $self->_auto_commit(1);
157
-        
158
-        # Restore RaiseError value
159
-        $self->dbh->{RaiseError} = $old_raise_error;
160
-        
161
-        if ($rollback_error) {
162
-            # Rollback is failed
163
-            croak("${tranzaction_error}Rollback is failed : $rollback_error");
164
-        }
165
-        else {
166
-            # Rollback is success
167
-            croak("${tranzaction_error}Rollback is success");
168
-        }
169
-    }
170
-    # Tranzaction is success
171
-    else {
172
-        # Commit
173
-        eval{$self->dbh->commit};
174
-        my $commit_error = $@;
175
-        
176
-        # Auto commit on
177
-        $self->_auto_commit(1);
178
-        
179
-        # Restore RaiseError value
180
-        $self->dbh->{RaiseError} = $old_raise_error;
181
-        
182
-        # Commit is failed
183
-        croak($commit_error) if $commit_error;
184
-    }
185
-}
186
-
187 132
 # Prepare statement handle
188 133
 sub prepare {
189 134
     my ($self, $sql) = @_;
190 135
     
191 136
     # Connect if not
192
-    eval{$self->connect unless $self->connected};
193
-    croak($@) if $@;
137
+    $self->connect unless $self->connected;
194 138
     
195 139
     # Prepare
196 140
     my $sth = eval{$self->dbh->prepare($sql)};
197
-    croak($@) if $@;
141
+    
142
+    # Error
143
+    croak("$@<Your SQL>\n$sql") if $@;
144
+    
198 145
     return $sth;
199 146
 }
200 147
 
... ...
@@ -203,12 +150,21 @@ sub do{
203 150
     my ($self, $sql, @bind_values) = @_;
204 151
     
205 152
     # Connect if not
206
-    eval{$self->connect unless $self->connected};
207
-    croak($@) if $@;
153
+    $self->connect unless $self->connected;
208 154
     
209 155
     # Do
210
-    eval{$self->dbh->do($sql, @bind_values)};
211
-    croak($@) if $@;
156
+    my $ret_val = eval{$self->dbh->do($sql, @bind_values)};
157
+    
158
+    # Error
159
+    if ($@) {
160
+        my $error = $@;
161
+        require Data::Dumper;
162
+        
163
+        my $bind_value_dump
164
+          = Data::Dumper->Dump([\@bind_values], ['*bind_valuds']);
165
+        
166
+        croak("$error<Your SQL>\n$sql\n<Your bind values>\n$bind_value_dump\n");
167
+    }
212 168
 }
213 169
 
214 170
 # Create query
... ...
@@ -224,16 +180,10 @@ sub create_query {
224 180
     $query = DBI::Custom::Query->new($query);
225 181
     
226 182
     # Connect if not
227
-    eval{$self->connect unless $self->connected};
228
-    croak($@) if $@;
183
+    $self->connect unless $self->connected;
229 184
     
230 185
     # Prepare statement handle
231
-    my $sth = eval{$self->dbh->prepare($query->{sql})};
232
-    if ($@) {
233
-        my $sql = $query->{sql} || '';
234
-        my $message = "<Created SQL>\n$sql\n";
235
-        croak("$@$message");
236
-    }
186
+    my $sth = $self->prepare($query->{sql});
237 187
     
238 188
     # Set statement handle
239 189
     $query->sth($sth);
... ...
@@ -274,13 +224,12 @@ sub execute {
274 224
     my $ret_val = eval{$sth->execute(@$bind_values)};
275 225
     
276 226
     # Execute error
277
-    if ($@) {
227
+    if (my $execute_error = $@) {
278 228
         require Data::Dumper;
279 229
         my $sql         = $query->{sql} || '';
280 230
         my $params_dump = Data::Dumper->Dump([$params], ['*params']);
281 231
         
282
-        my $message = "<Created SQL>\n$sql\n<Your parameters>$params_dump";
283
-        croak("$@$message");
232
+        croak("$execute_error<Your SQL>\n$sql\n<Your parameters>\n$params_dump");
284 233
     }
285 234
     
286 235
     # Return resultset if select statement is executed
... ...
@@ -332,11 +281,6 @@ sub _build_bind_values {
332 281
                 # Current key
333 282
                 my $current_key = $access_key->[$i];
334 283
                 
335
-                # Each access key must be string or array reference
336
-                croak("'access_keys' each value must be string or array reference")
337
-                  unless (ref $current_key eq 'ARRAY' ||
338
-                          ($current_key && !ref $current_key));
339
-                
340 284
                 # Last key
341 285
                 if ($i == @$access_key - 1) {
342 286
                     # Key is array reference
... ...
@@ -406,7 +350,7 @@ sub _build_bind_values {
406 350
             require Data::Dumper;
407 351
             my $key_info_dump  = Data::Dumper->Dump([$key_info], ['*key_info']);
408 352
             my $params_dump    = Data::Dumper->Dump([$params], ['*params']);
409
-            croak("Key not found in your parameters\n" . 
353
+            croak("Corresponding key is not found in your parameters\n" . 
410 354
                   "<Key information>\n$key_info_dump\n\n" .
411 355
                   "<Your parameters>\n$params_dump\n");
412 356
         }
... ...
@@ -414,6 +358,56 @@ sub _build_bind_values {
414 358
     return \@bind_values;
415 359
 }
416 360
 
361
+# Run tranzaction
362
+sub run_tranzaction {
363
+    my ($self, $tranzaction) = @_;
364
+    
365
+    # Check auto commit
366
+    croak("AutoCommit must be true before tranzaction start")
367
+      unless $self->_auto_commit;
368
+    
369
+    # Auto commit off
370
+    $self->_auto_commit(0);
371
+    
372
+    # Run tranzaction
373
+    eval {$tranzaction->()};
374
+    
375
+    # Tranzaction error
376
+    my $tranzaction_error = $@;
377
+    
378
+    # Tranzaction is failed.
379
+    if ($tranzaction_error) {
380
+        # Rollback
381
+        eval{$self->dbh->rollback};
382
+        
383
+        # Rollback error
384
+        my $rollback_error = $@;
385
+        
386
+        # Auto commit on
387
+        $self->_auto_commit(1);
388
+        
389
+        if ($rollback_error) {
390
+            # Rollback is failed
391
+            croak("${tranzaction_error}Rollback is failed : $rollback_error");
392
+        }
393
+        else {
394
+            # Rollback is success
395
+            croak("${tranzaction_error}Rollback is success");
396
+        }
397
+    }
398
+    # Tranzaction is success
399
+    else {
400
+        # Commit
401
+        eval{$self->dbh->commit};
402
+        my $commit_error = $@;
403
+        
404
+        # Auto commit on
405
+        $self->_auto_commit(1);
406
+        
407
+        # Commit is failed
408
+        croak($commit_error) if $commit_error;
409
+    }
410
+}
417 411
 
418 412
 Object::Simple->build_class;
419 413
 
... ...
@@ -674,6 +668,21 @@ See also L<DBI::Custom::SQL::Template>
674 668
 If tranzaction is success, commit is execute. 
675 669
 If tranzation is died, rollback is execute.
676 670
 
671
+=head1 CAUTION
672
+
673
+DBI::Custom have DIB object internal.
674
+This module is work well in the following DBI condition.
675
+
676
+    1. AutoCommit is true
677
+    2. RaiseError is true
678
+
679
+By default, Both AutoCommit and RaiseError is true.
680
+You must not change these mode not to damage your data.
681
+
682
+If you change these mode, 
683
+you cannot get correct error message, 
684
+or run_tranzaction may fail.
685
+
677 686
 =head1 AUTHOR
678 687
 
679 688
 Yuki Kimoto, C<< <kimoto.yuki at gmail.com> >>
+56
t/02-sqlite.t
... ...
@@ -58,12 +58,31 @@ $dbi->connect;
58 58
 $dbi->disconnect;
59 59
 ok(!$dbi->dbh, $test);
60 60
 
61
+
61 62
 test 'connected';
62 63
 $dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:');
63 64
 ok(!$dbi->connected, "$test : not connected");
64 65
 $dbi->connect;
65 66
 ok($dbi->connected, "$test : connected");
66 67
 
68
+
69
+test 'preapare';
70
+$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:');
71
+$sth = $dbi->prepare($CREATE_TABLE->{0});
72
+ok($sth, "$test : auto connect");
73
+$sth->execute;
74
+$sth = $dbi->prepare($DROP_TABLE->{0});
75
+ok($sth, "$test : basic");
76
+
77
+
78
+test 'do';
79
+$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:');
80
+$ret_val = $dbi->do($CREATE_TABLE->{0});
81
+ok(defined $ret_val, "$test : auto connect");
82
+$ret_val = $dbi->do($DROP_TABLE->{0});
83
+ok(defined $ret_val, "$test : basic");
84
+
85
+
67 86
 # Prepare table
68 87
 $dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:');
69 88
 $dbi->connect;
... ...
@@ -408,3 +427,40 @@ $rows   = $result->fetch_all_hash;
408 427
 is_deeply($rows, [], "$test : rollback");
409 428
 
410 429
 
430
+test 'Error case';
431
+$dbi = DBI::Custom->new;
432
+eval{$dbi->run_tranzaction};
433
+like($@, qr/Not yet connect to database/, "$test : Yet Connected");
434
+
435
+$dbi = DBI::Custom->new(data_source => 'dbi:SQLit');
436
+eval{$dbi->connect;};
437
+ok($@, "$test : connect error");
438
+
439
+$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:');
440
+$dbi->connect;
441
+$dbi->dbh->{AutoCommit} = 0;
442
+eval{$dbi->run_tranzaction()};
443
+like($@, qr/AutoCommit must be true before tranzaction start/,
444
+         "$test : run_tranzaction auto commit is false");
445
+
446
+$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:');
447
+$sql = 'laksjdf';
448
+eval{$dbi->prepare($sql)};
449
+like($@, qr/$sql/, "$test : prepare fail");
450
+
451
+$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:');
452
+$sql = 'laksjdf';
453
+eval{$dbi->do($sql, qw/1 2 3/)};
454
+like($@, qr/$sql/, "$test : do fail");
455
+
456
+$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:');
457
+eval{$dbi->create_query("{p }")};
458
+ok($@, "$test : create_query invalid SQL template");
459
+
460
+$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:');
461
+$dbi->do($CREATE_TABLE->{0});
462
+$query = $dbi->create_query("select * from table1 where {= key1}");
463
+eval{$dbi->execute($query, {key2 => 1})};
464
+like($@, qr/Corresponding key is not found in your parameters/, 
465
+        "$test : execute corresponding key not found");
466
+
-4
t/boilerplate.t 1000644 → 1000755
... ...
@@ -36,8 +36,6 @@ sub module_boilerplate_ok {
36 36
     );
37 37
 }
38 38
 
39
-TODO: {
40
-  local $TODO = "Need to replace the boilerplate text";
41 39
 
42 40
   not_in_file_ok(README =>
43 41
     "The README is used..."       => qr/The README is used/,
... ...
@@ -51,5 +49,3 @@ TODO: {
51 49
   module_boilerplate_ok('lib/DBI/Custom.pm');
52 50
 
53 51
 
54
-}
55
-