- added EXPERIMENTAL type() attribute to DBIx:...
...:Custom::Model
| ... | ... | 
                  @@ -1,5 +1,6 @@  | 
              
| 1 | 1 | 
                  0.1663  | 
              
| 2 | 
                  - - added bind_param_option can set bind_param option  | 
              |
| 2 | 
                  + - added EXPERIMENTAL type() attribute to DBIx::Custom::Model  | 
              |
| 3 | 
                  + - added EXPERIMENTAL bind_param_option can set bind_param option  | 
              |
| 3 | 4 | 
                  to insert(), update(), delete(), select(), insert_at(),  | 
              
| 4 | 5 | 
                  update_at(), delete_at(), select_at(), delete_all(), update_all()  | 
              
| 5 | 6 | 
                  0.1662  | 
              
| ... | ... | 
                  @@ -19,7 +19,7 @@ use DBIx::Custom::Tag;  | 
              
| 19 | 19 | 
                  use DBIx::Custom::Util;  | 
              
| 20 | 20 | 
                  use Encode qw/encode_utf8 decode_utf8/;  | 
              
| 21 | 21 | 
                   | 
              
| 22 | 
                  -our @COMMON_ARGS = qw/table query filter bind_param_option/;  | 
              |
| 22 | 
                  +our @COMMON_ARGS = qw/table query filter type/;  | 
              |
| 23 | 23 | 
                   | 
              
| 24 | 24 | 
                  __PACKAGE__->attr(  | 
              
| 25 | 25 | 
                  [qw/data_source password pid user/],  | 
              
| ... | ... | 
                  @@ -433,15 +433,23 @@ sub execute{
                 | 
              
| 433 | 433 | 
                  }  | 
              
| 434 | 434 | 
                       $filter = {%$filter, %$f};
                 | 
              
| 435 | 435 | 
                   | 
              
| 436 | 
                  + # Type  | 
              |
| 437 | 
                  +    my $type = DBIx::Custom::Util::array_to_hash($args{type});
                 | 
              |
| 438 | 
                  +  | 
              |
| 436 | 439 | 
                  # Bind  | 
              
| 437 | 
                  - my $bind = $self->_bind($params, $query->columns, $filter);  | 
              |
| 440 | 
                  + my $bind = $self->_bind($params, $query->columns, $filter, $type);  | 
              |
| 438 | 441 | 
                   | 
              
| 439 | 442 | 
                  # Execute  | 
              
| 440 | 443 | 
                  my $sth = $query->sth;  | 
              
| 441 | 444 | 
                  my $affected;  | 
              
| 442 | 445 | 
                       eval {
                 | 
              
| 443 | 446 | 
                           for (my $i = 0; $i < @$bind; $i++) {
                 | 
              
| 444 | 
                  - $sth->bind_param($i + 1, $bind->[$i]);  | 
              |
| 447 | 
                  +            if (my $type = $bind->[$i]->{type}) {
                 | 
              |
| 448 | 
                  +                $sth->bind_param($i + 1, $bind->[$i]->{value}, $type);
                 | 
              |
| 449 | 
                  + }  | 
              |
| 450 | 
                  +            else {
                 | 
              |
| 451 | 
                  +                $sth->bind_param($i + 1, $bind->[$i]->{value});
                 | 
              |
| 452 | 
                  + }  | 
              |
| 445 | 453 | 
                  }  | 
              
| 446 | 454 | 
                  $affected = $sth->execute;  | 
              
| 447 | 455 | 
                  };  | 
              
| ... | ... | 
                  @@ -678,6 +686,8 @@ sub include_model {
                 | 
              
| 678 | 686 | 
                           $table_alias = {%$table_alias, %{$model->table_alias}};
                 | 
              
| 679 | 687 | 
                   | 
              
| 680 | 688 | 
                  # Table - Model  | 
              
| 689 | 
                  + croak "Table name is duplicated"  | 
              |
| 690 | 
                  +          if exists $self->{_model_from}->{$model->table};
                 | 
              |
| 681 | 691 | 
                           $self->{_model_from}->{$model->table} = $model->name;
                 | 
              
| 682 | 692 | 
                  }  | 
              
| 683 | 693 | 
                   | 
              
| ... | ... | 
                  @@ -1163,10 +1173,10 @@ sub where {
                 | 
              
| 1163 | 1173 | 
                  }  | 
              
| 1164 | 1174 | 
                   | 
              
| 1165 | 1175 | 
                   sub _bind {
                 | 
              
| 1166 | 
                  - my ($self, $params, $columns, $filter) = @_;  | 
              |
| 1176 | 
                  + my ($self, $params, $columns, $filter, $type) = @_;  | 
              |
| 1167 | 1177 | 
                   | 
              
| 1168 | 1178 | 
                  # bind values  | 
              
| 1169 | 
                  - my @bind;  | 
              |
| 1179 | 
                  + my $bind = [];  | 
              |
| 1170 | 1180 | 
                   | 
              
| 1171 | 1181 | 
                  # Build bind values  | 
              
| 1172 | 1182 | 
                       my $count = {};
                 | 
              
| ... | ... | 
                  @@ -1196,13 +1206,17 @@ sub _bind {
                 | 
              
| 1196 | 1206 | 
                  # Filter  | 
              
| 1197 | 1207 | 
                           my $f = $filter->{$column} || $self->{default_out_filter} || '';
                 | 
              
| 1198 | 1208 | 
                   | 
              
| 1199 | 
                  - push @bind, $f ? $f->($value) : $value;  | 
              |
| 1209 | 
                  + # Type  | 
              |
| 1210 | 
                  +        push @$bind, {
                 | 
              |
| 1211 | 
                  + value => $f ? $f->($value) : $value,  | 
              |
| 1212 | 
                  +            type => $type->{$column}
                 | 
              |
| 1213 | 
                  + };  | 
              |
| 1200 | 1214 | 
                   | 
              
| 1201 | 1215 | 
                  # Count up  | 
              
| 1202 | 1216 | 
                           $count->{$column}++;
                 | 
              
| 1203 | 1217 | 
                  }  | 
              
| 1204 | 1218 | 
                   | 
              
| 1205 | 
                  - return \@bind;  | 
              |
| 1219 | 
                  + return $bind;  | 
              |
| 1206 | 1220 | 
                  }  | 
              
| 1207 | 1221 | 
                   | 
              
| 1208 | 1222 | 
                   sub _connect {
                 | 
              
| ... | ... | 
                  @@ -2403,6 +2417,17 @@ You can check SQL.  | 
              
| 2403 | 2417 | 
                   | 
              
| 2404 | 2418 | 
                  my $sql = $query->sql;  | 
              
| 2405 | 2419 | 
                   | 
              
| 2420 | 
                  +=item C<type> EXPERIMENTAL  | 
              |
| 2421 | 
                  +  | 
              |
| 2422 | 
                  +Specify database data type.  | 
              |
| 2423 | 
                  +  | 
              |
| 2424 | 
                  + $dbi->select(type => [image => DBI::SQL_BLOB]);  | 
              |
| 2425 | 
                  + $dbi->select(type => [[qw/image audio/] => DBI::SQL_BLOB]);  | 
              |
| 2426 | 
                  +  | 
              |
| 2427 | 
                  +This is used to bind paramter by C<bind_param()> of statment handle.  | 
              |
| 2428 | 
                  +  | 
              |
| 2429 | 
                  + $sth->bind_param($pos, $value, DBI::SQL_BLOB);  | 
              |
| 2430 | 
                  +  | 
              |
| 2406 | 2431 | 
                  =back  | 
              
| 2407 | 2432 | 
                   | 
              
| 2408 | 2433 | 
                  =head2 C<select_at()> EXPERIMENTAL  | 
              
| ... | ... | 
                  @@ -16,6 +16,7 @@ __PACKAGE__->attr(  | 
              
| 16 | 16 | 
                       columns => sub { [] },
                 | 
              
| 17 | 17 | 
                       filter => sub { [] },
                 | 
              
| 18 | 18 | 
                       join => sub { [] },
                 | 
              
| 19 | 
                  +    type => sub { [] },
                 | 
              |
| 19 | 20 | 
                       primary_key => sub { [] }
                 | 
              
| 20 | 21 | 
                  );  | 
              
| 21 | 22 | 
                   | 
              
| ... | ... | 
                  @@ -39,6 +40,25 @@ sub AUTOLOAD {
                 | 
              
| 39 | 40 | 
                  }  | 
              
| 40 | 41 | 
                  }  | 
              
| 41 | 42 | 
                   | 
              
| 43 | 
                  +my @methods = qw/insert insert_at update update_at update_all  | 
              |
| 44 | 
                  + delete delete_at delete_all select select_at/;  | 
              |
| 45 | 
                  +foreach my $method (@methods) {
                 | 
              |
| 46 | 
                  +  | 
              |
| 47 | 
                  +    my $code = sub {
                 | 
              |
| 48 | 
                  + my $self = shift;  | 
              |
| 49 | 
                  +  | 
              |
| 50 | 
                  + my @args = (table => $self->table, type => $self->type);  | 
              |
| 51 | 
                  + push @args, (primary_key => $self->primary_key) if $method =~ /_at$/;  | 
              |
| 52 | 
                  + push @args, (join => $self->join) if $method =~ /^select/;  | 
              |
| 53 | 
                  +  | 
              |
| 54 | 
                  + $self->dbi->$method(@args, @_);  | 
              |
| 55 | 
                  + };  | 
              |
| 56 | 
                  +  | 
              |
| 57 | 
                  + no strict 'refs';  | 
              |
| 58 | 
                  + my $class = __PACKAGE__;  | 
              |
| 59 | 
                  +    *{"${class}::$method"} = $code;
                 | 
              |
| 60 | 
                  +}  | 
              |
| 61 | 
                  +  | 
              |
| 42 | 62 | 
                   sub column {
                 | 
              
| 43 | 63 | 
                  my ($self, $table, $columns) = @_;  | 
              
| 44 | 64 | 
                   | 
              
| ... | ... | 
                  @@ -56,43 +76,8 @@ sub column {
                 | 
              
| 56 | 76 | 
                  return $self->dbi->column($table, $columns);  | 
              
| 57 | 77 | 
                  }  | 
              
| 58 | 78 | 
                   | 
              
| 59 | 
                  -sub delete {
                 | 
              |
| 60 | 
                  - my $self = shift;  | 
              |
| 61 | 
                  - $self->dbi->delete(table => $self->table, @_);  | 
              |
| 62 | 
                  -}  | 
              |
| 63 | 
                  -  | 
              |
| 64 | 
                  -sub delete_all {
                 | 
              |
| 65 | 
                  - my $self = shift;  | 
              |
| 66 | 
                  - $self->dbi->delete_all(table => $self->table, @_);  | 
              |
| 67 | 
                  -}  | 
              |
| 68 | 
                  -  | 
              |
| 69 | 
                  -sub delete_at {
                 | 
              |
| 70 | 
                  - my $self = shift;  | 
              |
| 71 | 
                  -  | 
              |
| 72 | 
                  - return $self->dbi->delete_at(  | 
              |
| 73 | 
                  - table => $self->table,  | 
              |
| 74 | 
                  - primary_key => $self->primary_key,  | 
              |
| 75 | 
                  - @_  | 
              |
| 76 | 
                  - );  | 
              |
| 77 | 
                  -}  | 
              |
| 78 | 
                  -  | 
              |
| 79 | 79 | 
                   sub DESTROY { }
                 | 
              
| 80 | 80 | 
                   | 
              
| 81 | 
                  -sub insert {
                 | 
              |
| 82 | 
                  - my $self = shift;  | 
              |
| 83 | 
                  - $self->dbi->insert(table => $self->table, @_);  | 
              |
| 84 | 
                  -}  | 
              |
| 85 | 
                  -  | 
              |
| 86 | 
                  -sub insert_at {
                 | 
              |
| 87 | 
                  - my $self = shift;  | 
              |
| 88 | 
                  -  | 
              |
| 89 | 
                  - return $self->dbi->insert_at(  | 
              |
| 90 | 
                  - table => $self->table,  | 
              |
| 91 | 
                  - primary_key => $self->primary_key,  | 
              |
| 92 | 
                  - @_  | 
              |
| 93 | 
                  - );  | 
              |
| 94 | 
                  -}  | 
              |
| 95 | 
                  -  | 
              |
| 96 | 81 | 
                   sub mycolumn {
                 | 
              
| 97 | 82 | 
                  my $self = shift;  | 
              
| 98 | 83 | 
                  my $table = shift unless ref $_[0];  | 
              
| ... | ... | 
                  @@ -104,46 +89,6 @@ sub mycolumn {
                 | 
              
| 104 | 89 | 
                  return $self->dbi->mycolumn($table, $columns);  | 
              
| 105 | 90 | 
                  }  | 
              
| 106 | 91 | 
                   | 
              
| 107 | 
                  -sub select {
                 | 
              |
| 108 | 
                  - my $self = shift;  | 
              |
| 109 | 
                  - $self->dbi->select(  | 
              |
| 110 | 
                  - table => $self->table,  | 
              |
| 111 | 
                  - join => $self->join,  | 
              |
| 112 | 
                  - @_  | 
              |
| 113 | 
                  - );  | 
              |
| 114 | 
                  -}  | 
              |
| 115 | 
                  -  | 
              |
| 116 | 
                  -sub select_at {
                 | 
              |
| 117 | 
                  - my $self = shift;  | 
              |
| 118 | 
                  -  | 
              |
| 119 | 
                  - return $self->dbi->select_at(  | 
              |
| 120 | 
                  - table => $self->table,  | 
              |
| 121 | 
                  - primary_key => $self->primary_key,  | 
              |
| 122 | 
                  - join => $self->join,  | 
              |
| 123 | 
                  - @_  | 
              |
| 124 | 
                  - );  | 
              |
| 125 | 
                  -}  | 
              |
| 126 | 
                  -  | 
              |
| 127 | 
                  -sub update {
                 | 
              |
| 128 | 
                  - my $self = shift;  | 
              |
| 129 | 
                  - $self->dbi->update(table => $self->table, @_)  | 
              |
| 130 | 
                  -}  | 
              |
| 131 | 
                  -  | 
              |
| 132 | 
                  -sub update_all {
                 | 
              |
| 133 | 
                  - my $self = shift;  | 
              |
| 134 | 
                  - $self->dbi->update_all(table => $self->table, @_);  | 
              |
| 135 | 
                  -}  | 
              |
| 136 | 
                  -  | 
              |
| 137 | 
                  -sub update_at {
                 | 
              |
| 138 | 
                  - my $self = shift;  | 
              |
| 139 | 
                  -  | 
              |
| 140 | 
                  - return $self->dbi->update_at(  | 
              |
| 141 | 
                  - table => $self->table,  | 
              |
| 142 | 
                  - primary_key => $self->primary_key,  | 
              |
| 143 | 
                  - @_  | 
              |
| 144 | 
                  - );  | 
              |
| 145 | 
                  -}  | 
              |
| 146 | 
                  -  | 
              |
| 147 | 92 | 
                  1;  | 
              
| 148 | 93 | 
                   | 
              
| 149 | 94 | 
                  =head1 NAME  | 
              
| ... | ... | 
                  @@ -204,6 +149,15 @@ Generally, this is automatically set from class name.  | 
              
| 204 | 149 | 
                  Foreign key, this is used as C<primary_key> of C<insert_at>,C<update_at()>,  | 
              
| 205 | 150 | 
                  C<delete_at()>,C<select_at()>.  | 
              
| 206 | 151 | 
                   | 
              
| 152 | 
                  +=head2 C<type>  | 
              |
| 153 | 
                  +  | 
              |
| 154 | 
                  + my $type = $model->type;  | 
              |
| 155 | 
                  + $model = $model->type(['image' => DBI::SQL_BLOB]);  | 
              |
| 156 | 
                  +  | 
              |
| 157 | 
                  +Database data type, this is used as type optioon of C<insert()>, C<insert_at()>,  | 
              |
| 158 | 
                  +C<update()>, C<update_at()>, C<update_all>, C<delete()>, C<delete_all()>,  | 
              |
| 159 | 
                  +C<select(), C<select_at()>  | 
              |
| 160 | 
                  +  | 
              |
| 207 | 161 | 
                  =head2 C<view>  | 
              
| 208 | 162 | 
                   | 
              
| 209 | 163 | 
                  my $view = $model->view;  | 
              
| ... | ... | 
                  @@ -265,7 +219,7 @@ you don't have to specify C<table> option.  | 
              
| 265 | 219 | 
                  Same as C<insert_at()> of L<DBIx::Custom> except that  | 
              
| 266 | 220 | 
                  you don't have to specify C<table> and C<primary_key> option.  | 
              
| 267 | 221 | 
                   | 
              
| 268 | 
                  -=head2 C<mycolumn> EXPERIMENTAL  | 
              |
| 222 | 
                  +=head2 C<mycolumn>  | 
              |
| 269 | 223 | 
                   | 
              
| 270 | 224 | 
                  my $column = $self->mycolumn;  | 
              
| 271 | 225 | 
                  my $column = $self->mycolumn(book => ['author', 'title']);  | 
              
| ... | ... | 
                  @@ -1403,11 +1403,13 @@ is_deeply($model->list->fetch_hash_all, [{name => 'a'}], 'basic');
                 | 
              
| 1403 | 1403 | 
                  }  | 
              
| 1404 | 1404 | 
                   $dbi = MyDBI5->connect($NEW_ARGS->{0});
                 | 
              
| 1405 | 1405 | 
                   $dbi->execute("create table company (name)");
                 | 
              
| 1406 | 
                  +$dbi->execute("create table table1 (key1)");
                 | 
              |
| 1406 | 1407 | 
                   $model = $dbi->model('company');
                 | 
              
| 1407 | 1408 | 
                   $model->insert({name => 'a'});
                 | 
              
| 1408 | 1409 | 
                   is_deeply($model->list->fetch_hash_all, [{name => 'a'}], 'include all model');
                 | 
              
| 1410 | 
                  +$dbi->insert(table => 'table1', param => {key1 => 1});
                 | 
              |
| 1409 | 1411 | 
                   $model = $dbi->model('book');
                 | 
              
| 1410 | 
                  -is_deeply($model->list->fetch_hash_all, [{name => 'a'}], 'include all model');
                 | 
              |
| 1412 | 
                  +is_deeply($model->list->fetch_hash_all, [{key1 => 1}], 'include all model');
                 | 
              |
| 1411 | 1413 | 
                   | 
              
| 1412 | 1414 | 
                  test 'primary_key';  | 
              
| 1413 | 1415 | 
                  use MyDBI1;  | 
              
| ... | ... | 
                  @@ -1602,13 +1604,15 @@ test 'model delete_at';  | 
              
| 1602 | 1604 | 
                  }  | 
              
| 1603 | 1605 | 
                   $dbi = MyDBI6->connect($NEW_ARGS->{0});
                 | 
              
| 1604 | 1606 | 
                   $dbi->execute($CREATE_TABLE->{1});
                 | 
              
| 1607 | 
                  +$dbi->execute("create table table2 (key1, key2, key3)");
                 | 
              |
| 1608 | 
                  +$dbi->execute("create table table3 (key1, key2, key3)");
                 | 
              |
| 1605 | 1609 | 
                   $dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2, key3 => 3});
                 | 
              
| 1606 | 1610 | 
                   $dbi->model('table1')->delete_at(where => [1, 2]);
                 | 
              
| 1607 | 1611 | 
                  is_deeply($dbi->select(table => 'table1')->fetch_hash_all, []);  | 
              
| 1608 | 
                  -$dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2, key3 => 3});
                 | 
              |
| 1612 | 
                  +$dbi->insert(table => 'table2', param => {key1 => 1, key2 => 2, key3 => 3});
                 | 
              |
| 1609 | 1613 | 
                   $dbi->model('table1_1')->delete_at(where => [1, 2]);
                 | 
              
| 1610 | 1614 | 
                  is_deeply($dbi->select(table => 'table1')->fetch_hash_all, []);  | 
              
| 1611 | 
                  -$dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2, key3 => 3});
                 | 
              |
| 1615 | 
                  +$dbi->insert(table => 'table3', param => {key1 => 1, key2 => 2, key3 => 3});
                 | 
              |
| 1612 | 1616 | 
                   $dbi->model('table1_3')->delete_at(where => [1, 2]);
                 | 
              
| 1613 | 1617 | 
                  is_deeply($dbi->select(table => 'table1')->fetch_hash_all, []);  | 
              
| 1614 | 1618 | 
                   | 
              
| ... | ... | 
                  @@ -1873,3 +1877,28 @@ $result = $model->select(  | 
              
| 1873 | 1877 | 
                  is_deeply($result->fetch_hash_first,  | 
              
| 1874 | 1878 | 
                             {table2_alias__key1 => 1, table2_alias__key3 => 48});
                 | 
              
| 1875 | 1879 | 
                   | 
              
| 1880 | 
                  +test 'type() option';  | 
              |
| 1881 | 
                  +$dbi = DBIx::Custom->connect(  | 
              |
| 1882 | 
                  + data_source => 'dbi:SQLite:dbname=:memory:',  | 
              |
| 1883 | 
                  +    dbi_option => {
                 | 
              |
| 1884 | 
                  + $DBD::SQLite::VERSION > 1.26 ? (sqlite_unicode => 1) : (unicode => 1)  | 
              |
| 1885 | 
                  + }  | 
              |
| 1886 | 
                  +);  | 
              |
| 1887 | 
                  +my $binary = pack("I3", 1, 2, 3);
                 | 
              |
| 1888 | 
                  +$dbi->execute('create table table1(key1, key2)');
                 | 
              |
| 1889 | 
                  +$dbi->insert(table => 'table1', param => {key1 => $binary, key2 => 'あ'}, type => [key1 => DBI::SQL_BLOB]);
                 | 
              |
| 1890 | 
                  +$result = $dbi->select(table => 'table1');  | 
              |
| 1891 | 
                  +$row = $result->fetch_hash_first;  | 
              |
| 1892 | 
                  +is_deeply($row, {key1 => $binary, key2 => 'あ'}, "basic");
                 | 
              |
| 1893 | 
                  +$result = $dbi->execute('select length(key1) as key1_length from table1');
                 | 
              |
| 1894 | 
                  +$row = $result->fetch_hash_first;  | 
              |
| 1895 | 
                  +is($row->{key1_length}, length $binary);
                 | 
              |
| 1896 | 
                  +  | 
              |
| 1897 | 
                  +$dbi->insert(table => 'table1', param => {key1 => $binary, key2 => 'あ'}, type => [['key1'] => DBI::SQL_BLOB]);
                 | 
              |
| 1898 | 
                  +$result = $dbi->select(table => 'table1');  | 
              |
| 1899 | 
                  +$row = $result->fetch_hash_first;  | 
              |
| 1900 | 
                  +is_deeply($row, {key1 => $binary, key2 => 'あ'}, "basic");
                 | 
              |
| 1901 | 
                  +$result = $dbi->execute('select length(key1) as key1_length from table1');
                 | 
              |
| 1902 | 
                  +$row = $result->fetch_hash_first;  | 
              |
| 1903 | 
                  +is($row->{key1_length}, length $binary);
                 | 
              |
| 1904 | 
                  +  | 
              
| ... | ... | 
                  @@ -2,7 +2,7 @@ package MyModel4::book;  | 
              
| 2 | 2 | 
                   | 
              
| 3 | 3 | 
                  use base 'MyModel4';  | 
              
| 4 | 4 | 
                   | 
              
| 5 | 
                  -sub table { 'company' }
                 | 
              |
| 5 | 
                  +sub table { 'table1' }
                 | 
              |
| 6 | 6 | 
                   | 
              
| 7 | 7 | 
                   sub list { shift->select }
                 | 
              
| 8 | 8 | 
                   | 
              
| ... | ... | 
                  @@ -5,7 +5,7 @@ use warnings;  | 
              
| 5 | 5 | 
                   | 
              
| 6 | 6 | 
                  use base 'MyModel5';  | 
              
| 7 | 7 | 
                   | 
              
| 8 | 
                  -__PACKAGE__->attr(table => 'table1');  | 
              |
| 8 | 
                  +__PACKAGE__->attr(table => 'table2');  | 
              |
| 9 | 9 | 
                   | 
              
| 10 | 10 | 
                   __PACKAGE__->attr('primary_key' => sub { ['key1', 'key2'] });
                 | 
              
| 11 | 11 | 
                   | 
              
| ... | ... | 
                  @@ -6,8 +6,8 @@ use warnings;  | 
              
| 6 | 6 | 
                  use base 'MyModel5';  | 
              
| 7 | 7 | 
                   | 
              
| 8 | 8 | 
                  __PACKAGE__->attr(name => 'table1_3');  | 
              
| 9 | 
                  -__PACKAGE__->attr(table => 'table1');  | 
              |
| 9 | 
                  +__PACKAGE__->attr(table => 'table3');  | 
              |
| 10 | 10 | 
                   | 
              
| 11 | 11 | 
                   __PACKAGE__->attr('primary_key' => sub { ['key1', 'key2'] });
                 | 
              
| 12 | 12 | 
                   | 
              
| 13 | 
                  -1;  | 
              |
| 13 | 
                  +1;  |