Showing 5 changed files with 144 additions and 4 deletions
+4
Changes
... ...
@@ -1,4 +1,8 @@
1
+0.1731
2
+    - removed DEPRECATED status from insert method's id option
3
+    - renamed EXPERIMENTAL insert_or_update to update_or_insert
1 4
 0.1730
5
+    - added EXPERIMENTAL insert_or_update method
2 6
     - method method of DBIx::Custom::Model is renamed to helper,
3 7
       method is DEPRECATED!
4 8
     - method method is renamed to helper, method is DEPRECATED!
+78 -2
lib/DBIx/Custom.pm
... ...
@@ -1,7 +1,7 @@
1 1
 package DBIx::Custom;
2 2
 use Object::Simple -base;
3 3
 
4
-our $VERSION = '0.1730';
4
+our $VERSION = '0.1731';
5 5
 use 5.008001;
6 6
 
7 7
 use Carp 'croak';
... ...
@@ -627,6 +627,7 @@ sub insert {
627 627
     my $prefix = delete $args{prefix};
628 628
     my $wrap = delete $args{wrap};
629 629
     my $timestamp = $args{timestamp};
630
+    delete $args{where};
630 631
     
631 632
     # Timestamp
632 633
     if ($timestamp && (my $insert_timestamp = $self->insert_timestamp)) {
... ...
@@ -639,7 +640,6 @@ sub insert {
639 640
 
640 641
     # Merge parameter
641 642
     if (defined $id) {
642
-        warn "insert method's id option is DEPRECATED!";
643 643
         my $id_param = $self->_create_param_from_id($id, $primary_key);
644 644
         $param = $self->merge_param($id_param, $param);
645 645
     }
... ...
@@ -656,6 +656,42 @@ sub insert {
656 656
     return $self->execute($sql, $param, table => $table, %args);
657 657
 }
658 658
 
659
+sub update_or_insert {
660
+    my $self = shift;
661
+
662
+    # Arguments
663
+    my $param  = shift;
664
+    my %args = @_;
665
+    my $id = delete $args{id};
666
+    my $primary_key = delete $args{primary_key};
667
+    $primary_key = [$primary_key] unless ref $primary_key eq 'ARRAY';
668
+    croak "update_or_insert method need primary_key option " .
669
+          "when id is specified" . _subname
670
+      if defined $id && !defined $primary_key;
671
+    my $table  = delete $args{table};
672
+    croak qq{"table" option must be specified } . _subname
673
+      unless defined $table;
674
+    my $select_option = delete $args{select_option};
675
+    
676
+    my $rows = $self->select(table => $table, id => $id,
677
+        primary_key => $primary_key, %$select_option)->all;
678
+    
679
+    croak "selected row count must be one or zero" . _subname
680
+      if @$rows > 1;
681
+    
682
+    my $row = $rows->[0];
683
+    my @options = (table => $table);
684
+    push @options, id => $id, primary_key => $primary_key if defined $id;
685
+    push @options, %args;
686
+    
687
+    if ($row) {
688
+        return $self->update($param, @options);
689
+    }
690
+    else {
691
+        return $self->insert($param, @options);
692
+    }
693
+}
694
+
659 695
 sub insert_timestamp {
660 696
     my $self = shift;
661 697
     
... ...
@@ -3439,6 +3475,46 @@ Create update parameter tag.
3439 3475
 
3440 3476
     set title = :title, author = :author
3441 3477
 
3478
+=head2 C<update_or_insert EXPERIMENTAL>
3479
+    
3480
+    # Where
3481
+    $dbi->update_or_insert(
3482
+        {id => 1, title => 'Perl'},
3483
+        table => 'book',
3484
+        where => {id => 1},
3485
+        select_option => {append => 'for update'}
3486
+    );
3487
+    
3488
+    # ID
3489
+    $dbi->update_or_insert(
3490
+        {title => 'Perl'},
3491
+        table => 'book',
3492
+        id => 1,
3493
+        primary_key => 'id',
3494
+        select_option => {append => 'for update'}
3495
+    );
3496
+    
3497
+Update or insert.
3498
+
3499
+In both examples, the following SQL is executed.
3500
+
3501
+    # In case insert
3502
+    insert into book (id, title) values (?, ?)
3503
+    
3504
+    # In case update
3505
+    update book set (id = ?, title = ?) where book.id = ?
3506
+
3507
+The following opitons are available adding to C<update> option.
3508
+
3509
+=over 4
3510
+
3511
+=item C<select_option>
3512
+
3513
+    select_option => {append => 'for update'}
3514
+
3515
+select method option,
3516
+select method is used to check the row is already exists.
3517
+
3442 3518
 =head2 C<update_timestamp>
3443 3519
 
3444 3520
     $dbi->update_timestamp(updated_at => sub { localtime });
+1 -1
t/common-oracle.t
... ...
@@ -12,7 +12,7 @@ use DBIx::Custom;
12 12
     package DBIx::Custom;
13 13
     no warnings 'redefine';
14 14
     
15
-    has dbi_option => sub {
15
+    has option => sub {
16 16
         {
17 17
             Callbacks => {
18 18
               connected => sub {
+45
t/common.t
... ...
@@ -538,6 +538,51 @@ $result = $dbi->execute("select * from $table1");
538 538
 $rows   = $result->all;
539 539
 is($rows->[0]->{$key1}, $rows->[0]->{$key2});
540 540
 
541
+test 'update_or_insert';
542
+eval { $dbi->execute("drop table $table1") };
543
+$dbi->execute($create_table1);
544
+$dbi->update_or_insert(
545
+    {$key2 => 2},
546
+    table => $table1,
547
+    primary_key => $key1,
548
+    id => 1
549
+);
550
+$row = $dbi->select(id => 1, table => $table1, primary_key => $key1)->one;
551
+is_deeply($row, {$key1 => 1, $key2 => 2}, "basic");
552
+
553
+$dbi->update_or_insert(
554
+    {$key2 => 3},
555
+    table => $table1,
556
+    primary_key => $key1,
557
+    id => 1
558
+);
559
+$rows = $dbi->select(id => 1, table => $table1, primary_key => $key1)->all;
560
+is_deeply($rows, [{$key1 => 1, $key2 => 3}], "basic");
561
+
562
+eval { $dbi->execute("drop table $table1") };
563
+$dbi->execute($create_table1);
564
+$dbi->update_or_insert(
565
+    {$key1 => 1, $key2 => 2},
566
+    table => $table1,
567
+    where => {$key1 => 1}
568
+);
569
+$row = $dbi->select(id => 1, table => $table1, primary_key => $key1)->one;
570
+is_deeply($row, {$key1 => 1, $key2 => 2}, "basic");
571
+
572
+
573
+test 'default_bind_filter';
574
+$dbi->execute("delete from $table1");
575
+$dbi->register_filter(
576
+    twice       => sub { $_[0] * 2 },
577
+    three_times => sub { $_[0] * 3 }
578
+);
579
+$dbi->default_bind_filter('twice');
580
+$dbi->insert(table => $table1, param => {$key1 => 1, $key2 => 2}, filter => {$key1 => 'three_times'});
581
+$result = $dbi->execute("select * from $table1");
582
+$rows   = $result->all;
583
+is_deeply($rows, [{$key1 => 3, $key2 => 4}], "filter");
584
+$dbi->default_bind_filter(undef);
585
+
541 586
 test 'update';
542 587
 eval { $dbi->execute("drop table $table1") };
543 588
 $dbi->execute($create_table1_2);
+16 -1
t/mysql.t
... ...
@@ -34,7 +34,7 @@ my $result;
34 34
 
35 35
 test 'connect';
36 36
 eval {
37
-    $dbi = DBIx::Custom->new(
37
+    $dbi = DBIx::Custom->connect(
38 38
         dsn => "dbi:mysql:database=$database;host=localhost;port=10000",
39 39
         user => $user,
40 40
         password => $password
... ...
@@ -42,6 +42,21 @@ eval {
42 42
 };
43 43
 ok(!$@);
44 44
 
45
+eval { $dbi->do('drop table table1') };
46
+$dbi->do('create table table1 (key1 varchar(255), key2 varchar(255)) engine=InnoDB');
47
+
48
+test 'update_or_insert';
49
+$dbi->delete_all(table => 'table1');
50
+$dbi->update_or_insert(
51
+    {key1 => 1, key2 => 2},
52
+    table => 'table1',
53
+    where => {key1 => 1},
54
+    select_option => {append => 'for update'}
55
+);
56
+
57
+my $row = $dbi->select(id => 1, table => 'table1', primary_key => 'key1')->one;
58
+is_deeply($row, {key1 => 1, key2 => 2}, "basic");
59
+
45 60
 # Test memory leaks
46 61
 for (1 .. 200) {
47 62
     $dbi = DBIx::Custom->connect(