The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Build.PL 15
Changes 09
MANIFEST 03
META.json 1017
META.yml 729
README.md 1228
lib/Teng/Schema/Declare.pm 11
lib/Teng/Schema/Table.pm 124
lib/Teng.pm 761
minil.toml 02
t/001_basic/015_row_class.t 015
t/001_basic/026_fork.t 02
t/001_basic/027_fork_self_reconnect.t 02
t/001_basic/028_fork_self_reconnect_dbh.t 02
t/001_basic/035_new_row_from_hash.t 039
t/002_common/023_multi_pk.t 22
t/999_regression/deflate_bug.t 01
xt/mysql/multi_pk_autoincr.t 053
18 files changed (This is a version diff) 52275
@@ -25,12 +25,16 @@ my %args = (
 
     name            => 'Teng',
     module_name     => 'Teng',
-    allow_pure_perl => 0,
+    allow_pureperl => 0,
 
     script_files => [glob('script/*'), glob('bin/*')],
+    c_source     => [qw()],
+    PL_files => {},
 
     test_files           => ((-d '.git' || $ENV{RELEASE_TESTING}) && -d 'xt') ? 't/ xt/' : 't/',
     recursive_test_files => 1,
+
+    
 );
 if (-d 'share') {
     $args{share_dir} = 'share';
@@ -1,5 +1,14 @@
 Revision history for Perl extension Teng
 
+0.22 2014-04-04T05:22:48Z
+        - FIXED: Allow calling `row_class` before `name` for Teng::Schema::Declare (thanks GeJ)
+        - MODIFY: Allow specify `txn_manager_class` parameter for Teng (thanks GeJ)
+
+0.21 2014-02-14T02:59:46Z
+        - ADD:: Implemented new_row_from_hash which just creates new Teng::Row instance with column data. (thanks karupanerura)
+        - MODIFY: Fixed around multiple primary key. (thanks Songmu)
+
+
 0.20 2013-08-21T07:39:25Z
         - Re-release for override UNAUTHORIZED flag (same as 0.19)
 
@@ -23,6 +23,7 @@ lib/Teng/Schema/Declare.pm
 lib/Teng/Schema/Dumper.pm
 lib/Teng/Schema/Loader.pm
 lib/Teng/Schema/Table.pm
+minil.toml
 t/001_basic/001_compile.t
 t/001_basic/002_schema.t
 t/001_basic/003_schema_loader.t
@@ -46,6 +47,7 @@ t/001_basic/030_reconnect_ping.t
 t/001_basic/032_reconnect_no_ping.t
 t/001_basic/033_load_plugin_with_args.t
 t/001_basic/034_execute.t
+t/001_basic/035_new_row_from_hash.t
 t/002_common/000_new.t
 t/002_common/001_insert.t
 t/002_common/002_update.t
@@ -106,6 +108,7 @@ xt/mysql/004_schema_dumper.t
 xt/mysql/bulk_insert.t
 xt/mysql/common.t
 xt/mysql/fork.t
+xt/mysql/multi_pk_autoincr.t
 xt/mysql/pager_mysql_found_rows.t
 xt/mysql/transaction.t
 xt/perlcritic.t
@@ -4,8 +4,10 @@
       "Atsushi Kobayashi  C<< <nekokak __at__ gmail.com> >>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Minilla/v0.4.5",
-   "license" : "perl_5",
+   "generated_by" : "Minilla/v0.11.0",
+   "license" : [
+      "perl_5"
+   ],
    "meta-spec" : {
       "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
       "version" : "2"
@@ -19,7 +21,8 @@
          "share",
          "eg",
          "examples",
-         "author"
+         "author",
+         "builder"
       ]
    },
    "prereqs" : {
@@ -65,7 +68,7 @@
    "provides" : {
       "Teng" : {
          "file" : "lib/Teng.pm",
-         "version" : "0.20"
+         "version" : "0.22"
       },
       "Teng::Iterator" : {
          "file" : "lib/Teng/Iterator.pm"
@@ -130,7 +133,8 @@
          "web" : "https://github.com/nekokak/p5-Teng"
       }
    },
-   "version" : "0.20",
+   "version" : "0.22",
+   "x_authority" : "cpan:NEKOKAK",
    "x_contributors" : [
       "Yuki Ibe <yibe@yibe.org>",
       "libkenta <libkenta@gmail.com>",
@@ -145,14 +149,17 @@
       "Atsushi Kato <ktat@cpan.org>",
       "ktat <ktat.is@gmail.com>",
       "Kazuhiro Osawa <yappo@shibuya.pl>",
-      "karupanerura <karupa@cpan.org>",
-      "Kenta Sato <k-sato@mfac.jp>",
       "Masahiro Chiba <chiba@everqueue.com>",
-      "Masayuki Matsuki <y.songmu@gmail.com>",
       "Atsushi Kobayashi <nekokak@gmail.com>",
       "Jun Kuriyama <kuriyama@s2factory.co.jp>",
       "Masahiro Nagano <kazeburo@gmail.com>",
-      "cho45 <cho45@lowreal.net>",
-      "Tokuhiro Matsuno <tokuhirom@gmail.com>"
+      "Tokuhiro Matsuno <tokuhirom@gmail.com>",
+      "k-sato <k-sato@mfac.jp>",
+      "Songmu <y.songmu@gmail.com>",
+      "ITO Nobuaki <daydream.trippers@gmail.com>",
+      "karupanerura <karupa@cpan.org>",
+      "Kenichi Ishigaki <ishigaki@cpan.org>",
+      "Geraud CONTINSOUZAS <geraud@hyaku.nijuu.nana>",
+      "cho45 <cho45@lowreal.net>"
    ]
 }
@@ -13,7 +13,7 @@ configure_requires:
   CPAN::Meta::Prereqs: 0
   Module::Build: 0.38
 dynamic_config: 0
-generated_by: 'Minilla/v0.4.5, CPAN::Meta::Converter version 2.131490'
+generated_by: 'Minilla/v0.11.0, CPAN::Meta::Converter version 2.120921'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -28,44 +28,62 @@ no_index:
     - eg
     - examples
     - author
+    - builder
 provides:
   Teng:
     file: lib/Teng.pm
-    version: 0.20
+    version: 0.22
   Teng::Iterator:
     file: lib/Teng/Iterator.pm
+    version: 0
   Teng::Plugin::BulkInsert:
     file: lib/Teng/Plugin/BulkInsert.pm
+    version: 0
   Teng::Plugin::Count:
     file: lib/Teng/Plugin/Count.pm
+    version: 0
   Teng::Plugin::FindOrCreate:
     file: lib/Teng/Plugin/FindOrCreate.pm
+    version: 0
   Teng::Plugin::Lookup:
     file: lib/Teng/Plugin/Lookup.pm
+    version: 0
   Teng::Plugin::Pager:
     file: lib/Teng/Plugin/Pager.pm
+    version: 0
   Teng::Plugin::Pager::MySQLFoundRows:
     file: lib/Teng/Plugin/Pager/MySQLFoundRows.pm
+    version: 0
   Teng::Plugin::Replace:
     file: lib/Teng/Plugin/Replace.pm
+    version: 0
   Teng::Plugin::SQLPager:
     file: lib/Teng/Plugin/SQLPager.pm
+    version: 0
   Teng::Plugin::SingleBySQL:
     file: lib/Teng/Plugin/SingleBySQL.pm
+    version: 0
   Teng::QueryBuilder:
     file: lib/Teng/QueryBuilder.pm
+    version: 0
   Teng::Row:
     file: lib/Teng/Row.pm
+    version: 0
   Teng::Schema:
     file: lib/Teng/Schema.pm
+    version: 0
   Teng::Schema::Declare:
     file: lib/Teng/Schema/Declare.pm
+    version: 0
   Teng::Schema::Dumper:
     file: lib/Teng/Schema/Dumper.pm
+    version: 0
   Teng::Schema::Loader:
     file: lib/Teng/Schema/Loader.pm
+    version: 0
   Teng::Schema::Table:
     file: lib/Teng/Schema/Table.pm
+    version: 0
 requires:
   Carp: 0
   Class::Accessor::Lite: 0.05
@@ -81,7 +99,8 @@ resources:
   bugtracker: https://github.com/nekokak/p5-Teng/issues
   homepage: https://github.com/nekokak/p5-Teng
   repository: git://github.com/nekokak/p5-Teng.git
-version: 0.20
+version: 0.22
+x_authority: cpan:NEKOKAK
 x_contributors:
   - 'Yuki Ibe <yibe@yibe.org>'
   - 'libkenta <libkenta@gmail.com>'
@@ -96,12 +115,15 @@ x_contributors:
   - 'Atsushi Kato <ktat@cpan.org>'
   - 'ktat <ktat.is@gmail.com>'
   - 'Kazuhiro Osawa <yappo@shibuya.pl>'
-  - 'karupanerura <karupa@cpan.org>'
-  - 'Kenta Sato <k-sato@mfac.jp>'
   - 'Masahiro Chiba <chiba@everqueue.com>'
-  - 'Masayuki Matsuki <y.songmu@gmail.com>'
   - 'Atsushi Kobayashi <nekokak@gmail.com>'
   - 'Jun Kuriyama <kuriyama@s2factory.co.jp>'
   - 'Masahiro Nagano <kazeburo@gmail.com>'
-  - 'cho45 <cho45@lowreal.net>'
   - 'Tokuhiro Matsuno <tokuhirom@gmail.com>'
+  - 'k-sato <k-sato@mfac.jp>'
+  - 'Songmu <y.songmu@gmail.com>'
+  - 'ITO Nobuaki <daydream.trippers@gmail.com>'
+  - 'karupanerura <karupa@cpan.org>'
+  - 'Kenichi Ishigaki <ishigaki@cpan.org>'
+  - 'Geraud CONTINSOUZAS <geraud@hyaku.nijuu.nana>'
+  - 'cho45 <cho45@lowreal.net>'
@@ -1,3 +1,7 @@
+# NAME
+
+Teng - very simple DBI wrapper/ORMapper
+
 # SYNOPSIS
 
     my $db = MyDB->new({ connect_info => [ 'dbi:SQLite:' ] });
@@ -36,7 +40,6 @@ in your script.
 
     use Your::Model;
     
-
     my $teng = Your::Model->new(\%args);
     # insert new record.
     my $row = $teng->insert('user',
@@ -145,6 +148,11 @@ Teng provides a number of methods to all your classes,
         Specifies the schema class to use.
         By default {YOUR\_MODEL\_CLASS}::Schema is used.
 
+    - `txn_manager_class`
+
+        Specifies the transaction manager class.
+        By default DBIx::TransactionManager is used.
+
     - `suppress_row_objects`
 
         Specifies the row object creation mode. By default this value is `false`.
@@ -258,7 +266,7 @@ Teng provides a number of methods to all your classes,
     simple search method.
     search method get Teng::Iterator's instance object.
 
-    see [Teng::Iterator](http://search.cpan.org/perldoc?Teng::Iterator)
+    see [Teng::Iterator](https://metacpan.org/pod/Teng::Iterator)
 
     get iterator:
 
@@ -275,6 +283,14 @@ Teng provides a number of methods to all your classes,
 
         my $row = $teng->single('user',{id =>1});
 
+- `$row = $teng->new_row_from_hash($table_name, \%row_data, [$sql])`
+
+    create row object from data. (not fetch from db.)
+    It's useful in such as testing.
+
+        my $row = $teng->new_row_from_hash('user', { id => 1, foo => "bar" });
+        say $row->foo; # say bar
+
 - `$itr = $teng->search_named($sql, [\%bind_values, [$table_name]])`
 
     execute named query
@@ -349,15 +365,15 @@ Teng provides a number of methods to all your classes,
 
     If an exception occurs, or the guard object otherwise leaves the scope
     before `$txn->commit` is called, the transaction will be rolled
-    back by an explicit ["txn\_rollback"](#txn\_rollback) call. In essence this is akin to
-    using a ["txn\_begin"](#txn\_begin)/["txn\_commit"](#txn\_commit) pair, without having to worry
-    about calling ["txn\_rollback"](#txn\_rollback) at the right places. Note that since there
+    back by an explicit ["txn\_rollback"](#txn_rollback) call. In essence this is akin to
+    using a ["txn\_begin"](#txn_begin)/["txn\_commit"](#txn_commit) pair, without having to worry
+    about calling ["txn\_rollback"](#txn_rollback) at the right places. Note that since there
     is no defined code closure, there will be no retries and other magic upon
     database disconnection.
 
 - `$txn_manager = $teng->txn_manager`
 
-    Get the DBIx::TransactionManager instance.
+    Create the transaction manager instance with specified `txn_manager_class`.
 
 - `$teng->txn_begin`
 
@@ -377,7 +393,7 @@ Teng provides a number of methods to all your classes,
 
 - `$teng->do($sql, [\%option, @bind_values])`
 
-    Execute the query specified by `$sql`, using `%option` and `@bind_values` as necessary. This pretty much a wrapper around [http://search.cpan.org/dist/DBI/DBI.pm\#do](http://search.cpan.org/dist/DBI/DBI.pm\#do)
+    Execute the query specified by `$sql`, using `%option` and `@bind_values` as necessary. This pretty much a wrapper around [http://search.cpan.org/dist/DBI/DBI.pm#do](http://search.cpan.org/dist/DBI/DBI.pm#do)
 
 - `$teng->dbh`
 
@@ -421,17 +437,17 @@ Teng provides a number of methods to all your classes,
 
 - How do you use display the profiling result?
 
-    use [Devel::KYTProf](http://search.cpan.org/perldoc?Devel::KYTProf).
+    use [Devel::KYTProf](https://metacpan.org/pod/Devel::KYTProf).
 
 # TRIGGERS
 
-Teng does not support triggers (NOTE: do not confuse it with SQL triggers - we're talking about Perl level triggers). If you really want to hook into the various methods, use something like [Moose](http://search.cpan.org/perldoc?Moose), [Mouse](http://search.cpan.org/perldoc?Mouse), and [Class::Method::Modifiers](http://search.cpan.org/perldoc?Class::Method::Modifiers).
+Teng does not support triggers (NOTE: do not confuse it with SQL triggers - we're talking about Perl level triggers). If you really want to hook into the various methods, use something like [Moose](https://metacpan.org/pod/Moose), [Mouse](https://metacpan.org/pod/Mouse), and [Class::Method::Modifiers](https://metacpan.org/pod/Class::Method::Modifiers).
 
 # SEE ALSO
 
 ## Fork
 
-This module was forked from [DBIx::Skinny](http://search.cpan.org/perldoc?DBIx::Skinny), around version 0.0732.
+This module was forked from [DBIx::Skinny](https://metacpan.org/pod/DBIx::Skinny), around version 0.0732.
 many incompatible changes have been made.
 
 # BUGS AND LIMITATIONS
@@ -458,7 +474,7 @@ Daisuke Maki `<daisuke@endeworks.jp>`
 
 # LICENCE AND COPYRIGHT
 
-Copyright (c) 2010, the Teng ["AUTHOR"](#AUTHOR). All rights reserved.
+Copyright (c) 2010, the Teng ["AUTHOR"](#author). All rights reserved.
 
 This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself. See [perlartistic](http://search.cpan.org/perldoc?perlartistic).
+modify it under the same terms as Perl itself. See [perlartistic](https://metacpan.org/pod/perlartistic).
@@ -91,7 +91,7 @@ sub table(&) {
     no warnings 'once';
     local *{"$dest_class\::name"}      = sub ($) { 
         $table_name = shift;
-        $row_class  = row_namespace($table_name);
+        $row_class  ||= row_namespace($table_name);
     };
     local *{"$dest_class\::pk"}        = sub (@) { @table_pk = @_ };
     local *{"$dest_class\::columns"}   = sub (@) { @table_columns = @_ };
@@ -139,21 +139,13 @@ create new Teng::Schema::Table's object.
 
 get column SQL type.
 
-=item $table->get_deflator
+=item $table->add_deflator($column_rule, $code)
 
-get deflate code reference.
+add deflate code reference.
 
-=item $table->get_inflator
+=item $table->add_inflator($column_rule, $code)
 
-get inflate code reference.
-
-=item $table->set_deflator
-
-set deflate code reference.
-
-=item $table->set_inflator
-
-set inflate code reference.
+add inflate code reference.
 
 =item $table->call_deflate
 
@@ -24,7 +24,7 @@ use Class::Accessor::Lite
     )]
 ;
 
-our $VERSION = '0.20';
+our $VERSION = '0.22';
 
 sub load_plugin {
     my ($class, $pkg, $opt) = @_;
@@ -341,14 +341,27 @@ sub insert {
 
     my $table = $self->schema->get_table($table_name);
     my $pk = $table->primary_keys();
-    if (scalar(@$pk) == 1 && not defined $args->{$pk->[0]}) {
-        $args->{$pk->[0]} = $self->_last_insert_id($table_name);
+
+    my @missing_primary_keys = grep { not defined $args->{$_} } @$pk;
+    if (@missing_primary_keys == 1) {
+        $args->{$missing_primary_keys[0]} = $self->_last_insert_id($table_name);
     }
 
     return $args if $self->suppress_row_objects;
 
-    if (scalar(@$pk) == 1) {
-        return $self->single($table_name, {$pk->[0] => $args->{$pk->[0]}});
+    my %where;
+    my $refetch = 1;
+    for my $key (@$pk) {
+        if (ref $args->{$key}) {
+            # care references. eg. \'NOW()'
+            $refetch = undef;
+            last;
+        }
+        $where{$key} = $args->{$key};
+    }
+    if (%where && $refetch) {
+        # refetch the row for cleanup scalar refs and fill default values
+        return $self->single($table_name, \%where);
     }
 
     $table->row_class->new(
@@ -440,7 +453,9 @@ sub delete {
 sub txn_manager  {
     my $self = shift;
     $self->_verify_pid;
-    $self->{txn_manager} ||= DBIx::TransactionManager->new($self->dbh);
+    $self->{txn_manager} ||= ($self->{txn_manager_class})
+        ? $self->{txn_manager_class}->new($self->dbh)
+        : DBIx::TransactionManager->new($self->dbh);
 }
 
 sub in_transaction_check {
@@ -607,6 +622,32 @@ sub single_by_sql {
     );
 }
 
+sub new_row_from_hash {
+    my ($self, $table_name, $data, $sql) = @_;
+
+    my $table = $self->{schema}->get_table( $table_name );
+    Carp::croak("No such table $table_name") unless $table;
+
+    return $data if $self->{suppress_row_objects};
+
+    $table->{row_class}->new(
+        {
+            sql => $sql || do {
+                my @caller = caller(0);
+                my $level = 0;
+                while ($caller[0] eq __PACKAGE__ || $caller[0] eq ref $self) {
+                    @caller = caller(++$level);
+                }
+                sprintf '/* DUMMY QUERY %s->new_row_from_hash created from %s line %d */', ref $self, $caller[1], $caller[2];
+            },
+            row_data   => $data,
+            teng       => $self,
+            table      => $table,
+            table_name => $table_name,
+        }
+    );
+}
+
 sub single_named {
     my ($self, $sql, $args, $table_name) = @_;
 
@@ -801,6 +842,11 @@ instantiated for you.
 Specifies the schema class to use.
 By default {YOUR_MODEL_CLASS}::Schema is used.
 
+=item * C<txn_manager_class>
+
+Specifies the transaction manager class.
+By default DBIx::TransactionManager is used.
+
 =item * C<suppress_row_objects>
 
 Specifies the row object creation mode. By default this value is C<false>.
@@ -933,6 +979,14 @@ give back one case of the beginning when it is acquired plural records by single
 
     my $row = $teng->single('user',{id =>1});
 
+=item C<$row = $teng-E<gt>new_row_from_hash($table_name, \%row_data, [$sql])>
+
+create row object from data. (not fetch from db.)
+It's useful in such as testing.
+
+    my $row = $teng->new_row_from_hash('user', { id => 1, foo => "bar" });
+    say $row->foo; # say bar
+
 =item C<$itr = $teng-E<gt>search_named($sql, [\%bind_values, [$table_name]])>
 
 execute named query
@@ -1015,7 +1069,7 @@ database disconnection.
 
 =item C<$txn_manager = $teng-E<gt>txn_manager>
 
-Get the DBIx::TransactionManager instance.
+Create the transaction manager instance with specified C<txn_manager_class>.
 
 =item C<$teng-E<gt>txn_begin>
 
@@ -0,0 +1,2 @@
+authority = "cpan:NEKOKAK"
+
@@ -38,6 +38,20 @@ use Test::More;
         row_class 'Mock::BasicRow::FooRow';
     };
 
+    table {
+        row_class 'Mock::BasicRow::BarRow';
+        name 'mock_basic_row_bar';
+        pk 'id';
+        columns qw/
+            id
+            name
+        /;
+    };
+    package Mock::BasicRow::BarRow;
+    use strict;
+    use warnings;
+    use base 'Teng::Row';
+
     package Mock::BasicRow::FooRow;
     use strict;
     use warnings;
@@ -85,6 +99,7 @@ subtest 'your row class' => sub {
 
 subtest 'row_class specific Schema.pm' => sub {
     is +$db_basic_row->schema->get_row_class('mock_basic_row_foo'), 'Mock::BasicRow::FooRow';
+    is +$db_basic_row->schema->get_row_class('mock_basic_row_bar'), 'Mock::BasicRow::BarRow';
 };
 
 subtest 'handle' => sub {
@@ -3,6 +3,8 @@ use Test::More;
 use Mock::Basic;
 use Test::SharedFork;
 
+plan skip_all => 'not for Win32' if $^O eq 'MSWin32';
+
 my $dbh = t::Utils->setup_dbh;
 my $db = Mock::Basic->new({dbh => $dbh});
 $db->setup_test_db;
@@ -3,6 +3,8 @@ use Test::More;
 use Mock::Basic;
 use Test::SharedFork;
 
+plan skip_all => 'not for Win32' if $^O eq 'MSWin32';
+
 unlink './t/main.db' if -f './t/main.db';
 my $db = Mock::Basic->new(
     {
@@ -3,6 +3,8 @@ use Test::More;
 use Mock::Basic;
 use Test::SharedFork;
 
+plan skip_all => 'not for Win32' if $^O eq 'MSWin32';
+
 my $dbh = t::Utils->setup_dbh('./t/main.db');
 my $db = Mock::Basic->new({dbh => $dbh});
 $db->setup_test_db;
@@ -0,0 +1,39 @@
+use t::Utils;
+use Mock::Basic;
+use Test::More;
+
+my $dbh = t::Utils->setup_dbh;
+my $db_basic = Mock::Basic->new({dbh => $dbh});
+$db_basic->setup_test_db;
+
+subtest 'new_row_from_hash method' => sub {
+    my $raw_data = [
+        {
+            id   => 1,
+            name => 'perl',
+        },
+        {
+            id   => 2,
+            name => 'ruby',
+        },
+        {
+            id   => 3,
+            name => 'python',
+        },
+    ];
+
+    my $rows = [ map { $db_basic->new_row_from_hash(mock_basic => $_) } @$raw_data ];
+    is $rows->[0]->{sql}, sprintf('/* DUMMY QUERY Mock::Basic->new_row_from_hash created from %s line %d */', __FILE__, __LINE__ - 1);
+    isa_ok $_, 'Teng::Row' for @$rows;
+    is $rows->[0]->id, 1;
+    is $rows->[1]->id, 2;
+    is $rows->[2]->id, 3;
+
+    subtest 'with sql' => sub {
+        my $sql = 'SELECT * FROM mock_basic WHERE id = 1';
+        is $db_basic->new_row_from_hash(mock_basic => $raw_data->[0], $sql)->{sql}, $sql;
+    };
+};
+
+done_testing;
+
@@ -133,7 +133,7 @@ my $guard = MyGuard->new(sub { unlink $db_file });
 
         $row = $teng->insert( 'a_multi_pk_table', { id_a => 3, id_b => 40 } );
 
-        is_deeply( $row->get_columns, { id_a => 3, id_b => 40 } );
+        is_deeply( $row->get_columns, { id_a => 3, id_b => 40, memo => 'foobar' } );
 
         @rows = $teng->search( 'a_multi_pk_table', { id_a => 3 } );
         is( 0+@rows, 4 );
@@ -214,7 +214,7 @@ my $guard = MyGuard->new(sub { unlink $db_file });
 
         $row = $teng->insert( 'c_multi_pk_table', { id_c => 3, id_d => 40 } );
 
-        is_deeply( $row->get_columns, { id_c => 3, id_d => 40 } );
+        is_deeply( $row->get_columns, { id_c => 3, id_d => 40, memo => 'foobar' } );
 
         @rows = $teng->search( 'c_multi_pk_table', { id_c => 3 } );
         is( 0+@rows, 4 );
@@ -12,6 +12,7 @@ subtest 'scalar data bug case' => sub {
 
     my $row = $db->insert('mock_inflate',{
         id   => 1,
+        bar  => 'baz',
         name => 'azumakuniyuki',
     });
 
@@ -0,0 +1,53 @@
+use xt::Utils::mysql;
+use Test::More;
+
+{
+    package Mock::MultiPK;
+    use parent 'Teng';
+
+    sub setup_test_db {
+        my $self = shift;
+
+        for my $table ( qw( multi_pk_table ) ) {
+            $self->do(qq{
+                DROP TABLE IF EXISTS $table
+            });
+        }
+
+        {
+            $self->do(q{
+                CREATE TABLE multi_pk_table (
+                    id         INTEGER AUTO_INCREMENT,
+                    created_at DATETIME,
+                    memo       VARCHAR(255) NOT NULL DEFAULT 'foobar',
+                    PRIMARY KEY( id, created_at )
+                )
+            });
+        }
+    }
+
+    package Mock::MultiPK::Schema;
+    use utf8;
+    use Teng::Schema::Declare;
+
+    table {
+        name 'multi_pk_table';
+        pk qw( id created_at );
+        columns qw( id created_at memo );
+    };
+}
+
+my $dbh = t::Utils->setup_dbh;
+my $db = Mock::MultiPK->new({dbh => $dbh});
+$db->setup_test_db;
+
+my $row = $db->insert('multi_pk_table', {
+    created_at => '2000-11-11',
+    memo       => 'blah',
+});
+
+isa_ok $row, 'Mock::MultiPK::Row::MultiPkTable';
+ok $row->id;
+is $row->memo, 'blah';
+
+done_testing;