| ... | ... | 
                  @@ -1,3 +1,9 @@  | 
              
| 1 | 
                  +0.1720  | 
              |
| 2 | 
                  + - removed placeholder count check  | 
              |
| 3 | 
                  + - added EXPERIMENTAL execute method's id and primary key option.  | 
              |
| 4 | 
                  + - added EXPERIMENTAL DBIx::Custom::Model execute method  | 
              |
| 5 | 
                  +0.1719  | 
              |
| 6 | 
                  + - DBIx::Custom support Microsoft Access through DBD::ODBC  | 
              |
| 1 | 7 | 
                  0.1718  | 
              
| 2 | 8 | 
                  - added EXPERIMENTAL DBIx::Custom::Model call_dbi method  | 
              
| 3 | 9 | 
                  - added EXPERIMENTAL count method  | 
              
| ... | ... | 
                  @@ -1,7 +1,7 @@  | 
              
| 1 | 1 | 
                  package DBIx::Custom;  | 
              
| 2 | 2 | 
                  use Object::Simple -base;  | 
              
| 3 | 3 | 
                   | 
              
| 4 | 
                  -our $VERSION = '0.1718';  | 
              |
| 4 | 
                  +our $VERSION = '0.1720';  | 
              |
| 5 | 5 | 
                  use 5.008001;  | 
              
| 6 | 6 | 
                   | 
              
| 7 | 7 | 
                  use Carp 'croak';  | 
              
| ... | ... | 
                  @@ -397,6 +397,17 @@ sub execute {
                 | 
              
| 397 | 397 | 
                       my $query_return = delete $args{query};
                 | 
              
| 398 | 398 | 
                       my $table_alias = delete $args{table_alias} || {};
                 | 
              
| 399 | 399 | 
                       my $sqlfilter = $args{sqlfilter};
                 | 
              
| 400 | 
                  +    my $id = delete $args{id};
                 | 
              |
| 401 | 
                  +    my $primary_key = delete $args{primary_key};
                 | 
              |
| 402 | 
                  + croak "insert method primary_key option " .  | 
              |
| 403 | 
                  + "must be specified when id is specified " . _subname  | 
              |
| 404 | 
                  + if defined $id && !defined $primary_key;  | 
              |
| 405 | 
                  + $primary_key = [$primary_key] unless ref $primary_key eq 'ARRAY';  | 
              |
| 406 | 
                  +  | 
              |
| 407 | 
                  +    if (defined $id) {
                 | 
              |
| 408 | 
                  + my $id_param = $self->_create_param_from_id($id, $primary_key);  | 
              |
| 409 | 
                  + $param = $self->merge_param($id_param, $param);  | 
              |
| 410 | 
                  + }  | 
              |
| 400 | 411 | 
                   | 
              
| 401 | 412 | 
                  # Check argument names  | 
              
| 402 | 413 | 
                       foreach my $name (keys %args) {
                 | 
              
| ... | ... | 
                  @@ -2521,6 +2532,28 @@ registered by by C<register_filter>.  | 
              
| 2521 | 2532 | 
                  This filter is executed before data is saved into database.  | 
              
| 2522 | 2533 | 
                  and before type rule filter is executed.  | 
              
| 2523 | 2534 | 
                   | 
              
| 2535 | 
                  +=item C<id>  | 
              |
| 2536 | 
                  +  | 
              |
| 2537 | 
                  + id => 4  | 
              |
| 2538 | 
                  + id => [4, 5]  | 
              |
| 2539 | 
                  +  | 
              |
| 2540 | 
                  +ID corresponding to C<primary_key>.  | 
              |
| 2541 | 
                  +You can delete rows by C<id> and C<primary_key>.  | 
              |
| 2542 | 
                  +  | 
              |
| 2543 | 
                  + $dbi->execute(  | 
              |
| 2544 | 
                  + "select * from book where id1 = :id1 and id2 = :id2",  | 
              |
| 2545 | 
                  +        {},
                 | 
              |
| 2546 | 
                  + parimary_key => ['id1', 'id2'],  | 
              |
| 2547 | 
                  + id => [4, 5],  | 
              |
| 2548 | 
                  + );  | 
              |
| 2549 | 
                  +  | 
              |
| 2550 | 
                  +The above is same as the followin one.  | 
              |
| 2551 | 
                  +  | 
              |
| 2552 | 
                  + $dbi->execute(  | 
              |
| 2553 | 
                  + "select * from book where id1 = :id1 and id2 = :id2",  | 
              |
| 2554 | 
                  +        {id1 => 4, id2 => 5}
                 | 
              |
| 2555 | 
                  + );  | 
              |
| 2556 | 
                  +  | 
              |
| 2524 | 2557 | 
                  =item C<query>  | 
              
| 2525 | 2558 | 
                   | 
              
| 2526 | 2559 | 
                  query => 1  | 
              
| ... | ... | 
                  @@ -2558,6 +2591,10 @@ Note that $row must be simple hash reference, such as  | 
              
| 2558 | 2591 | 
                   {title => 'Perl', author => 'Ken'}.
                 | 
              
| 2559 | 2592 | 
                  and don't forget to sort $row values by $row key asc order.  | 
              
| 2560 | 2593 | 
                   | 
              
| 2594 | 
                  +=item C<primary_key>  | 
              |
| 2595 | 
                  +  | 
              |
| 2596 | 
                  +See C<id> option.  | 
              |
| 2597 | 
                  +  | 
              |
| 2561 | 2598 | 
                  =item C<sqlfilter EXPERIMENTAL>  | 
              
| 2562 | 2599 | 
                   | 
              
| 2563 | 2600 | 
                  SQL filter function.  | 
              
| ... | ... | 
                  @@ -67,6 +67,12 @@ sub call_dbi {
                 | 
              
| 67 | 67 | 
                  return $self->dbi->$method(@args, @_);  | 
              
| 68 | 68 | 
                  }  | 
              
| 69 | 69 | 
                   | 
              
| 70 | 
                  +sub execute {
                 | 
              |
| 71 | 
                  + my $self = shift;  | 
              |
| 72 | 
                  + push @_, ($_ => $self->$_) for qw/table bind_type primary_key type/;  | 
              |
| 73 | 
                  + return $self->dbi->execute(@_);  | 
              |
| 74 | 
                  +}  | 
              |
| 75 | 
                  +  | 
              |
| 70 | 76 | 
                   sub DESTROY { }
                 | 
              
| 71 | 77 | 
                   | 
              
| 72 | 78 | 
                   sub method {
                 | 
              
| ... | ... | 
                  @@ -116,9 +122,9 @@ DBIx::Custom::Model - Model  | 
              
| 116 | 122 | 
                   | 
              
| 117 | 123 | 
                  =head1 SYNOPSIS  | 
              
| 118 | 124 | 
                   | 
              
| 119 | 
                  -use DBIx::Custom::Table;  | 
              |
| 125 | 
                  +use DBIx::Custom::Model;  | 
              |
| 120 | 126 | 
                   | 
              
| 121 | 
                  -my $table = DBIx::Custom::Model->new(table => 'books');  | 
              |
| 127 | 
                  +my $model = DBIx::Custom::Model->new(table => 'books');  | 
              |
| 122 | 128 | 
                   | 
              
| 123 | 129 | 
                  =head1 ATTRIBUTES  | 
              
| 124 | 130 | 
                   | 
              
| ... | ... | 
                  @@ -148,7 +154,7 @@ C<delete>, and C<select> method.  | 
              
| 148 | 154 | 
                   | 
              
| 149 | 155 | 
                  =head2 C<table>  | 
              
| 150 | 156 | 
                   | 
              
| 151 | 
                  - my $table = $model->table;  | 
              |
| 157 | 
                  + my $model = $model->table;  | 
              |
| 152 | 158 | 
                       $model = $model->table('book');
                 | 
              
| 153 | 159 | 
                   | 
              
| 154 | 160 | 
                  Table name, this is passed to C<select> method.  | 
              
| ... | ... | 
                  @@ -193,24 +199,31 @@ Options is same as C<select> method's ones.  | 
              
| 193 | 199 | 
                   | 
              
| 194 | 200 | 
                  =head2 C<delete>  | 
              
| 195 | 201 | 
                   | 
              
| 196 | 
                  - $table->delete(...);  | 
              |
| 202 | 
                  + $model->delete(...);  | 
              |
| 197 | 203 | 
                   | 
              
| 198 | 204 | 
                  Same as C<delete> of L<DBIx::Custom> except that  | 
              
| 199 | 
                  -you don't have to specify C<table> option.  | 
              |
| 205 | 
                  +you don't have to specify C<table> and C<primary_key> option.  | 
              |
| 200 | 206 | 
                   | 
              
| 201 | 207 | 
                  =head2 C<delete_all>  | 
              
| 202 | 208 | 
                   | 
              
| 203 | 
                  - $table->delete_all(...);  | 
              |
| 209 | 
                  + $model->delete_all(...);  | 
              |
| 204 | 210 | 
                   | 
              
| 205 | 211 | 
                  Same as C<delete_all> of L<DBIx::Custom> except that  | 
              
| 206 | 
                  -you don't have to specify C<table> option.  | 
              |
| 212 | 
                  +you don't have to specify C<table> and C<primary_key> option.  | 
              |
| 213 | 
                  +  | 
              |
| 214 | 
                  +=head2 C<execute EXPERIMENTAL>  | 
              |
| 215 | 
                  +  | 
              |
| 216 | 
                  + $model->execute(...);  | 
              |
| 217 | 
                  +  | 
              |
| 218 | 
                  +Same as C<execute> of L<DBIx::Custom> except that  | 
              |
| 219 | 
                  +you don't have to specify C<table> and C<primary_key> option.  | 
              |
| 207 | 220 | 
                   | 
              
| 208 | 221 | 
                  =head2 C<insert>  | 
              
| 209 | 222 | 
                   | 
              
| 210 | 
                  - $table->insert(...);  | 
              |
| 223 | 
                  + $model->insert(...);  | 
              |
| 211 | 224 | 
                   | 
              
| 212 | 225 | 
                  Same as C<insert> of L<DBIx::Custom> except that  | 
              
| 213 | 
                  -you don't have to specify C<table> option.  | 
              |
| 226 | 
                  +you don't have to specify C<table> and C<primary_key> option.  | 
              |
| 214 | 227 | 
                   | 
              
| 215 | 228 | 
                  =head2 C<method>  | 
              
| 216 | 229 | 
                   | 
              
| ... | ... | 
                  @@ -247,29 +260,29 @@ If column names is omitted, C<columns> attribute of the model is used.  | 
              
| 247 | 260 | 
                   | 
              
| 248 | 261 | 
                  =head2 C<new>  | 
              
| 249 | 262 | 
                   | 
              
| 250 | 
                  - my $table = DBIx::Custom::Table->new;  | 
              |
| 263 | 
                  + my $model = DBIx::Custom::Model->new;  | 
              |
| 251 | 264 | 
                   | 
              
| 252 | 
                  -Create a L<DBIx::Custom::Table> object.  | 
              |
| 265 | 
                  +Create a L<DBIx::Custom::Model> object.  | 
              |
| 253 | 266 | 
                   | 
              
| 254 | 267 | 
                  =head2 C<select>  | 
              
| 255 | 268 | 
                   | 
              
| 256 | 
                  - $table->select(...);  | 
              |
| 269 | 
                  + $model->select(...);  | 
              |
| 257 | 270 | 
                   | 
              
| 258 | 271 | 
                  Same as C<select> of L<DBIx::Custom> except that  | 
              
| 259 | 
                  -you don't have to specify C<table> option.  | 
              |
| 272 | 
                  +you don't have to specify C<table>, C<primary_key> and C<jon> option.  | 
              |
| 260 | 273 | 
                   | 
              
| 261 | 274 | 
                  =head2 C<update>  | 
              
| 262 | 275 | 
                   | 
              
| 263 | 
                  - $table->update(...);  | 
              |
| 276 | 
                  + $model->update(...);  | 
              |
| 264 | 277 | 
                   | 
              
| 265 | 278 | 
                  Same as C<update> of L<DBIx::Custom> except that  | 
              
| 266 | 
                  -you don't have to specify C<table> option.  | 
              |
| 279 | 
                  +you don't have to specify C<table> and C<primary_key> option.  | 
              |
| 267 | 280 | 
                   | 
              
| 268 | 281 | 
                  =head2 C<update_all>  | 
              
| 269 | 282 | 
                   | 
              
| 270 | 
                  - $table->update_all(param => \%param);  | 
              |
| 283 | 
                  + $model->update_all(param => \%param);  | 
              |
| 271 | 284 | 
                   | 
              
| 272 | 285 | 
                  Same as C<update_all> of L<DBIx::Custom> except that  | 
              
| 273 | 
                  -you don't have to specify table name.  | 
              |
| 286 | 
                  +you don't have to specify C<table> and C<primary_key> option.  | 
              |
| 274 | 287 | 
                   | 
              
| 275 | 288 | 
                  =cut  | 
              
| ... | ... | 
                  @@ -42,28 +42,10 @@ sub build_query {
                 | 
              
| 42 | 42 | 
                   | 
              
| 43 | 43 | 
                  my $sql = $query->sql;  | 
              
| 44 | 44 | 
                  $query->sql($sql);  | 
              
| 45 | 
                  -  | 
              |
| 46 | 
                  - # Check placeholder count  | 
              |
| 47 | 
                  -    croak qq{Placeholder count in "$sql" must be same as column count}
                 | 
              |
| 48 | 
                  - . _subname  | 
              |
| 49 | 
                  -      unless $self->_placeholder_count($sql) eq @{$query->columns};
                 | 
              |
| 50 | 45 | 
                   | 
              
| 51 | 46 | 
                  return $query;  | 
              
| 52 | 47 | 
                  }  | 
              
| 53 | 48 | 
                   | 
              
| 54 | 
                  -sub _placeholder_count {
                 | 
              |
| 55 | 
                  - my ($self, $sql) = @_;  | 
              |
| 56 | 
                  -  | 
              |
| 57 | 
                  - # Count  | 
              |
| 58 | 
                  - $sql ||= '';  | 
              |
| 59 | 
                  - my $count = 0;  | 
              |
| 60 | 
                  - my $pos = -1;  | 
              |
| 61 | 
                  -    while (($pos = index($sql, '?', $pos + 1)) != -1) {
                 | 
              |
| 62 | 
                  - $count++;  | 
              |
| 63 | 
                  - }  | 
              |
| 64 | 
                  - return $count;  | 
              |
| 65 | 
                  -}  | 
              |
| 66 | 
                  -  | 
              |
| 67 | 49 | 
                   sub _parse_parameter {
                 | 
              
| 68 | 50 | 
                  my ($self, $source) = @_;  | 
              
| 69 | 51 | 
                   | 
              
| ... | ... | 
                  @@ -2767,6 +2767,27 @@ $rows = [  | 
              
| 2767 | 2767 | 
                  );  | 
              
| 2768 | 2768 | 
                  }  | 
              
| 2769 | 2769 | 
                   | 
              
| 2770 | 
                  +$dbi->execute("drop table $table1");
                 | 
              |
| 2771 | 
                  +$dbi->execute($create_table1_highperformance);  | 
              |
| 2772 | 
                  +$rows = [  | 
              |
| 2773 | 
                  +    {$key7 => 10, $key6 => 2, $key5 => 3, $key4 => 4, $key3 => 5, $key2 => 5},
                 | 
              |
| 2774 | 
                  +    {$key7 => 11, $key6 => 2, $key5 => 3, $key4 => 4, $key3 => 5, $key2 => 6},
                 | 
              |
| 2775 | 
                  +];  | 
              |
| 2776 | 
                  +{
                 | 
              |
| 2777 | 
                  + $model = $dbi->create_model(table => $table1, primary_key => $key1);  | 
              |
| 2778 | 
                  + my $query;  | 
              |
| 2779 | 
                  +    foreach my $row (@$rows) {
                 | 
              |
| 2780 | 
                  + $query ||= $model->insert($row, id => 1, query => 1);  | 
              |
| 2781 | 
                  +      $model->execute($query, $row, id => 1, filter => {$key7 => sub { $_[0] * 2 }});
                 | 
              |
| 2782 | 
                  + }  | 
              |
| 2783 | 
                  + is_deeply($dbi->select(table => $table1, append => 'order by key2')->all,  | 
              |
| 2784 | 
                  + [  | 
              |
| 2785 | 
                  +          {$key7 => 20, $key6 => 2, $key5 => 3, $key4 => 4, $key3 => 5, $key2 => 5, $key1 => 1},
                 | 
              |
| 2786 | 
                  +          {$key7 => 22, $key6 => 2, $key5 => 3, $key4 => 4, $key3 => 5, $key2 => 6, $key1 => 1},
                 | 
              |
| 2787 | 
                  + ]  | 
              |
| 2788 | 
                  + );  | 
              |
| 2789 | 
                  +}  | 
              |
| 2790 | 
                  +  | 
              |
| 2770 | 2791 | 
                  test 'result';  | 
              
| 2771 | 2792 | 
                  $dbi = DBIx::Custom->connect;  | 
              
| 2772 | 2793 | 
                   eval { $dbi->execute("drop table $table1") };
                 | 
              
| ... | ... | 
                  @@ -2909,15 +2930,6 @@ $dbi->register_tag(  | 
              
| 2909 | 2930 | 
                  );  | 
              
| 2910 | 2931 | 
                   | 
              
| 2911 | 2932 | 
                   | 
              
| 2912 | 
                  -$dbi->register_tag(  | 
              |
| 2913 | 
                  -    a => sub {
                 | 
              |
| 2914 | 
                  - return ["? ? ?", ['']];  | 
              |
| 2915 | 
                  - }  | 
              |
| 2916 | 
                  -);  | 
              |
| 2917 | 
                  -eval{$builder->build_query("{a}")};
                 | 
              |
| 2918 | 
                  -like($@, qr/\QPlaceholder count/, "placeholder count is invalid");  | 
              |
| 2919 | 
                  -  | 
              |
| 2920 | 
                  -  | 
              |
| 2921 | 2933 | 
                  test 'Default tag Error case';  | 
              
| 2922 | 2934 | 
                   eval{$builder->build_query("{= }")};
                 | 
              
| 2923 | 2935 | 
                   like($@, qr/Column name must be specified in tag "{= }"/, "basic '=' : key not exist");
                 |