... | ... |
@@ -7,35 +7,35 @@ use Carp 'croak'; |
7 | 7 |
use DBI; |
8 | 8 |
|
9 | 9 |
# Model |
10 |
-sub model : ClassAttr { auto_build => \&_inherit_model } |
|
10 |
+sub prototype : ClassAttr { auto_build => \&_inherit_prototype } |
|
11 | 11 |
|
12 |
-# Inherit super class model |
|
13 |
-sub _inherit_model { |
|
12 |
+# Inherit super class prototype |
|
13 |
+sub _inherit_prototype { |
|
14 | 14 |
my $class = shift; |
15 | 15 |
my $super = do { |
16 | 16 |
no strict 'refs'; |
17 | 17 |
${"${class}::ISA"}[0]; |
18 | 18 |
}; |
19 |
- my $model = eval{$super->can('model')} |
|
20 |
- ? $super->model->clone |
|
19 |
+ my $prototype = eval{$super->can('prototype')} |
|
20 |
+ ? $super->prototype->clone |
|
21 | 21 |
: $class->Object::Simple::new; |
22 | 22 |
|
23 |
- $class->model($model); |
|
23 |
+ $class->prototype($prototype); |
|
24 | 24 |
} |
25 | 25 |
|
26 | 26 |
# New |
27 | 27 |
sub new { |
28 | 28 |
my $self = shift->Object::Simple::new(@_); |
29 | 29 |
my $class = ref $self; |
30 |
- return bless {%{$class->model->clone}, %{$self}}, $class; |
|
30 |
+ return bless {%{$class->prototype->clone}, %{$self}}, $class; |
|
31 | 31 |
} |
32 | 32 |
|
33 |
-# Initialize modle |
|
34 |
-sub initialize_model { |
|
33 |
+# Initialize class |
|
34 |
+sub initialize_class { |
|
35 | 35 |
my ($class, $callback) = @_; |
36 | 36 |
|
37 |
- # Callback to initialize model |
|
38 |
- $callback->($class->model); |
|
37 |
+ # Callback to initialize prototype |
|
38 |
+ $callback->($class->prototype); |
|
39 | 39 |
} |
40 | 40 |
|
41 | 41 |
# Clone |
... | ... |
@@ -60,7 +60,7 @@ sub add_filter { shift->filters(@_) } |
60 | 60 |
|
61 | 61 |
sub result_class : Attr { auto_build => sub { shift->result_class('DBI::Custom::Result') }} |
62 | 62 |
sub dbh : Attr {} |
63 |
-sub sql_template : Attr { auto_build => sub { shift->sql_template(DBI::Custom::SQLTemplate->new) } } |
|
63 |
+sub sql_template : Attr { auto_build => sub { shift->sql_template(DBI::Custom::SQL::Template->new) } } |
|
64 | 64 |
|
65 | 65 |
# Auto commit |
66 | 66 |
sub auto_commit { |
... | ... |
@@ -232,9 +232,11 @@ Object::Simple->build_class; |
232 | 232 |
package DBI::Custom::Result; |
233 | 233 |
use Object::Simple; |
234 | 234 |
|
235 |
+# Attributes |
|
235 | 236 |
sub sth : Attr {} |
236 | 237 |
sub fetch_filter : Attr {} |
237 | 238 |
|
239 |
+ |
|
238 | 240 |
# Fetch (array) |
239 | 241 |
sub fetch { |
240 | 242 |
my ($self, $type) = @_; |
... | ... |
@@ -252,7 +254,8 @@ sub fetch { |
252 | 254 |
my $keys = $sth->{NAME_lc}; |
253 | 255 |
my $types = $sth->{TYPE}; |
254 | 256 |
for (my $i = 0; $i < @$keys; $i++) { |
255 |
- $row->[$i] = $fetch_filter->($keys->[$i], $row->[$i], $types->[$i], $sth, $i); |
|
257 |
+ $row->[$i]= $fetch_filter->($keys->[$i], $row->[$i], $types->[$i], |
|
258 |
+ $sth, $i); |
|
256 | 259 |
} |
257 | 260 |
} |
258 | 261 |
return wantarray ? @$row : $row; |
... | ... |
@@ -278,9 +281,12 @@ sub fetch_hash { |
278 | 281 |
if ($fetch_filter) { |
279 | 282 |
my $types = $sth->{TYPE}; |
280 | 283 |
for (my $i = 0; $i < @$keys; $i++) { |
281 |
- $row_hash->{$keys->[$i]} = $fetch_filter->($keys->[$i], $row->[$i], $types->[$i], $sth, $i); |
|
284 |
+ $row_hash->{$keys->[$i]} = $fetch_filter->($keys->[$i], $row->[$i], |
|
285 |
+ $types->[$i], $sth, $i); |
|
282 | 286 |
} |
283 | 287 |
} |
288 |
+ |
|
289 |
+ # No filter |
|
284 | 290 |
else { |
285 | 291 |
for (my $i = 0; $i < @$keys; $i++) { |
286 | 292 |
$row_hash->{$keys->[$i]} = $row->[$i]; |
... | ... |
@@ -289,28 +295,6 @@ sub fetch_hash { |
289 | 295 |
return wantarray ? %$row_hash : $row_hash; |
290 | 296 |
} |
291 | 297 |
|
292 |
-# Fetch (hash) |
|
293 |
-#sub fetch_hash { |
|
294 |
-# my $self = shift; |
|
295 |
-# my $sth = $self->sth; |
|
296 |
-# my $fetch_filter = $self->fetch_filter; |
|
297 |
-# |
|
298 |
-# # Fetch |
|
299 |
-# my $row = $sth->fetchrow_hashref; |
|
300 |
-# |
|
301 |
-# # Cannot fetch |
|
302 |
-# return unless $row; |
|
303 |
-# |
|
304 |
-# # Filter |
|
305 |
-# if ($fetch_filter) { |
|
306 |
-# foreach my $key (keys %$row) { |
|
307 |
-# $row->{$key} = $fetch_filter->($key, $row->{$key}); |
|
308 |
-# } |
|
309 |
-# } |
|
310 |
-# return wantarray ? %$row : $row; |
|
311 |
-#} |
|
312 |
- |
|
313 |
- |
|
314 | 298 |
# Fetch all (array) |
315 | 299 |
sub fetch_all { |
316 | 300 |
my $self = shift; |
... | ... |
@@ -333,15 +317,20 @@ sub fetch_all_hash { |
333 | 317 |
return wantarray ? @$rows : $rows; |
334 | 318 |
} |
335 | 319 |
|
336 |
-sub err { shift->sth->err } |
|
337 |
-sub errstr { shift->sth->errstr } |
|
338 |
-sub state { shift->sth->state } |
|
320 |
+# Finish |
|
339 | 321 |
sub finish { shift->sth->finish } |
340 | 322 |
|
323 |
+# Error |
|
324 |
+sub error { |
|
325 |
+ my $self = shift; |
|
326 |
+ my $sth = $self->sth; |
|
327 |
+ wantarray ? ($sth->errstr, $sth->err, $sth->state) : $sth->errstr; |
|
328 |
+} |
|
329 |
+ |
|
341 | 330 |
Object::Simple->build_class; |
342 | 331 |
|
343 | 332 |
|
344 |
-package DBI::Custom::SQLTemplate; |
|
333 |
+package DBI::Custom::SQL::Template; |
|
345 | 334 |
use Object::Simple; |
346 | 335 |
use Carp 'croak'; |
347 | 336 |
|
... | ... |
@@ -512,9 +501,91 @@ sub build_sql { |
512 | 501 |
return ($sql, @bind_values); |
513 | 502 |
} |
514 | 503 |
|
504 |
+sub tag_processors : Attr {type => 'hash', deref => 1, auto_build => sub { |
|
505 |
+ shift->tag_processors( |
|
506 |
+ '=' => \&DBI::Custom::SQL::Template::TagProcessor::expand_place_holder, |
|
507 |
+ '<>' => \&DBI::Custom::SQL::Template::TagProcessor::expand_place_holder, |
|
508 |
+ '<' => \&DBI::Custom::SQL::Template::TagProcessor::expand_place_holder, |
|
509 |
+ '>=' => \&DBI::Custom::SQL::Template::TagProcessor::expand_place_holder, |
|
510 |
+ '<=' => \&DBI::Custom::SQL::Template::TagProcessor::expand_place_holder, |
|
511 |
+ 'like' => \&DBI::Custom::SQL::Template::TagProcessor::expand_place_holder, |
|
512 |
+ 'in' => \&DBI::Custom::SQL::Template::TagProcessor::expand_place_holder |
|
513 |
+ ); |
|
514 |
+}} |
|
515 |
+ |
|
516 |
+sub add_tag_processor { |
|
517 |
+ |
|
518 |
+} |
|
515 | 519 |
|
516 | 520 |
Object::Simple->build_class; |
517 | 521 |
|
522 |
+ |
|
523 |
+package DBI::Custom::SQL::Template::TagProcessor; |
|
524 |
+ |
|
525 |
+sub expand_place_holder { |
|
526 |
+ my ($tag_name, $args, $values, $bind_filter, $sql_tmpl_obj) = @_; |
|
527 |
+ |
|
528 |
+ my $key = $args->[0]; |
|
529 |
+ |
|
530 |
+ my @bind_values; |
|
531 |
+ # Filter Value |
|
532 |
+ if ($tag_name eq 'in') { |
|
533 |
+ $values->{$key} = [$values->{$key}] unless ref $values->{$key} eq 'ARRAY'; |
|
534 |
+ if ($bind_filter) { |
|
535 |
+ for (my $i = 0; $i < @$values; $i++) { |
|
536 |
+ push @bind_values, scalar $bind_filter->($key, $values->{$key}->[$i]); |
|
537 |
+ } |
|
538 |
+ } |
|
539 |
+ else { |
|
540 |
+ for (my $i = 0; $i < @$values; $i++) { |
|
541 |
+ push @bind_values, $values->{$key}->[$i]; |
|
542 |
+ } |
|
543 |
+ } |
|
544 |
+ } |
|
545 |
+ else { |
|
546 |
+ if ($bind_filter) { |
|
547 |
+ push @bind_values, scalar $bind_filter->($key, $values->{$key}); |
|
548 |
+ } |
|
549 |
+ else { |
|
550 |
+ push @bind_values, $values->{$key}; |
|
551 |
+ } |
|
552 |
+ } |
|
553 |
+ if ($bind_filter) { |
|
554 |
+ if ($tag_name eq 'in') { |
|
555 |
+ for (my $i = 0; $i < @$values; $i++) { |
|
556 |
+ push @bind_values, scalar $bind_filter->($key, $values->{$key}->[$i]); |
|
557 |
+ } |
|
558 |
+ } |
|
559 |
+ else { |
|
560 |
+ push @bind_values, scalar $bind_filter->($key, $values->{$key}); |
|
561 |
+ } |
|
562 |
+ } |
|
563 |
+ else { |
|
564 |
+ push @bind_values, $values->{$key}; |
|
565 |
+ } |
|
566 |
+ |
|
567 |
+ $tag_name = uc $tag_name if $sql_tmpl_obj->upper_case; |
|
568 |
+ |
|
569 |
+ my $expand; |
|
570 |
+ if ($tag_name eq '?') { |
|
571 |
+ $expand = '?'; |
|
572 |
+ } |
|
573 |
+ elsif ($tag_name eq 'in') { |
|
574 |
+ $expand = '('; |
|
575 |
+ for (my $i = 0; $i < @$values; $i++) { |
|
576 |
+ $expand .= '?, '; |
|
577 |
+ } |
|
578 |
+ $expand =~ s/, $'//; |
|
579 |
+ $expand .= ')'; |
|
580 |
+ } |
|
581 |
+ else { |
|
582 |
+ $expand = "$key $tag_name ?"; |
|
583 |
+ } |
|
584 |
+ |
|
585 |
+ return ($expand, \@bind_values); |
|
586 |
+} |
|
587 |
+ |
|
588 |
+ |
|
518 | 589 |
package DBI::Custom; |
519 | 590 |
1; |
520 | 591 |
|
... | ... |
@@ -552,9 +623,9 @@ Version 0.0101 |
552 | 623 |
|
553 | 624 |
=head2 filters |
554 | 625 |
|
555 |
-=head2 initialize_model |
|
626 |
+=head2 initialize_class |
|
556 | 627 |
|
557 |
-=head2 model |
|
628 |
+=head2 prototype |
|
558 | 629 |
|
559 | 630 |
=head2 new |
560 | 631 |
|
... | ... |
@@ -33,7 +33,7 @@ use Scalar::Util qw/blessed/; |
33 | 33 |
package DBI::Custom::T1; |
34 | 34 |
use base 'DBI::Custom'; |
35 | 35 |
|
36 |
- __PACKAGE__->initialize_model(sub { |
|
36 |
+ __PACKAGE__->initialize_class(sub { |
|
37 | 37 |
my $model = shift; |
38 | 38 |
|
39 | 39 |
$model |
... | ... |
@@ -101,7 +101,7 @@ use Scalar::Util qw/blessed/; |
101 | 101 |
package DBI::Custom::T1_3; |
102 | 102 |
use base 'DBI::Custom::T1'; |
103 | 103 |
|
104 |
- __PACKAGE__->initialize_model(sub { |
|
104 |
+ __PACKAGE__->initialize_class(sub { |
|
105 | 105 |
my $model = shift; |
106 | 106 |
|
107 | 107 |
$model |