line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::DataLoader::MySQL; |
2
|
5
|
|
|
5
|
|
345735
|
use strict; |
|
5
|
|
|
|
|
16
|
|
|
5
|
|
|
|
|
255
|
|
3
|
5
|
|
|
5
|
|
28
|
use warnings; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
163
|
|
4
|
5
|
|
|
5
|
|
13920
|
use DBI; |
|
5
|
|
|
|
|
36122
|
|
|
5
|
|
|
|
|
214
|
|
5
|
5
|
|
|
5
|
|
7922
|
use DBD::mysql; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
use Carp; |
7
|
|
|
|
|
|
|
use base qw(Exporter); |
8
|
|
|
|
|
|
|
our $VERSION = '0.1.0'; |
9
|
|
|
|
|
|
|
use 5.008; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 NAME |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
Test::DataLoader::MySQL - Load testdata into MySQL database |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 SYNOPSIS |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
my $data = Test::DataLoader::MySQL->new($dbh); |
18
|
|
|
|
|
|
|
$data->add('foo', #table name |
19
|
|
|
|
|
|
|
1, # data id |
20
|
|
|
|
|
|
|
{# data_href: column => value |
21
|
|
|
|
|
|
|
id => 1, |
22
|
|
|
|
|
|
|
name => 'aaa', |
23
|
|
|
|
|
|
|
}, |
24
|
|
|
|
|
|
|
['id']); # primary keys |
25
|
|
|
|
|
|
|
$data->add('foo', 2, |
26
|
|
|
|
|
|
|
{ |
27
|
|
|
|
|
|
|
id => 2, |
28
|
|
|
|
|
|
|
name => 'bbb', |
29
|
|
|
|
|
|
|
}, |
30
|
|
|
|
|
|
|
['id']); |
31
|
|
|
|
|
|
|
$data->load('foo', 1); #load data into database |
32
|
|
|
|
|
|
|
# ... tests using database |
33
|
|
|
|
|
|
|
$data->clear;# when finished |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
if table has auto_increment |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
$data->add('foo', 1, |
38
|
|
|
|
|
|
|
{ |
39
|
|
|
|
|
|
|
name => 'aaa', |
40
|
|
|
|
|
|
|
}, |
41
|
|
|
|
|
|
|
['id']); |
42
|
|
|
|
|
|
|
my $keys = $data->load('foo', 1);#load data and get auto_increment |
43
|
|
|
|
|
|
|
is( $keys->{id}, 2); # get key value(generated by auto_increment) |
44
|
|
|
|
|
|
|
# ... tests using database |
45
|
|
|
|
|
|
|
$data->clear;# when finished |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
read from external file |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# data.pm |
50
|
|
|
|
|
|
|
my $data = Test::DataLoader::MySQL->init(); # use init(not new) |
51
|
|
|
|
|
|
|
$data->add('foo', 1, |
52
|
|
|
|
|
|
|
{ |
53
|
|
|
|
|
|
|
id => 1, |
54
|
|
|
|
|
|
|
name => 'aaa', |
55
|
|
|
|
|
|
|
}, |
56
|
|
|
|
|
|
|
['id']); |
57
|
|
|
|
|
|
|
# in your testcode |
58
|
|
|
|
|
|
|
my $data = Test::DataLoader::MySQL->new($dbh); |
59
|
|
|
|
|
|
|
$data->load('foo', 1); |
60
|
|
|
|
|
|
|
# ... tests using database |
61
|
|
|
|
|
|
|
$data->clear;# when finished |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=head1 DESCRIPTION |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Load testdata into MySQL database. |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=cut |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head1 methods |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=cut |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
my $singleton; #instance object is shared for reading data from external file. |
74
|
|
|
|
|
|
|
END {#delete data if test code is abort |
75
|
|
|
|
|
|
|
if (defined $singleton && @{ $singleton->{loaded} } ) { |
76
|
|
|
|
|
|
|
$singleton->clear; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=head2 new($dbh, %options) |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
create new instance |
83
|
|
|
|
|
|
|
parameter $dbh(provided by DBI) is required; |
84
|
|
|
|
|
|
|
If Keep option is NOT specified(default), loaded data is deleted when instance is destroyed, otherwise(specified Keep option) loaded data is remain. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
#$dbh = DBI->connect(...); |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
my $data = Test::DataLoader::MySQL->new($dbh); # loaded data is deleted when $data is DESTROYed |
89
|
|
|
|
|
|
|
# or |
90
|
|
|
|
|
|
|
my $data = Test::DataLoader::MySQL->new($dbh, Keep => 1); # loaded data is remain |
91
|
|
|
|
|
|
|
# or |
92
|
|
|
|
|
|
|
my $data = Test::DataLoader::MySQL->new($dbh, DeleteBeforeInsert => 1); # delete data which has same keys before load |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
if you want to use external file and in external file, use init() instead of new(). |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=cut |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub new { |
99
|
|
|
|
|
|
|
my $class = shift; |
100
|
|
|
|
|
|
|
my ($dbh, %options) = @_; |
101
|
|
|
|
|
|
|
my $self = defined $singleton ? $singleton : {}; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
$self = { |
104
|
|
|
|
|
|
|
dbh => $dbh, |
105
|
|
|
|
|
|
|
loaded => [], |
106
|
|
|
|
|
|
|
keynames => undef,#keys set in set_keys() |
107
|
|
|
|
|
|
|
Keep => !!$options{Keep}, |
108
|
|
|
|
|
|
|
DeleteBeforeInsert => !!$options{DeleteBeforeInsert}, |
109
|
|
|
|
|
|
|
}; |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
bless $self, $class; |
112
|
|
|
|
|
|
|
$singleton = $self; |
113
|
|
|
|
|
|
|
return $self; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head2 add($table_name, $data_id, $data_href, $keynames_aref) |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
add testdata into this modules (not loading testdata) |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
$data->add('foo', # table_name |
121
|
|
|
|
|
|
|
1, # data_id, |
122
|
|
|
|
|
|
|
{ # data which you want to load into database. specified by hash_ref |
123
|
|
|
|
|
|
|
id => 1, |
124
|
|
|
|
|
|
|
name => 'aaa', |
125
|
|
|
|
|
|
|
}, |
126
|
|
|
|
|
|
|
['id'] #key(s), specified by array_ref, this is important. |
127
|
|
|
|
|
|
|
); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
table_name and data_id is like a database's key. For example, table_name is 'foo' and data_id is 1 and 'foo' and 2 is dealt with defferent data even if contained data is equal( ex id=>1, name=>'aaa'). |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Key is important, because when $data is DESTROYed, this module delete all data which had been loaded and deleted data is found by specified key(s) in this method. |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
if set_keys() was called before, $keynames_aref is ommittable. |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=cut |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub add { |
138
|
|
|
|
|
|
|
my $self = shift; |
139
|
|
|
|
|
|
|
my ($table_name, $data_id, $data_href, $key_aref) = @_; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
carp "already exists $table_name : $data_id" if ( exists $self->{data} && |
142
|
|
|
|
|
|
|
exists $self->{data}->{$table_name}->{$data_id} ); |
143
|
|
|
|
|
|
|
$self->{data}->{$table_name}->{$data_id} = { data => $data_href, key => $key_aref }; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head2 load |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
load testdata from this module into database. |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
$data->load('foo', 1); |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
first parameter is table_name, second parameter is data_id. meaning of them are same as specified in add-method. |
153
|
|
|
|
|
|
|
third parameter is option href, if you want to alter data with add method. for example, |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
$data->add('foo', 1, { id=>1, name=>'aaa' }); #registered name is 'aaa' |
156
|
|
|
|
|
|
|
$data->load('foo', 1, { name=>'bbb' }); #but loaded name is 'bbb' because option href is specified. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
return hash_ref. it contains database key and value. this is useful for AUTO_INCREMENT key. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
my $key = $data->load('foo', 1); |
161
|
|
|
|
|
|
|
my $id = $key->{id}; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=cut |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub load { |
166
|
|
|
|
|
|
|
my $self = shift; |
167
|
|
|
|
|
|
|
my ($table_name, $data_id, $option_href) = @_; |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
my %data = $self->_data_with_option($table_name, $data_id, $option_href); |
170
|
|
|
|
|
|
|
my $keynames_aref = $self->_get_keys($table_name, $data_id); |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
return $self->_load($table_name, $keynames_aref, %data); |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub _get_keys { |
176
|
|
|
|
|
|
|
my $self = shift; |
177
|
|
|
|
|
|
|
my ($table_name, $data_id) = @_; |
178
|
|
|
|
|
|
|
my $keynames_aref = $self->{data}->{$table_name}->{$data_id}->{key}; |
179
|
|
|
|
|
|
|
if ( $self->_aref_is_empty($keynames_aref) ) { |
180
|
|
|
|
|
|
|
$keynames_aref = $self->{keynames}->{$table_name}; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
return $keynames_aref; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
sub _data_with_option { |
186
|
|
|
|
|
|
|
my $self = shift; |
187
|
|
|
|
|
|
|
my ($table_name, $data_id, $option_href) = @_; |
188
|
|
|
|
|
|
|
my %data = %{$self->_data($table_name, $data_id)}; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
if ( defined $option_href ) { |
191
|
|
|
|
|
|
|
for my $key ( keys %{$option_href} ) { |
192
|
|
|
|
|
|
|
$data{$key} = $option_href->{$key}; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
return %data; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head2 load_direct($table_name, $data_href, $keynames_aref) |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
load testdata from this module into database directly. |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
$data->load_direct('foo', { id=>1, name=>'aaa' }, ['id']); |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
first parameter is table_name, second parameter is hashref for data. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
for example, |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
my $key = $data->load_direct('foo', { id=>1, name=>'aaa' }, ['id']); |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
is equivalent to |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
$data->add('foo', 1, { id=>1, name=>'aaa' }, ['id']); |
215
|
|
|
|
|
|
|
my $key = $data->load('foo', 1); |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
if set_keys() was called before, $keynames_aref is ommittable. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=cut |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
sub load_direct { |
223
|
|
|
|
|
|
|
my $self = shift; |
224
|
|
|
|
|
|
|
my ($table_name, $data_href, $keynames_aref) = @_; |
225
|
|
|
|
|
|
|
my %data = %{ $data_href }; |
226
|
|
|
|
|
|
|
if ( $self->_aref_is_empty($keynames_aref) ) { |
227
|
|
|
|
|
|
|
$keynames_aref = $self->{keynames}->{$table_name}; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
return $self->_load($table_name, $keynames_aref, %data); |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
sub _load { |
234
|
|
|
|
|
|
|
my $self = shift; |
235
|
|
|
|
|
|
|
my ($table_name, $keynames_aref, %data) = @_; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
croak "primary keys are not defined\n" if ( $self->_aref_is_empty($keynames_aref) ); |
238
|
|
|
|
|
|
|
if ( $self->{DeleteBeforeInsert} && $self->_data_for_key_exists($keynames_aref, %data) ) { |
239
|
|
|
|
|
|
|
$self->_delete($table_name, \%data, $keynames_aref); |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
$self->_do_insert($table_name, %data); |
242
|
|
|
|
|
|
|
my $keys = $self->_primary_keys($keynames_aref, \%data); |
243
|
|
|
|
|
|
|
$self->{dbh}->do('commit'); |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
push @{$self->{loaded}}, [$table_name, \%data, $keynames_aref]; |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
return $keys; |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub _aref_is_empty { |
252
|
|
|
|
|
|
|
my $self = shift; |
253
|
|
|
|
|
|
|
my ($keynames_aref) = @_; |
254
|
|
|
|
|
|
|
return !defined $keynames_aref || !@{ $keynames_aref }; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
sub _data_for_key_exists { |
258
|
|
|
|
|
|
|
my $self = shift; |
259
|
|
|
|
|
|
|
my ($keynames_aref, %data) = @_; |
260
|
|
|
|
|
|
|
for my $key ( @{ $keynames_aref } ) { |
261
|
|
|
|
|
|
|
return 0 if ( !exists $data{$key} ); |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
return 1; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub _do_insert { |
269
|
|
|
|
|
|
|
my $self = shift; |
270
|
|
|
|
|
|
|
my ($table_name, %data) = @_; |
271
|
|
|
|
|
|
|
my $dbh = $self->{dbh}; |
272
|
|
|
|
|
|
|
my $sth = $dbh->prepare($self->_insert_sql($table_name, %data)) || croak $dbh->errstr; |
273
|
|
|
|
|
|
|
my $i=1; |
274
|
|
|
|
|
|
|
for my $column ( sort keys %data ) { |
275
|
|
|
|
|
|
|
$sth->bind_param($i++, $data{$column}); |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
$sth->execute() || croak $dbh->errstr; |
278
|
|
|
|
|
|
|
$sth->finish; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head2 load_file |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
add data from external file |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
$data->load_file('data.pm'); |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
parameter is filename. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
=cut |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
sub load_file { |
292
|
|
|
|
|
|
|
my $self = shift; |
293
|
|
|
|
|
|
|
my ( $filename ) = @_; |
294
|
|
|
|
|
|
|
require $filename; |
295
|
|
|
|
|
|
|
croak("can't read $filename") if ( $@ ); |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=head2 init |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
create new instance for external file |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
my $data = Test::DataLoader::MySQL->init(); |
303
|
|
|
|
|
|
|
#$data->add(... |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=cut |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
sub init { |
308
|
|
|
|
|
|
|
my $class = shift; |
309
|
|
|
|
|
|
|
my $self = {}; |
310
|
|
|
|
|
|
|
if ( defined $singleton ) { |
311
|
|
|
|
|
|
|
$self = $singleton; |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
else { |
314
|
|
|
|
|
|
|
bless $self, $class; |
315
|
|
|
|
|
|
|
$singleton = $self; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
return $self; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head2 set_keys($table_name, $keynames_aref) |
321
|
|
|
|
|
|
|
set primary key information |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=cut |
324
|
|
|
|
|
|
|
sub set_keys { |
325
|
|
|
|
|
|
|
my $self = shift; |
326
|
|
|
|
|
|
|
my($table_name, $keynames_aref) = @_; |
327
|
|
|
|
|
|
|
$self->{keynames}->{$table_name} = $keynames_aref; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
sub _primary_keys { |
331
|
|
|
|
|
|
|
my $self = shift; |
332
|
|
|
|
|
|
|
my ($keynames_aref, $data_href) = @_; |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
my $result; |
335
|
|
|
|
|
|
|
for my $key ( @{ $keynames_aref } ) { |
336
|
|
|
|
|
|
|
if ( !defined $data_href->{$key} ) { #for auto_increment |
337
|
|
|
|
|
|
|
$data_href->{$key} = $self->_last_insert_id() || undef; #if LAST_INSERT_ID returns '0' its not auto_increment |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
$result->{$key} = $data_href->{$key} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
return $result; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
sub _last_insert_id { |
346
|
|
|
|
|
|
|
my $self = shift; |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
my $dbh = $self->{dbh}; |
349
|
|
|
|
|
|
|
my $sth = $dbh->prepare("select LAST_INSERT_ID() from dual") || croak $dbh->errstr; |
350
|
|
|
|
|
|
|
$sth->execute() || croak $dbh->errstr; |
351
|
|
|
|
|
|
|
if ( my @id = $sth->fetchrow_array ) { |
352
|
|
|
|
|
|
|
return $id[0]; |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
return; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=head2 do_select |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
do select statement |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
$data->do_select('foo', "id=1"); |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
first parameter is table_name which you want to select. second parameter is where closure. Omitting second parameter is not allowed, if you want to use all data, use condition which is aloways true such as "1=1". |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=cut |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub do_select { |
369
|
|
|
|
|
|
|
my $self = shift; |
370
|
|
|
|
|
|
|
my ($table, $condition) = @_; |
371
|
|
|
|
|
|
|
my $dbh = $self->{dbh}; |
372
|
|
|
|
|
|
|
croak( "Error: condition undefined" ) if !defined $condition; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
my $sth = $dbh->prepare("select * from $table where $condition"); |
375
|
|
|
|
|
|
|
$sth->execute(); |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
my @result; |
378
|
|
|
|
|
|
|
while( my $item = $sth->fetchrow_hashref ) { |
379
|
|
|
|
|
|
|
push @result, $item; |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
$sth->finish(); |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
return @result if wantarray; |
384
|
|
|
|
|
|
|
return $result[0]; |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub _insert_sql { |
388
|
|
|
|
|
|
|
my $self = shift; |
389
|
|
|
|
|
|
|
my ($table_name, %data) = @_; |
390
|
|
|
|
|
|
|
my $sql = sprintf("insert into %s set ", $table_name); |
391
|
|
|
|
|
|
|
$sql .= join(',', map { "$_=?" } sort keys %data); |
392
|
|
|
|
|
|
|
return $sql; |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
sub _data { |
396
|
|
|
|
|
|
|
my $self = shift; |
397
|
|
|
|
|
|
|
my ($table_name, $data_id) = @_; |
398
|
|
|
|
|
|
|
croak "$table_name not found" if ( !exists $self->{data}->{$table_name} ); |
399
|
|
|
|
|
|
|
croak "$data_id for $table_name not found" if ( !exists $self->{data}->{$table_name}->{$data_id} ); |
400
|
|
|
|
|
|
|
return $self->{data}->{$table_name}->{$data_id}->{data}; |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
sub DESTROY { |
405
|
|
|
|
|
|
|
my $self = shift; |
406
|
|
|
|
|
|
|
if ( @{ $self->{loaded} } ) { |
407
|
|
|
|
|
|
|
carp "clear was not called in $0"; |
408
|
|
|
|
|
|
|
$self->clear; |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=head2 clear |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
clear all loaded data from database; |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=cut |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
sub clear { |
420
|
|
|
|
|
|
|
my $self = shift; |
421
|
|
|
|
|
|
|
my $dbh = $self->{dbh}; |
422
|
|
|
|
|
|
|
if ( $self->{Keep} || !defined $dbh ) { |
423
|
|
|
|
|
|
|
$self->{loaded} = []; |
424
|
|
|
|
|
|
|
return; |
425
|
|
|
|
|
|
|
} |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
for my $loaded ( reverse @{ $self->{loaded} } ) { |
428
|
|
|
|
|
|
|
$self->_delete_loaded($loaded); |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
$dbh->do('commit'); |
431
|
|
|
|
|
|
|
$self->{loaded} = []; |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
sub _delete_loaded { |
435
|
|
|
|
|
|
|
my $self = shift; |
436
|
|
|
|
|
|
|
my ($loaded) = @_; |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
my( $table_name, $data_href, $keynames_aref ) = @{ $loaded }; |
439
|
|
|
|
|
|
|
$self->_delete($table_name, $data_href, $keynames_aref); |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
sub _delete { |
443
|
|
|
|
|
|
|
my $self = shift; |
444
|
|
|
|
|
|
|
my ($table_name, $data_href, $keynames_aref) = @_; |
445
|
|
|
|
|
|
|
my $dbh = $self->{dbh}; |
446
|
|
|
|
|
|
|
my %data = %{ $data_href }; |
447
|
|
|
|
|
|
|
my @keys = @{ $keynames_aref }; |
448
|
|
|
|
|
|
|
my $condition = join(' And ', map { |
449
|
|
|
|
|
|
|
defined $data{$_} ? "$_=?" : "$_ IS NULL" |
450
|
|
|
|
|
|
|
} @keys); |
451
|
|
|
|
|
|
|
my $sth = $dbh->prepare("delete from $table_name where $condition"); |
452
|
|
|
|
|
|
|
my $i=1; |
453
|
|
|
|
|
|
|
for my $key ( @keys ) { |
454
|
|
|
|
|
|
|
$sth->bind_param($i++, $data{$key}); |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
$sth->execute() || croak $dbh->errstr; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
1; |
460
|
|
|
|
|
|
|
__END__ |