first commit
|
1 |
package DBI::Custom; |
2 |
use Object::Simple; |
|
add some method
|
3 |
use DBI; |
4 |
use SQL::Abstract; |
|
first commit
|
5 | |
cleanup
|
6 |
# Model |
7 |
sub model : ClassAttr { auto_build => \&_inherit_model } |
|
first commit
|
8 | |
cleanup
|
9 |
# Inherit super class model |
10 |
sub _inherit_model { |
|
11 |
$class = shict; |
|
12 |
my $super = do { |
|
13 |
no strict 'refs'; |
|
14 |
${"${class}::ISA"}[0]; |
|
15 |
}; |
|
16 |
my $model = eval{$super->can('model')} |
|
17 |
? $super->model->clone |
|
18 |
: $class->Object::Simple::new; |
|
cleanup
|
19 |
|
20 |
$class->model($model); |
|
first commit
|
21 |
} |
22 | ||
cleanup
|
23 |
# New |
24 |
sub new { |
|
25 |
my $self = shift->Object::Simple::new(@_); |
|
26 |
my $class = ref $self; |
|
27 |
return bless {%{$class->model->clone}, %{$self}}, $class; |
|
first commit
|
28 |
} |
29 | ||
cleanup
|
30 |
# Initialize modle |
31 |
sub initialize_model { |
|
32 |
my ($class, $callback) = @_; |
|
first commit
|
33 |
|
cleanup
|
34 |
# Callback to initialize model |
35 |
$callback->($class->model); |
|
first commit
|
36 |
} |
37 | ||
cleanup
|
38 |
# Clone |
39 |
sub clone { |
|
cleanup
|
40 |
my $self = shift; |
cleanup
|
41 |
my $new = $self->Object::Simple::new; |
42 |
$new->connect_infos(%{$self->connect_infos || {}}); |
|
43 |
$new->filters(%{$self->filters || {}}); |
|
cleanup
|
44 |
|
cleanup
|
45 |
$new->global_bind_rules(@{$self->global_bind_rules || []}); |
46 |
$new->global_fetch_rules(@{$self->global_fetch_rules || []}); |
|
cleanup
|
47 |
|
cleanup
|
48 |
foreach my $method (qw/bind_rules fetch_rules/) { |
49 |
my $new_rules = []; |
|
50 |
foreach my $rule (@{$self->method}) { |
|
51 |
my $new_rule = {}; |
|
52 |
foreach my $key ($rule) { |
|
53 |
if ($key eq 'filter') { |
|
54 |
my $new_filters = []; |
|
55 |
foreach my $filter (@{$rule->{$key} || []}) { |
|
56 |
push @$new_filters, $filter |
|
57 |
} |
|
58 |
$new_rule->{$key} = $new_filters; |
|
59 |
} |
|
60 |
else { |
|
61 |
$new_rule->{$key} = $rule->{$key}; |
|
62 |
} |
|
63 |
} |
|
64 |
push @$new_rules, $new_rule; |
|
65 |
} |
|
66 |
$self->$method($new_rules); |
|
cleanup
|
67 |
} |
68 |
} |
|
69 | ||
cleanup
|
70 |
# Attribute |
71 |
sub connect_info : Attr { type => 'hash', auto_build => sub { shift->connect_info({}) } } |
|
72 |
sub global_bind_rules : Attr { type => 'array', auto_build => sub { shift->global_bind_rules([]) } } |
|
73 |
sub global_fetch_rules : Attr { type => 'array', auto_build => sub { shift->global_fetch_rules([]) } } |
|
74 |
sub bind_rules : Attr { type => 'hash', auto_build => sub { shift->bind_rules({}) } |
|
75 |
sub fetch_rules : Attr { type => 'hash', auto_build => sub { shift->fetch_rules({}) } |
|
76 | ||
77 |
sub dbh : Attr { auto_build => sub { shift->connect } } |
|
78 |
sub sql_abstract : Attr { auto_build => sub { shift->sql_abstract(SQL::Abstract->new) }} |
|
cleanup
|
79 | |
add some method
|
80 |
sub connect { |
81 |
my $self = shift; |
|
82 |
my $connect_info = $self->connect_info; |
|
83 |
|
|
84 |
my $dbh = DBI->connect( |
|
85 |
$connect_info->{dsn}, |
|
86 |
$connect_info->{user}, |
|
87 |
$connect_info->{password}, |
|
88 |
{ |
|
89 |
RaiseError => 1, |
|
90 |
PrintError => 0, |
|
91 |
AutoCommit => 1, |
|
92 |
%{$connect_info->{options} || {} } |
|
93 |
} |
|
94 |
); |
|
95 |
|
|
96 |
$self->dbh($dbh); |
|
97 |
} |
|
first commit
|
98 | |
add some method
|
99 |
sub reconnect { |
100 |
my $self = shift; |
|
101 |
$self->dbh(undef); |
|
102 |
$self->connect; |
|
103 |
} |
|
first commit
|
104 | |
add some method
|
105 |
sub query { |
106 |
my ($self, $query, @binds) = @_; |
|
107 |
$self->{success} = 0; |
|
108 | ||
109 |
$self->_replace_omniholder(\$query, \@binds); |
|
110 | ||
111 |
my $st; |
|
112 |
my $sth; |
|
113 | ||
114 |
my $old = $old_statements{$self}; |
|
115 | ||
116 |
if (my $i = (grep $old->[$_][0] eq $query, 0..$#$old)[0]) { |
|
117 |
$st = splice(@$old, $i, 1)->[1]; |
|
118 |
$sth = $st->{sth}; |
|
119 |
} else { |
|
120 |
eval { $sth = $self->{dbh}->prepare($query) } or do { |
|
121 |
if ($@) { |
|
122 |
$@ =~ s/ at \S+ line \d+\.\n\z//; |
|
123 |
Carp::croak($@); |
|
124 |
} |
|
125 |
$self->{reason} = "Prepare failed ($DBI::errstr)"; |
|
126 |
return _dummy; |
|
127 |
}; |
|
128 | ||
129 |
# $self is quoted on purpose, to pass along the stringified version, |
|
130 |
# and avoid increasing reference count. |
|
131 |
$st = bless { |
|
132 |
db => "$self", |
|
133 |
sth => $sth, |
|
134 |
query => $query |
|
135 |
}, 'DBIx::Simple::Statement'; |
|
136 |
$statements{$self}{$st} = $st; |
|
137 |
} |
|
first commit
|
138 | |
add some method
|
139 |
eval { $sth->execute(@binds) } or do { |
140 |
if ($@) { |
|
141 |
$@ =~ s/ at \S+ line \d+\.\n\z//; |
|
142 |
Carp::croak($@); |
|
143 |
} |
|
first commit
|
144 | |
add some method
|
145 |
$self->{reason} = "Execute failed ($DBI::errstr)"; |
146 |
return _dummy; |
|
147 |
}; |
|
148 | ||
149 |
$self->{success} = 1; |
|
150 | ||
151 |
return bless { st => $st, lc_columns => $self->{lc_columns} }, $self->{result_class}; |
|
152 |
} |
|
153 | ||
154 |
sub query { |
|
155 |
my ($self, $sql) = @_; |
|
156 |
my $sth = $self->dbh->prepare($sql); |
|
157 |
$sth->execute(@bind); |
|
158 |
} |
|
159 | ||
160 |
sub select { |
|
161 |
my ($table, $column_names, $where, $order) = @_; |
|
first commit
|
162 |
|
add some method
|
163 |
my ($stmt, @bind) = $self->sql_abstract->select($table, $column_names, $where, $order); |
164 |
my $sth = $self->dbh->prepare($stmt); |
|
165 |
$sth->execute(@bind); |
|
166 |
} |
|
167 | ||
168 |
sub insert { |
|
169 |
my ($self, $table, $values) = @_; |
|
first commit
|
170 |
|
add some method
|
171 |
my ($stmt, @bind) = $self->sql_abstract->insert($table, $values); |
172 |
my $sth = $self->dbh->prepare($stmt); |
|
173 |
$sth->execute(@bind); |
|
174 |
} |
|
175 | ||
176 |
sub update { |
|
177 |
my ($self, $values, $where) = @_; |
|
178 |
my ($stmt, @bind) = $self->sql_abstract->update($table, $values, $where); |
|
179 |
my $sth = $self->dbh->prepare($stmt); |
|
180 |
$sth->execute(@bind); |
|
first commit
|
181 |
} |
182 | ||
add some method
|
183 |
sub delete { |
184 |
my ($self, $where) = @_; |
|
185 |
my ($stmt, @bind) = $self->sql_abstract->delete($table, $where); |
|
186 |
my $sth = $self->dbh->prepare($stmt); |
|
187 |
$sth->execute(@bind); |
|
188 |
} |
|
189 | ||
190 | ||
first commit
|
191 | |
192 |
Object::Simple->build_class; |
|
193 | ||
194 |
=head1 NAME |
|
195 | ||
196 |
DBI::Custom - The great new DBI::Custom! |
|
197 | ||
198 |
=head1 VERSION |
|
199 | ||
200 |
Version 0.01 |
|
201 | ||
202 |
=cut |
|
203 | ||
204 |
our $VERSION = '0.01'; |
|
205 | ||
206 | ||
207 |
=head1 SYNOPSIS |
|
208 | ||
209 |
Quick summary of what the module does. |
|
210 | ||
211 |
Perhaps a little code snippet. |
|
212 | ||
213 |
use DBI::Custom; |
|
214 | ||
215 |
my $foo = DBI::Custom->new(); |
|
216 |
... |
|
217 | ||
218 |
=head1 EXPORT |
|
219 | ||
220 |
A list of functions that can be exported. You can delete this section |
|
221 |
if you don't export anything, such as for a purely object-oriented module. |
|
222 | ||
223 |
=head1 FUNCTIONS |
|
224 | ||
225 |
=head2 function1 |
|
226 | ||
227 |
=cut |
|
228 | ||
229 |
sub function1 { |
|
230 |
} |
|
231 | ||
232 |
=head2 function2 |
|
233 | ||
234 |
=cut |
|
235 | ||
236 |
sub function2 { |
|
237 |
} |
|
238 | ||
239 |
=head1 AUTHOR |
|
240 | ||
241 |
Yuki Kimoto, C<< <kimoto.yuki at gmail.com> >> |
|
242 | ||
243 |
=head1 BUGS |
|
244 | ||
245 |
Please report any bugs or feature requests to C<bug-dbi-custom at rt.cpan.org>, or through |
|
246 |
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DBI-Custom>. I will be notified, and then you'll |
|
247 |
automatically be notified of progress on your bug as I make changes. |
|
248 | ||
249 | ||
250 | ||
251 | ||
252 |
=head1 SUPPORT |
|
253 | ||
254 |
You can find documentation for this module with the perldoc command. |
|
255 | ||
256 |
perldoc DBI::Custom |
|
257 | ||
258 | ||
259 |
You can also look for information at: |
|
260 | ||
261 |
=over 4 |
|
262 | ||
263 |
=item * RT: CPAN's request tracker |
|
264 | ||
265 |
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=DBI-Custom> |
|
266 | ||
267 |
=item * AnnoCPAN: Annotated CPAN documentation |
|
268 | ||
269 |
L<http://annocpan.org/dist/DBI-Custom> |
|
270 | ||
271 |
=item * CPAN Ratings |
|
272 | ||
273 |
L<http://cpanratings.perl.org/d/DBI-Custom> |
|
274 | ||
275 |
=item * Search CPAN |
|
276 | ||
277 |
L<http://search.cpan.org/dist/DBI-Custom/> |
|
278 | ||
279 |
=back |
|
280 | ||
281 | ||
282 |
=head1 ACKNOWLEDGEMENTS |
|
283 | ||
284 | ||
285 |
=head1 COPYRIGHT & LICENSE |
|
286 | ||
287 |
Copyright 2009 Yuki Kimoto, all rights reserved. |
|
288 | ||
289 |
This program is free software; you can redistribute it and/or modify it |
|
290 |
under the same terms as Perl itself. |
|
291 | ||
292 | ||
293 |
=cut |
|
294 | ||
295 |
1; # End of DBI::Custom |