DBIx-Custom / lib / DBIx / Custom.pm /
Newer Older
1339 lines | 33.175kb
packaging one directory
yuki-kimoto authored on 2009-11-16
1
use 5.008001;
2

            
3
package DBIx::Custom;
4
use Object::Simple;
5

            
fix timeformat tests
yuki-kimoto authored on 2009-11-23
6
our $VERSION = '0.0605';
packaging one directory
yuki-kimoto authored on 2009-11-16
7

            
8
use Carp 'croak';
9
use DBI;
10
use DBIx::Custom::Result;
11
use DBIx::Custom::SQL::Template;
12

            
13

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
14
### Accessors
packaging one directory
yuki-kimoto authored on 2009-11-16
15
sub user        : ClassObjectAttr { initialize => {clone => 'scalar'} }
16
sub password    : ClassObjectAttr { initialize => {clone => 'scalar'} }
17
sub data_source : ClassObjectAttr { initialize => {clone => 'scalar'} }
18
sub dbi_options : ClassObjectAttr { initialize => {clone => 'hash', 
19
                                                   default => sub { {} } } }
20
sub database    : ClassObjectAttr { initialize => {clone => 'scalar'} }
add port and host method
yuki-kimoto authored on 2009-11-16
21
sub host        : ClassObjectAttr { initialize => {clone => 'scalar'} }
22
sub port        : ClassObjectAttr { initialize => {clone => 'scalar'} }
packaging one directory
yuki-kimoto authored on 2009-11-16
23

            
24
sub bind_filter  : ClassObjectAttr { initialize => {clone => 'scalar'} }
25
sub fetch_filter : ClassObjectAttr { initialize => {clone => 'scalar'} }
26

            
27
sub no_bind_filters   : ClassObjectAttr { initialize => {clone => 'array'} }
28
sub no_fetch_filters  : ClassObjectAttr { initialize => {clone => 'array'} }
29

            
30
sub filters : ClassObjectAttr {
31
    type => 'hash',
32
    deref => 1,
33
    initialize => {
34
        clone   => 'hash',
35
        default => sub { {} }
36
    }
37
}
38

            
39
sub formats : ClassObjectAttr {
40
    type => 'hash',
41
    deref => 1,
42
    initialize => {
43
        clone   => 'hash',
44
        default => sub { {} }
45
    }
46
}
47

            
48
sub result_class : ClassObjectAttr {
49
    initialize => {
50
        clone   => 'scalar',
51
        default => 'DBIx::Custom::Result'
52
    }
53
}
54

            
55
sub sql_template : ClassObjectAttr {
56
    initialize => {
57
        clone   => sub {$_[0] ? $_[0]->clone : undef},
58
        default => sub {DBIx::Custom::SQL::Template->new}
59
    }
60
}
61

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
62
sub dbh : Attr {}
packaging one directory
yuki-kimoto authored on 2009-11-16
63

            
64

            
65
### Methods
66

            
67
# Add filter
68
sub add_filter {
69
    my $invocant = shift;
70
    
71
    my %old_filters = $invocant->filters;
72
    my %new_filters = ref $_[0] eq 'HASH' ? %{$_[0]} : @_;
73
    $invocant->filters(%old_filters, %new_filters);
74
    return $invocant;
75
}
76

            
77
# Add format
78
sub add_format{
79
    my $invocant = shift;
80
    
81
    my %old_formats = $invocant->formats;
82
    my %new_formats = ref $_[0] eq 'HASH' ? %{$_[0]} : @_;
83
    $invocant->formats(%old_formats, %new_formats);
84
    return $invocant;
85
}
86

            
87
# Auto commit
88
sub _auto_commit {
89
    my $self = shift;
90
    
91
    croak("Not yet connect to database") unless $self->dbh;
92
    
93
    if (@_) {
94
        $self->dbh->{AutoCommit} = $_[0];
95
        return $self;
96
    }
97
    return $self->dbh->{AutoCommit};
98
}
99

            
100
# Connect
101
sub connect {
102
    my $self = shift;
103
    my $data_source = $self->data_source;
104
    my $user        = $self->user;
105
    my $password    = $self->password;
106
    my $dbi_options  = $self->dbi_options;
107
    
108
    my $dbh = eval{DBI->connect(
109
        $data_source,
110
        $user,
111
        $password,
112
        {
113
            RaiseError => 1,
114
            PrintError => 0,
115
            AutoCommit => 1,
116
            %{$dbi_options || {} }
117
        }
118
    )};
119
    
120
    croak $@ if $@;
121
    
122
    $self->dbh($dbh);
123
    return $self;
124
}
125

            
126
# DESTROY
127
sub DESTROY {
128
    my $self = shift;
129
    $self->disconnect if $self->connected;
130
}
131

            
132
# Is connected?
133
sub connected {
134
    my $self = shift;
135
    return ref $self->{dbh} eq 'DBI::db';
136
}
137

            
138
# Disconnect
139
sub disconnect {
140
    my $self = shift;
141
    if ($self->connected) {
142
        $self->dbh->disconnect;
143
        delete $self->{dbh};
144
    }
145
}
146

            
147
# Reconnect
148
sub reconnect {
149
    my $self = shift;
150
    $self->disconnect if $self->connected;
151
    $self->connect;
152
}
153

            
154
# Prepare statement handle
155
sub prepare {
156
    my ($self, $sql) = @_;
157
    
158
    # Connect if not
159
    $self->connect unless $self->connected;
160
    
161
    # Prepare
162
    my $sth = eval{$self->dbh->prepare($sql)};
163
    
164
    # Error
165
    croak("$@<Your SQL>\n$sql") if $@;
166
    
167
    return $sth;
168
}
169

            
170
# Execute SQL directly
171
sub do{
172
    my ($self, $sql, @bind_values) = @_;
173
    
174
    # Connect if not
175
    $self->connect unless $self->connected;
176
    
177
    # Do
178
    my $ret_val = eval{$self->dbh->do($sql, @bind_values)};
179
    
180
    # Error
181
    if ($@) {
182
        my $error = $@;
183
        require Data::Dumper;
184
        
185
        my $bind_value_dump
186
          = Data::Dumper->Dump([\@bind_values], ['*bind_valuds']);
187
        
188
        croak("$error<Your SQL>\n$sql\n<Your bind values>\n$bind_value_dump\n");
189
    }
190
}
191

            
192
# Create query
193
sub create_query {
194
    my ($self, $template) = @_;
195
    my $class = ref $self;
196
    
197
    # Create query from SQL template
198
    my $sql_template = $self->sql_template;
199
    
200
    # Try to get cached query
fix timeformat tests
yuki-kimoto authored on 2009-11-23
201
    my $cached_query = $class->_query_caches->{$template};
packaging one directory
yuki-kimoto authored on 2009-11-16
202
    
203
    # Create query
fix timeformat tests
yuki-kimoto authored on 2009-11-23
204
    my $query;
205
    if ($query) {
206
        $query = $self->new(sql       => $cached_query->sql, 
207
                            key_infos => $cached_query->key_infos);
208
    }
209
    else {
packaging one directory
yuki-kimoto authored on 2009-11-16
210
        $query = eval{$sql_template->create_query($template)};
211
        croak($@) if $@;
212
        
213
        $class->_add_query_cache($template, $query);
214
    }
215
    
216
    # Connect if not
217
    $self->connect unless $self->connected;
218
    
219
    # Prepare statement handle
220
    my $sth = $self->prepare($query->{sql});
221
    
222
    # Set statement handle
223
    $query->sth($sth);
224
    
225
    # Set bind filter
226
    $query->bind_filter($self->bind_filter);
227
    
228
    # Set no filter keys when binding
229
    $query->no_bind_filters($self->no_bind_filters);
230
    
231
    # Set fetch filter
232
    $query->fetch_filter($self->fetch_filter);
233
    
234
    # Set no filter keys when fetching
235
    $query->no_fetch_filters($self->no_fetch_filters);
236
    
237
    return $query;
238
}
239

            
240
# Execute query
241
sub execute {
242
    my ($self, $query, $params)  = @_;
243
    $params ||= {};
244
    
245
    # First argument is SQL template
246
    if (!ref $query) {
247
        my $template = $query;
248
        $query = $self->create_query($template);
249
        my $query_edit_cb = $_[3];
250
        $query_edit_cb->($query) if ref $query_edit_cb eq 'CODE';
251
    }
252
    
253
    # Create bind value
254
    my $bind_values = $self->_build_bind_values($query, $params);
255
    
256
    # Execute
257
    my $sth = $query->sth;
258
    my $ret_val = eval{$sth->execute(@$bind_values)};
259
    
260
    # Execute error
261
    if (my $execute_error = $@) {
262
        require Data::Dumper;
263
        my $sql              = $query->{sql} || '';
264
        my $key_infos_dump   = Data::Dumper->Dump([$query->key_infos], ['*key_infos']);
265
        my $params_dump      = Data::Dumper->Dump([$params], ['*params']);
266
        
267
        croak("$execute_error" . 
268
              "<Your SQL>\n$sql\n" . 
269
              "<Your parameters>\n$params_dump");
270
    }
271
    
272
    # Return resultset if select statement is executed
273
    if ($sth->{NUM_OF_FIELDS}) {
274
        
275
        # Get result class
276
        my $result_class = $self->result_class;
277
        
278
        # Create result
279
        my $result = $result_class->new({
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
280
            _dbi             => $self,
packaging one directory
yuki-kimoto authored on 2009-11-16
281
            sth              => $sth,
282
            fetch_filter     => $query->fetch_filter,
283
            no_fetch_filters => $query->no_fetch_filters
284
        });
285
        return $result;
286
    }
287
    return $ret_val;
288
}
289

            
290
# Build binding values
291
sub _build_bind_values {
292
    my ($self, $query, $params) = @_;
293
    my $key_infos           = $query->key_infos;
294
    my $bind_filter         = $query->bind_filter;
295
    my $no_bind_filters_map = $query->_no_bind_filters_map || {};
296
    
297
    # binding values
298
    my @bind_values;
299
    
300
    # Create bind values
301
    KEY_INFOS :
302
    foreach my $key_info (@$key_infos) {
303
        # Set variable
304
        my $access_keys  = $key_info->{access_keys};
305
        my $original_key = $key_info->{original_key} || '';
306
        my $table        = $key_info->{table}        || '';
307
        my $column       = $key_info->{column}       || '';
308
        
309
        # Key is found?
310
        my $found;
311
        
312
        # Build bind values
313
        ACCESS_KEYS :
314
        foreach my $access_key (@$access_keys) {
315
            # Root parameter
316
            my $root_params = $params;
317
            
318
            # Search corresponding value
319
            for (my $i = 0; $i < @$access_key; $i++) {
320
                # Current key
321
                my $current_key = $access_key->[$i];
322
                
323
                # Last key
324
                if ($i == @$access_key - 1) {
325
                    # Key is array reference
326
                    if (ref $current_key eq 'ARRAY') {
327
                        # Filtering 
328
                        if ($bind_filter &&
329
                            !$no_bind_filters_map->{$original_key})
330
                        {
331
                            push @bind_values, 
332
                                 $bind_filter->($root_params->[$current_key->[0]], 
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
333
                                                $original_key, $self,
334
                                                {table => $table, column => $column});
packaging one directory
yuki-kimoto authored on 2009-11-16
335
                        }
336
                        # Not filtering
337
                        else {
338
                            push @bind_values,
339
                                 scalar $root_params->[$current_key->[0]];
340
                        }
341
                    }
342
                    # Key is string
343
                    else {
344
                        # Key is not found
345
                        next ACCESS_KEYS
346
                          unless exists $root_params->{$current_key};
347
                        
348
                        # Filtering
349
                        if ($bind_filter &&
350
                            !$no_bind_filters_map->{$original_key}) 
351
                        {
352
                            push @bind_values,
353
                                 $bind_filter->($root_params->{$current_key},
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
354
                                                $original_key, $self,
355
                                                {table => $table, column => $column});
packaging one directory
yuki-kimoto authored on 2009-11-16
356
                        }
357
                        # Not filtering
358
                        else {
359
                            push @bind_values,
360
                                 scalar $root_params->{$current_key};
361
                        }
362
                    }
363
                    
364
                    # Key is found
365
                    $found = 1;
366
                    next KEY_INFOS;
367
                }
368
                # First or middle key
369
                else {
370
                    # Key is array reference
371
                    if (ref $current_key eq 'ARRAY') {
372
                        # Go next key
373
                        $root_params = $root_params->[$current_key->[0]];
374
                    }
375
                    # Key is string
376
                    else {
377
                        # Not found
378
                        next ACCESS_KEYS
379
                          unless exists $root_params->{$current_key};
380
                        
381
                        # Go next key
382
                        $root_params = $root_params->{$current_key};
383
                    }
384
                }
385
            }
386
        }
387
        
388
        # Key is not found
389
        unless ($found) {
390
            require Data::Dumper;
391
            my $key_info_dump  = Data::Dumper->Dump([$key_info], ['*key_info']);
392
            my $params_dump    = Data::Dumper->Dump([$params], ['*params']);
393
            croak("Corresponding key is not found in your parameters\n" . 
394
                  "<Key information>\n$key_info_dump\n\n" .
395
                  "<Your parameters>\n$params_dump\n");
396
        }
397
    }
398
    return \@bind_values;
399
}
400

            
401
# Run transaction
402
sub run_transaction {
403
    my ($self, $transaction) = @_;
404
    
405
    # Check auto commit
406
    croak("AutoCommit must be true before transaction start")
407
      unless $self->_auto_commit;
408
    
409
    # Auto commit off
410
    $self->_auto_commit(0);
411
    
412
    # Run transaction
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
413
    eval {$transaction->($self)};
packaging one directory
yuki-kimoto authored on 2009-11-16
414
    
415
    # Tranzaction error
416
    my $transaction_error = $@;
417
    
418
    # Tranzaction is failed.
419
    if ($transaction_error) {
420
        # Rollback
421
        eval{$self->dbh->rollback};
422
        
423
        # Rollback error
424
        my $rollback_error = $@;
425
        
426
        # Auto commit on
427
        $self->_auto_commit(1);
428
        
429
        if ($rollback_error) {
430
            # Rollback is failed
431
            croak("${transaction_error}Rollback is failed : $rollback_error");
432
        }
433
        else {
434
            # Rollback is success
435
            croak("${transaction_error}Rollback is success");
436
        }
437
    }
438
    # Tranzaction is success
439
    else {
440
        # Commit
441
        eval{$self->dbh->commit};
442
        my $commit_error = $@;
443
        
444
        # Auto commit on
445
        $self->_auto_commit(1);
446
        
447
        # Commit is failed
448
        croak($commit_error) if $commit_error;
449
    }
450
}
451

            
452
# Get last insert id
453
sub last_insert_id {
454
    my $self = shift;
add Oracle, DB2, Pg,
yuki-kimoto authored on 2009-11-16
455
    my $class = ref $self;
456
    croak "'$class' do not suppert 'last_insert_id'";
packaging one directory
yuki-kimoto authored on 2009-11-16
457
}
458

            
459
# Insert
460
sub insert {
insert, update, delete appnd...
yuki-kimoto authored on 2009-11-16
461
    my $self             = shift;
462
    my $table            = shift || '';
463
    my $insert_params    = shift || {};
464
    my $append_statement = shift unless ref $_[0];
465
    my $query_edit_cb    = shift;
packaging one directory
yuki-kimoto authored on 2009-11-16
466
    
467
    # Insert keys
468
    my @insert_keys = keys %$insert_params;
469
    
470
    # Not exists insert keys
471
    croak("Key-value pairs for insert must be specified to 'insert' second argument")
472
      unless @insert_keys;
473
    
474
    # Templte for insert
475
    my $template = "insert into $table {insert " . join(' ', @insert_keys) . '}';
insert, update, delete appnd...
yuki-kimoto authored on 2009-11-16
476
    $template .= " $append_statement" if $append_statement;
packaging one directory
yuki-kimoto authored on 2009-11-16
477
    # Create query
478
    my $query = $self->create_query($template);
479
    
480
    # Query edit callback must be code reference
481
    croak("Query edit callback must be code reference")
482
      if $query_edit_cb && ref $query_edit_cb ne 'CODE';
483
    
484
    # Query edit if need
485
    $query_edit_cb->($query) if $query_edit_cb;
486
    
487
    # Execute query
488
    my $ret_val = $self->execute($query, $insert_params);
489
    
490
    return $ret_val;
491
}
492

            
493
# Update
494
sub update {
insert, update, delete appnd...
yuki-kimoto authored on 2009-11-16
495
    my $self             = shift;
496
    my $table            = shift || '';
497
    my $update_params    = shift || {};
498
    my $where_params     = shift || {};
499
    my $append_statement = shift unless ref $_[0];
500
    my $query_edit_cb    = shift;
501
    my $options          = shift;
packaging one directory
yuki-kimoto authored on 2009-11-16
502
    
503
    # Update keys
504
    my @update_keys = keys %$update_params;
505
    
506
    # Not exists update kyes
507
    croak("Key-value pairs for update must be specified to 'update' second argument")
508
      unless @update_keys;
509
    
510
    # Where keys
511
    my @where_keys = keys %$where_params;
512
    
513
    # Not exists where keys
514
    croak("Key-value pairs for where clause must be specified to 'update' third argument")
515
      if !@where_keys && !$options->{allow_update_all};
516
    
517
    # Update clause
518
    my $update_clause = '{update ' . join(' ', @update_keys) . '}';
519
    
520
    # Where clause
521
    my $where_clause = '';
522
    if (@where_keys) {
523
        $where_clause = 'where ';
524
        foreach my $where_key (@where_keys) {
525
            $where_clause .= "{= $where_key} and ";
526
        }
527
        $where_clause =~ s/ and $//;
528
    }
529
    
530
    # Template for update
531
    my $template = "update $table $update_clause $where_clause";
insert, update, delete appnd...
yuki-kimoto authored on 2009-11-16
532
    $template .= " $append_statement" if $append_statement;
packaging one directory
yuki-kimoto authored on 2009-11-16
533
    
534
    # Create query
535
    my $query = $self->create_query($template);
536
    
537
    # Query edit callback must be code reference
538
    croak("Query edit callback must be code reference")
539
      if $query_edit_cb && ref $query_edit_cb ne 'CODE';
540
    
541
    # Query edit if need
542
    $query_edit_cb->($query) if $query_edit_cb;
543
    
544
    # Rearrange parammeters
545
    my $params = {'#update' => $update_params, %$where_params};
546
    
547
    # Execute query
548
    my $ret_val = $self->execute($query, $params);
549
    
550
    return $ret_val;
551
}
552

            
553
# Update all rows
554
sub update_all {
insert, update, delete appnd...
yuki-kimoto authored on 2009-11-16
555
    my $self             = shift;
556
    my $table            = shift || '';
557
    my $update_params    = shift || {};
558
    my $append_statement = shift unless ref $_[0];
559
    my $query_edit_cb    = shift;
560
    my $options          = {allow_update_all => 1};
561
    
562
    return $self->update($table, $update_params, {}, $append_statement,
563
                         $query_edit_cb, $options);
packaging one directory
yuki-kimoto authored on 2009-11-16
564
}
565

            
566
# Delete
567
sub delete {
insert, update, delete appnd...
yuki-kimoto authored on 2009-11-16
568
    my $self             = shift;
569
    my $table            = shift || '';
570
    my $where_params     = shift || {};
571
    my $append_statement = shift unless ref $_[0];
572
    my $query_edit_cb    = shift;
573
    my $options          = shift;
packaging one directory
yuki-kimoto authored on 2009-11-16
574
    
575
    # Where keys
576
    my @where_keys = keys %$where_params;
577
    
578
    # Not exists where keys
579
    croak("Key-value pairs for where clause must be specified to 'delete' second argument")
580
      if !@where_keys && !$options->{allow_delete_all};
581
    
582
    # Where clause
583
    my $where_clause = '';
584
    if (@where_keys) {
585
        $where_clause = 'where ';
586
        foreach my $where_key (@where_keys) {
587
            $where_clause .= "{= $where_key} and ";
588
        }
589
        $where_clause =~ s/ and $//;
590
    }
591
    
592
    # Template for delete
593
    my $template = "delete from $table $where_clause";
insert, update, delete appnd...
yuki-kimoto authored on 2009-11-16
594
    $template .= " $append_statement" if $append_statement;
packaging one directory
yuki-kimoto authored on 2009-11-16
595
    
596
    # Create query
597
    my $query = $self->create_query($template);
598
    
599
    # Query edit callback must be code reference
600
    croak("Query edit callback must be code reference")
601
      if $query_edit_cb && ref $query_edit_cb ne 'CODE';
602
    
603
    # Query edit if need
604
    $query_edit_cb->($query) if $query_edit_cb;
605
    
606
    # Execute query
607
    my $ret_val = $self->execute($query, $where_params);
608
    
609
    return $ret_val;
610
}
611

            
612
# Delete all rows
613
sub delete_all {
insert, update, delete appnd...
yuki-kimoto authored on 2009-11-16
614
    my $self             = shift;
615
    my $table            = shift || '';
616
    my $append_statement = shift unless ref $_[0];
617
    my $query_edit_cb    = shift;
618
    my $options          = {allow_delete_all => 1};
619
    
620
    return $self->delete($table, {}, $append_statement, $query_edit_cb,
621
                         $options);
packaging one directory
yuki-kimoto authored on 2009-11-16
622
}
623

            
624
sub _select_usage { return << 'EOS' }
625
Your select arguments is wrong.
626
select usage:
627
$dbi->select(
628
    $table,                # must be string or array ref
629
    [@$columns],           # must be array reference. this is optional
630
    {%$where_params},      # must be hash reference.  this is optional
631
    $append_statement,     # must be string.          this is optional
632
    $query_edit_callback   # must be code reference.  this is optional
633
);
634
EOS
635

            
636
sub select {
637
    my $self = shift;
638
    
639
    # Check argument
640
    croak($self->_select_usage) unless @_;
641
    
642
    # Arguments
643
    my $tables = shift || '';
644
    $tables    = [$tables] unless ref $tables;
645
    
646
    my $columns          = ref $_[0] eq 'ARRAY' ? shift : [];
647
    my $where_params     = ref $_[0] eq 'HASH'  ? shift : {};
648
    my $append_statement = $_[0] && !ref $_[0]  ? shift : '';
649
    my $query_edit_cb    = shift if ref $_[0] eq 'CODE';
650
    
651
    # Check rest argument
652
    croak($self->_select_usage) if @_;
653
    
654
    # SQL template for select statement
655
    my $template = 'select ';
656
    
657
    # Join column clause
658
    if (@$columns) {
659
        foreach my $column (@$columns) {
660
            $template .= "$column, ";
661
        }
662
        $template =~ s/, $/ /;
663
    }
664
    else {
665
        $template .= '* ';
666
    }
667
    
668
    # Join table
669
    $template .= 'from ';
670
    foreach my $table (@$tables) {
671
        $template .= "$table, ";
672
    }
673
    $template =~ s/, $/ /;
674
    
675
    # Where clause keys
676
    my @where_keys = keys %$where_params;
677
    
678
    # Join where clause
679
    if (@where_keys) {
680
        $template .= 'where ';
681
        foreach my $where_key (@where_keys) {
682
            $template .= "{= $where_key} and ";
683
        }
684
    }
685
    $template =~ s/ and $//;
686
    
687
    # Append something to last of statement
688
    if ($append_statement =~ s/^where //) {
689
        if (@where_keys) {
690
            $template .= " and $append_statement";
691
        }
692
        else {
693
            $template .= " where $append_statement";
694
        }
695
    }
696
    else {
697
        $template .= " $append_statement";
698
    }
699
    
700
    # Create query
701
    my $query = $self->create_query($template);
702
    
703
    # Query edit
704
    $query_edit_cb->($query) if $query_edit_cb;
705
    
706
    # Execute query
707
    my $result = $self->execute($query, $where_params);
708
    
709
    return $result;
710
}
711

            
712
sub _query_caches     : ClassAttr { type => 'hash',
713
                                    auto_build => sub {shift->_query_caches({}) } }
714
                                    
715
sub _query_cache_keys : ClassAttr { type => 'array',
716
                                    auto_build => sub {shift->_query_cache_keys([])} }
717
                                    
718
sub query_cache_max   : ClassAttr { auto_build => sub {shift->query_cache_max(50)} }
719

            
720
# Add query cahce
721
sub _add_query_cache {
722
    my ($class, $template, $query) = @_;
723
    my $query_cache_keys = $class->_query_cache_keys;
724
    my $query_caches     = $class->_query_caches;
725
    
726
    return $class if $query_caches->{$template};
727
    
728
    $query_caches->{$template} = $query;
729
    push @$query_cache_keys, $template;
730
    
731
    my $overflow = @$query_cache_keys - $class->query_cache_max;
732
    
733
    for (my $i = 0; $i < $overflow; $i++) {
734
        my $template = shift @$query_cache_keys;
735
        delete $query_caches->{$template};
736
    }
737
    
738
    return $class;
739
}
740

            
741
# Both bind_filter and fetch_filter off
742
sub filter_off {
743
    my $self = shift;
744
    
745
    # filter off
746
    $self->bind_filter(undef);
747
    $self->fetch_filter(undef);
748
    
749
    return $self;
750
}
751

            
752
Object::Simple->build_class;
753

            
754
=head1 NAME
755

            
756
DBIx::Custom - Customizable simple DBI
757

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
758
=head1 Version
packaging one directory
yuki-kimoto authored on 2009-11-16
759

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
760
Version 0.0601
packaging one directory
yuki-kimoto authored on 2009-11-16
761

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
762
=head1 Caution
packaging one directory
yuki-kimoto authored on 2009-11-16
763

            
764
This module is now experimental stage.
765

            
766
I want you to try this module
767
because I want this module stable, and not to damage your DB data by this module bug.
768

            
769
Please tell me bug if you find
770

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
771
=head1 Synopsys
packaging one directory
yuki-kimoto authored on 2009-11-16
772

            
773
  my $dbi = DBIx::Custom->new;
774
  
775
  my $query = $dbi->create_query($template);
776
  $dbi->execute($query);
777

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
778
=head1 Accessors
packaging one directory
yuki-kimoto authored on 2009-11-16
779

            
780
=head2 user
781

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
782
Set and get database user name
783
    
784
    # For object
785
    $self  = $self->user($user);
786
    $user  = $self->user;
787
    
788
    # For class
789
    $class = $class->user($user);
790
    $user  = $class->user;
packaging one directory
yuki-kimoto authored on 2009-11-16
791
    
792
    # Sample
793
    $dbi->user('taro');
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
794
    
packaging one directory
yuki-kimoto authored on 2009-11-16
795
=head2 password
796

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
797
Set and get database password
798
    
799
    # For object
800
    $self     = $self->password($password);
801
    $password = $self->password;
802

            
803
    # For class
804
    $class    = $class->password($password);
805
    $password = $class->password;
packaging one directory
yuki-kimoto authored on 2009-11-16
806
    
807
    # Sample
808
    $dbi->password('lkj&le`@s');
809

            
810
=head2 data_source
811

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
812
Set and get database data source
813
    
814
    # For object
815
    $self        = $self->data_source($data_soruce);
816
    $data_source = $self->data_source;
817
    
818
    # For class
819
    $class       = $class->data_source($data_soruce);
820
    $data_source = $class->data_source;
packaging one directory
yuki-kimoto authored on 2009-11-16
821
    
822
    # Sample(SQLite)
823
    $dbi->data_source(dbi:SQLite:dbname=$database);
824
    
825
    # Sample(MySQL);
826
    $dbi->data_source("dbi:mysql:dbname=$database");
827
    
828
    # Sample(PostgreSQL)
829
    $dbi->data_source("dbi:Pg:dbname=$database");
830
    
831
=head2 database
832

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
833
Set and get database name
834

            
835
    # For object
836
    $self     = $self->database($database);
837
    $database = $self->database;
838

            
839
    # For class
840
    $class    = $class->database($database);
841
    $database = $class->database;
842
    
843
    # Sample
844
    $dbi->database('books');
packaging one directory
yuki-kimoto authored on 2009-11-16
845

            
add port and host method
yuki-kimoto authored on 2009-11-16
846
=head2 host
847

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
848
Set and get host name
849

            
850
    # For object
851
    $self = $self->host($host);
852
    $host = $self->host;
853

            
854
    # For class
855
    $class = $class->host($host);
856
    $host  = $class->host;
857
    
858
    # Sample
859
    $dbi->host('somehost.com');
860
    $dbi->host('127.1.2.3');
add port and host method
yuki-kimoto authored on 2009-11-16
861

            
862
=head2 port
863

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
864
Set and get port
865

            
866
    # For object
867
    $self = $self->port($port);
868
    $port = $self->port;
add port and host method
yuki-kimoto authored on 2009-11-16
869

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
870
    # For class
871
    $class = $class->port($port);
872
    $port = $class->port;
873
    
874
    # Sample
875
    $dbi->port(1198);
packaging one directory
yuki-kimoto authored on 2009-11-16
876

            
877
=head2 dbi_options
878

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
879
Set and get DBI option
packaging one directory
yuki-kimoto authored on 2009-11-16
880

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
881
    # For object
882
    $self        = $self->dbi_options({$options => $value, ...});
883
    $dbi_options = $self->dbi_options;
884
    
885
    # For class
886
    $class       = $class->dbi_options({$options => $value, ...});
887
    $dbi_options = $class->dbi_options;
888
    
packaging one directory
yuki-kimoto authored on 2009-11-16
889
    # Sample
890
    $dbi->dbi_options({PrintError => 0, RaiseError => 1});
891

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
892
=head2 sql_template
packaging one directory
yuki-kimoto authored on 2009-11-16
893

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
894
Set and get SQL::Template object
packaging one directory
yuki-kimoto authored on 2009-11-16
895

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
896
    # For object
897
    $self         = $self->sql_template($sql_template);
898
    $sql_template = $self->sql_template;
packaging one directory
yuki-kimoto authored on 2009-11-16
899

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
900
    # For class
901
    $class        = $class->sql_template($sql_template);
902
    $sql_template = $class->sql_template;
packaging one directory
yuki-kimoto authored on 2009-11-16
903

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
904
    # Sample
905
    $dbi->sql_template(DBI::Cutom::SQL::Template->new);
packaging one directory
yuki-kimoto authored on 2009-11-16
906

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
907
=head2 filters
packaging one directory
yuki-kimoto authored on 2009-11-16
908

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
909
Set and get filters
packaging one directory
yuki-kimoto authored on 2009-11-16
910

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
911
    # For object
912
    $self    = $self->filters($filters);
913
    $filters = $self->filters;
packaging one directory
yuki-kimoto authored on 2009-11-16
914

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
915
    # For class
916
    $class   = $class->filters($filters);
917
    $filters = $class->filters;
packaging one directory
yuki-kimoto authored on 2009-11-16
918
    
919
    # Sample
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
920
    $ret = $dbi->filters->{encode_utf8}->($value);
packaging one directory
yuki-kimoto authored on 2009-11-16
921

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
922
=head2 formats
packaging one directory
yuki-kimoto authored on 2009-11-16
923

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
924
Set and get formats
packaging one directory
yuki-kimoto authored on 2009-11-16
925

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
926
    # For object
927
    $self    = $self->formats($formats);
928
    $formats = $self->formats;
929

            
930
    # For class
931
    $self    = $self->formats($formats);
932
    $formats = $self->formats;
933

            
934
    # Sample
935
    $datetime_format = $dbi->formats->{datetime};
packaging one directory
yuki-kimoto authored on 2009-11-16
936

            
937
=head2 bind_filter
938

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
939
Set and get binding filter
packaging one directory
yuki-kimoto authored on 2009-11-16
940

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
941
    # For object
942
    $self        = $self->bind_filter($bind_filter);
943
    $bind_filter = $self->bind_filter
packaging one directory
yuki-kimoto authored on 2009-11-16
944

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
945
    # For object
946
    $class       = $class->bind_filter($bind_filter);
947
    $bind_filter = $class->bind_filter
948

            
949
    # Sample
950
    $dbi->bind_filter(sub {
951
        my ($value, $key, $dbi, $infos) = @_;
952
        
953
        # edit $value
954
        
955
        return $value;
956
    });
packaging one directory
yuki-kimoto authored on 2009-11-16
957

            
958
=head2 fetch_filter
959

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
960
Set and get Fetch filter
961

            
962
    # For object
963
    $self         = $self->fetch_filter($fetch_filter);
964
    $fetch_filter = $self->fetch_filter;
965

            
966
    # For class
967
    $class        = $class->fetch_filter($fetch_filter);
968
    $fetch_filter = $class->fetch_filter;
packaging one directory
yuki-kimoto authored on 2009-11-16
969

            
970
    # Sample
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
971
    $dbi->fetch_filter(sub {
972
        my ($value, $key, $dbi, $infos) = @_;
973
        
974
        # edit $value
975
        
976
        return $value;
977
    });
packaging one directory
yuki-kimoto authored on 2009-11-16
978

            
979
=head2 no_bind_filters
980

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
981
Set and get no filter keys when binding
982
    
983
    # For object
984
    $self            = $self->no_bind_filters($no_bind_filters);
985
    $no_bind_filters = $self->no_bind_filters;
986

            
987
    # For class
988
    $class           = $class->no_bind_filters($no_bind_filters);
989
    $no_bind_filters = $class->no_bind_filters;
990

            
991
    # Sample
992
    $dbi->no_bind_filters(qw/title author/);
packaging one directory
yuki-kimoto authored on 2009-11-16
993

            
994
=head2 no_fetch_filters
995

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
996
Set and get no filter keys when fetching
997

            
998
    # For object
999
    $self             = $self->no_fetch_filters($no_fetch_filters);
1000
    $no_fetch_filters = $self->no_fetch_filters;
1001

            
1002
    # For class
1003
    $class            = $class->no_fetch_filters($no_fetch_filters);
1004
    $no_fetch_filters = $class->no_fetch_filters;
1005

            
1006
    # Sample
1007
    $dbi->no_fetch_filters(qw/title author/);
packaging one directory
yuki-kimoto authored on 2009-11-16
1008

            
1009
=head2 result_class
1010

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1011
Set and get resultset class
1012

            
1013
    # For object
packaging one directory
yuki-kimoto authored on 2009-11-16
1014
    $self         = $dbi->result_class($result_class);
1015
    $result_class = $dbi->result_class;
1016
    
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1017
    # For class
1018
    $class        = $class->result_class($result_class);
1019
    $result_class = $class->result_class;
1020
    
packaging one directory
yuki-kimoto authored on 2009-11-16
1021
    # Sample
1022
    $dbi->result_class('DBIx::Custom::Result');
1023

            
1024
=head2 dbh
1025

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1026
Get database handle
1027
    
1028
    $self = $self->dbh($dbh);
1029
    $dbh  = $self->dbh;
1030
    
1031
    # Sample
1032
    $table_info = $dbi->dbh->table_info
1033
    
1034
=head2 query_cache_max
1035

            
1036
Set and get query cache max
1037

            
1038
    $class           = $class->query_cache_max($query_cache_max);
1039
    $query_cache_max = $class->query_cache_max;
1040
    
1041
    # Sample
1042
    DBIx::Custom->query_cache_max(50);
packaging one directory
yuki-kimoto authored on 2009-11-16
1043

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1044
DBIx::Custom cache queries for performance.
1045

            
1046
Default is 50
1047

            
1048
=head1 Methods
packaging one directory
yuki-kimoto authored on 2009-11-16
1049

            
1050
=head2 connect
1051

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1052
Connect to database
1053

            
packaging one directory
yuki-kimoto authored on 2009-11-16
1054
    $self = $dbi->connect;
1055
    
1056
    # Sample
1057
    $dbi = DBIx::Custom->new(user => 'taro', password => 'lji8(', 
1058
                            data_soruce => "dbi:mysql:dbname=$database");
1059
    $dbi->connect;
1060

            
1061
=head2 disconnect
1062

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1063
Disconnect database
1064

            
1065
    $self = $dbi->disconnect;
1066
    
1067
    # Sample
packaging one directory
yuki-kimoto authored on 2009-11-16
1068
    $dbi->disconnect;
1069

            
1070
If database is already disconnected, this method do noting.
1071

            
1072
=head2 reconnect
1073

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1074
Reconnect to database
1075

            
1076
    $self = $dbi->reconnect;
1077
    
1078
    # Sample
packaging one directory
yuki-kimoto authored on 2009-11-16
1079
    $dbi->reconnect;
1080

            
1081
=head2 connected
1082

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1083
Check connected
1084
    
1085
    $is_connected = $self->connected;
1086
    
1087
    # Sample
1088
    if ($dbi->connected) { # do something }
packaging one directory
yuki-kimoto authored on 2009-11-16
1089
    
1090
=head2 filter_off
1091

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1092
bind_filter and fitch_filter off
1093
    
1094
    $self = $self->filter_off
1095
    
1096
    # Sample
1097
    $dbi->filter_off;
packaging one directory
yuki-kimoto authored on 2009-11-16
1098
    
1099
This is equeal to
1100
    
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1101
    $dbi->bind_filter(undef);
1102
    $dbi->fetch_filter(undef);
packaging one directory
yuki-kimoto authored on 2009-11-16
1103

            
1104
=head2 add_filter
1105

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1106
Resist filter
packaging one directory
yuki-kimoto authored on 2009-11-16
1107
    
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1108
    $self = $self->add_filter({$name => $filter, ...});
1109
    # or
1110
    $self = $self->add_filter($name => $filter, ...);
1111
    
1112
    # Sample (For example DBIx::Custom::Basic)
packaging one directory
yuki-kimoto authored on 2009-11-16
1113
    $dbi->add_filter(
1114
        encode_utf8 => sub {
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1115
            my ($value, $key, $dbi, $infos) = @_;
1116
            utf8::upgrade($value) unless Encode::is_utf8($value);
1117
            return encode('UTF-8', $value);
packaging one directory
yuki-kimoto authored on 2009-11-16
1118
        },
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1119
        decode_utf8 => sub {
1120
            my ($value, $key, $dbi, $infos) = @_;
1121
            return decode('UTF-8', $value)
packaging one directory
yuki-kimoto authored on 2009-11-16
1122
        }
1123
    );
1124

            
1125
=head2 add_format
1126

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1127
Resist format
1128

            
1129
    $self = $self->add_format({$name => $format, ...});
1130
    # or
1131
    $self = $self->add_format($name => $format, ...);
1132
    
1133
    # Sample
1134
    $dbi->add_format(date => '%Y:%m:%d', datetime => '%Y-%m-%d %H:%M:%S');
1135

            
1136
=head2 prepare
1137

            
1138
Prepare statement handle
1139

            
1140
    $sth = $self->prepare($sql);
1141
    
1142
    # Sample
1143
    $sth = $dbi->prepare('select * from books;');
1144

            
1145
This method is same as DBI prepare method.
1146

            
1147
=head2 do
1148

            
1149
Execute SQL
1150

            
1151
    $ret_val = $self->do($sql, @bind_values);
1152
    
1153
    # Sample
1154
    $ret_val = $dbi->do('insert into books (title, author) values (?, ?)',
1155
                        'Perl', 'taro');
1156

            
1157
This method is same as DBI do method.
packaging one directory
yuki-kimoto authored on 2009-11-16
1158

            
1159
=head2 create_query
1160
    
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1161
Create Query object from SQL template
1162

            
packaging one directory
yuki-kimoto authored on 2009-11-16
1163
    my $query = $dbi->create_query($template);
1164
    
1165
=head2 execute
1166

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1167
Parse SQL template and execute SQL
1168

            
packaging one directory
yuki-kimoto authored on 2009-11-16
1169
    $result = $dbi->query($query, $params);
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1170
    $result = $dbi->query($template, $params); # Shortcut
packaging one directory
yuki-kimoto authored on 2009-11-16
1171
    
1172
    # Sample
1173
    $result = $dbi->query("select * from authors where {= name} and {= age}", 
1174
                          {author => 'taro', age => 19});
1175
    
1176
    while (my @row = $result->fetch) {
1177
        # do something
1178
    }
1179

            
1180
See also L<DBIx::Custom::SQL::Template>
1181

            
1182
=head2 run_transaction
1183

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1184
Run transaction
1185

            
packaging one directory
yuki-kimoto authored on 2009-11-16
1186
    $dbi->run_transaction(sub {
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1187
        my $dbi = shift;
1188
        
packaging one directory
yuki-kimoto authored on 2009-11-16
1189
        # do something
1190
    });
1191

            
1192
If transaction is success, commit is execute. 
1193
If tranzation is died, rollback is execute.
1194

            
1195
=head2 insert
1196

            
update document
yuki-kimoto authored on 2009-11-19
1197
Insert row
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1198

            
update document
yuki-kimoto authored on 2009-11-19
1199
    $ret_val = $self->insert($table, \%$insert_params);
1200

            
1201
$ret_val is maybe affected rows count
packaging one directory
yuki-kimoto authored on 2009-11-16
1202
    
1203
    # Sample
1204
    $dbi->insert('books', {title => 'Perl', author => 'Taro'});
1205

            
1206
=head2 update
1207

            
update document
yuki-kimoto authored on 2009-11-19
1208
Update rows
1209

            
1210
    $self = $self->update($table, \%update_params, \%where);
1211

            
1212
$ret_val is maybe affected rows count
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1213

            
packaging one directory
yuki-kimoto authored on 2009-11-16
1214
    # Sample
1215
    $dbi->update('books', {title => 'Perl', author => 'Taro'}, {id => 5});
1216

            
1217
=head2 update_all
1218

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1219
Update all rows
1220

            
update document
yuki-kimoto authored on 2009-11-19
1221
    $ret_val = $self->update_all($table, \%updat_params);
1222

            
1223
$ret_val is maybe affected rows count
1224

            
1225
    # Sample
1226
    $dbi->update_all('books', {author => 'taro'});
packaging one directory
yuki-kimoto authored on 2009-11-16
1227

            
1228
=head2 delete
1229

            
update document
yuki-kimoto authored on 2009-11-19
1230
Delete rows
1231

            
1232
    $ret_val = $self->delete($table, \%where);
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1233

            
update document
yuki-kimoto authored on 2009-11-19
1234
$ret_val is maybe affected rows count
packaging one directory
yuki-kimoto authored on 2009-11-16
1235
    
1236
    # Sample
update document
yuki-kimoto authored on 2009-11-19
1237
    $dbi->delete('books', {id => 5});
packaging one directory
yuki-kimoto authored on 2009-11-16
1238

            
1239
=head2 delete_all
1240

            
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1241
Delete all rows
1242

            
update document
yuki-kimoto authored on 2009-11-19
1243
    $ret_val = $self->delete_all($table);
packaging one directory
yuki-kimoto authored on 2009-11-16
1244

            
update document
yuki-kimoto authored on 2009-11-19
1245
$ret_val is maybe affected rows count
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1246

            
update document
yuki-kimoto authored on 2009-11-19
1247
    # Sample
1248
    $dib->delete_all('books');
packaging one directory
yuki-kimoto authored on 2009-11-16
1249

            
1250
=head2 select
1251
    
update document
yuki-kimoto authored on 2009-11-19
1252
Select rows
bind_filter argument is chan...
yuki-kimoto authored on 2009-11-19
1253

            
update document
yuki-kimoto authored on 2009-11-19
1254
    $resut = $self->select(
packaging one directory
yuki-kimoto authored on 2009-11-16
1255
        $table,                # must be string or array;
update document
yuki-kimoto authored on 2009-11-19
1256
        \@$columns,            # must be array reference. this is optional
1257
        \%$where_params,       # must be hash reference.  this is optional
packaging one directory
yuki-kimoto authored on 2009-11-16
1258
        $append_statement,     # must be string.          this is optional
1259
        $query_edit_callback   # must be code reference.  this is optional
1260
    );
update document
yuki-kimoto authored on 2009-11-19
1261

            
1262
$reslt is L<DBI::Custom::Result> object
1263

            
1264
The following is some select samples
1265

            
1266
    # select * from books;
1267
    $result = $dbi->select('books');
packaging one directory
yuki-kimoto authored on 2009-11-16
1268
    
update document
yuki-kimoto authored on 2009-11-19
1269
    # select * from books where title = 'Perl';
1270
    $result = $dbi->select('books', {title => 1});
1271
    
1272
    # select title, author from books where id = 1 for update;
1273
    $result = $dbi->select(
1274
        'books',              # table
1275
        ['title', 'author'],  # columns
1276
        {id => 1},            # where clause
1277
        'for update',         # append statement
1278
    );
1279

            
1280
You can join multi tables
1281
    
1282
    $result = $dbi->select(
1283
        ['table1', 'table2'],                # tables
1284
        ['table1.id as table1_id', 'title'], # columns (alias is ok)
1285
        {table1.id => 1},                    # where clase
1286
        "where table1.id = table2.id",       # join clause (must start 'where')
1287
    );
1288

            
1289
You can also edit query
1290
        
packaging one directory
yuki-kimoto authored on 2009-11-16
1291
    $dbi->select(
update document
yuki-kimoto authored on 2009-11-19
1292
        'books',
1293
        # column, where clause, append statement,
packaging one directory
yuki-kimoto authored on 2009-11-16
1294
        sub {
1295
            my $query = shift;
1296
            $query->bind_filter(sub {
1297
                # ...
1298
            });
1299
        }
update document
yuki-kimoto authored on 2009-11-19
1300
    }
1301

            
1302

            
1303
=head2 last_insert_id
1304

            
1305
Get last insert id
packaging one directory
yuki-kimoto authored on 2009-11-16
1306

            
update document
yuki-kimoto authored on 2009-11-19
1307
    $last_insert_id = $dbi->last_insert_id;
packaging one directory
yuki-kimoto authored on 2009-11-16
1308

            
update document
yuki-kimoto authored on 2009-11-19
1309
This method is implemented by subclass.
1310

            
1311
=head1 Caution
packaging one directory
yuki-kimoto authored on 2009-11-16
1312

            
update document
yuki-kimoto authored on 2009-11-19
1313
DBIx::Custom have DBI object.
packaging one directory
yuki-kimoto authored on 2009-11-16
1314
This module is work well in the following DBI condition.
1315

            
1316
    1. AutoCommit is true
1317
    2. RaiseError is true
1318

            
1319
By default, Both AutoCommit and RaiseError is true.
1320
You must not change these mode not to damage your data.
1321

            
1322
If you change these mode, 
1323
you cannot get correct error message, 
1324
or run_transaction may fail.
1325

            
1326
=head1 AUTHOR
1327

            
1328
Yuki Kimoto, C<< <kimoto.yuki at gmail.com> >>
1329

            
1330
Github L<http://github.com/yuki-kimoto>
1331

            
1332
=head1 COPYRIGHT & LICENSE
1333

            
1334
Copyright 2009 Yuki Kimoto, all rights reserved.
1335

            
1336
This program is free software; you can redistribute it and/or modify it
1337
under the same terms as Perl itself.
1338

            
1339
=cut