... | ... |
@@ -13,7 +13,6 @@ use DBI::Custom::Query; |
13 | 13 |
sub user : ClassObjectAttr { initialize => {clone => 'scalar'} } |
14 | 14 |
sub password : ClassObjectAttr { initialize => {clone => 'scalar'} } |
15 | 15 |
sub data_source : ClassObjectAttr { initialize => {clone => 'scalar'} } |
16 |
-sub database : ClassObjectAttr { initialize => {clone => 'scalar'} } |
|
17 | 16 |
sub dbi_options : ClassObjectAttr { initialize => {clone => 'hash', |
18 | 17 |
default => sub { {} } } } |
19 | 18 |
|
... | ... |
@@ -67,7 +66,7 @@ sub _auto_commit { |
67 | 66 |
my $self = shift; |
68 | 67 |
|
69 | 68 |
croak("Cannot change AutoCommit becouse of not connected") |
70 |
- unless $self->dbh; |
|
69 |
+ unless $self->dbh; |
|
71 | 70 |
|
72 | 71 |
if (@_) { |
73 | 72 |
$self->dbh->{AutoCommit} = $_[0]; |
... | ... |
@@ -109,7 +108,7 @@ sub DESTROY { |
109 | 108 |
# Is connected? |
110 | 109 |
sub connected { |
111 | 110 |
my $self = shift; |
112 |
- return exists $self->{dbh} && eval {$self->{dbh}->can('prepare')}; |
|
111 |
+ return ref $self->{dbh} eq 'DBI::db'; |
|
113 | 112 |
} |
114 | 113 |
|
115 | 114 |
# Disconnect |
... | ... |
@@ -132,41 +131,87 @@ sub reconnect { |
132 | 131 |
sub run_tranzaction { |
133 | 132 |
my ($self, $tranzaction) = @_; |
134 | 133 |
|
134 |
+ # Auto commit off |
|
135 | 135 |
$self->_auto_commit(0); |
136 | 136 |
|
137 |
- eval { |
|
138 |
- $tranzaction->(); |
|
139 |
- $self->dbh->commit; |
|
140 |
- }; |
|
137 |
+ # Run tranzaction |
|
138 |
+ eval {$tranzaction->()}; |
|
141 | 139 |
|
142 |
- if ($@) { |
|
143 |
- my $tranzaction_error = $@; |
|
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 = $@; |
|
144 | 154 |
|
145 |
- $self->dbh->rollback or croak("$@ and rollback also failed"); |
|
146 |
- croak("$tranzaction_error"); |
|
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; |
|
147 | 184 |
} |
148 |
- $self->_auto_commit(1); |
|
149 | 185 |
} |
150 | 186 |
|
187 |
+# Prepare statement handle |
|
151 | 188 |
sub prepare { |
152 | 189 |
my ($self, $sql) = @_; |
190 |
+ |
|
191 |
+ # Connect if not |
|
153 | 192 |
eval{$self->connect unless $self->connected}; |
154 | 193 |
croak($@) if $@; |
155 | 194 |
|
195 |
+ # Prepare |
|
156 | 196 |
my $sth = eval{$self->dbh->prepare($sql)}; |
157 | 197 |
croak($@) if $@; |
158 | 198 |
return $sth; |
159 | 199 |
} |
160 | 200 |
|
201 |
+# Execute SQL directly |
|
161 | 202 |
sub do{ |
162 | 203 |
my ($self, $sql, @bind_values) = @_; |
204 |
+ |
|
205 |
+ # Connect if not |
|
163 | 206 |
eval{$self->connect unless $self->connected}; |
164 | 207 |
croak($@) if $@; |
165 | 208 |
|
209 |
+ # Do |
|
166 | 210 |
eval{$self->dbh->do($sql, @bind_values)}; |
167 | 211 |
croak($@) if $@; |
168 | 212 |
} |
169 | 213 |
|
214 |
+# Create query |
|
170 | 215 |
sub create_query { |
171 | 216 |
my ($self, $template) = @_; |
172 | 217 |
|
... | ... |
@@ -178,8 +223,9 @@ sub create_query { |
178 | 223 |
# Create Query object; |
179 | 224 |
$query = DBI::Custom::Query->new($query); |
180 | 225 |
|
181 |
- # connect if not |
|
182 |
- $self->connect unless $self->connected; |
|
226 |
+ # Connect if not |
|
227 |
+ eval{$self->connect unless $self->connected}; |
|
228 |
+ croak($@) if $@; |
|
183 | 229 |
|
184 | 230 |
# Prepare statement handle |
185 | 231 |
my $sth = eval{$self->dbh->prepare($query->{sql})}; |
... | ... |
@@ -207,6 +253,7 @@ sub create_query { |
207 | 253 |
return $query; |
208 | 254 |
} |
209 | 255 |
|
256 |
+# Execute query |
|
210 | 257 |
sub execute { |
211 | 258 |
my ($self, $query, $params) = @_; |
212 | 259 |
$params ||= {}; |
... | ... |
@@ -225,6 +272,8 @@ sub execute { |
225 | 272 |
# Execute |
226 | 273 |
my $sth = $query->sth; |
227 | 274 |
my $ret_val = eval{$sth->execute(@$bind_values)}; |
275 |
+ |
|
276 |
+ # Execute error |
|
228 | 277 |
if ($@) { |
229 | 278 |
require Data::Dumper; |
230 | 279 |
my $sql = $query->{sql} || ''; |
... | ... |
@@ -236,7 +285,11 @@ sub execute { |
236 | 285 |
|
237 | 286 |
# Return resultset if select statement is executed |
238 | 287 |
if ($sth->{NUM_OF_FIELDS}) { |
288 |
+ |
|
289 |
+ # Get result class |
|
239 | 290 |
my $result_class = $self->result_class; |
291 |
+ |
|
292 |
+ # Create result |
|
240 | 293 |
my $result = $result_class->new({ |
241 | 294 |
sth => $sth, |
242 | 295 |
fetch_filter => $query->fetch_filter, |
... | ... |
@@ -247,9 +300,9 @@ sub execute { |
247 | 300 |
return $ret_val; |
248 | 301 |
} |
249 | 302 |
|
303 |
+# Build binding values |
|
250 | 304 |
sub _build_bind_values { |
251 | 305 |
my ($self, $query, $params) = @_; |
252 |
- |
|
253 | 306 |
my $key_infos = $query->key_infos; |
254 | 307 |
my $bind_filter = $query->bind_filter; |
255 | 308 |
my $no_bind_filters_map = $query->_no_bind_filters_map || {}; |
... | ... |
@@ -259,58 +312,96 @@ sub _build_bind_values { |
259 | 312 |
|
260 | 313 |
# Create bind values |
261 | 314 |
foreach my $key_info (@$key_infos) { |
262 |
- my $filtering_key = $key_info->{key}; |
|
263 |
- my $access_keys = $key_info->{access_keys}; |
|
264 |
- |
|
315 |
+ # Set variable |
|
316 |
+ my $access_keys = $key_info->{access_keys}; |
|
265 | 317 |
my $original_key = $key_info->{original_key} || ''; |
266 | 318 |
my $table = $key_info->{table} || ''; |
267 | 319 |
my $column = $key_info->{column} || ''; |
268 | 320 |
|
321 |
+ # Key is found? |
|
269 | 322 |
my $found; |
323 |
+ |
|
324 |
+ # Build bind values |
|
270 | 325 |
ACCESS_KEYS : |
271 | 326 |
foreach my $access_key (@$access_keys) { |
327 |
+ # Root parameter |
|
272 | 328 |
my $root_params = $params; |
329 |
+ |
|
330 |
+ # Search corresponding value |
|
273 | 331 |
for (my $i = 0; $i < @$access_key; $i++) { |
274 |
- my $key = $access_key->[$i]; |
|
332 |
+ # Current key |
|
333 |
+ my $current_key = $access_key->[$i]; |
|
275 | 334 |
|
335 |
+ # Each access key must be string or array reference |
|
276 | 336 |
croak("'access_keys' each value must be string or array reference") |
277 |
- unless (ref $key eq 'ARRAY' || ($key && !ref $key)); |
|
337 |
+ unless (ref $current_key eq 'ARRAY' || |
|
338 |
+ ($current_key && !ref $current_key)); |
|
278 | 339 |
|
340 |
+ # Last key |
|
279 | 341 |
if ($i == @$access_key - 1) { |
280 |
- if (ref $key eq 'ARRAY') { |
|
281 |
- if ($bind_filter && !$no_bind_filters_map->{$original_key}) { |
|
342 |
+ # Key is array reference |
|
343 |
+ if (ref $current_key eq 'ARRAY') { |
|
344 |
+ # Filtering |
|
345 |
+ if ($bind_filter && |
|
346 |
+ !$no_bind_filters_map->{$original_key}) |
|
347 |
+ { |
|
282 | 348 |
push @bind_values, |
283 |
- $bind_filter->($original_key, $root_params->[$key->[0]], |
|
349 |
+ $bind_filter->($original_key, |
|
350 |
+ $root_params->[$current_key->[0]], |
|
284 | 351 |
$table, $column); |
285 | 352 |
} |
353 |
+ # Not filtering |
|
286 | 354 |
else { |
287 |
- push @bind_values, scalar $root_params->[$key->[0]]; |
|
355 |
+ push @bind_values, |
|
356 |
+ scalar $root_params->[$current_key->[0]]; |
|
288 | 357 |
} |
289 | 358 |
} |
359 |
+ # Key is string |
|
290 | 360 |
else { |
291 |
- next ACCESS_KEYS unless exists $root_params->{$key}; |
|
292 |
- if ($bind_filter && !$no_bind_filters_map->{$original_key}) { |
|
361 |
+ # Key is not found |
|
362 |
+ next ACCESS_KEYS |
|
363 |
+ unless exists $root_params->{$current_key}; |
|
364 |
+ |
|
365 |
+ # Filtering |
|
366 |
+ if ($bind_filter && |
|
367 |
+ !$no_bind_filters_map->{$original_key}) |
|
368 |
+ { |
|
293 | 369 |
push @bind_values, |
294 |
- $bind_filter->($original_key, $root_params->{$key}, |
|
370 |
+ $bind_filter->($original_key, |
|
371 |
+ $root_params->{$current_key}, |
|
295 | 372 |
$table, $column); |
296 | 373 |
} |
374 |
+ # Not filtering |
|
297 | 375 |
else { |
298 |
- push @bind_values, scalar $root_params->{$key}; |
|
376 |
+ push @bind_values, |
|
377 |
+ scalar $root_params->{$current_key}; |
|
299 | 378 |
} |
300 | 379 |
} |
380 |
+ |
|
381 |
+ # Key is found |
|
301 | 382 |
$found = 1; |
302 | 383 |
} |
303 |
- |
|
304 |
- if (ref $key eq 'ARRAY') { |
|
305 |
- $root_params = $root_params->[$key->[0]]; |
|
306 |
- } |
|
384 |
+ # First or middle key |
|
307 | 385 |
else { |
308 |
- next ACCESS_KEYS unless exists $root_params->{$key}; |
|
309 |
- $root_params = $root_params->{$key}; |
|
386 |
+ # Key is array reference |
|
387 |
+ if (ref $current_key eq 'ARRAY') { |
|
388 |
+ # Go next key |
|
389 |
+ $root_params = $root_params->[$current_key->[0]]; |
|
390 |
+ } |
|
391 |
+ # Key is string |
|
392 |
+ else { |
|
393 |
+ # Not found |
|
394 |
+ next ACCESS_KEYS |
|
395 |
+ unless exists $root_params->{$current_key}; |
|
396 |
+ |
|
397 |
+ # Go next key |
|
398 |
+ $root_params = $root_params->{$current_key}; |
|
399 |
+ } |
|
310 | 400 |
} |
311 | 401 |
} |
312 | 402 |
} |
313 | 403 |
|
404 |
+ # Key is not found |
|
314 | 405 |
unless ($found) { |
315 | 406 |
require Data::Dumper; |
316 | 407 |
my $key_info_dump = Data::Dumper->Dump([$key_info], ['*key_info']); |
... | ... |
@@ -334,7 +425,14 @@ DBI::Custom - Customizable simple DBI |
334 | 425 |
|
335 | 426 |
Version 0.0101 |
336 | 427 |
|
337 |
-=cut |
|
428 |
+=head1 CAUTION |
|
429 |
+ |
|
430 |
+This module is now experimental stage. |
|
431 |
+ |
|
432 |
+I want you to try this module |
|
433 |
+because I want this module stable, and not to damage your DB data by this module bug. |
|
434 |
+ |
|
435 |
+Please tell me bug if you find |
|
338 | 436 |
|
339 | 437 |
=head1 SYNOPSIS |
340 | 438 |
|
... | ... |
@@ -576,8 +674,6 @@ See also L<DBI::Custom::SQL::Template> |
576 | 674 |
If tranzaction is success, commit is execute. |
577 | 675 |
If tranzation is died, rollback is execute. |
578 | 676 |
|
579 |
- |
|
580 |
- |
|
581 | 677 |
=head1 AUTHOR |
582 | 678 |
|
583 | 679 |
Yuki Kimoto, C<< <kimoto.yuki at gmail.com> >> |
... | ... |
@@ -591,7 +687,4 @@ Copyright 2009 Yuki Kimoto, all rights reserved. |
591 | 687 |
This program is free software; you can redistribute it and/or modify it |
592 | 688 |
under the same terms as Perl itself. |
593 | 689 |
|
594 |
- |
|
595 | 690 |
=cut |
596 |
- |
|
597 |
-1; # End of DBI::Custom |
... | ... |
@@ -3,7 +3,6 @@ use strict; |
3 | 3 |
use warnings; |
4 | 4 |
|
5 | 5 |
use DBI::Custom; |
6 |
-use Scalar::Util qw/blessed/; |
|
7 | 6 |
use DBI::Custom::SQL::Template; |
8 | 7 |
|
9 | 8 |
# Function for test name |
... | ... |
@@ -12,15 +11,16 @@ sub test { |
12 | 11 |
$test = shift; |
13 | 12 |
} |
14 | 13 |
|
15 |
-# Varialbes for test |
|
14 |
+# Variables for test |
|
15 |
+our $SQL_TMPL = { |
|
16 |
+ 0 => DBI::Custom::SQL::Template->new->tag_start(0), |
|
17 |
+ 1 => DBI::Custom::SQL::Template->new->tag_start(1), |
|
18 |
+ 2 => DBI::Custom::SQL::Template->new->tag_start(2) |
|
19 |
+}; |
|
16 | 20 |
my $dbi; |
17 |
-my $sql_tmpl; |
|
18 | 21 |
|
19 |
-my $sql_tmpl1 = DBI::Custom::SQL::Template->new->tag_start(0); |
|
20 |
-my $sql_tmpl2 = DBI::Custom::SQL::Template->new->tag_start(1); |
|
21 |
-my $sql_tmpl3 = DBI::Custom::SQL::Template->new->tag_start(2); |
|
22 | 22 |
|
23 |
-test 'constructor'; |
|
23 |
+test 'Constructor'; |
|
24 | 24 |
$dbi = DBI::Custom->new( |
25 | 25 |
user => 'a', |
26 | 26 |
password => 'b', |
... | ... |
@@ -32,12 +32,12 @@ $dbi = DBI::Custom->new( |
32 | 32 |
bind_filter => 'f', |
33 | 33 |
fetch_filter => 'g', |
34 | 34 |
result_class => 'g', |
35 |
- sql_template => $sql_tmpl1, |
|
35 |
+ sql_template => $SQL_TMPL->{0}, |
|
36 | 36 |
); |
37 | 37 |
is_deeply($dbi,{user => 'a', password => 'b', data_source => 'c', |
38 | 38 |
dbi_options => {d => 1, e => 2}, filters => {f => 3}, bind_filter => 'f', |
39 | 39 |
fetch_filter => 'g', result_class => 'g', |
40 |
- sql_template => $sql_tmpl1}, $test); |
|
40 |
+ sql_template => $SQL_TMPL->{0}}, $test); |
|
41 | 41 |
isa_ok($dbi, 'DBI::Custom'); |
42 | 42 |
|
43 | 43 |
|
... | ... |
@@ -57,7 +57,7 @@ test 'Sub class constructor'; |
57 | 57 |
->bind_filter('f') |
58 | 58 |
->fetch_filter('g') |
59 | 59 |
->result_class('DBI::Custom::Result') |
60 |
- ->sql_template($sql_tmpl1) |
|
60 |
+ ->sql_template($SQL_TMPL->{0}) |
|
61 | 61 |
; |
62 | 62 |
} |
63 | 63 |
$dbi = DBI::Custom::T1->new( |
... | ... |
@@ -71,7 +71,7 @@ $dbi = DBI::Custom::T1->new( |
71 | 71 |
bind_filter => 'fo', |
72 | 72 |
fetch_filter => 'go', |
73 | 73 |
result_class => 'ho', |
74 |
- sql_template => $sql_tmpl1, |
|
74 |
+ sql_template => $SQL_TMPL->{0}, |
|
75 | 75 |
); |
76 | 76 |
is($dbi->user, 'ao', "$test : user"); |
77 | 77 |
is($dbi->password, 'bo', "$test : passowr"); |
... | ... |
@@ -97,12 +97,12 @@ is($dbi->result_class, 'DBI::Custom::Result', "$test : result_class"); |
97 | 97 |
is($dbi->sql_template->tag_start, 0, "$test : sql_template"); |
98 | 98 |
isa_ok($dbi, 'DBI::Custom::T1'); |
99 | 99 |
|
100 |
+ |
|
100 | 101 |
test 'Sub sub class constructor default'; |
101 | 102 |
{ |
102 | 103 |
package DBI::Custom::T1_2; |
103 | 104 |
use base 'DBI::Custom::T1'; |
104 | 105 |
} |
105 |
- |
|
106 | 106 |
$dbi = DBI::Custom::T1_2->new; |
107 | 107 |
is($dbi->user, 'a', "$test : user"); |
108 | 108 |
is($dbi->password, 'b', "$test : passowrd"); |
... | ... |
@@ -132,7 +132,7 @@ test 'Customized sub class constructor default'; |
132 | 132 |
->bind_filter('fo') |
133 | 133 |
->fetch_filter('go') |
134 | 134 |
->result_class('ho') |
135 |
- ->sql_template($sql_tmpl2) |
|
135 |
+ ->sql_template($SQL_TMPL->{1}) |
|
136 | 136 |
; |
137 | 137 |
} |
138 | 138 |
$dbi = DBI::Custom::T1_3->new; |
... | ... |
@@ -160,7 +160,7 @@ $dbi = DBI::Custom::T1_3->new( |
160 | 160 |
bind_filter => 'f', |
161 | 161 |
fetch_filter => 'g', |
162 | 162 |
result_class => 'h', |
163 |
- sql_template => $sql_tmpl3, |
|
163 |
+ sql_template => $SQL_TMPL->{2}, |
|
164 | 164 |
); |
165 | 165 |
is($dbi->user, 'a', "$test : user"); |
166 | 166 |
is($dbi->password, 'b', "$test : password"); |
... | ... |
@@ -173,3 +173,9 @@ is($dbi->result_class, 'h', "$test : result_class"); |
173 | 173 |
is($dbi->sql_template->tag_start, 2, "$test : sql_template"); |
174 | 174 |
isa_ok($dbi, 'DBI::Custom'); |
175 | 175 |
|
176 |
+ |
|
177 |
+test 'add_filters'; |
|
178 |
+$dbi = DBI::Custom->new; |
|
179 |
+$dbi->add_filter(a => sub {1}); |
|
180 |
+is($dbi->filters->{a}->(), 1, $test); |
|
181 |
+ |
... | ... |
@@ -18,6 +18,8 @@ sub test { |
18 | 18 |
$test = shift; |
19 | 19 |
} |
20 | 20 |
|
21 |
+ |
|
22 |
+ |
|
21 | 23 |
# Varialbes for test |
22 | 24 |
our $CREATE_TABLE = { |
23 | 25 |
0 => 'create table table1 (key1 char(255), key2 char(255));', |
... | ... |
@@ -28,6 +30,10 @@ our $SELECT_TMPL = { |
28 | 30 |
0 => 'select * from table1;' |
29 | 31 |
}; |
30 | 32 |
|
33 |
+our $DROP_TABLE = { |
|
34 |
+ 0 => 'drop table table1' |
|
35 |
+}; |
|
36 |
+ |
|
31 | 37 |
my $dbi; |
32 | 38 |
my $sth; |
33 | 39 |
my $tmpl; |
... | ... |
@@ -46,13 +52,18 @@ my $update_query; |
46 | 52 |
my $ret_val; |
47 | 53 |
|
48 | 54 |
|
49 |
- |
|
50 |
-test 'Disconnect'; |
|
55 |
+test 'disconnect'; |
|
51 | 56 |
$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:'); |
52 | 57 |
$dbi->connect; |
53 | 58 |
$dbi->disconnect; |
54 | 59 |
ok(!$dbi->dbh, $test); |
55 | 60 |
|
61 |
+test 'connected'; |
|
62 |
+$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:'); |
|
63 |
+ok(!$dbi->connected, "$test : not connected"); |
|
64 |
+$dbi->connect; |
|
65 |
+ok($dbi->connected, "$test : connected"); |
|
66 |
+ |
|
56 | 67 |
# Prepare table |
57 | 68 |
$dbi = DBI::Custom->new(data_source => 'dbi:SQLite:dbname=:memory:'); |
58 | 69 |
$dbi->connect; |
... | ... |
@@ -112,7 +123,7 @@ is_deeply(\@rows, [[1, 2], [3, 4]], "$test : fetch_all_hash list context"); |
112 | 123 |
|
113 | 124 |
|
114 | 125 |
test 'Insert query return value'; |
115 |
-$dbi->reconnect; |
|
126 |
+$dbi->do($DROP_TABLE->{0}); |
|
116 | 127 |
$dbi->do($CREATE_TABLE->{0}); |
117 | 128 |
$tmpl = "insert into table1 {insert key1 key2}"; |
118 | 129 |
$query = $dbi->create_query($tmpl); |
... | ... |
@@ -121,7 +132,7 @@ ok($ret_val, $test); |
121 | 132 |
|
122 | 133 |
|
123 | 134 |
test 'Direct execute'; |
124 |
-$dbi->reconnect; |
|
135 |
+$dbi->do($DROP_TABLE->{0}); |
|
125 | 136 |
$dbi->do($CREATE_TABLE->{0}); |
126 | 137 |
$insert_tmpl = "insert into table1 {insert key1 key2}"; |
127 | 138 |
$dbi->execute($insert_tmpl, {key1 => 1, key2 => 2}, sub { |
... | ... |
@@ -140,7 +151,7 @@ is_deeply($rows, [{key1 => 1, key2 => 3}], $test); |
140 | 151 |
|
141 | 152 |
|
142 | 153 |
test 'Filter basic'; |
143 |
-$dbi->reconnect; |
|
154 |
+$dbi->do($DROP_TABLE->{0}); |
|
144 | 155 |
$dbi->do($CREATE_TABLE->{0}); |
145 | 156 |
|
146 | 157 |
$insert_tmpl = "insert into table1 {insert key1 key2};"; |
... | ... |
@@ -173,7 +184,7 @@ $result = $dbi->execute($select_query); |
173 | 184 |
$rows = $result->fetch_all_hash; |
174 | 185 |
is_deeply($rows, [{key1 => 1, key2 => 2}], "$test : no_fetch_filters no_bind_filters"); |
175 | 186 |
|
176 |
-$dbi->reconnect; |
|
187 |
+$dbi->do($DROP_TABLE->{0}); |
|
177 | 188 |
$dbi->do($CREATE_TABLE->{0}); |
178 | 189 |
$insert_tmpl = "insert into table1 {insert table1.key1 table1.key2}"; |
179 | 190 |
$insert_query = $dbi->create_query($insert_tmpl); |
... | ... |
@@ -209,7 +220,7 @@ is_deeply($rows, [{key1 => 2, key2 => 4}], "$test : bind_filter"); |
209 | 220 |
|
210 | 221 |
|
211 | 222 |
test 'DBI::Custom::SQL::Template basic tag'; |
212 |
-$dbi->reconnect; |
|
223 |
+$dbi->do($DROP_TABLE->{0}); |
|
213 | 224 |
$dbi->do($CREATE_TABLE->{1}); |
214 | 225 |
$sth = $dbi->prepare("insert into table1 (key1, key2, key3, key4, key5) values (?, ?, ?, ?, ?);"); |
215 | 226 |
$sth->execute(1, 2, 3, 4, 5); |
... | ... |
@@ -253,7 +264,7 @@ is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}], "$te |
253 | 264 |
|
254 | 265 |
|
255 | 266 |
test 'DIB::Custom::SQL::Template in tag'; |
256 |
-$dbi->reconnect; |
|
267 |
+$dbi->do($DROP_TABLE->{0}); |
|
257 | 268 |
$dbi->do($CREATE_TABLE->{1}); |
258 | 269 |
$sth = $dbi->prepare("insert into table1 (key1, key2, key3, key4, key5) values (?, ?, ?, ?, ?);"); |
259 | 270 |
$sth->execute(1, 2, 3, 4, 5); |
... | ... |
@@ -366,3 +377,34 @@ $rows = $result->fetch_all_hash; |
366 | 377 |
is_deeply($rows, [{key1 => 6, key2 => 6, key3 => 6, key4 => 6, key5 => 5}, |
367 | 378 |
{key1 => 6, key2 => 7, key3 => 8, key4 => 9, key5 => 10}], "$test : update tag #update with table name dot"); |
368 | 379 |
|
380 |
+ |
|
381 |
+test 'run_tansaction'; |
|
382 |
+$dbi->do($DROP_TABLE->{0}); |
|
383 |
+$dbi->do($CREATE_TABLE->{0}); |
|
384 |
+$dbi->run_tranzaction(sub { |
|
385 |
+ $insert_tmpl = 'insert into table1 {insert key1 key2}'; |
|
386 |
+ $dbi->execute($insert_tmpl, {key1 => 1, key2 => 2}); |
|
387 |
+ $dbi->execute($insert_tmpl, {key1 => 3, key2 => 4}); |
|
388 |
+}); |
|
389 |
+$result = $dbi->execute($SELECT_TMPL->{0}); |
|
390 |
+$rows = $result->fetch_all_hash; |
|
391 |
+is_deeply($rows, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}], "$test : commit"); |
|
392 |
+ |
|
393 |
+$dbi->do($DROP_TABLE->{0}); |
|
394 |
+$dbi->do($CREATE_TABLE->{0}); |
|
395 |
+$dbi->dbh->{RaiseError} = 0; |
|
396 |
+eval{ |
|
397 |
+ $dbi->run_tranzaction(sub { |
|
398 |
+ $insert_tmpl = 'insert into table1 {insert key1 key2}'; |
|
399 |
+ $dbi->execute($insert_tmpl, {key1 => 1, key2 => 2}); |
|
400 |
+ die "Fatal Error"; |
|
401 |
+ $dbi->execute($insert_tmpl, {key1 => 3, key2 => 4}); |
|
402 |
+ }) |
|
403 |
+}; |
|
404 |
+like($@, qr/Fatal Error.*Rollback is success/ms, "$test : Rollback success message"); |
|
405 |
+ok(!$dbi->dbh->{RaiseError}, "$test : restore RaiseError value"); |
|
406 |
+$result = $dbi->execute($SELECT_TMPL->{0}); |
|
407 |
+$rows = $result->fetch_all_hash; |
|
408 |
+is_deeply($rows, [], "$test : rollback"); |
|
409 |
+ |
|
410 |
+ |
... | ... |
@@ -3,9 +3,9 @@ use strict; |
3 | 3 |
use warnings; |
4 | 4 |
|
5 | 5 |
# user password database |
6 |
-our ($U, $P, $D) = connect_info(); |
|
6 |
+our ($USER, $PASSWORD, $DATABASE) = connect_info(); |
|
7 | 7 |
|
8 |
-plan skip_all => 'private MySQL test' unless $U; |
|
8 |
+plan skip_all => 'private MySQL test' unless $USER; |
|
9 | 9 |
|
10 | 10 |
plan 'no_plan'; |
11 | 11 |
|
... | ... |
@@ -13,9 +13,9 @@ use DBI::Custom; |
13 | 13 |
use Scalar::Util 'blessed'; |
14 | 14 |
{ |
15 | 15 |
my $dbi = DBI::Custom->new( |
16 |
- user => $U, |
|
17 |
- password => $P, |
|
18 |
- data_source => "dbi:mysql:dbname=$D" |
|
16 |
+ user => $USER, |
|
17 |
+ password => $PASSWORD, |
|
18 |
+ data_source => "dbi:mysql:dbname=$DATABASE" |
|
19 | 19 |
); |
20 | 20 |
$dbi->connect; |
21 | 21 |
|