DBIx-Custom / lib / DBI / Custom.pm /
Newer Older
936 lines | 23.979kb
first commit
yuki-kimoto authored on 2009-10-13
1
package DBI::Custom;
2
use Object::Simple;
add test
yuki-kimoto authored on 2009-10-16
3

            
4
our $VERSION = '0.0101';
5

            
6
use Carp 'croak';
add some method
yuki-kimoto authored on 2009-10-14
7
use DBI;
cleanup
yuki-kimoto authored on 2009-10-29
8
use DBI::Custom::Query;
add tests
yuki-kimoto authored on 2009-10-31
9
use DBI::Custom::Result;
10
use DBI::Custom::SQL::Template;
11

            
add tests
yuki-kimoto authored on 2009-10-25
12

            
13
### Class-Object Accessors
update document
yuki-kimoto authored on 2009-10-27
14
sub user        : ClassObjectAttr { initialize => {clone => 'scalar'} }
15
sub password    : ClassObjectAttr { initialize => {clone => 'scalar'} }
16
sub data_source : ClassObjectAttr { initialize => {clone => 'scalar'} }
cleanup
yuki-kimoto authored on 2009-10-29
17
sub dbi_options : ClassObjectAttr { initialize => {clone => 'hash', 
add tests
yuki-kimoto authored on 2009-10-31
18
                                                   default => sub { {} } } }
catch up Object::Simple upda...
yuki-kimoto authored on 2009-10-26
19

            
update document
yuki-kimoto authored on 2009-10-27
20
sub bind_filter  : ClassObjectAttr { initialize => {clone => 'scalar'} }
21
sub fetch_filter : ClassObjectAttr { initialize => {clone => 'scalar'} }
catch up Object::Simple upda...
yuki-kimoto authored on 2009-10-26
22

            
add no_bind_filters
yuki-kimoto authored on 2009-10-30
23
sub no_bind_filters   : ClassObjectAttr { initialize => {clone => 'array'} }
24
sub no_fetch_filters  : ClassObjectAttr { initialize => {clone => 'array'} }
add various thins
yuki-kimoto authored on 2009-10-29
25

            
catch up Object::Simple upda...
yuki-kimoto authored on 2009-10-26
26
sub filters : ClassObjectAttr {
27
    type => 'hash',
28
    deref => 1,
29
    initialize => {
add tests
yuki-kimoto authored on 2009-10-25
30
        clone   => 'hash',
31
        default => sub { {} }
catch up Object::Simple upda...
yuki-kimoto authored on 2009-10-26
32
    }
33
}
first commit
yuki-kimoto authored on 2009-10-13
34

            
catch up Object::Simple upda...
yuki-kimoto authored on 2009-10-26
35
sub result_class : ClassObjectAttr {
36
    initialize => {
add tests
yuki-kimoto authored on 2009-10-25
37
        clone   => 'scalar',
38
        default => 'DBI::Custom::Result'
catch up Object::Simple upda...
yuki-kimoto authored on 2009-10-26
39
    }
40
}
cleanup
yuki-kimoto authored on 2009-10-14
41

            
catch up Object::Simple upda...
yuki-kimoto authored on 2009-10-26
42
sub sql_template : ClassObjectAttr {
43
    initialize => {
update document
yuki-kimoto authored on 2009-10-27
44
        clone   => sub {$_[0] ? $_[0]->clone : undef},
catch up Object::Simple upda...
yuki-kimoto authored on 2009-10-26
45
        default => sub {DBI::Custom::SQL::Template->new}
46
    }
47
}
cleanup
yuki-kimoto authored on 2009-10-15
48

            
add tests
yuki-kimoto authored on 2009-10-25
49
### Object Accessor
add tests
yuki-kimoto authored on 2009-10-18
50
sub dbh          : Attr {}
add tests
yuki-kimoto authored on 2009-10-25
51

            
52

            
53
### Methods
add various thins
yuki-kimoto authored on 2009-10-29
54

            
add tests
yuki-kimoto authored on 2009-10-25
55
# Add filter
56
sub add_filter {
57
    my $invocant = shift;
58
    
59
    my %old_filters = $invocant->filters;
60
    my %new_filters = ref $_[0] eq 'HASH' ? %{$_[0]} : @_;
61
    $invocant->filters(%old_filters, %new_filters);
update document
yuki-kimoto authored on 2009-10-27
62
    return $invocant;
add tests
yuki-kimoto authored on 2009-10-25
63
}
add various
yuki-kimoto authored on 2009-10-18
64

            
65
# Auto commit
update document
yuki-kimoto authored on 2009-10-27
66
sub _auto_commit {
add various
yuki-kimoto authored on 2009-10-18
67
    my $self = shift;
68
    
add tests
yuki-kimoto authored on 2009-10-31
69
    croak("Not yet connect to database") unless $self->dbh;
add various
yuki-kimoto authored on 2009-10-18
70
    
71
    if (@_) {
72
        $self->dbh->{AutoCommit} = $_[0];
73
        return $self;
74
    }
75
    return $self->dbh->{AutoCommit};
76
}
add test
yuki-kimoto authored on 2009-10-16
77

            
add various things
yuki-kimoto authored on 2009-10-17
78
# Connect
add some method
yuki-kimoto authored on 2009-10-14
79
sub connect {
80
    my $self = shift;
update document
yuki-kimoto authored on 2009-10-27
81
    my $data_source = $self->data_source;
82
    my $user        = $self->user;
83
    my $password    = $self->password;
cleanup
yuki-kimoto authored on 2009-10-29
84
    my $dbi_options  = $self->dbi_options;
add test
yuki-kimoto authored on 2009-10-16
85
    
add tests
yuki-kimoto authored on 2009-10-31
86
    my $dbh = eval{DBI->connect(
update document
yuki-kimoto authored on 2009-10-27
87
        $data_source,
88
        $user,
89
        $password,
add some method
yuki-kimoto authored on 2009-10-14
90
        {
91
            RaiseError => 1,
92
            PrintError => 0,
93
            AutoCommit => 1,
cleanup
yuki-kimoto authored on 2009-10-29
94
            %{$dbi_options || {} }
add some method
yuki-kimoto authored on 2009-10-14
95
        }
add tests
yuki-kimoto authored on 2009-10-31
96
    )};
97
    
98
    croak $@ if $@;
add some method
yuki-kimoto authored on 2009-10-14
99
    
100
    $self->dbh($dbh);
add various
yuki-kimoto authored on 2009-10-18
101
    return $self;
add some method
yuki-kimoto authored on 2009-10-14
102
}
first commit
yuki-kimoto authored on 2009-10-13
103

            
add tests
yuki-kimoto authored on 2009-10-25
104
# DESTROY
add tests
yuki-kimoto authored on 2009-10-18
105
sub DESTROY {
106
    my $self = shift;
add tests
yuki-kimoto authored on 2009-10-18
107
    $self->disconnect if $self->connected;
add tests
yuki-kimoto authored on 2009-10-18
108
}
109

            
add various things
yuki-kimoto authored on 2009-10-17
110
# Is connected?
111
sub connected {
112
    my $self = shift;
cleanup
yuki-kimoto authored on 2009-10-31
113
    return ref $self->{dbh} eq 'DBI::db';
add various things
yuki-kimoto authored on 2009-10-17
114
}
115

            
116
# Disconnect
117
sub disconnect {
118
    my $self = shift;
add tests
yuki-kimoto authored on 2009-10-18
119
    if ($self->connected) {
add various things
yuki-kimoto authored on 2009-10-17
120
        $self->dbh->disconnect;
121
        delete $self->{dbh};
122
    }
123
}
124

            
125
# Reconnect
126
sub reconnect {
127
    my $self = shift;
add tests
yuki-kimoto authored on 2009-10-18
128
    $self->disconnect if $self->connected;
add various things
yuki-kimoto authored on 2009-10-17
129
    $self->connect;
130
}
131

            
cleanup
yuki-kimoto authored on 2009-10-31
132
# Prepare statement handle
add prepare
yuki-kimoto authored on 2009-10-31
133
sub prepare {
134
    my ($self, $sql) = @_;
cleanup
yuki-kimoto authored on 2009-10-31
135
    
136
    # Connect if not
add tests
yuki-kimoto authored on 2009-10-31
137
    $self->connect unless $self->connected;
add prepare
yuki-kimoto authored on 2009-10-31
138
    
cleanup
yuki-kimoto authored on 2009-10-31
139
    # Prepare
add prepare
yuki-kimoto authored on 2009-10-31
140
    my $sth = eval{$self->dbh->prepare($sql)};
add tests
yuki-kimoto authored on 2009-10-31
141
    
142
    # Error
143
    croak("$@<Your SQL>\n$sql") if $@;
144
    
add prepare
yuki-kimoto authored on 2009-10-31
145
    return $sth;
146
}
147

            
cleanup
yuki-kimoto authored on 2009-10-31
148
# Execute SQL directly
add prepare
yuki-kimoto authored on 2009-10-31
149
sub do{
150
    my ($self, $sql, @bind_values) = @_;
cleanup
yuki-kimoto authored on 2009-10-31
151
    
152
    # Connect if not
add tests
yuki-kimoto authored on 2009-10-31
153
    $self->connect unless $self->connected;
add prepare
yuki-kimoto authored on 2009-10-31
154
    
cleanup
yuki-kimoto authored on 2009-10-31
155
    # Do
add tests
yuki-kimoto authored on 2009-10-31
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
    }
add prepare
yuki-kimoto authored on 2009-10-31
168
}
169

            
cleanup
yuki-kimoto authored on 2009-10-31
170
# Create query
add various thins
yuki-kimoto authored on 2009-10-29
171
sub create_query {
172
    my ($self, $template) = @_;
add query cache system
yuki-kimoto authored on 2009-11-02
173
    my $class = ref $self;
add test
yuki-kimoto authored on 2009-10-17
174
    
add various thins
yuki-kimoto authored on 2009-10-29
175
    # Create query from SQL template
add prepare
yuki-kimoto authored on 2009-10-31
176
    my $sql_template = $self->sql_template;
add test
yuki-kimoto authored on 2009-10-17
177
    
add query cache system
yuki-kimoto authored on 2009-11-02
178
    # Try to get cached query
179
    my $query = $class->_query_caches->{$template};
180
    
181
    # Create query
182
    unless ($query) {
183
        $query = eval{$sql_template->create_query($template)};
184
        croak($@) if $@;
185
        
186
        $query = DBI::Custom::Query->new($query);
187
        
188
        $class->_add_query_cache($template, $query);
189
    }
add various thins
yuki-kimoto authored on 2009-10-29
190
    
cleanup
yuki-kimoto authored on 2009-10-31
191
    # Connect if not
add tests
yuki-kimoto authored on 2009-10-31
192
    $self->connect unless $self->connected;
try varioud way
yuki-kimoto authored on 2009-10-17
193
    
add various thins
yuki-kimoto authored on 2009-10-29
194
    # Prepare statement handle
add tests
yuki-kimoto authored on 2009-10-31
195
    my $sth = $self->prepare($query->{sql});
add tests
yuki-kimoto authored on 2009-10-18
196
    
add no_bind_filters
yuki-kimoto authored on 2009-10-30
197
    # Set statement handle
add various thins
yuki-kimoto authored on 2009-10-29
198
    $query->sth($sth);
add tests
yuki-kimoto authored on 2009-10-18
199
    
add no_bind_filters
yuki-kimoto authored on 2009-10-30
200
    # Set bind filter
201
    $query->bind_filter($self->bind_filter);
202
    
203
    # Set no filter keys when binding
204
    $query->no_bind_filters($self->no_bind_filters);
add tests
yuki-kimoto authored on 2009-10-31
205
    
add no_bind_filters
yuki-kimoto authored on 2009-10-30
206
    # Set fetch filter
207
    $query->fetch_filter($self->fetch_filter);
208
    
209
    # Set no filter keys when fetching
210
    $query->no_fetch_filters($self->no_fetch_filters);
211
    
add various thins
yuki-kimoto authored on 2009-10-29
212
    return $query;
213
}
214

            
cleanup
yuki-kimoto authored on 2009-10-31
215
# Execute query
add various thins
yuki-kimoto authored on 2009-10-29
216
sub execute {
217
    my ($self, $query, $params)  = @_;
add tests
yuki-kimoto authored on 2009-10-29
218
    $params ||= {};
try varioud way
yuki-kimoto authored on 2009-10-17
219
    
add tests
yuki-kimoto authored on 2009-10-31
220
    # First argument is SQL template
221
    if (!ref $query) {
222
        my $template = $query;
223
        $query = $self->create_query($template);
224
        my $query_edit_cb = $_[3];
225
        $query_edit_cb->($query) if ref $query_edit_cb eq 'CODE';
226
    }
227
    
add various thins
yuki-kimoto authored on 2009-10-29
228
    # Create bind value
229
    my $bind_values = $self->_build_bind_values($query, $params);
add tests
yuki-kimoto authored on 2009-10-18
230
    
cleanup
yuki-kimoto authored on 2009-10-18
231
    # Execute
cleanup
yuki-kimoto authored on 2009-10-29
232
    my $sth = $query->sth;
add tests
yuki-kimoto authored on 2009-10-31
233
    my $ret_val = eval{$sth->execute(@$bind_values)};
cleanup
yuki-kimoto authored on 2009-10-31
234
    
235
    # Execute error
add tests
yuki-kimoto authored on 2009-10-31
236
    if (my $execute_error = $@) {
add tests
yuki-kimoto authored on 2009-10-31
237
        require Data::Dumper;
238
        my $sql         = $query->{sql} || '';
239
        my $params_dump = Data::Dumper->Dump([$params], ['*params']);
240
        
add tests
yuki-kimoto authored on 2009-10-31
241
        croak("$execute_error<Your SQL>\n$sql\n<Your parameters>\n$params_dump");
add tests
yuki-kimoto authored on 2009-10-31
242
    }
add various things
yuki-kimoto authored on 2009-10-17
243
    
cleanup
yuki-kimoto authored on 2009-10-18
244
    # Return resultset if select statement is executed
add various things
yuki-kimoto authored on 2009-10-17
245
    if ($sth->{NUM_OF_FIELDS}) {
cleanup
yuki-kimoto authored on 2009-10-31
246
        
247
        # Get result class
add various things
yuki-kimoto authored on 2009-10-17
248
        my $result_class = $self->result_class;
cleanup
yuki-kimoto authored on 2009-10-31
249
        
250
        # Create result
add various
yuki-kimoto authored on 2009-10-18
251
        my $result = $result_class->new({
add no_bind_filters
yuki-kimoto authored on 2009-10-30
252
            sth              => $sth,
253
            fetch_filter     => $query->fetch_filter,
254
            no_fetch_filters => $query->no_fetch_filters
add various
yuki-kimoto authored on 2009-10-18
255
        });
add various things
yuki-kimoto authored on 2009-10-17
256
        return $result;
257
    }
add tests
yuki-kimoto authored on 2009-10-18
258
    return $ret_val;
add test
yuki-kimoto authored on 2009-10-17
259
}
260

            
cleanup
yuki-kimoto authored on 2009-10-31
261
# Build binding values
add various thins
yuki-kimoto authored on 2009-10-29
262
sub _build_bind_values {
263
    my ($self, $query, $params) = @_;
add no_bind_filters
yuki-kimoto authored on 2009-10-30
264
    my $key_infos           = $query->key_infos;
265
    my $bind_filter         = $query->bind_filter;
266
    my $no_bind_filters_map = $query->_no_bind_filters_map || {};
cleanup
yuki-kimoto authored on 2009-10-18
267
    
add various thins
yuki-kimoto authored on 2009-10-29
268
    # binding values
269
    my @bind_values;
cleanup
yuki-kimoto authored on 2009-10-18
270
    
add tests
yuki-kimoto authored on 2009-10-31
271
    # Create bind values
cleanup
yuki-kimoto authored on 2009-10-29
272
    foreach my $key_info (@$key_infos) {
cleanup
yuki-kimoto authored on 2009-10-31
273
        # Set variable
274
        my $access_keys  = $key_info->{access_keys};
cleanup
yuki-kimoto authored on 2009-10-29
275
        my $original_key = $key_info->{original_key} || '';
276
        my $table        = $key_info->{table}        || '';
277
        my $column       = $key_info->{column}       || '';
add various thins
yuki-kimoto authored on 2009-10-29
278
        
cleanup
yuki-kimoto authored on 2009-10-31
279
        # Key is found?
add tests
yuki-kimoto authored on 2009-10-31
280
        my $found;
cleanup
yuki-kimoto authored on 2009-10-31
281
        
282
        # Build bind values
add various thins
yuki-kimoto authored on 2009-10-29
283
        ACCESS_KEYS :
284
        foreach my $access_key (@$access_keys) {
cleanup
yuki-kimoto authored on 2009-10-31
285
            # Root parameter
add various thins
yuki-kimoto authored on 2009-10-29
286
            my $root_params = $params;
cleanup
yuki-kimoto authored on 2009-10-31
287
            
288
            # Search corresponding value
add various thins
yuki-kimoto authored on 2009-10-29
289
            for (my $i = 0; $i < @$access_key; $i++) {
cleanup
yuki-kimoto authored on 2009-10-31
290
                # Current key
291
                my $current_key = $access_key->[$i];
add various thins
yuki-kimoto authored on 2009-10-29
292
                
cleanup
yuki-kimoto authored on 2009-10-31
293
                # Last key
add various thins
yuki-kimoto authored on 2009-10-29
294
                if ($i == @$access_key - 1) {
cleanup
yuki-kimoto authored on 2009-10-31
295
                    # Key is array reference
296
                    if (ref $current_key eq 'ARRAY') {
297
                        # Filtering 
298
                        if ($bind_filter &&
299
                            !$no_bind_filters_map->{$original_key})
300
                        {
add no_bind_filters
yuki-kimoto authored on 2009-10-30
301
                            push @bind_values, 
cleanup
yuki-kimoto authored on 2009-10-31
302
                                 $bind_filter->($original_key, 
303
                                                $root_params->[$current_key->[0]],
cleanup
yuki-kimoto authored on 2009-10-30
304
                                                $table, $column);
add various thins
yuki-kimoto authored on 2009-10-29
305
                        }
cleanup
yuki-kimoto authored on 2009-10-31
306
                        # Not filtering
add various thins
yuki-kimoto authored on 2009-10-29
307
                        else {
cleanup
yuki-kimoto authored on 2009-10-31
308
                            push @bind_values,
309
                                 scalar $root_params->[$current_key->[0]];
add various thins
yuki-kimoto authored on 2009-10-29
310
                        }
311
                    }
cleanup
yuki-kimoto authored on 2009-10-31
312
                    # Key is string
add various thins
yuki-kimoto authored on 2009-10-29
313
                    else {
cleanup
yuki-kimoto authored on 2009-10-31
314
                        # Key is not found
315
                        next ACCESS_KEYS
316
                          unless exists $root_params->{$current_key};
317
                        
318
                        # Filtering
319
                        if ($bind_filter &&
320
                            !$no_bind_filters_map->{$original_key}) 
321
                        {
add no_bind_filters
yuki-kimoto authored on 2009-10-30
322
                            push @bind_values,
cleanup
yuki-kimoto authored on 2009-10-31
323
                                 $bind_filter->($original_key,
324
                                                $root_params->{$current_key}, 
cleanup
yuki-kimoto authored on 2009-10-30
325
                                                $table, $column);
add various thins
yuki-kimoto authored on 2009-10-29
326
                        }
cleanup
yuki-kimoto authored on 2009-10-31
327
                        # Not filtering
add various thins
yuki-kimoto authored on 2009-10-29
328
                        else {
cleanup
yuki-kimoto authored on 2009-10-31
329
                            push @bind_values,
330
                                 scalar $root_params->{$current_key};
add various thins
yuki-kimoto authored on 2009-10-29
331
                        }
332
                    }
cleanup
yuki-kimoto authored on 2009-10-31
333
                    
334
                    # Key is found
add tests
yuki-kimoto authored on 2009-10-31
335
                    $found = 1;
add various thins
yuki-kimoto authored on 2009-10-29
336
                }
cleanup
yuki-kimoto authored on 2009-10-31
337
                # First or middle key
add various thins
yuki-kimoto authored on 2009-10-29
338
                else {
cleanup
yuki-kimoto authored on 2009-10-31
339
                    # Key is array reference
340
                    if (ref $current_key eq 'ARRAY') {
341
                        # Go next key
342
                        $root_params = $root_params->[$current_key->[0]];
343
                    }
344
                    # Key is string
345
                    else {
346
                        # Not found
347
                        next ACCESS_KEYS
348
                          unless exists $root_params->{$current_key};
349
                        
350
                        # Go next key
351
                        $root_params = $root_params->{$current_key};
352
                    }
add various thins
yuki-kimoto authored on 2009-10-29
353
                }
354
            }
355
        }
add tests
yuki-kimoto authored on 2009-10-31
356
        
cleanup
yuki-kimoto authored on 2009-10-31
357
        # Key is not found
add tests
yuki-kimoto authored on 2009-10-31
358
        unless ($found) {
359
            require Data::Dumper;
add tests
yuki-kimoto authored on 2009-10-31
360
            my $key_info_dump  = Data::Dumper->Dump([$key_info], ['*key_info']);
add tests
yuki-kimoto authored on 2009-10-31
361
            my $params_dump    = Data::Dumper->Dump([$params], ['*params']);
add tests
yuki-kimoto authored on 2009-10-31
362
            croak("Corresponding key is not found in your parameters\n" . 
add tests
yuki-kimoto authored on 2009-10-31
363
                  "<Key information>\n$key_info_dump\n\n" .
364
                  "<Your parameters>\n$params_dump\n");
365
        }
update document
yuki-kimoto authored on 2009-10-27
366
    }
add tests
yuki-kimoto authored on 2009-10-31
367
    return \@bind_values;
add test
yuki-kimoto authored on 2009-10-17
368
}
369

            
add tests
yuki-kimoto authored on 2009-10-31
370
# Run tranzaction
371
sub run_tranzaction {
372
    my ($self, $tranzaction) = @_;
373
    
374
    # Check auto commit
375
    croak("AutoCommit must be true before tranzaction start")
376
      unless $self->_auto_commit;
377
    
378
    # Auto commit off
379
    $self->_auto_commit(0);
380
    
381
    # Run tranzaction
382
    eval {$tranzaction->()};
383
    
384
    # Tranzaction error
385
    my $tranzaction_error = $@;
386
    
387
    # Tranzaction is failed.
388
    if ($tranzaction_error) {
389
        # Rollback
390
        eval{$self->dbh->rollback};
391
        
392
        # Rollback error
393
        my $rollback_error = $@;
394
        
395
        # Auto commit on
396
        $self->_auto_commit(1);
397
        
398
        if ($rollback_error) {
399
            # Rollback is failed
400
            croak("${tranzaction_error}Rollback is failed : $rollback_error");
401
        }
402
        else {
403
            # Rollback is success
404
            croak("${tranzaction_error}Rollback is success");
405
        }
406
    }
407
    # Tranzaction is success
408
    else {
409
        # Commit
410
        eval{$self->dbh->commit};
411
        my $commit_error = $@;
412
        
413
        # Auto commit on
414
        $self->_auto_commit(1);
415
        
416
        # Commit is failed
417
        croak($commit_error) if $commit_error;
418
    }
419
}
add various thins
yuki-kimoto authored on 2009-10-29
420

            
add methods
yuki-kimoto authored on 2009-11-02
421
# Get last insert id
422
sub last_insert_id {
423
    my $self = shift;
424
    
425
    # Not connected
426
    croak("Not yet connect to database")
427
      unless $self->connected;
428
    
429
    return $self->dbh->last_insert_id(@_);
430
}
431

            
432
# Insert
433
sub insert {
434
    my ($self, $table, $insert_params, $edit_query_cb) = @_;
435
    $insert_params ||= {};
436
    
437
    # Insert keys
438
    my @insert_keys = keys %$insert_params;
439
    
440
    # Not exists insert keys
441
    croak("Insert key must be specified")
442
      unless @insert_keys;
443
    
444
    # Templte for insert
445
    my $template = "insert into $table {insert " . join(' ', @insert_keys) . '}';
446
    
447
    # Create query
448
    my $query = $self->create_query($template);
449
    
450
    # Edit query callback must be code reference
451
    croak("Edit query callback must be code reference")
452
      if $edit_query_cb && !ref $edit_query_cb eq 'CODE';
453
    
454
    # Edit query if need
455
    $edit_query_cb->($query) if ref $edit_query_cb eq 'CODE';
456
    
457
    # Execute query
458
    my $ret_val = $self->execute($query, $insert_params);
459
    
460
    return $ret_val;
461
}
462

            
463
sub update {
464
    my ($self, $table, $update_params,
465
        $where_params, $edit_query_cb, $options) = @_;
466
    
467
    $update_params ||= {};
468
    $where_params  ||= {};
469
    
470
    # Update keys
471
    my @update_keys = keys %$where_params;
472
    
473
    # Not exists update kyes
474
    croak("Update key must be specified")
475
      unless @update_keys;
476
    
477
    # Where keys
478
    my @where_keys = keys %$where_params;
479
    
480
    # Not exists where keys
481
    croak("Where key must be specified")
482
      if !@where_keys && !$options->{allow_update_all};
483
    
484
    # Update clause
485
    my $update_clause = '{update ' . join(' ', @update_keys) . '}';
486
    
487
    # Where clause
488
    my $where_clause = 'where ';
489
    foreach my $where_key (@where_keys) {
490
        $where_clause .= "{= $where_key} && ";
491
    }
492
    $where_clause =~ s/ && $//;
493
    
494
    # Template for update
495
    my $template = "update $table $update_clause $where_clause";
496
    
497
    # Create query
498
    my $query = $self->create_query($template);
499
    
500
    # Edit query callback must be code reference
501
    croak("Edit query callback must be code reference")
502
      if $edit_query_cb && !ref $edit_query_cb eq 'CODE';
503
    
504
    # Edit query if need
505
    $edit_query_cb->($query) if $edit_query_cb;
506
    
507
    # Rearrange parammeters
508
    my $params = {'#update' => $update_params, %$where_params};
509
    
510
    # Execute query
511
    my $ret_val = $self->execute($query, $params);
512
    
513
    return $ret_val;
514
}
515

            
516
# Update all rows
517
sub update_all {
518
    my ($self, $table, $update_params, $edit_query_cb) = @_;
519
    
520
    return $self->update($table, $update_params, {}, $edit_query_cb,
521
                         {allow_update_all => 1});
522
}
523

            
524
# Delete
525
sub delete {
526
    my ($self, $table, $where_params, $edit_query_cb, $options) = @_;
527
    $where_params ||= {};
528
    
529
    # Where keys
530
    my @where_keys = keys %$where_params;
531
    
532
    # Not exists where keys
533
    croak("Where key must be specified")
534
      if !@where_keys && !$options->{allow_update_all};
535
    
536
    # Where clause
537
    my $where_clause = 'where ';
538
    foreach my $where_key (@where_keys) {
539
        $where_clause .= "{= $where_key} && ";
540
    }
541
    $where_clause =~ s/ && $//;
542
    
543
    # Template for delete
544
    my $template = "delete from $table $where_clause";
545
    
546
    # Create query
547
    my $query = $self->create_query($template);
548
    
549
    # Edit query callback must be code reference
550
    croak("Edit query callback must be code reference")
551
      if $edit_query_cb && !ref $edit_query_cb eq 'CODE';
552
    
553
    # Edit query if need
554
    $edit_query_cb->($query) if $edit_query_cb;
555
    
556
    # Execute query
557
    my $ret_val = $self->execute($query, $where_params);
558
    
559
    return $ret_val;
560
}
561

            
562
# Delete all rows
563
sub delete_all {
564
    my ($self, $table, $edit_query_cb) = @_;
565
    return $self->delete($table, {}, $edit_query_cb, {allow_delete_all => 1});
566
}
567

            
add query cache system
yuki-kimoto authored on 2009-11-02
568
sub _query_caches     : ClassAttr { type => 'hash',
569
                                    auto_build => sub {shift->_query_caches({}) } }
570
                                    
571
sub _query_cache_keys : ClassAttr { type => 'array',
572
                                    auto_build => sub {shift->_query_cache_keys([])} }
573
                                    
574
sub query_cache_max   : ClassAttr { auto_build => sub {shift->query_cache_max(50)} }
575

            
576
# Add query cahce
577
sub _add_query_cache {
578
    my ($class, $template, $query) = @_;
579
    my $query_cache_keys = $class->_query_cache_keys;
580
    my $query_caches     = $class->_query_caches;
581
    
582
    return $class if $query_caches->{$template};
583
    
584
    $query_caches->{$template} = $query;
585
    push @$query_cache_keys, $template;
586
    
587
    my $overflow = @$query_cache_keys - $class->query_cache_max;
588
    
589
    for (my $i = 0; $i < $overflow; $i++) {
590
        my $template = shift @$query_cache_keys;
591
        delete $query_caches->{$template};
592
    }
593
    
594
    return $class;
595
}
add methods
yuki-kimoto authored on 2009-11-02
596

            
add test
yuki-kimoto authored on 2009-10-17
597
Object::Simple->build_class;
598

            
first commit
yuki-kimoto authored on 2009-10-13
599
=head1 NAME
600

            
add test
yuki-kimoto authored on 2009-10-17
601
DBI::Custom - Customizable simple DBI
first commit
yuki-kimoto authored on 2009-10-13
602

            
603
=head1 VERSION
604

            
add test
yuki-kimoto authored on 2009-10-16
605
Version 0.0101
first commit
yuki-kimoto authored on 2009-10-13
606

            
cleanup
yuki-kimoto authored on 2009-10-31
607
=head1 CAUTION
608

            
609
This module is now experimental stage.
610

            
611
I want you to try this module
612
because I want this module stable, and not to damage your DB data by this module bug.
613

            
614
Please tell me bug if you find
first commit
yuki-kimoto authored on 2009-10-13
615

            
616
=head1 SYNOPSIS
617

            
add test
yuki-kimoto authored on 2009-10-16
618
  my $dbi = DBI::Custom->new;
add various thins
yuki-kimoto authored on 2009-10-29
619
  
620
  my $query = $dbi->create_query($template);
621
  $dbi->execute($query);
first commit
yuki-kimoto authored on 2009-10-13
622

            
update document
yuki-kimoto authored on 2009-10-27
623
=head1 CLASS-OBJECT ACCESSORS
first commit
yuki-kimoto authored on 2009-10-13
624

            
update document
yuki-kimoto authored on 2009-10-27
625
=head2 user
626

            
627
    # Set and get database user name
628
    $self = $dbi->user($user);
629
    $user = $dbi->user;
630
    
631
    # Sample
632
    $dbi->user('taro');
633

            
634
=head2 password
635

            
636
    # Set and get database password
637
    $self     = $dbi->password($password);
638
    $password = $dbi->password;
639
    
640
    # Sample
641
    $dbi->password('lkj&le`@s');
642

            
643
=head2 data_source
644

            
645
    # Set and get database data source
646
    $self        = $dbi->data_source($data_soruce);
647
    $data_source = $dbi->data_source;
648
    
649
    # Sample(SQLite)
650
    $dbi->data_source(dbi:SQLite:dbname=$database);
651
    
652
    # Sample(MySQL);
653
    $dbi->data_source("dbi:mysql:dbname=$database");
654
    
655
    # Sample(PostgreSQL)
656
    $dbi->data_source("dbi:Pg:dbname=$database");
cleanup
yuki-kimoto authored on 2009-10-29
657
    
658
=head2 database
659

            
660
    # Set and get database name
661
    $self     = $dbi->database($database);
662
    $database = $dbi->database;
update document
yuki-kimoto authored on 2009-10-27
663

            
cleanup
yuki-kimoto authored on 2009-10-29
664
=head2 dbi_options
update document
yuki-kimoto authored on 2009-10-27
665

            
666
    # Set and get DBI option
cleanup
yuki-kimoto authored on 2009-10-29
667
    $self       = $dbi->dbi_options({$options => $value, ...});
668
    $dbi_options = $dbi->dbi_options;
update document
yuki-kimoto authored on 2009-10-27
669

            
670
    # Sample
cleanup
yuki-kimoto authored on 2009-10-29
671
    $dbi->dbi_options({PrintError => 0, RaiseError => 1});
update document
yuki-kimoto authored on 2009-10-27
672

            
cleanup
yuki-kimoto authored on 2009-10-29
673
dbi_options is used when you connect database by using connect.
update document
yuki-kimoto authored on 2009-10-27
674

            
add prepare
yuki-kimoto authored on 2009-10-31
675
=head2 prepare
676

            
677
    $sth = $dbi->prepare($sql);
678

            
679
This method is same as DBI::prepare
680

            
681
=head2 do
682

            
683
    $dbi->do($sql, @bind_values);
684

            
685
This method is same as DBI::do
686

            
update document
yuki-kimoto authored on 2009-10-27
687
=head2 sql_template
688

            
689
    # Set and get SQL::Template object
690
    $self         = $dbi->sql_template($sql_template);
691
    $sql_template = $dbi->sql_template;
692
    
693
    # Sample
694
    $dbi->sql_template(DBI::Cutom::SQL::Template->new);
695

            
696
=head2 filters
697

            
698
    # Set and get filters
699
    $self    = $dbi->filters($filters);
700
    $filters = $dbi->filters;
first commit
yuki-kimoto authored on 2009-10-13
701

            
add test
yuki-kimoto authored on 2009-10-16
702
=head2 bind_filter
first commit
yuki-kimoto authored on 2009-10-13
703

            
update document
yuki-kimoto authored on 2009-10-27
704
    # Set and get binding filter
705
    $self        = $dbi->bind_filter($bind_filter);
706
    $bind_filter = $dbi->bind_filter
first commit
yuki-kimoto authored on 2009-10-13
707

            
update document
yuki-kimoto authored on 2009-10-27
708
    # Sample
709
    $dbi->bind_filter($self->filters->{default_bind_filter});
710
    
first commit
yuki-kimoto authored on 2009-10-13
711

            
update document
yuki-kimoto authored on 2009-10-27
712
you can get DBI database handle if you need.
first commit
yuki-kimoto authored on 2009-10-13
713

            
add test
yuki-kimoto authored on 2009-10-16
714
=head2 fetch_filter
first commit
yuki-kimoto authored on 2009-10-13
715

            
update document
yuki-kimoto authored on 2009-10-27
716
    # Set and get Fetch filter
717
    $self         = $dbi->fetch_filter($fetch_filter);
718
    $fetch_filter = $dbi->fetch_filter;
first commit
yuki-kimoto authored on 2009-10-13
719

            
update document
yuki-kimoto authored on 2009-10-27
720
    # Sample
721
    $dbi->fetch_filter($self->filters->{default_fetch_filter});
add test
yuki-kimoto authored on 2009-10-16
722

            
add no_bind_filters
yuki-kimoto authored on 2009-10-30
723
=head2 no_bind_filters
724

            
725
    # Set and get no filter keys when binding
726
    $self            = $dbi->no_bind_filters($no_bind_filters);
727
    $no_bind_filters = $dbi->no_bind_filters;
728

            
729
=head2 no_fetch_filters
cleanup
yuki-kimoto authored on 2009-10-29
730

            
add no_bind_filters
yuki-kimoto authored on 2009-10-30
731
    # Set and get no filter keys when fetching
732
    $self             = $dbi->no_fetch_filters($no_fetch_filters);
733
    $no_fetch_filters = $dbi->no_fetch_filters;
cleanup
yuki-kimoto authored on 2009-10-29
734

            
update document
yuki-kimoto authored on 2009-10-27
735
=head2 result_class
first commit
yuki-kimoto authored on 2009-10-13
736

            
update document
yuki-kimoto authored on 2009-10-27
737
    # Set and get resultset class
738
    $self         = $dbi->result_class($result_class);
739
    $result_class = $dbi->result_class;
740
    
741
    # Sample
742
    $dbi->result_class('DBI::Custom::Result');
add test
yuki-kimoto authored on 2009-10-17
743

            
update document
yuki-kimoto authored on 2009-10-27
744
=head2 dbh
add test
yuki-kimoto authored on 2009-10-17
745

            
update document
yuki-kimoto authored on 2009-10-27
746
    # Get database handle
747
    $dbh = $self->dbh;
add test
yuki-kimoto authored on 2009-10-17
748

            
update document
yuki-kimoto authored on 2009-10-27
749
=head1 METHODS
add tests
yuki-kimoto authored on 2009-10-18
750

            
update document
yuki-kimoto authored on 2009-10-27
751
=head2 connect
752

            
753
    # Connect to database
754
    $self = $dbi->connect;
755
    
756
    # Sample
757
    $dbi = DBI::Custom->new(user => 'taro', password => 'lji8(', 
758
                            data_soruce => "dbi:mysql:dbname=$database");
759
    $dbi->connect;
add tests
yuki-kimoto authored on 2009-10-18
760

            
761
=head2 disconnect
762

            
update document
yuki-kimoto authored on 2009-10-27
763
    # Disconnect database
764
    $dbi->disconnect;
765

            
766
If database is already disconnected, this method do noting.
767

            
add tests
yuki-kimoto authored on 2009-10-18
768
=head2 reconnect
769

            
update document
yuki-kimoto authored on 2009-10-27
770
    # Reconnect
771
    $dbi->reconnect;
772

            
773
=head2 connected
774

            
775
    # Check connected
776
    $dbi->connected
777

            
778
=head2 add_filter
779

            
780
    # Add filter (hash ref or hash can be recieve)
781
    $self = $dbi->add_filter({$filter_name => $filter, ...});
782
    $self = $dbi->add_filter($filetr_name => $filter, ...);
783
    
784
    # Sample
785
    $dbi->add_filter(
786
        decode_utf8 => sub {
cleanup
yuki-kimoto authored on 2009-10-30
787
            my ($key, $value, $table, $column) = @_;
update document
yuki-kimoto authored on 2009-10-27
788
            return Encode::decode('UTF-8', $value);
789
        },
790
        datetime_to_string => sub {
cleanup
yuki-kimoto authored on 2009-10-30
791
            my ($key, $value, $table, $column) = @_;
update document
yuki-kimoto authored on 2009-10-27
792
            return $value->strftime('%Y-%m-%d %H:%M:%S')
793
        },
794
        default_bind_filter => sub {
cleanup
yuki-kimoto authored on 2009-10-30
795
            my ($key, $value, $table, $column) = @_;
update document
yuki-kimoto authored on 2009-10-27
796
            if (ref $value eq 'Time::Piece') {
cleanup
yuki-kimoto authored on 2009-10-30
797
                return $dbi->filters->{datetime_to_string}->($value);
update document
yuki-kimoto authored on 2009-10-27
798
            }
799
            else {
cleanup
yuki-kimoto authored on 2009-10-30
800
                return $dbi->filters->{decode_utf8}->($value);
update document
yuki-kimoto authored on 2009-10-27
801
            }
802
        },
803
        
804
        encode_utf8 => sub {
cleanup
yuki-kimoto authored on 2009-10-30
805
            my ($key, $value) = @_;
update document
yuki-kimoto authored on 2009-10-27
806
            return Encode::encode('UTF-8', $value);
807
        },
808
        string_to_datetime => sub {
cleanup
yuki-kimoto authored on 2009-10-30
809
            my ($key, $value) = @_;
update document
yuki-kimoto authored on 2009-10-27
810
            return DateTime::Format::MySQL->parse_datetime($value);
811
        },
812
        default_fetch_filter => sub {
cleanup
yuki-kimoto authored on 2009-10-30
813
            my ($key, $value, $type, $sth, $i) = @_;
update document
yuki-kimoto authored on 2009-10-27
814
            if ($type eq 'DATETIME') {
cleanup
yuki-kimoto authored on 2009-10-30
815
                return $dbi->filters->{string_to_datetime}->($value);
update document
yuki-kimoto authored on 2009-10-27
816
            }
817
            else {
cleanup
yuki-kimoto authored on 2009-10-30
818
                return $dbi->filters->{encode_utf8}->($value);
update document
yuki-kimoto authored on 2009-10-27
819
            }
820
        }
821
    );
822

            
823
add_filter add filter to filters
add tests
yuki-kimoto authored on 2009-10-18
824

            
cleanup
yuki-kimoto authored on 2009-10-29
825
=head2 create_query
826
    
827
    # Create Query object from SQL template
828
    my $query = $dbi->create_query($template);
829
    
830
=head2 execute
update document
yuki-kimoto authored on 2009-10-27
831

            
832
    # Parse SQL template and execute SQL
cleanup
yuki-kimoto authored on 2009-10-29
833
    $result = $dbi->query($query, $params);
834
    $result = $dbi->query($template, $params); # Shorcut
update document
yuki-kimoto authored on 2009-10-27
835
    
836
    # Sample
837
    $result = $dbi->query("select * from authors where {= name} && {= age}", 
838
                          {author => 'taro', age => 19});
839
    
840
    while (my @row = $result->fetch) {
841
        # do something
842
    }
843

            
844
See also L<DBI::Custom::SQL::Template>
845

            
cleanup
yuki-kimoto authored on 2009-10-22
846
=head2 run_tranzaction
first commit
yuki-kimoto authored on 2009-10-13
847

            
update document
yuki-kimoto authored on 2009-10-27
848
    # Run tranzaction
849
    $dbi->run_tranzaction(sub {
850
        # do something
851
    });
first commit
yuki-kimoto authored on 2009-10-13
852

            
update document
yuki-kimoto authored on 2009-10-27
853
If tranzaction is success, commit is execute. 
854
If tranzation is died, rollback is execute.
first commit
yuki-kimoto authored on 2009-10-13
855

            
add methods
yuki-kimoto authored on 2009-11-02
856
=head2 insert
857

            
858
    # Insert
859
    $dbi->insert($table, $insert_values);
860
    
861
    # Sample
862
    $dbi->insert('books', {title => 'Perl', author => 'Taro'});
863

            
864
=head2 update
865

            
866
    # Update
867
    $dbi->update($table, $update_values, $where);
868
    
869
    # Sample
870
    $dbi->update('books', {title => 'Perl', author => 'Taro'}, {id => 5});
871

            
872
=head2 update_all
873

            
874
    # Update all rows
875
    $dbi->update($table, $updat_values);
876

            
877
=head2 delete
878

            
879
    # Delete
880
    $dbi->delete($table, $where);
881
    
882
    # Sample
883
    $dbi->delete('Books', {id => 5});
884

            
885
=head2 delete_all
886

            
887
    # Delete all rows
888
    $dbi->delete_all($table);
889

            
890
=head2 last_insert_id
891

            
892
    # Get last insert id
893
    $last_insert_id = $dbi->last_insert_id;
894
    
895
This method is same as DBI last_insert_id;
896

            
add query cache system
yuki-kimoto authored on 2009-11-02
897
=head1 Class Accessors
898

            
899
=head2 query_cache_max
900

            
901
    # Max query cache count
902
    $class           = $class->query_cache_max($query_cache_max);
903
    $query_cache_max = $class->query_cache_max;
904
    
905
    # Sample
906
    DBI::Custom->query_cache_max(50);
907

            
add tests
yuki-kimoto authored on 2009-10-31
908
=head1 CAUTION
909

            
910
DBI::Custom have DIB object internal.
911
This module is work well in the following DBI condition.
912

            
913
    1. AutoCommit is true
914
    2. RaiseError is true
915

            
916
By default, Both AutoCommit and RaiseError is true.
917
You must not change these mode not to damage your data.
918

            
919
If you change these mode, 
920
you cannot get correct error message, 
921
or run_tranzaction may fail.
922

            
add various
yuki-kimoto authored on 2009-10-18
923
=head1 AUTHOR
first commit
yuki-kimoto authored on 2009-10-13
924

            
add various
yuki-kimoto authored on 2009-10-18
925
Yuki Kimoto, C<< <kimoto.yuki at gmail.com> >>
first commit
yuki-kimoto authored on 2009-10-13
926

            
add tests
yuki-kimoto authored on 2009-10-31
927
Github L<http://github.com/yuki-kimoto>
928

            
first commit
yuki-kimoto authored on 2009-10-13
929
=head1 COPYRIGHT & LICENSE
930

            
931
Copyright 2009 Yuki Kimoto, all rights reserved.
932

            
933
This program is free software; you can redistribute it and/or modify it
934
under the same terms as Perl itself.
935

            
936
=cut