Newer Older
2809 lines | 70.59kb
added Next version
Yuki Kimoto authored on 2011-11-16
1
package DBIx::Custom::Next;
2
use Object::Simple -base;
3

            
4
our $VERSION = '0.20_01';
5
$VERSION = eval $VERSION;
6
use 5.008001;
7

            
8
use Carp 'croak';
9
use DBI;
10
use DBIx::Custom::Next::Result;
11
use DBIx::Custom::Next::Where;
12
use DBIx::Custom::Next::Model;
13
use DBIx::Custom::Next::Order;
14
use DBIx::Custom::Next::Util qw/_array_to_hash _subname/;
15
use DBIx::Custom::Next::Mapper;
16
use DBIx::Custom::Next::NotExists;
17
use Encode qw/encode encode_utf8 decode_utf8/;
18
use Scalar::Util qw/weaken/;
19

            
20
has [qw/connector dsn password quote user exclude_table user_table_info
21
        user_column_info/],
22
    option => sub { {} },
23
    default_option => sub {
24
        {
25
            RaiseError => 1,
26
            PrintError => 0,
27
            AutoCommit => 1
28
        }
29
    },
30
    filters => sub {
31
        {
32
            encode_utf8 => sub { encode_utf8($_[0]) },
33
            decode_utf8 => sub { decode_utf8($_[0]) }
34
        }
35
    },
36
    last_sql => '',
37
    models => sub { {} },
38
    now => sub {
39
        sub {
40
            my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
41
            $mon++;
42
            $year += 1900;
43
            my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d",
44
              $year, $mon, $mday, $hour, $min, $sec);
45
            return $now;
46
        }
47
    },
48
    result_class  => 'DBIx::Custom::Next::Result',
49
    safety_character => '\w',
50
    separator => '.',
51
    stash => sub { {} };
52

            
53
sub available_datatype {
54
    my $self = shift;
55
    
56
    my $data_types = '';
57
    for my $i (-1000 .. 1000) {
58
         my $type_info = $self->dbh->type_info($i);
59
         my $data_type = $type_info->{DATA_TYPE};
60
         my $type_name = $type_info->{TYPE_NAME};
61
         $data_types .= "$data_type ($type_name)\n"
62
           if defined $data_type;
63
    }
64
    return "Data Type maybe equal to Type Name" unless $data_types;
65
    $data_types = "Data Type (Type name)\n" . $data_types;
66
    return $data_types;
67
}
68

            
69
sub available_typename {
70
    my $self = shift;
71
    
72
    # Type Names
73
    my $type_names = {};
74
    $self->each_column(sub {
75
        my ($self, $table, $column, $column_info) = @_;
76
        $type_names->{$column_info->{TYPE_NAME}} = 1
77
          if $column_info->{TYPE_NAME};
78
    });
79
    my @output = sort keys %$type_names;
80
    unshift @output, "Type Name";
81
    return join "\n", @output;
82
}
83

            
84
our $AUTOLOAD;
85
sub AUTOLOAD {
86
    my $self = shift;
87

            
88
    # Method name
89
    my ($package, $mname) = $AUTOLOAD =~ /^([\w\:]+)\:\:(\w+)$/;
90

            
91
    # Call method
92
    $self->{_methods} ||= {};
93
    if (my $method = $self->{_methods}->{$mname}) {
94
        return $self->$method(@_)
95
    }
96
    elsif ($self->{dbh} && (my $dbh_method = $self->dbh->can($mname))) {
97
        $self->dbh->$dbh_method(@_);
98
    }
99
    else {
100
        croak qq{Can't locate object method "$mname" via "$package" }
101
            . _subname;
102
    }
103
}
104

            
105
sub assign_clause {
106
    my ($self, $param, $opts) = @_;
107
    
108
    my $wrap = $opts->{wrap} || {};
109
    my ($q, $p) = split //, $self->q('');
110
    
111
    # Assign clause (performance is important)
112
    join(
113
      ', ',
114
      map {
115
          ref $param->{$_} eq 'SCALAR' ? "$q$_$p = " . ${$param->{$_}}
116
          : $wrap->{$_} ? "$q$_$p = " . $wrap->{$_}->(":$_")
117
          : "$q$_$p = :$_";
118
      } sort keys %$param
119
    );
120
}
121

            
122
sub column {
123
    my $self = shift;
124
    my $option = pop if ref $_[-1] eq 'HASH';
125
    my $real_table = shift;
126
    my $columns = shift;
127
    my $table = $option->{alias} || $real_table;
128
    
129
    # Columns
130
    unless (defined $columns) {
131
        $columns ||= $self->model($real_table)->columns;
132
    }
133
    
134
    # Separator
135
    my $separator = $self->separator;
136
    
137
    # Column clause
138
    my @column;
139
    $columns ||= [];
140
    push @column, $self->q($table) . "." . $self->q($_) .
141
      " as " . $self->q("${table}${separator}$_")
142
      for @$columns;
143
    
144
    return join (', ', @column);
145
}
146

            
147
sub connect {
148
    my $self = ref $_[0] ? shift : shift->new(@_);
149
    
150
    my $connector = $self->connector;
151
    
152
    if (!ref $connector && $connector) {
153
        require DBIx::Connector;
154
        
155
        my $dsn = $self->dsn;
156
        my $user = $self->user;
157
        my $password = $self->password;
158
        my $option = $self->option;
159
        my $connector = DBIx::Connector->new($dsn, $user, $password,
160
          {%{$self->default_option} , %$option});
161
        $self->connector($connector);
162
    }
163
    
164
    # Connect
165
    $self->dbh;
166
    
167
    return $self;
168
}
169

            
170
sub count { shift->select(column => 'count(*)', @_)->fetch_first->[0] }
171

            
172
sub dbh {
173
    my $self = shift;
174
    
175
    # Set
176
    if (@_) {
177
        $self->{dbh} = $_[0];
178
        
179
        return $self;
180
    }
181
    
182
    # Get
183
    else {
184
        # From Connction manager
185
        if (my $connector = $self->connector) {
186
            croak "connector must have dbh() method " . _subname
187
              unless ref $connector && $connector->can('dbh');
188
              
189
            $self->{dbh} = $connector->dbh;
190
        }
191
        
192
        # Connect
193
        $self->{dbh} ||= $self->_connect;
194
        
195
        # Quote
196
        unless (defined $self->quote) {
197
            my $driver = $self->_driver;
198
            my $quote =  $driver eq 'odbc' ? '[]'
199
                       : $driver eq 'ado' ? '[]'
200
                       : $driver eq 'mysql' ? '`'
201
                       : '"';
202
            $self->quote($quote);
203
        }
204
        
205
        return $self->{dbh};
206
    }
207
}
208

            
209
sub delete {
210
    my ($self, %opt) = @_;
211
    
212
    # Don't allow delete all rows
213
    croak qq{delete method where or id option must be specified } . _subname
214
      if !$opt{where} && !defined $opt{id} && !$opt{allow_delete_all};
215
    
216
    # Where
217
    my $w = $self->_where_clause_and_param($opt{where}, {},
218
      delete $opt{id}, $opt{primary_key}, $opt{table});
219

            
220
    # Delete statement
221
    my $sql = "delete ";
222
    $sql .= "$opt{prefix} " if defined $opt{prefix};
223
    $sql .= "from " . $self->q($opt{table}) . " $w->{clause} ";
224
    
225
    # Execute query
226
    $self->execute($sql, $w->{param}, %opt);
227
}
228

            
229
sub delete_all { shift->delete(@_, allow_delete_all => 1) }
230

            
231
sub DESTROY {}
232

            
233
sub create_model {
234
    my $self = shift;
235
    
236
    # Options
237
    my $opt = ref $_[0] eq 'HASH' ? $_[0] : {@_};
238
    $opt->{dbi} = $self;
239
    my $model_class = delete $opt->{model_class} || 'DBIx::Custom::Next::Model';
240
    my $model_table = delete $opt->{table};
241
    
242
    # Create model
243
    my $model = $model_class->new($opt);
244
    weaken $model->{dbi};
245
    $model->table($model_table) unless $model->table;
246
    
247
    # Set model
248
    $self->model($model->table, $model);
249
    
250
    return $self->model($model->table);
251
}
252

            
253
sub each_column {
254
    my ($self, $cb, %options) = @_;
255

            
256
    my $user_column_info = $self->user_column_info;
257
    
258
    if ($user_column_info) {
259
        $self->$cb($_->{table}, $_->{column}, $_->{info}) for @$user_column_info;
260
    }
261
    else {
262
    
263
        my $re = $self->exclude_table || $options{exclude_table};
264
        # Tables
265
        my %tables;
266
        $self->each_table(sub { $tables{$_[1]}++ });
267

            
268
        # Iterate all tables
269
        my @tables = sort keys %tables;
270
        for (my $i = 0; $i < @tables; $i++) {
271
            my $table = $tables[$i];
272
            
273
            # Iterate all columns
274
            my $sth_columns;
275
            eval {$sth_columns = $self->dbh->column_info(undef, undef, $table, '%')};
276
            next if $@;
277
            while (my $column_info = $sth_columns->fetchrow_hashref) {
278
                my $column = $column_info->{COLUMN_NAME};
279
                $self->$cb($table, $column, $column_info);
280
            }
281
        }
282
    }
283
}
284

            
285
sub each_table {
286
    my ($self, $cb, %option) = @_;
287
    
288
    my $user_table_infos = $self->user_table_info;
289
    
290
    # Iterate tables
291
    if ($user_table_infos) {
292
        $self->$cb($_->{table}, $_->{info}) for @$user_table_infos;
293
    }
294
    else {
295
        my $re = $self->exclude_table || $option{exclude};
296
        my $sth_tables = $self->dbh->table_info;
297
        while (my $table_info = $sth_tables->fetchrow_hashref) {
298
            
299
            # Table
300
            my $table = $table_info->{TABLE_NAME};
301
            next if defined $re && $table =~ /$re/;
302
            $self->$cb($table, $table_info);
303
        }
304
    }
305
}
306

            
307
sub execute {
308
    my ($self, $sql, $param, %opt) = @_;
309
    $param ||= {};
310

            
311
    my $tables = $opt{table} || [];
312
    $tables = [$tables] unless ref $tables eq 'ARRAY';
313
    
314
    # Merge second parameter
315
    my @cleanup;
316
    my $saved_param;
317
    if (ref $param eq 'ARRAY') {
318
        my $param2 = $param->[1];
319
        $param = $param->[0];
320
        for my $column (keys %$param2) {
321
            if (!exists $param->{$column}) {
322
                $param->{$column} = $param2->{$column};
323
                push @cleanup, $column;
324
            }
325
            else {
326
                delete $param->{$_} for @cleanup;
327
                @cleanup = ();
328
                $saved_param  = $param;
329
                $param = $self->merge_param($param, $param2);
330
                delete $saved_param->{$_} for (@{$opt{cleanup} || []});
331
                last;
332
            }
333
        }
334
    }
335
    
336
    # Append
337
    $sql .= " $opt{append}" if defined $opt{append};
338
    
339
    # Query
340
    my $query;
341
    $query = $opt{reuse}->{$sql} if $opt{reuse};
342
    
343
    if ($query) {
344
        # Save query
345
        $self->{last_sql} = $query->{sql};
346
    }
347
    else {
348
        
349
        my $safety = $self->{safety_character} || $self->safety_character;
350
        # Check unsafety keys
351
        unless ((join('', keys %$param) || '') =~ /^[$safety\.]+$/) {
352
            for my $column (keys %$param) {
353
                croak qq{"$column" is not safety column name } . _subname
354
                  unless $column =~ /^[$safety\.]+$/;
355
            }
356
        }
357

            
358
        # Query
359
        $query = $self->_build_query($sql);
360

            
361
        # After build sql
362
        $query->{sql} = $opt{after_build_sql}->($query->{sql})
363
          if $opt{after_build_sql};
364
            
365
        # Save sql
366
        $self->{last_sql} = $query->{sql};
367
        
368
        # Prepare statement handle
369
        my $sth;
370
        eval { $sth = $self->dbh->prepare($query->{sql}) };
371
        
372
        if ($@) {
373
            $self->_croak($@, qq{. Following SQL is executed.\n}
374
              . qq{$query->{sql}\n} . _subname);
375
        }
376
        
377
        # Set statement handle
378
        $query->{sth} = $sth;
379
        
380
        # Save query
381
        $opt{reuse}->{$sql} = $query if $opt{reuse};
382
    }
383

            
384
    # Return query
385
    if ($opt{query}) {
386
      delete $param->{$_} for (@cleanup, @{$opt{cleanup} || []});
387
      return $query;
388
    }
389
    
390
    # Tables
391
    my $main_table = @{$tables}[-1];
392
    
393
    # Type rule
394
    my $type_filters = {};
395
    my $type_rule_off = !$self->{_type_rule_is_called} || $opt{type_rule_off};
396
    unless ($type_rule_off) {
397
        my $type_rule_off_parts = {
398
            1 => $opt{type_rule1_off},
399
            2 => $opt{type_rule2_off}
400
        };
401
        for my $i (1, 2) {
402
            unless ($type_rule_off_parts->{$i}) {
403
                $type_filters->{$i} = {};
404
                my $table_alias = $opt{table_alias} || {};
405
                for my $alias (keys %$table_alias) {
406
                    my $table = $table_alias->{$alias};
407
                    
408
                    for my $column (keys %{$self->{"_into$i"}{key}{$table} || {}}) {
409
                        $type_filters->{$i}->{"$alias.$column"} = $self->{"_into$i"}{key}{$table}{$column};
410
                    }
411
                }
412
                $type_filters->{$i} = {%{$type_filters->{$i}}, %{$self->{"_into$i"}{key}{$main_table} || {}}}
413
                  if $main_table;
414
            }
415
        }
416
    }
417

            
418
    my $sth = $query->{sth};
419
    my $affected;
420
    
421
    # Execute
422
    my $bind;
423
    my $bind_types;
424
    if (!$query->{duplicate} && $type_rule_off &&
425
      !$opt{filter} && !$opt{bind_type} && !$ENV{DBIX_CUSTOM_DEBUG}) 
426
    {
427
        eval { $affected = $sth->execute(map { $param->{$_} } @{$query->{columns}}) };
428
    }
429
    else {
430
        ($bind, $bind_types) = $self->_create_bind_values($param,
431
           $query->{columns}, $opt{filter}, $type_filters, $opt{bind_type});
432
        eval {
433
            if ($opt{bind_type}) {
434
                $sth->bind_param($_ + 1, $bind->[$_],
435
                    $bind_types->[$_] ? $bind_types->[$_] : ())
436
                  for (0 .. @$bind - 1);
437
                $affected = $sth->execute;
438
            }
439
            else { $affected = $sth->execute(@$bind) }
440
        };
441
    }
442
    $self->_croak($@, qq{. Following SQL is executed.\n}
443
      . qq{$query->{sql}\n} . _subname) if $@;
444

            
445
    # Remove id from parameter
446
    delete $param->{$_} for (@cleanup, @{$opt{cleanup} || []});
447
    
448
    # DEBUG message
449
    if ($ENV{DBIX_CUSTOM_DEBUG}) {
450
        warn "SQL:\n" . $query->{sql} . "\n";
451
        my @output;
452
        for my $value (@$bind) {
453
            $value = 'undef' unless defined $value;
454
            $value = encode($ENV{DBIX_CUSTOM_DEBUG_ENCODING} || 'UTF-8', $value)
455
              if utf8::is_utf8($value);
456
            push @output, $value;
457
        }
458
        warn "Bind values: " . join(', ', @output) . "\n\n";
459
    }
460
    
461
    # Not select statement
462
    return $affected unless $sth->{NUM_OF_FIELDS};
463
    
464
    # Result
465
    return $self->result_class->new(
466
        sth => $sth,
467
        dbi => $self,
468
        type_rule => {
469
            from1 => $self->type_rule->{from1},
470
            from2 => $self->type_rule->{from2}
471
        },
472
    );
473
}
474

            
475
sub get_table_info {
476
    my ($self, %opt) = @_;
477
    
478
    my $exclude = delete $opt{exclude};
479
    croak qq/"$_" is wrong option/ for keys %opt;
480
    
481
    my $table_info = [];
482
    $self->each_table(
483
        sub { push @$table_info, {table => $_[1], info => $_[2] } },
484
        exclude => $exclude
485
    );
486
    
487
    return [sort {$a->{table} cmp $b->{table} } @$table_info];
488
}
489

            
490
sub get_column_info {
491
    my ($self, %opt) = @_;
492
    
493
    my $exclude_table = delete $opt{exclude_table};
494
    croak qq/"$_" is wrong option/ for keys %opt;
495
    
496
    my $column_info = [];
497
    $self->each_column(
498
        sub { push @$column_info, {table => $_[1], column => $_[2], info => $_[3] } },
499
        exclude_table => $exclude_table
500
    );
501
    
502
    return [
503
      sort {$a->{table} cmp $b->{table} || $a->{column} cmp $b->{column} }
504
        @$column_info];
505
}
506

            
507
sub helper {
508
    my $self = shift;
509
    
510
    # Register method
511
    my $methods = ref $_[0] eq 'HASH' ? $_[0] : {@_};
512
    $self->{_methods} = {%{$self->{_methods} || {}}, %$methods};
513
    
514
    return $self;
515
}
516

            
517
sub insert {
518
    my ($self, $param, %opt) = @_;
519
    $param ||= {};
520

            
521
    # Created time and updated time
522
    my @cleanup;
523
    if (defined $opt{created_at} || defined $opt{updated_at}) {
524
        my $now = $self->now;
525
        $now = $now->() if ref $now eq 'CODE';
526
        if (defined $opt{created_at}) {
527
            $param->{$opt{created_at}} = $now;
528
            push @cleanup, $opt{created_at};
529
        }
530
        if (defined $opt{updated_at}) {
531
            $param->{$opt{updated_at}} = $now;
532
            push @cleanup, $opt{updated_at};
533
        }
534
    }
535
    
536
    # Merge id to parameter
537
    my $id_param = {};
538
    if (defined $opt{id}) {
539
        croak "insert id option must be specified with primary_key option"
540
          unless $opt{primary_key};
541
        $opt{primary_key} = [$opt{primary_key}] unless ref $opt{primary_key};
542
        $opt{id} = [$opt{id}] unless ref $opt{id};
543
        for (my $i = 0; $i < @{$opt{id}}; $i++) {
544
           my $key = $opt{primary_key}->[$i];
545
           next if exists $param->{$key};
546
           $param->{$key} = $opt{id}->[$i];
547
           push @cleanup, $key;
548
        }
549
        delete $opt{id};
550
    }
551
    
552
    # Insert statement
553
    my $sql = "insert ";
554
    $sql .= "$opt{prefix} " if defined $opt{prefix};
555
    $sql .= "into " . $self->q($opt{table}) . " "
556
      . $self->values_clause($param, {wrap => $opt{wrap}}) . " ";
557
    
558
    # Execute query
559
    $opt{cleanup} = \@cleanup;
560
    $self->execute($sql, $param, %opt);
561
}
562

            
563
sub include_model {
564
    my ($self, $name_space, $model_infos) = @_;
565
    
566
    # Name space
567
    $name_space ||= '';
568
    
569
    # Get Model infomations
570
    unless ($model_infos) {
571

            
572
        # Load name space module
573
        croak qq{"$name_space" is invalid class name } . _subname
574
          if $name_space =~ /[^\w:]/;
575
        eval "use $name_space";
576
        croak qq{Name space module "$name_space.pm" is needed. $@ }
577
            . _subname
578
          if $@;
579
        
580
        # Search model modules
581
        my $path = $INC{"$name_space.pm"};
582
        $path =~ s/\.pm$//;
583
        opendir my $dh, $path
584
          or croak qq{Can't open directory "$path": $! } . _subname
585
        $model_infos = [];
586
        while (my $module = readdir $dh) {
587
            push @$model_infos, $module
588
              if $module =~ s/\.pm$//;
589
        }
590
        close $dh;
591
    }
592
    
593
    # Include models
594
    for my $model_info (@$model_infos) {
595
        
596
        # Load model
597
        my $model_class;
598
        my $model_table;
599
        if (ref $model_info eq 'HASH') {
600
            $model_class = $model_info->{class};
601
            $model_table = $model_info->{table};
602
            $model_table ||= $model_class;
603
        }
604
        else { $model_class = $model_table = $model_info }
605
        my $mclass = "${name_space}::$model_class";
606
        croak qq{"$mclass" is invalid class name } . _subname
607
          if $mclass =~ /[^\w:]/;
608
        unless ($mclass->can('isa')) {
609
            eval "use $mclass";
610
            croak "$@ " . _subname if $@;
611
        }
612
        
613
        # Create model
614
        my $opt = {};
615
        $opt->{model_class} = $mclass if $mclass;
616
        $opt->{table}       = $model_table if $model_table;
617
        $self->create_model($opt);
618
    }
619
    
620
    return $self;
621
}
622

            
623
sub like_value { sub { "%$_[0]%" } }
624

            
625
sub mapper {
626
    my $self = shift;
627
    return DBIx::Custom::Next::Mapper->new(@_);
628
}
629

            
630
sub merge_param {
631
    my ($self, @params) = @_;
632
    
633
    # Merge parameters
634
    my $merge = {};
635
    for my $param (@params) {
636
        for my $column (keys %$param) {
637
            my $param_is_array = ref $param->{$column} eq 'ARRAY' ? 1 : 0;
638
            
639
            if (exists $merge->{$column}) {
640
                $merge->{$column} = [$merge->{$column}]
641
                  unless ref $merge->{$column} eq 'ARRAY';
642
                push @{$merge->{$column}},
643
                  ref $param->{$column} ? @{$param->{$column}} : $param->{$column};
644
            }
645
            else {
646
                $merge->{$column} = $param->{$column};
647
            }
648
        }
649
    }
650
    
651
    return $merge;
652
}
653

            
654
sub model {
655
    my ($self, $name, $model) = @_;
656
    
657
    # Set model
658
    if ($model) {
659
        $self->models->{$name} = $model;
660
        return $self;
661
    }
662
    
663
    # Check model existance
664
    croak qq{Model "$name" is not included } . _subname
665
      unless $self->models->{$name};
666
    
667
    # Get model
668
    return $self->models->{$name};
669
}
670

            
671
sub mycolumn {
672
    my ($self, $table, $columns) = @_;
673
    
674
    # Create column clause
675
    my @column;
676
    $columns ||= [];
677
    push @column, $self->q($table) . "." . $self->q($_) .
678
      " as " . $self->q($_)
679
      for @$columns;
680
    
681
    return join (', ', @column);
682
}
683

            
684
sub new {
685
    my $self = shift->SUPER::new(@_);
686
    
687
    # Check attributes
688
    my @attrs = keys %$self;
689
    for my $attr (@attrs) {
690
        croak qq{Invalid attribute: "$attr" } . _subname
691
          unless $self->can($attr);
692
    }
693

            
694
    return $self;
695
}
696

            
697
sub not_exists { DBIx::Custom::Next::NotExists->singleton }
698

            
699
sub order {
700
    my $self = shift;
701
    return DBIx::Custom::Next::Order->new(dbi => $self, @_);
702
}
703

            
704
sub q {
705
    my ($self, $value, $quotemeta) = @_;
706
    
707
    my $quote = $self->{quote} || $self->quote || '';
708
    return "$quote$value$quote"
709
      if !$quotemeta && ($quote eq '`' || $quote eq '"');
710
    
711
    my $q = substr($quote, 0, 1) || '';
712
    my $p;
713
    if (defined $quote && length $quote > 1) {
714
        $p = substr($quote, 1, 1);
715
    }
716
    else { $p = $q }
717
    
718
    if ($quotemeta) {
719
        $q = quotemeta($q);
720
        $p = quotemeta($p);
721
    }
722
    
723
    return "$q$value$p";
724
}
725

            
726
sub register_filter {
727
    my $self = shift;
728
    
729
    # Register filter
730
    my $filters = ref $_[0] eq 'HASH' ? $_[0] : {@_};
731
    $self->filters({%{$self->filters}, %$filters});
732
    
733
    return $self;
734
}
735

            
736
sub select {
737
    my ($self, %opt) = @_;
738

            
739
    # Options
740
    my $tables = [$opt{table}];
741
    my $param = delete $opt{param} || {};
742
    
743
    # Select statement
744
    my $sql = 'select ';
745
    
746
    # Prefix
747
    $sql .= "$opt{prefix} " if defined $opt{prefix};
748
    
749
    # Column
750
    if (defined $opt{column}) {
751
        my $columns
752
          = ref $opt{column} eq 'ARRAY' ? $opt{column} : [$opt{column}];
753
        for my $column (@$columns) {
754
            $column = $self->column(%$column) if ref $column eq 'HASH';
755
            unshift @$tables, @{$self->_search_tables($column)};
756
            $sql .= "$column, ";
757
        }
758
        $sql =~ s/, $/ /;
759
    }
760
    else { $sql .= '* ' }
761
    
762
    # Table
763
    croak "select method table option must be specified " . _subname
764
      unless defined $tables->[-1];
765
    $sql .= 'from ' . $self->q($tables->[-1] || '') . ' ';
766
    $sql =~ s/, $/ /;
767

            
768
    # Add tables in parameter
769
    unshift @$tables,
770
            @{$self->_search_tables(join(' ', keys %$param) || '')};
771
    
772
    # Where
773
    my $w = $self->_where_clause_and_param($opt{where}, $param,
774
      delete $opt{id}, $opt{primary_key}, $tables->[-1]);
775
    
776
    # Add table names in where clause
777
    unshift @$tables, @{$self->_search_tables($w->{clause})};
778
    
779
    # Join statement
780
    $self->_push_join(\$sql, $opt{join}, $tables) if defined $opt{join};
781
    
782
    # Add where clause
783
    $sql .= "$w->{clause} ";
784
    
785
    # Execute query
786
    my $result = $self->execute($sql, $w->{param}, %opt);
787
    
788
    $result;
789
}
790

            
791
sub setup_model {
792
    my $self = shift;
793
    
794
    # Setup model
795
    $self->each_column(
796
        sub {
797
            my ($self, $table, $column, $column_info) = @_;
798
            if (my $model = $self->models->{$table}) {
799
                push @{$model->columns}, $column;
800
            }
801
        }
802
    );
803
    return $self;
804
}
805

            
806
sub show_datatype {
807
    my ($self, $table) = @_;
808
    croak "Table name must be specified" unless defined $table;
809
    print "$table\n";
810
    
811
    my $result = $self->select(table => $table, where => "'0' <> '0'");
812
    my $sth = $result->sth;
813

            
814
    my $columns = $sth->{NAME};
815
    my $data_types = $sth->{TYPE};
816
    
817
    for (my $i = 0; $i < @$columns; $i++) {
818
        my $column = $columns->[$i];
819
        my $data_type = lc $data_types->[$i];
820
        print "$column: $data_type\n";
821
    }
822
}
823

            
824
sub show_typename {
825
    my ($self, $t) = @_;
826
    croak "Table name must be specified" unless defined $t;
827
    print "$t\n";
828
    
829
    $self->each_column(sub {
830
        my ($self, $table, $column, $infos) = @_;
831
        return unless $table eq $t;
832
        my $typename = lc $infos->{TYPE_NAME};
833
        print "$column: $typename\n";
834
    });
835
    
836
    return $self;
837
}
838

            
839
sub show_tables {
840
    my $self = shift;
841
    
842
    my %tables;
843
    $self->each_table(sub { $tables{$_[1]}++ });
844
    print join("\n", sort keys %tables) . "\n";
845
    return $self;
846
}
847

            
848
sub type_rule {
849
    my $self = shift;
850

            
851
    $self->{_type_rule_is_called} = 1;
852
    
853
    if (@_) {
854
        my $type_rule = ref $_[0] eq 'HASH' ? $_[0] : {@_};
855
        
856
        # Into
857
        for my $i (1 .. 2) {
858
            my $into = "into$i";
859
            my $exists_into = exists $type_rule->{$into};
860
            $type_rule->{$into} = _array_to_hash($type_rule->{$into});
861
            $self->{type_rule} = $type_rule;
862
            $self->{"_$into"} = {};
863
            for my $type_name (keys %{$type_rule->{$into} || {}}) {
864
                croak qq{type name of $into section must be lower case}
865
                  if $type_name =~ /[A-Z]/;
866
            }
867
            
868
            $self->each_column(sub {
869
                my ($dbi, $table, $column, $column_info) = @_;
870
                
871
                my $type_name = lc $column_info->{TYPE_NAME};
872
                if ($type_rule->{$into} &&
873
                    (my $filter = $type_rule->{$into}->{$type_name}))
874
                {
875
                    return unless exists $type_rule->{$into}->{$type_name};
876
                    if  (defined $filter && ref $filter ne 'CODE') 
877
                    {
878
                        my $fname = $filter;
879
                        croak qq{Filter "$fname" is not registered" } . _subname
880
                          unless exists $self->filters->{$fname};
881
                        
882
                        $filter = $self->filters->{$fname};
883
                    }
884

            
885
                    $self->{"_$into"}{key}{$table}{$column} = $filter;
886
                    $self->{"_$into"}{dot}{"$table.$column"} = $filter;
887
                }
888
            });
889
        }
890

            
891
        # From
892
        for my $i (1 .. 2) {
893
            $type_rule->{"from$i"} = _array_to_hash($type_rule->{"from$i"});
894
            for my $data_type (keys %{$type_rule->{"from$i"} || {}}) {
895
                croak qq{data type of from$i section must be lower case or number}
896
                  if $data_type =~ /[A-Z]/;
897
                my $fname = $type_rule->{"from$i"}{$data_type};
898
                if (defined $fname && ref $fname ne 'CODE') {
899
                    croak qq{Filter "$fname" is not registered" } . _subname
900
                      unless exists $self->filters->{$fname};
901
                    
902
                    $type_rule->{"from$i"}{$data_type} = $self->filters->{$fname};
903
                }
904
            }
905
        }
906
        
907
        return $self;
908
    }
909
    
910
    return $self->{type_rule} || {};
911
}
912

            
913
sub update {
914
    my ($self, $param, %opt) = @_;
915
    $param ||= {};
916
    
917
    # Don't allow update all rows
918
    croak qq{update method where option must be specified } . _subname
919
      if !$opt{where} && !defined $opt{id} && !$opt{allow_update_all};
920
    
921
    # Created time and updated time
922
    my @cleanup;
923
    if (defined $opt{updated_at}) {
924
        my $now = $self->now;
925
        $now = $now->() if ref $now eq 'CODE';
926
        $param->{$opt{updated_at}} = $self->now->();
927
        push @cleanup, $opt{updated_at};
928
    }
929

            
930
    # Assign clause
931
    my $assign_clause = $self->assign_clause($param, {wrap => $opt{wrap}});
932
    
933
    # Where
934
    my $w = $self->_where_clause_and_param($opt{where}, {},
935
      delete $opt{id}, $opt{primary_key}, $opt{table});
936
    
937
    # Update statement
938
    my $sql = "update ";
939
    $sql .= "$opt{prefix} " if defined $opt{prefix};
940
    $sql .= $self->q($opt{table}) . " set $assign_clause $w->{clause} ";
941
    
942
    # Execute query
943
    $opt{cleanup} = \@cleanup;
944
    $self->execute($sql, [$param, $w->{param}], %opt);
945
}
946

            
947
sub update_all { shift->update(@_, allow_update_all => 1) };
948

            
949
sub update_or_insert {
950
    my ($self, $param, %opt) = @_;
951
    croak "update_or_insert method need primary_key and id option "
952
      unless defined $opt{id} && defined $opt{primary_key};
953
    my $statement_opt = $opt{option} || {};
954

            
955
    my $rows = $self->select(%opt, %{$statement_opt->{select} || {}})->all;
956
    if (@$rows == 0) {
957
        return $self->insert($param, %opt, %{$statement_opt->{insert} || {}});
958
    }
959
    elsif (@$rows == 1) {
960
        return $self->update($param, %opt, %{$statement_opt->{update} || {}});
961
    }
962
    else {
963
        croak "selected row must be one " . _subname;
964
    }
965
}
966

            
967
sub values_clause {
968
    my ($self, $param, $opts) = @_;
969
    
970
    my $wrap = $opts->{wrap} || {};
971
    
972
    # Create insert parameter
973
    my ($q, $p) = split //, $self->q('');
974
    
975
    # values clause(performance is important)
976
    '(' .
977
    join(
978
      ', ',
979
      map { "$q$_$p" } sort keys %$param
980
    ) .
981
    ') values (' .
982
    join(
983
      ', ',
984
      map {
985
          ref $param->{$_} eq 'SCALAR' ? ${$param->{$_}} :
986
          $wrap->{$_} ? $wrap->{$_}->(":$_") :
987
          ":$_";
988
      } sort keys %$param
989
    ) .
990
    ')'
991
}
992

            
993
sub where { DBIx::Custom::Next::Where->new(dbi => shift, @_) }
994

            
995
sub _build_query {
996
    my ($self, $sql) = @_;
997
    
998
    $sql ||= '';
999
    my $columns = [];
1000
    my %duplicate;
1001
    my $duplicate;
1002
    my $c = $self->{safety_character} || $self->safety_character;
1003
    # Parameter regex
1004
    $sql =~ s/([0-9]):/$1\\:/g;
1005
    while ($sql =~ /(^|.*?[^\\]):([$c\.]+)(?:\{(.*?)\})?(.*)/sg) {
1006
        push @$columns, $2;
1007
        $duplicate = 1 if ++$duplicate{$columns->[-1]} > 1;
1008
        $sql = defined $3 ? "$1$2 $3 ?$4" : "$1?$4";
1009
    }
1010
    $sql =~ s/\\:/:/g if index($sql, "\\:") != -1;
1011

            
1012
    # Create query
1013
    {sql => $sql, columns => $columns, duplicate => $duplicate};
1014
}
1015

            
1016
sub _create_query {
1017
    
1018
    my ($self, $source, $after_build_sql) = @_;
1019
    
1020
    # Query
1021
    my $query = $self->_build_query($source);
1022

            
1023
    # After build sql
1024
    $query->{sql} = $after_build_sql->($query->{sql}) if $after_build_sql;
1025
        
1026
    # Save sql
1027
    $self->{last_sql} = $query->{sql};
1028
    
1029
    # Prepare statement handle
1030
    my $sth;
1031
    eval { $sth = $self->dbh->prepare($query->{sql}) };
1032
    
1033
    if ($@) {
1034
        $self->_croak($@, qq{. Following SQL is executed.\n}
1035
          . qq{$query->{sql}\n} . _subname);
1036
    }
1037
    
1038
    # Set statement handle
1039
    $query->{sth} = $sth;
1040
    
1041
    return $query;
1042
}
1043

            
1044
sub _create_bind_values {
1045
    my ($self, $params, $columns, $filter, $type_filters, $bind_type) = @_;
1046
    
1047
    # Bind type
1048
    $bind_type ||= {};
1049
    $bind_type = _array_to_hash($bind_type) if ref $bind_type eq 'ARRAY';
1050

            
1051
    # Replace filter name to code
1052
    $filter ||= {};
1053
    $filter = ref $filter eq 'ARRAY' ? _array_to_hash($filter) : $filter;
1054
    for my $column (keys %$filter) {
1055
        my $name = $filter->{$column};
1056
        if (!defined $name) {
1057
            $filter->{$column} = undef;
1058
        }
1059
        elsif (ref $name ne 'CODE') {
1060
          croak qq{Filter "$name" is not registered" } . _subname
1061
            unless exists $self->filters->{$name};
1062
          $filter->{$column} = $self->filters->{$name};
1063
        }
1064
    }
1065
    
1066
    # Create bind values
1067
    my @bind;
1068
    my @types;
1069
    my %count;
1070
    my %not_exists;
1071
    for my $column (@$columns) {
1072
        
1073
        # Bind value
1074
        if(ref $params->{$column} eq 'ARRAY') {
1075
            my $i = $count{$column} || 0;
1076
            $i += $not_exists{$column} || 0;
1077
            my $found;
1078
            for (my $k = $i; $i < @{$params->{$column}}; $k++) {
1079
                if (ref $params->{$column}->[$k] eq 'DBIx::Custom::Next::NotExists') {
1080
                    $not_exists{$column}++;
1081
                }
1082
                else  {
1083
                    push @bind, $params->{$column}->[$k];
1084
                    $found = 1;
1085
                    last
1086
                }
1087
            }
1088
            next unless $found;
1089
        }
1090
        else { push @bind, $params->{$column} }
1091
        
1092
        # Filter
1093
        $bind[-1] = $filter->{$column}->($bind[-1]) if $filter->{$column};
1094
        
1095
        # Type rule
1096
        if ($self->{_type_rule_is_called}) {
1097
            my $tf1 = $self->{"_into1"}->{dot}->{$column}
1098
              || $type_filters->{1}->{$column};
1099
            $bind[-1] = $tf1->($bind[-1]) if $tf1;
1100
            my $tf2 = $self->{"_into2"}->{dot}->{$column}
1101
              || $type_filters->{2}->{$column};
1102
            $bind[-1] = $tf2->($bind[-1]) if $tf2;
1103
        }
1104
       
1105
        # Bind types
1106
        push @types, $bind_type->{$column};
1107
        
1108
        # Count up 
1109
        $count{$column}++;
1110
    }
1111
    
1112
    return (\@bind, \@types);
1113
}
1114

            
1115
sub _id_to_param {
1116
    my ($self, $id, $primary_keys, $table) = @_;
1117
    
1118
    # Check primary key
1119
    croak "primary_key option " .
1120
          "must be specified when id option is used" . _subname
1121
      unless defined $primary_keys;
1122
    $primary_keys = [$primary_keys] unless ref $primary_keys eq 'ARRAY';
1123
    
1124
    # Create parameter
1125
    my $param = {};
1126
    if (defined $id) {
1127
        $id = [$id] unless ref $id;
1128
        for(my $i = 0; $i < @$id; $i++) {
1129
           my $key = $primary_keys->[$i];
1130
           $key = "$table." . $key if $table;
1131
           $param->{$key} = $id->[$i];
1132
        }
1133
    }
1134
    
1135
    return $param;
1136
}
1137

            
1138
sub _connect {
1139
    my $self = shift;
1140
    
1141
    # Attributes
1142
    my $dsn = $self->dsn;
1143
    croak qq{"dsn" must be specified } . _subname
1144
      unless $dsn;
1145
    my $user        = $self->user;
1146
    my $password    = $self->password;
1147
    my $option = $self->option;
1148
    $option = {%{$self->default_option}, %$option};
1149
    
1150
    # Connect
1151
    my $dbh;
1152
    eval {
1153
        $dbh = DBI->connect(
1154
            $dsn,
1155
            $user,
1156
            $password,
1157
            $option
1158
        );
1159
    };
1160
    
1161
    # Connect error
1162
    croak "$@ " . _subname if $@;
1163
    
1164
    return $dbh;
1165
}
1166

            
1167
sub _croak {
1168
    my ($self, $error, $append) = @_;
1169
    
1170
    # Append
1171
    $append ||= "";
1172
    
1173
    # Verbose
1174
    if ($Carp::Verbose) { croak $error }
1175
    
1176
    # Not verbose
1177
    else {
1178
        
1179
        # Remove line and module infromation
1180
        my $at_pos = rindex($error, ' at ');
1181
        $error = substr($error, 0, $at_pos);
1182
        $error =~ s/\s+$//;
1183
        croak "$error$append";
1184
    }
1185
}
1186

            
1187
sub _driver { lc shift->{dbh}->{Driver}->{Name} }
1188

            
1189
sub _need_tables {
1190
    my ($self, $tree, $need_tables, $tables) = @_;
1191
    
1192
    # Get needed tables
1193
    for my $table (@$tables) {
1194
        if ($tree->{$table}) {
1195
            $need_tables->{$table} = 1;
1196
            $self->_need_tables($tree, $need_tables, [$tree->{$table}{parent}])
1197
        }
1198
    }
1199
}
1200

            
1201
sub _push_join {
1202
    my ($self, $sql, $join, $join_tables) = @_;
1203
    
1204
    $join = [$join] unless ref $join eq 'ARRAY';
1205
    
1206
    # No join
1207
    return unless @$join;
1208
    
1209
    # Push join clause
1210
    my $tree = {};
1211
    for (my $i = 0; $i < @$join; $i++) {
1212
        
1213
        # Arrange
1214
        my $join_clause;;
1215
        my $option;
1216
        if (ref $join->[$i] eq 'HASH') {
1217
            $join_clause = $join->[$i]->{clause};
1218
            $option = {table => $join->[$i]->{table}};
1219
        }
1220
        else {
1221
            $join_clause = $join->[$i];
1222
            $option = {};
1223
        };
1224

            
1225
        # Find tables in join clause
1226
        my $table1;
1227
        my $table2;
1228
        if (my $table = $option->{table}) {
1229
            $table1 = $table->[0];
1230
            $table2 = $table->[1];
1231
        }
1232
        else {
1233
            my $q = $self->quote || '';
1234
            my $j_clause = (split /\s+on\s+/, $join_clause)[-1];
1235
            $j_clause =~ s/'.+?'//g;
1236
            my $q_re = quotemeta($q);
1237
            $j_clause =~ s/[$q_re]//g;
1238
            
1239
            my @j_clauses = reverse split /\s(and|on)\s/, $j_clause;
1240
            my $c = $self->safety_character;
1241
            my $join_re = qr/($c+)\.$c+[^$c].*?($c+)\.$c+/sm;
1242
            for my $clause (@j_clauses) {
1243
                if ($clause =~ $join_re) {
1244
                    $table1 = $1;
1245
                    $table2 = $2;
1246
                    last;
1247
                }                
1248
            }
1249
        }
1250
        croak qq{join clause must have two table name after "on" keyword. } .
1251
              qq{"$join_clause" is passed }  . _subname
1252
          unless defined $table1 && defined $table2;
1253
        croak qq{right side table of "$join_clause" must be unique }
1254
            . _subname
1255
          if exists $tree->{$table2};
1256
        croak qq{Same table "$table1" is specified} . _subname
1257
          if $table1 eq $table2;
1258
        $tree->{$table2}
1259
          = {position => $i, parent => $table1, join => $join_clause};
1260
    }
1261
    
1262
    # Search need tables
1263
    my $need_tables = {};
1264
    $self->_need_tables($tree, $need_tables, $join_tables);
1265
    my @need_tables = sort { $tree->{$a}{position} <=> $tree->{$b}{position} }
1266
      keys %$need_tables;
1267
    
1268
    # Add join clause
1269
    $$sql .= $tree->{$_}{join} . ' ' for @need_tables;
1270
}
1271

            
1272
sub _remove_duplicate_table {
1273
    my ($self, $tables, $main_table) = @_;
1274
    
1275
    # Remove duplicate table
1276
    my %tables = map {defined $_ ? ($_ => 1) : ()} @$tables;
1277
    delete $tables{$main_table} if $main_table;
1278
    
1279
    my $new_tables = [keys %tables, $main_table ? $main_table : ()];
1280
    if (my $q = $self->quote || '') {
1281
        $q = quotemeta($q);
1282
        $_ =~ s/[$q]//g for @$new_tables;
1283
    }
1284

            
1285
    return $new_tables;
1286
}
1287

            
1288
sub _search_tables {
1289
    my ($self, $source) = @_;
1290
    
1291
    # Search tables
1292
    my $tables = [];
1293
    my $safety_character = $self->safety_character;
1294
    my $q = $self->quote;
1295
    my $quoted_safety_character_re = $self->q("?([$safety_character]+)", 1);
1296
    my $table_re = $q ? qr/(?:^|[^$safety_character])${quoted_safety_character_re}?\./
1297
                      : qr/(?:^|[^$safety_character])([$safety_character]+)\./;
1298
    while ($source =~ /$table_re/g) {
1299
        push @$tables, $1;
1300
    }
1301
    
1302
    return $tables;
1303
}
1304

            
1305
sub _where_clause_and_param {
1306
    my ($self, $where, $param, $id, $primary_key, $table) = @_;
1307

            
1308
    $where ||= {};
1309
    $where = $self->_id_to_param($id, $primary_key, $table) if defined $id;
1310
    $param ||= {};
1311
    my $w = {};
1312
    my $where_clause = '';
1313

            
1314
    my $obj;
1315
    
1316
    if (ref $where) {
1317
        if (ref $where eq 'HASH') {
1318
            my $clause = ['and'];
1319
            my $column_join = '';
1320
            for my $column (keys %$where) {
1321
                $column_join .= $column;
1322
                my $table;
1323
                my $c;
1324
                if ($column =~ /(?:(.*?)\.)?(.*)/) {
1325
                    $table = $1;
1326
                    $c = $2;
1327
                }
1328
                
1329
                my $table_quote;
1330
                $table_quote = $self->q($table) if defined $table;
1331
                my $column_quote = $self->q($c);
1332
                $column_quote = $table_quote . '.' . $column_quote
1333
                  if defined $table_quote;
1334
                push @$clause, "$column_quote = :$column";
1335
            }
1336

            
1337
            # Check unsafety column
1338
            my $safety = $self->safety_character;
1339
            unless ($column_join =~ /^[$safety\.]+$/) {
1340
                for my $column (keys %$where) {
1341
                    croak qq{"$column" is not safety column name } . _subname
1342
                      unless $column =~ /^[$safety\.]+$/;
1343
                }
1344
            }
1345
            
1346
            $obj = $self->where(clause => $clause, param => $where);
1347
        }
1348
        elsif (ref $where eq 'DBIx::Custom::Next::Where') { $obj = $where }
1349
        elsif (ref $where eq 'ARRAY') {
1350
            $obj = $self->where(clause => $where->[0], param => $where->[1]);
1351
        }
1352
        
1353
        # Check where argument
1354
        croak qq{"where" must be hash reference or DBIx::Custom::Next::Where object}
1355
            . qq{or array reference, which contains where clause and parameter}
1356
            . _subname
1357
          unless ref $obj eq 'DBIx::Custom::Next::Where';
1358

            
1359
        $w->{param} = keys %$param
1360
                    ? $self->merge_param($param, $obj->param)
1361
                    : $obj->param;
1362
        $w->{clause} = $obj->to_string;
1363
    }
1364
    elsif ($where) {
1365
        $w->{clause} = "where $where";
1366
        $w->{param} = $param;
1367
    }
1368
    
1369
    return $w;
1370
}
1371

            
1372
1;
1373

            
1374
=head1 NAME
1375

            
1376
DBIx::Custom::Next - DBI extension to execute insert, update, delete, and select easily
1377

            
1378
=head1 SYNOPSIS
1379

            
1380
    use DBIx::Custom::Next;
1381
    
1382
    # Connect
1383
    my $dbi = DBIx::Custom::Next->connect(
1384
        dsn => "dbi:mysql:database=dbname",
1385
        user => 'ken',
1386
        password => '!LFKD%$&',
1387
        option => {mysql_enable_utf8 => 1}
1388
    );
1389

            
1390
    # Insert 
1391
    $dbi->insert({title => 'Perl', author => 'Ken'}, table  => 'book');
1392
    
1393
    # Update 
1394
    $dbi->update({title => 'Perl', author => 'Ken'}, table  => 'book',
1395
      where  => {id => 5});
1396
    
1397
    # Delete
1398
    $dbi->delete(table  => 'book', where => {author => 'Ken'});
1399

            
1400
    # Select
1401
    my $result = $dbi->select(table  => 'book',
1402
      column => ['title', 'author'], where  => {author => 'Ken'});
1403

            
1404
    # Select, more complex
1405
    my $result = $dbi->select(
1406
        table  => 'book',
1407
        column => [
1408
            {book => [qw/title author/]},
1409
            {company => ['name']}
1410
        ],
1411
        where  => {'book.author' => 'Ken'},
1412
        join => ['left outer join company on book.company_id = company.id'],
1413
        append => 'order by id limit 5'
1414
    );
1415
    
1416
    # Fetch
1417
    while (my $row = $result->fetch) {
1418
        
1419
    }
1420
    
1421
    # Fetch as hash
1422
    while (my $row = $result->fetch_hash) {
1423
        
1424
    }
1425
    
1426
    # Execute SQL with parameter.
1427
    $dbi->execute(
1428
        "select id from book where author = :author and title like :title",
1429
        {author => 'ken', title => '%Perl%'}
1430
    );
1431
    
1432
=head1 DESCRIPTION
1433

            
1434
L<DBIx::Custom::Next> is L<DBI> wrapper module to execute SQL easily.
1435
This module have the following features.
1436

            
1437
=over 4
1438

            
1439
=item *
1440

            
1441
Execute C<insert>, C<update>, C<delete>, or C<select> statement easily
1442

            
1443
=item *
1444

            
1445
Create C<where> clause flexibly
1446

            
1447
=item *
1448

            
1449
Named place holder support
1450

            
1451
=item *
1452

            
1453
Model support
1454

            
1455
=item *
1456

            
1457
Connection manager support
1458

            
1459
=item *
1460

            
1461
Choice your favorite relational database management system,
1462
C<MySQL>, C<SQLite>, C<PostgreSQL>, C<Oracle>,
1463
C<Microsoft SQL Server>, C<Microsoft Access>, C<DB2> or anything, 
1464

            
1465
=item *
1466

            
1467
Filtering by data type or column name
1468

            
1469
=item *
1470

            
1471
Create C<order by> clause flexibly
1472

            
1473
=back
1474

            
1475
=head1 DOCUMENTATION
1476

            
1477
L<DBIx::Custom::Next::Guide> - How to use L<DBIx::Custom::Next>
1478

            
1479
L<DBIx::Custom::Next Wiki|https://github.com/yuki-kimoto/DBIx-Custom/wiki>
1480
- Theare are various examples.
1481

            
1482
Module documentations - 
1483
L<DBIx::Custom::Next::Result>,
1484
L<DBIx::Custom::Next::Query>,
1485
L<DBIx::Custom::Next::Where>,
1486
L<DBIx::Custom::Next::Model>,
1487
L<DBIx::Custom::Next::Order>
1488

            
1489
=head1 ATTRIBUTES
1490

            
1491
=head2 C<connector>
1492

            
1493
    my $connector = $dbi->connector;
1494
    $dbi = $dbi->connector($connector);
1495

            
1496
Connection manager object. if C<connector> is set, you can get C<dbh>
1497
through connection manager. Conection manager object must have C<dbh> mehtod.
1498

            
1499
This is L<DBIx::Connector> example. Please pass
1500
C<default_option> to L<DBIx::Connector> C<new> method.
1501

            
1502
    my $connector = DBIx::Connector->new(
1503
        "dbi:mysql:database=$database",
1504
        $user,
1505
        $password,
1506
        DBIx::Custom::Next->new->default_option
1507
    );
1508
    
1509
    my $dbi = DBIx::Custom::Next->connect(connector => $connector);
1510

            
1511
If C<connector> is set to 1 when connect method is called,
1512
L<DBIx::Connector> is automatically set to C<connector>
1513

            
1514
    my $dbi = DBIx::Custom::Next->connect(
1515
      dsn => $dsn, user => $user, password => $password, connector => 1);
1516
    
1517
    my $connector = $dbi->connector; # DBIx::Connector
1518

            
1519
Note that L<DBIx::Connector> must be installed.
1520

            
1521
=head2 C<dsn>
1522

            
1523
    my $dsn = $dbi->dsn;
1524
    $dbi = $dbi->dsn("DBI:mysql:database=dbname");
1525

            
1526
Data source name, used when C<connect> method is executed.
1527

            
1528
=head2 C<default_option>
1529

            
1530
    my $default_option = $dbi->default_option;
1531
    $dbi = $dbi->default_option($default_option);
1532

            
1533
L<DBI> default option, used when C<connect> method is executed,
1534
default to the following values.
1535

            
1536
    {
1537
        RaiseError => 1,
1538
        PrintError => 0,
1539
        AutoCommit => 1,
1540
    }
1541

            
1542
=head2 C<exclude_table>
1543

            
1544
    my $exclude_table = $dbi->exclude_table;
1545
    $dbi = $dbi->exclude_table(qr/pg_/);
1546

            
1547
Excluded table regex.
1548
C<each_column>, C<each_table>, C<type_rule>,
1549
and C<setup_model> methods ignore matching tables.
1550

            
1551
=head2 C<filters>
1552

            
1553
    my $filters = $dbi->filters;
1554
    $dbi = $dbi->filters(\%filters);
1555

            
1556
Filters, registered by C<register_filter> method.
1557

            
1558
=head2 C<last_sql>
1559

            
1560
    my $last_sql = $dbi->last_sql;
1561
    $dbi = $dbi->last_sql($last_sql);
1562

            
1563
Get last successed SQL executed by C<execute> method.
1564

            
1565
=head2 C<now>
1566

            
1567
    my $now = $dbi->now;
1568
    $dbi = $dbi->now($now);
1569

            
1570
Code reference which return current time, default to the following code reference.
1571

            
1572
    sub {
1573
        my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
1574
        $mon++;
1575
        $year += 1900;
1576
        return sprintf("%04d-%02d-%02d %02d:%02d:%02d");
1577
    }
1578

            
1579
This return the time like C<2011-10-14 05:05:27>.
1580

            
1581
This is used by C<insert> method's C<created_at> option and C<updated_at> option,
1582
and C<update> method's C<updated_at> option.
1583

            
1584
=head2 C<models>
1585

            
1586
    my $models = $dbi->models;
1587
    $dbi = $dbi->models(\%models);
1588

            
1589
Models, included by C<include_model> method.
1590

            
1591
=head2 C<option>
1592

            
1593
    my $option = $dbi->option;
1594
    $dbi = $dbi->option($option);
1595

            
1596
L<DBI> option, used when C<connect> method is executed.
1597
Each value in option override the value of C<default_option>.
1598

            
1599
=head2 C<password>
1600

            
1601
    my $password = $dbi->password;
1602
    $dbi = $dbi->password('lkj&le`@s');
1603

            
1604
Password, used when C<connect> method is executed.
1605

            
1606
=head2 C<quote>
1607

            
1608
     my quote = $dbi->quote;
1609
     $dbi = $dbi->quote('"');
1610

            
1611
Reserved word quote.
1612
Default to double quote '"' except for mysql.
1613
In mysql, default to back quote '`'
1614

            
1615
You can set quote pair.
1616

            
1617
    $dbi->quote('[]');
1618

            
1619
=head2 C<result_class>
1620

            
1621
    my $result_class = $dbi->result_class;
1622
    $dbi = $dbi->result_class('DBIx::Custom::Next::Result');
1623

            
1624
Result class, default to L<DBIx::Custom::Next::Result>.
1625

            
1626
=head2 C<safety_character>
1627

            
1628
    my $safety_character = $dbi->safety_character;
1629
    $dbi = $dbi->safety_character($character);
1630

            
1631
Regex of safety character for table and column name, default to '\w'.
1632
Note that you don't have to specify like '[\w]'.
1633

            
1634
=head2 C<separator>
1635

            
1636
    my $separator = $dbi->separator;
1637
    $dbi = $dbi->separator('-');
1638

            
1639
Separator which join table name and column name.
1640
This have effect to C<column> and C<mycolumn> method,
1641
and C<select> method's column option.
1642

            
1643
Default to C<.>.
1644

            
1645
=head2 C<user>
1646

            
1647
    my $user = $dbi->user;
1648
    $dbi = $dbi->user('Ken');
1649

            
1650
User name, used when C<connect> method is executed.
1651

            
1652
=head2 C<user_column_info>
1653

            
1654
    my $user_column_info = $dbi->user_column_info;
1655
    $dbi = $dbi->user_column_info($user_column_info);
1656

            
1657
You can set the date like the following one.
1658

            
1659
    [
1660
        {table => 'book', column => 'title', info => {...}},
1661
        {table => 'author', column => 'name', info => {...}}
1662
    ]
1663

            
1664
Usually, you set return value of C<get_column_info>.
1665

            
1666
    my $user_column_info
1667
      = $dbi->get_column_info(exclude_table => qr/^system/);
1668
    $dbi->user_column_info($user_column_info);
1669

            
1670
If C<user_column_info> is set, C<each_column> use C<user_column_info>
1671
to find column info. this is very fast.
1672

            
1673
=head2 C<user_table_info>
1674

            
1675
    my $user_table_info = $dbi->user_table_info;
1676
    $dbi = $dbi->user_table_info($user_table_info);
1677

            
1678
You can set the following data.
1679

            
1680
    [
1681
        {table => 'book', info => {...}},
1682
        {table => 'author', info => {...}}
1683
    ]
1684

            
1685
Usually, you can set return value of C<get_table_info>.
1686

            
1687
    my $user_table_info = $dbi->get_table_info(exclude => qr/^system/);
1688
    $dbi->user_table_info($user_table_info);
1689

            
1690
If C<user_table_info> is set, C<each_table> use C<user_table_info>
1691
to find table info.
1692

            
1693
=head1 METHODS
1694

            
1695
L<DBIx::Custom::Next> inherits all methods from L<Object::Simple>
1696
and use all methods of L<DBI>
1697
and implements the following new ones.
1698

            
1699
=head2 C<available_datatype>
1700

            
1701
    print $dbi->available_datatype;
1702

            
1703
Get available data types. You can use these data types
1704
in C<type rule>'s C<from1> and C<from2> section.
1705

            
1706
=head2 C<available_typename>
1707

            
1708
    print $dbi->available_typename;
1709

            
1710
Get available type names. You can use these type names in
1711
C<type_rule>'s C<into1> and C<into2> section.
1712

            
1713
=head2 C<assign_clause>
1714

            
1715
    my $assign_clause = $dbi->assign_clause({title => 'a', age => 2});
1716

            
1717
Create assign clause
1718

            
1719
    title = :title, author = :author
1720

            
1721
This is used to create update clause.
1722

            
1723
    "update book set " . $dbi->assign_clause({title => 'a', age => 2});
1724

            
1725
=head2 C<column>
1726

            
1727
    my $column = $dbi->column(book => ['author', 'title']);
1728

            
1729
Create column clause. The follwoing column clause is created.
1730

            
1731
    book.author as "book.author",
1732
    book.title as "book.title"
1733

            
1734
You can change separator by C<separator> attribute.
1735

            
1736
    # Separator is hyphen
1737
    $dbi->separator('-');
1738
    
1739
    book.author as "book-author",
1740
    book.title as "book-title"
1741
    
1742
=head2 C<connect>
1743

            
1744
    my $dbi = DBIx::Custom::Next->connect(
1745
        dsn => "dbi:mysql:database=dbname",
1746
        user => 'ken',
1747
        password => '!LFKD%$&',
1748
        option => {mysql_enable_utf8 => 1}
1749
    );
1750

            
1751
Connect to the database and create a new L<DBIx::Custom::Next> object.
1752

            
1753
L<DBIx::Custom::Next> is a wrapper of L<DBI>.
1754
C<AutoCommit> and C<RaiseError> options are true, 
1755
and C<PrintError> option is false by default.
1756

            
1757
=head2 C<count>
1758

            
1759
    my $count = $dbi->count(table => 'book');
1760

            
1761
Get rows count.
1762

            
1763
Options is same as C<select> method's ones.
1764

            
1765
=head2 C<create_model>
1766

            
1767
    my $model = $dbi->create_model(
1768
        table => 'book',
1769
        primary_key => 'id',
1770
        join => [
1771
            'inner join company on book.comparny_id = company.id'
1772
        ],
1773
    );
1774

            
1775
Create L<DBIx::Custom::Next::Model> object and initialize model.
1776
the module is also used from C<model> method.
1777

            
1778
   $dbi->model('book')->select(...);
1779

            
1780
=head2 C<dbh>
1781

            
1782
    my $dbh = $dbi->dbh;
1783

            
1784
Get L<DBI> database handle. if C<connector> is set, you can get
1785
database handle through C<connector> object.
1786

            
1787
=head2 C<delete>
1788

            
1789
    $dbi->delete(table => 'book', where => {title => 'Perl'});
1790

            
1791
Execute delete statement.
1792

            
1793
The following opitons are available.
1794

            
1795
B<OPTIONS>
1796

            
1797
C<delete> method use all of C<execute> method's options,
1798
and use the following new ones.
1799

            
1800
=over 4
1801

            
1802
=item C<id>
1803

            
1804
    id => 4
1805
    id => [4, 5]
1806

            
1807
ID corresponding to C<primary_key>.
1808
You can delete rows by C<id> and C<primary_key>.
1809

            
1810
    $dbi->delete(
1811
        primary_key => ['id1', 'id2'],
1812
        id => [4, 5],
1813
        table => 'book',
1814
    );
1815

            
1816
The above is same as the followin one.
1817

            
1818
    $dbi->delete(where => {id1 => 4, id2 => 5}, table => 'book');
1819

            
1820
=item C<prefix>
1821

            
1822
    prefix => 'some'
1823

            
1824
prefix before table name section.
1825

            
1826
    delete some from book
1827

            
1828
=item C<table>
1829

            
1830
    table => 'book'
1831

            
1832
Table name.
1833

            
1834
=item C<where>
1835

            
1836
Same as C<select> method's C<where> option.
1837

            
1838
=back
1839

            
1840
=head2 C<delete_all>
1841

            
1842
    $dbi->delete_all(table => $table);
1843

            
1844
Execute delete statement for all rows.
1845
Options is same as C<delete>.
1846

            
1847
=head2 C<each_column>
1848

            
1849
    $dbi->each_column(
1850
        sub {
1851
            my ($dbi, $table, $column, $column_info) = @_;
1852
            
1853
            my $type = $column_info->{TYPE_NAME};
1854
            
1855
            if ($type eq 'DATE') {
1856
                # ...
1857
            }
1858
        }
1859
    );
1860

            
1861
Iterate all column informations in database.
1862
Argument is callback which is executed when one column is found.
1863
Callback receive four arguments. C<DBIx::Custom::Next object>, C<table name>,
1864
C<column name>, and C<column information>.
1865

            
1866
If C<user_column_info> is set, C<each_column> method use C<user_column_info>
1867
infromation, you can improve the performance of C<each_column> in
1868
the following way.
1869

            
1870
    my $column_infos = $dbi->get_column_info(exclude_table => qr/^system_/);
1871
    $dbi->user_column_info($column_info);
1872
    $dbi->each_column(sub { ... });
1873

            
1874
=head2 C<each_table>
1875

            
1876
    $dbi->each_table(
1877
        sub {
1878
            my ($dbi, $table, $table_info) = @_;
1879
            
1880
            my $table_name = $table_info->{TABLE_NAME};
1881
        }
1882
    );
1883

            
1884
Iterate all table informationsfrom in database.
1885
Argument is callback which is executed when one table is found.
1886
Callback receive three arguments, C<DBIx::Custom::Next object>, C<table name>,
1887
C<table information>.
1888

            
1889
If C<user_table_info> is set, C<each_table> method use C<user_table_info>
1890
infromation, you can improve the performance of C<each_table> in
1891
the following way.
1892

            
1893
    my $table_infos = $dbi->get_table_info(exclude => qr/^system_/);
1894
    $dbi->user_table_info($table_info);
1895
    $dbi->each_table(sub { ... });
1896

            
1897
=head2 C<execute>
1898

            
1899
    my $result = $dbi->execute(
1900
      "select * from book where title = :title and author like :author",
1901
      {title => 'Perl', author => '%Ken%'}
1902
    );
1903

            
1904
    my $result = $dbi->execute(
1905
      "select * from book where title = :book.title and author like :book.author",
1906
      {'book.title' => 'Perl', 'book.author' => '%Ken%'}
1907
    );
1908

            
1909
Execute SQL. SQL can contain column parameter such as :author and :title.
1910
You can append table name to column name such as :book.title and :book.author.
1911
Second argunet is data, embedded into column parameter.
1912
Return value is L<DBIx::Custom::Next::Result> object when select statement is executed,
1913
or the count of affected rows when insert, update, delete statement is executed.
1914

            
1915
Named placeholder such as C<:title> is replaced by placeholder C<?>.
1916
    
1917
    # Original
1918
    select * from book where title = :title and author like :author
1919
    
1920
    # Replaced
1921
    select * from where title = ? and author like ?;
1922

            
1923
You can specify operator with named placeholder
1924
by C<name{operator}> syntax.
1925

            
1926
    # Original
1927
    select * from book where :title{=} and :author{like}
1928
    
1929
    # Replaced
1930
    select * from where title = ? and author like ?;
1931

            
1932
Note that colons in time format such as 12:13:15 is exeption,
1933
it is not parsed as named placeholder.
1934
If you want to use colon generally, you must escape it by C<\\>
1935

            
1936
    select * from where title = "aa\\:bb";
1937

            
1938
B<OPTIONS>
1939

            
1940
The following opitons are available.
1941

            
1942
=over 4
1943

            
1944
=item C<after_build_sql> 
1945

            
1946
You can filter sql after the sql is build.
1947

            
1948
    after_build_sql => $code_ref
1949

            
1950
The following one is one example.
1951

            
1952
    $dbi->select(
1953
        table => 'book',
1954
        column => 'distinct(name)',
1955
        after_build_sql => sub {
1956
            "select count(*) from ($_[0]) as t1"
1957
        }
1958
    );
1959

            
1960
The following SQL is executed.
1961

            
1962
    select count(*) from (select distinct(name) from book) as t1;
1963

            
1964
=item C<append>
1965

            
1966
    append => 'order by name'
1967

            
1968
Append some statement after SQL.
1969

            
1970
=item C<bind_type>
1971

            
1972
Specify database bind data type.
1973

            
1974
    bind_type => [image => DBI::SQL_BLOB]
1975
    bind_type => [[qw/image audio/] => DBI::SQL_BLOB]
1976

            
1977
This is used to bind parameter by C<bind_param> of statment handle.
1978

            
1979
    $sth->bind_param($pos, $value, DBI::SQL_BLOB);
1980

            
1981
=item C<filter>
1982
    
1983
    filter => {
1984
        title  => sub { uc $_[0] }
1985
        author => sub { uc $_[0] }
1986
    }
1987

            
1988
    # Filter name
1989
    filter => {
1990
        title  => 'upper_case',
1991
        author => 'upper_case'
1992
    }
1993
        
1994
    # At once
1995
    filter => [
1996
        [qw/title author/]  => sub { uc $_[0] }
1997
    ]
1998

            
1999
Filter. You can set subroutine or filter name
2000
registered by by C<register_filter>.
2001
This filter is executed before data is saved into database.
2002
and before type rule filter is executed.
2003

            
2004
=item C<query>
2005

            
2006
    query => 1
2007

            
2008
C<execute> method return L<DBIx::Custom::Next::Query> object, not executing SQL.
2009
You can check SQL, column, or get statment handle.
2010

            
2011
    my $sql = $query->{sql};
2012
    my $sth = $query->{sth};
2013
    my $columns = $query->{columns};
2014
    
2015
=item C<reuse>
2016
    
2017
    reuse => $hash_ref
2018

            
2019
Reuse query object if the hash reference variable is set.
2020
    
2021
    my $queries = {};
2022
    $dbi->execute($sql, $param, reuse => $queries);
2023

            
2024
This will improved performance when you want to execute same query repeatedly
2025
because generally creating query object is slow.
2026

            
2027
=item C<primary_key>
2028

            
2029
    primary_key => 'id'
2030
    primary_key => ['id1', 'id2']
2031

            
2032
Priamry key. This is used for C<id> option.
2033

            
2034
=item C<table>
2035
    
2036
    table => 'author'
2037

            
2038
If you want to omit table name in column name
2039
and enable C<into1> and C<into2> type filter,
2040
You must set C<table> option.
2041

            
2042
    $dbi->execute("select * from book where title = :title and author = :author",
2043
        {title => 'Perl', author => 'Ken', table => 'book');
2044

            
2045
    # Same
2046
    $dbi->execute(
2047
      "select * from book where title = :book.title and author = :book.author",
2048
      {title => 'Perl', author => 'Ken');
2049

            
2050
=item C<table_alias>
2051

            
2052
    table_alias => {user => 'worker'}
2053

            
2054
Table alias. Key is real table name, value is alias table name.
2055
If you set C<table_alias>, you can enable C<into1> and C<into2> type rule
2056
on alias table name.
2057

            
2058
=item C<type_rule_off>
2059

            
2060
    type_rule_off => 1
2061

            
2062
Turn C<into1> and C<into2> type rule off.
2063

            
2064
=item C<type_rule1_off>
2065

            
2066
    type_rule1_off => 1
2067

            
2068
Turn C<into1> type rule off.
2069

            
2070
=item C<type_rule2_off>
2071

            
2072
    type_rule2_off => 1
2073

            
2074
Turn C<into2> type rule off.
2075

            
2076
=back
2077

            
2078
=head2 C<get_column_info>
2079

            
2080
    my $column_infos = $dbi->get_column_info(exclude_table => qr/^system_/);
2081

            
2082
get column infomation except for one which match C<exclude_table> pattern.
2083

            
2084
    [
2085
        {table => 'book', column => 'title', info => {...}},
2086
        {table => 'author', column => 'name' info => {...}}
2087
    ]
2088

            
2089
=head2 C<get_table_info>
2090

            
2091
    my $table_infos = $dbi->get_table_info(exclude => qr/^system_/);
2092

            
2093
get table infomation except for one which match C<exclude> pattern.
2094

            
2095
    [
2096
        {table => 'book', info => {...}},
2097
        {table => 'author', info => {...}}
2098
    ]
2099

            
2100
You can set this value to C<user_table_info>.
2101

            
2102
=head2 C<helper>
2103

            
2104
    $dbi->helper(
2105
        find_or_create   => sub {
2106
            my $self = shift;
2107
            
2108
            # Process
2109
        },
2110
        ...
2111
    );
2112

            
2113
Register helper. These helper is called directly from L<DBIx::Custom::Next> object.
2114

            
2115
    $dbi->find_or_create;
2116

            
2117
=head2 C<insert>
2118

            
2119
    $dbi->insert({title => 'Perl', author => 'Ken'}, table  => 'book');
2120

            
2121
Execute insert statement. First argument is row data. Return value is
2122
affected row count.
2123

            
2124
If you want to set constant value to row data, use scalar reference
2125
as parameter value.
2126

            
2127
    {date => \"NOW()"}
2128

            
2129
B<options>
2130

            
2131
C<insert> method use all of C<execute> method's options,
2132
and use the following new ones.
2133

            
2134
=over 4
2135

            
2136
=item C<created_at>
2137

            
2138
    created_at => 'created_datetime'
2139

            
2140
Created timestamp column name. time when row is created is set to the column.
2141
default time format is "YYYY-mm-dd HH:MM:SS", which can be changed by
2142
C<now> attribute.
2143

            
2144
=item C<id>
2145

            
2146
    id => 4
2147
    id => [4, 5]
2148

            
2149
ID corresponding to C<primary_key>.
2150
You can insert a row by C<id> and C<primary_key>.
2151

            
2152
    $dbi->insert(
2153
        {title => 'Perl', author => 'Ken'}
2154
        primary_key => ['id1', 'id2'],
2155
        id => [4, 5],
2156
        table => 'book'
2157
    );
2158

            
2159
The above is same as the followin one.
2160

            
2161
    $dbi->insert(
2162
        {id1 => 4, id2 => 5, title => 'Perl', author => 'Ken'},
2163
        table => 'book'
2164
    );
2165

            
2166
=item C<prefix>
2167

            
2168
    prefix => 'or replace'
2169

            
2170
prefix before table name section
2171

            
2172
    insert or replace into book
2173

            
2174
=item C<table>
2175

            
2176
    table => 'book'
2177

            
2178
Table name.
2179

            
2180
=item C<updated_at>
2181

            
2182
This option is same as C<update> method C<updated_at> option.
2183

            
2184
=item C<wrap>
2185

            
2186
    wrap => {price => sub { "max($_[0])" }}
2187

            
2188
placeholder wrapped string.
2189

            
2190
If the following statement
2191

            
2192
    $dbi->insert({price => 100}, table => 'book',
2193
      {price => sub { "$_[0] + 5" }});
2194

            
2195
is executed, the following SQL is executed.
2196

            
2197
    insert into book price values ( ? + 5 );
2198

            
2199
=back
2200

            
2201
=over 4
2202

            
2203
=head2 C<include_model>
2204

            
2205
    $dbi->include_model('MyModel');
2206

            
2207
Include models from specified namespace,
2208
the following layout is needed to include models.
2209

            
2210
    lib / MyModel.pm
2211
        / MyModel / book.pm
2212
                  / company.pm
2213

            
2214
Name space module, extending L<DBIx::Custom::Next::Model>.
2215

            
2216
B<MyModel.pm>
2217

            
2218
    package MyModel;
2219
    use DBIx::Custom::Next::Model -base;
2220
    
2221
    1;
2222

            
2223
Model modules, extending name space module.
2224

            
2225
B<MyModel/book.pm>
2226

            
2227
    package MyModel::book;
2228
    use MyModel -base;
2229
    
2230
    1;
2231

            
2232
B<MyModel/company.pm>
2233

            
2234
    package MyModel::company;
2235
    use MyModel -base;
2236
    
2237
    1;
2238
    
2239
MyModel::book and MyModel::company is included by C<include_model>.
2240

            
2241
You can get model object by C<model>.
2242

            
2243
    my $book_model = $dbi->model('book');
2244
    my $company_model = $dbi->model('company');
2245

            
2246
See L<DBIx::Custom::Next::Model> to know model features.
2247

            
2248
=head2 C<like_value>
2249

            
2250
    my $like_value = $dbi->like_value
2251

            
2252
Code reference which return a value for the like value.
2253

            
2254
    sub { "%$_[0]%" }
2255

            
2256
=head2 C<mapper>
2257

            
2258
    my $mapper = $dbi->mapper(param => $param);
2259

            
2260
Create a new L<DBIx::Custom::Next::Mapper> object.
2261

            
2262
=head2 C<merge_param>
2263

            
2264
    my $param = $dbi->merge_param({key1 => 1}, {key1 => 1, key2 => 2});
2265

            
2266
Merge parameters. The following new parameter is created.
2267

            
2268
    {key1 => [1, 1], key2 => 2}
2269

            
2270
If same keys contains, the value is converted to array reference.
2271

            
2272
=head2 C<model>
2273

            
2274
    my $model = $dbi->model('book');
2275

            
2276
Get a L<DBIx::Custom::Next::Model> object
2277
create by C<create_model> or C<include_model>
2278

            
2279
=head2 C<mycolumn>
2280

            
2281
    my $column = $dbi->mycolumn(book => ['author', 'title']);
2282

            
2283
Create column clause for myself. The follwoing column clause is created.
2284

            
2285
    book.author as author,
2286
    book.title as title
2287

            
2288
=head2 C<new>
2289

            
2290
    my $dbi = DBIx::Custom::Next->new(
2291
        dsn => "dbi:mysql:database=dbname",
2292
        user => 'ken',
2293
        password => '!LFKD%$&',
2294
        option => {mysql_enable_utf8 => 1}
2295
    );
2296

            
2297
Create a new L<DBIx::Custom::Next> object.
2298

            
2299
=head2 C<not_exists>
2300

            
2301
    my $not_exists = $dbi->not_exists;
2302

            
2303
DBIx::Custom::Next::NotExists object, indicating the column is not exists.
2304
This is used in C<param> of L<DBIx::Custom::Next::Where> .
2305

            
2306
=head2 C<order>
2307

            
2308
    my $order = $dbi->order;
2309

            
2310
Create a new L<DBIx::Custom::Next::Order> object.
2311

            
2312
=head2 C<q>
2313

            
2314
    my $quooted = $dbi->q("title");
2315

            
2316
Quote string by value of C<quote>.
2317

            
2318
=head2 C<register_filter>
2319

            
2320
    $dbi->register_filter(
2321
        # Time::Piece object to database DATE format
2322
        tp_to_date => sub {
2323
            my $tp = shift;
2324
            return $tp->strftime('%Y-%m-%d');
2325
        },
2326
        # database DATE format to Time::Piece object
2327
        date_to_tp => sub {
2328
           my $date = shift;
2329
           return Time::Piece->strptime($date, '%Y-%m-%d');
2330
        }
2331
    );
2332
    
2333
Register filters, used by C<filter> option of many methods.
2334

            
2335
=head2 C<select>
2336

            
2337
    my $result = $dbi->select(
2338
        table  => 'book',
2339
        column => ['author', 'title'],
2340
        where  => {author => 'Ken'},
2341
    );
2342
    
2343
Execute select statement.
2344

            
2345
B<OPTIONS>
2346

            
2347
C<select> method use all of C<execute> method's options,
2348
and use the following new ones.
2349

            
2350
=over 4
2351

            
2352
=item C<column>
2353
    
2354
    column => 'author'
2355
    column => ['author', 'title']
2356

            
2357
Column clause.
2358
    
2359
if C<column> is not specified, '*' is set.
2360

            
2361
    column => '*'
2362

            
2363
You can specify hash of array reference.
2364

            
2365
    column => [
2366
        {book => [qw/author title/]},
2367
        {person => [qw/name age/]}
2368
    ]
2369

            
2370
This is expanded to the following one by using C<colomn> method.
2371

            
2372
    book.author as "book.author",
2373
    book.title as "book.title",
2374
    person.name as "person.name",
2375
    person.age as "person.age"
2376

            
2377
You can specify array of array reference, first argument is
2378
column name, second argument is alias.
2379

            
2380
    column => [
2381
        ['date(book.register_datetime)' => 'book.register_date']
2382
    ];
2383

            
2384
Alias is quoted properly and joined.
2385

            
2386
    date(book.register_datetime) as "book.register_date"
2387

            
2388
=item C<id>
2389

            
2390
    id => 4
2391
    id => [4, 5]
2392

            
2393
ID corresponding to C<primary_key>.
2394
You can select rows by C<id> and C<primary_key>.
2395

            
2396
    $dbi->select(
2397
        primary_key => ['id1', 'id2'],
2398
        id => [4, 5],
2399
        table => 'book'
2400
    );
2401

            
2402
The above is same as the followin one.
2403

            
2404
    $dbi->select(
2405
        where => {id1 => 4, id2 => 5},
2406
        table => 'book'
2407
    );
2408
    
2409
=item C<param>
2410

            
2411
    param => {'table2.key3' => 5}
2412

            
2413
Parameter shown before where clause.
2414
    
2415
For example, if you want to contain tag in join clause, 
2416
you can pass parameter by C<param> option.
2417

            
2418
    join  => ['inner join (select * from table2 where table2.key3 = :table2.key3)' . 
2419
              ' as table2 on table1.key1 = table2.key1']
2420

            
2421
=itme C<prefix>
2422

            
2423
    prefix => 'SQL_CALC_FOUND_ROWS'
2424

            
2425
Prefix of column cluase
2426

            
2427
    select SQL_CALC_FOUND_ROWS title, author from book;
2428

            
2429
=item C<join>
2430

            
2431
    join => [
2432
        'left outer join company on book.company_id = company_id',
2433
        'left outer join location on company.location_id = location.id'
2434
    ]
2435
        
2436
Join clause. If column cluase or where clause contain table name like "company.name",
2437
join clausees needed when SQL is created is used automatically.
2438

            
2439
    $dbi->select(
2440
        table => 'book',
2441
        column => ['company.location_id as location_id'],
2442
        where => {'company.name' => 'Orange'},
2443
        join => [
2444
            'left outer join company on book.company_id = company.id',
2445
            'left outer join location on company.location_id = location.id'
2446
        ]
2447
    );
2448

            
2449
In above select, column and where clause contain "company" table,
2450
the following SQL is created
2451

            
2452
    select company.location_id as location_id
2453
    from book
2454
      left outer join company on book.company_id = company.id
2455
    where company.name = ?;
2456

            
2457
You can specify two table by yourself. This is useful when join parser can't parse
2458
the join clause correctly.
2459

            
2460
    $dbi->select(
2461
        table => 'book',
2462
        column => ['company.location_id as location_id'],
2463
        where => {'company.name' => 'Orange'},
2464
        join => [
2465
            {
2466
                clause => 'left outer join location on company.location_id = location.id',
2467
                table => ['company', 'location']
2468
            }
2469
        ]
2470
    );
2471

            
2472
=item C<table>
2473

            
2474
    table => 'book'
2475

            
2476
Table name.
2477

            
2478
=item C<where>
2479
    
2480
    # Hash refrence
2481
    where => {author => 'Ken', 'title' => 'Perl'}
2482
    
2483
    # DBIx::Custom::Next::Where object
2484
    where => $dbi->where(
2485
        clause => ['and', ':author{=}', ':title{like}'],
2486
        param  => {author => 'Ken', title => '%Perl%'}
2487
    );
2488
    
2489
    # Array reference, this is same as above
2490
    where => [
2491
        ['and', ':author{=}', ':title{like}'],
2492
        {author => 'Ken', title => '%Perl%'}
2493
    ];
2494
    
2495
    # String
2496
    where => 'title is null'
2497

            
2498
Where clause. See L<DBIx::Custom::Next::Where>.
2499
    
2500
=back
2501

            
2502
=head2 C<setup_model>
2503

            
2504
    $dbi->setup_model;
2505

            
2506
Setup all model objects.
2507
C<columns> of model object is automatically set, parsing database information.
2508

            
2509
=head2 C<type_rule>
2510

            
2511
    $dbi->type_rule(
2512
        into1 => {
2513
            date => sub { ... },
2514
            datetime => sub { ... }
2515
        },
2516
        into2 => {
2517
            date => sub { ... },
2518
            datetime => sub { ... }
2519
        },
2520
        from1 => {
2521
            # DATE
2522
            9 => sub { ... },
2523
            # DATETIME or TIMESTAMP
2524
            11 => sub { ... },
2525
        }
2526
        from2 => {
2527
            # DATE
2528
            9 => sub { ... },
2529
            # DATETIME or TIMESTAMP
2530
            11 => sub { ... },
2531
        }
2532
    );
2533

            
2534
Filtering rule when data is send into and get from database.
2535
This has a little complex problem.
2536

            
2537
In C<into1> and C<into2> you can specify
2538
type name as same as type name defined
2539
by create table, such as C<DATETIME> or C<DATE>.
2540

            
2541
Note that type name and data type don't contain upper case.
2542
If these contain upper case charactor, you convert it to lower case.
2543

            
2544
C<into2> is executed after C<into1>.
2545

            
2546
Type rule of C<into1> and C<into2> is enabled on the following
2547
column name.
2548

            
2549
=over 4
2550

            
2551
=item 1. column name
2552

            
2553
    issue_date
2554
    issue_datetime
2555

            
2556
This need C<table> option in each method.
2557

            
2558
=item 2. table name and column name, separator is dot
2559

            
2560
    book.issue_date
2561
    book.issue_datetime
2562

            
2563
=back
2564

            
2565
You get all type name used in database by C<available_typename>.
2566

            
2567
    print $dbi->available_typename;
2568

            
2569
In C<from1> and C<from2> you specify data type, not type name.
2570
C<from2> is executed after C<from1>.
2571
You get all data type by C<available_datatype>.
2572

            
2573
    print $dbi->available_datatype;
2574

            
2575
You can also specify multiple types at once.
2576

            
2577
    $dbi->type_rule(
2578
        into1 => [
2579
            [qw/DATE DATETIME/] => sub { ... },
2580
        ],
2581
    );
2582

            
2583
=head2 C<update>
2584

            
2585
    $dbi->update({title => 'Perl'}, table  => 'book', where  => {id => 4});
2586

            
2587
Execute update statement. First argument is update row data.
2588

            
2589
If you want to set constant value to row data, use scalar reference
2590
as parameter value.
2591

            
2592
    {date => \"NOW()"}
2593

            
2594
B<OPTIONS>
2595

            
2596
C<update> method use all of C<execute> method's options,
2597
and use the following new ones.
2598

            
2599
=over 4
2600

            
2601
=item C<id>
2602

            
2603
    id => 4
2604
    id => [4, 5]
2605

            
2606
ID corresponding to C<primary_key>.
2607
You can update rows by C<id> and C<primary_key>.
2608

            
2609
    $dbi->update(
2610
        {title => 'Perl', author => 'Ken'}
2611
        primary_key => ['id1', 'id2'],
2612
        id => [4, 5],
2613
        table => 'book'
2614
    );
2615

            
2616
The above is same as the followin one.
2617

            
2618
    $dbi->update(
2619
        {title => 'Perl', author => 'Ken'}
2620
        where => {id1 => 4, id2 => 5},
2621
        table => 'book'
2622
    );
2623

            
2624
=item C<prefix>
2625

            
2626
    prefix => 'or replace'
2627

            
2628
prefix before table name section
2629

            
2630
    update or replace book
2631

            
2632
=item C<table>
2633

            
2634
    table => 'book'
2635

            
2636
Table name.
2637

            
2638
=item C<where>
2639

            
2640
Same as C<select> method's C<where> option.
2641

            
2642
=item C<wrap>
2643

            
2644
    wrap => {price => sub { "max($_[0])" }}
2645

            
2646
placeholder wrapped string.
2647

            
2648
If the following statement
2649

            
2650
    $dbi->update({price => 100}, table => 'book',
2651
      {price => sub { "$_[0] + 5" }});
2652

            
2653
is executed, the following SQL is executed.
2654

            
2655
    update book set price =  ? + 5;
2656

            
2657
=item C<updated_at>
2658

            
2659
    updated_at => 'updated_datetime'
2660

            
2661
Updated timestamp column name. time when row is updated is set to the column.
2662
default time format is C<YYYY-mm-dd HH:MM:SS>, which can be changed by
2663
C<now> attribute.
2664

            
2665
=back
2666

            
2667
=head2 C<update_all>
2668

            
2669
    $dbi->update_all({title => 'Perl'}, table => 'book', );
2670

            
2671
Execute update statement for all rows.
2672
Options is same as C<update> method.
2673

            
2674
=head2 C<update_or_insert>
2675
    
2676
    # ID
2677
    $dbi->update_or_insert(
2678
        {title => 'Perl'},
2679
        table => 'book',
2680
        id => 1,
2681
        primary_key => 'id',
2682
        option => {
2683
            select => {
2684
                 append => 'for update'
2685
            }
2686
        }
2687
    );
2688

            
2689
Update or insert.
2690

            
2691
C<update_or_insert> method execute C<select> method first to find row.
2692
If the row is exists, C<update> is executed.
2693
If not, C<insert> is executed.
2694

            
2695
C<OPTIONS>
2696

            
2697
C<update_or_insert> method use all common option
2698
in C<select>, C<update>, C<delete>, and has the following new ones.
2699

            
2700
=over 4
2701

            
2702
=item C<option>
2703

            
2704
    option => {
2705
        select => {
2706
            append => '...'
2707
        },
2708
        insert => {
2709
            prefix => '...'
2710
        },
2711
        update => {
2712
            filter => {}
2713
        }
2714
    }
2715

            
2716
If you want to pass option to each method,
2717
you can use C<option> option.
2718

            
2719
=over 4
2720

            
2721
=item C<select_option>
2722

            
2723
    select_option => {append => 'for update'}
2724

            
2725
select method option,
2726
select method is used to check the row is already exists.
2727

            
2728
=head2 C<show_datatype>
2729

            
2730
    $dbi->show_datatype($table);
2731

            
2732
Show data type of the columns of specified table.
2733

            
2734
    book
2735
    title: 5
2736
    issue_date: 91
2737

            
2738
This data type is used in C<type_rule>'s C<from1> and C<from2>.
2739

            
2740
=head2 C<show_tables>
2741

            
2742
    $dbi->show_tables;
2743

            
2744
Show tables.
2745

            
2746
=head2 C<show_typename>
2747

            
2748
    $dbi->show_typename($table);
2749

            
2750
Show type name of the columns of specified table.
2751

            
2752
    book
2753
    title: varchar
2754
    issue_date: date
2755

            
2756
This type name is used in C<type_rule>'s C<into1> and C<into2>.
2757

            
2758
=head2 C<values_clause>
2759

            
2760
    my $values_clause = $dbi->values_clause({title => 'a', age => 2});
2761

            
2762
Create values clause.
2763

            
2764
    (title, author) values (title = :title, age = :age);
2765

            
2766
You can use this in insert statement.
2767

            
2768
    my $insert_sql = "insert into book $values_clause";
2769

            
2770
=head2 C<where>
2771

            
2772
    my $where = $dbi->where(
2773
        clause => ['and', 'title = :title', 'author = :author'],
2774
        param => {title => 'Perl', author => 'Ken'}
2775
    );
2776

            
2777
Create a new L<DBIx::Custom::Next::Where> object.
2778

            
2779
=head1 ENVIRONMENTAL VARIABLES
2780

            
2781
=head2 C<DBIX_CUSTOM_DEBUG>
2782

            
2783
If environment variable C<DBIX_CUSTOM_DEBUG> is set to true,
2784
executed SQL and bind values are printed to STDERR.
2785

            
2786
=head2 C<DBIX_CUSTOM_DEBUG_ENCODING>
2787

            
2788
DEBUG output encoding. Default to UTF-8.
2789

            
2790
=head1 BUGS
2791

            
2792
Please tell me bugs if found.
2793

            
2794
C<< <kimoto.yuki at gmail.com> >>
2795

            
2796
L<http://github.com/yuki-kimoto/DBIx-Custom>
2797

            
2798
=head1 AUTHOR
2799

            
2800
Yuki Kimoto, C<< <kimoto.yuki at gmail.com> >>
2801

            
2802
=head1 COPYRIGHT & LICENSE
2803

            
2804
Copyright 2009-2011 Yuki Kimoto, all rights reserved.
2805

            
2806
This program is free software; you can redistribute it and/or modify it
2807
under the same terms as Perl itself.
2808

            
2809
=cut