Merge 'bulk_create' into 'DBIx-Class-current'
Matt S Trout [Tue, 29 May 2007 01:08:17 +0000 (01:08 +0000)]
16 files changed:
Changes
lib/DBIx/Class/InflateColumn.pm
lib/DBIx/Class/InflateColumn/DateTime.pm
lib/DBIx/Class/Manual/Cookbook.pod
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/Row.pm
lib/DBIx/Class/Storage/DBI.pm
lib/DBIx/Class/Storage/DBI/Oracle/WhereJoins.pm
t/30dbicplain.t
t/41orrible.t
t/60core.t
t/61findnot.t [new file with mode: 0644]
t/76joins.t
t/97result_class.t [new file with mode: 0644]
t/lib/DBICTest/Schema/Track.pm
t/lib/sqlite.sql

diff --git a/Changes b/Changes
index d4cc20e..cff1189 100644 (file)
--- a/Changes
+++ b/Changes
@@ -10,6 +10,9 @@ Revision history for DBIx::Class
           not a foreign constraint is needed
         - resultset_class/result_class now (again) auto loads the specified
           class; requires Class::Accessor::Grouped 0.05002+
+        - added 97result_class.t test, failing ATM
+        - added get_inflated_columns to Row
+        - %colinfo accessor and inflate_column now work together
 
 0.07006 2007-04-17 23:18:00
         - Lots of documentation updates
index 721894f..422d8b9 100644 (file)
@@ -73,7 +73,7 @@ sub inflate_column {
   $self->throw_exception("inflate_column needs attr hashref")
     unless ref $attrs eq 'HASH';
   $self->column_info($col)->{_inflate_info} = $attrs;
-  $self->mk_group_accessors('inflated_column' => $col);
+  $self->mk_group_accessors('inflated_column' => [$self->column_info($col)->{accessor} || $col, $col]);
   return 1;
 }
 
index 6b012d8..f92481d 100644 (file)
@@ -14,7 +14,7 @@ Load this component and then declare one or more
 columns to be of the datetime, timestamp or date datatype.
 
   package Event;
-  __PACKAGE__->load_components(qw/Core InflateColumn::DateTime/);
+  __PACKAGE__->load_components(qw/InflateColumn::DateTime Core/);
   __PACKAGE__->add_columns(
     starts_when => { data_type => 'datetime' }
   );
index 4dec7ae..3e5aa7b 100644 (file)
@@ -70,6 +70,56 @@ This results in the following C<WHERE> clause:
 For more information on generating complex queries, see
 L<SQL::Abstract/WHERE CLAUSES>.
 
+=head3 Arbitrary SQL through a custom ResultSource
+
+Sometimes you have to run arbitrary SQL because your query is too complex
+(e.g. it contains Unions, Sub-Selects, Stored Procedures, etc.) or has to
+be optimized for your database in a special way, but you still want to 
+get the results as a L<DBIx::Class::ResultSet>. 
+The recommended way to accomplish this is by defining a separate ResultSource 
+for your query. You can then inject complete SQL statements using a scalar 
+reference (this is a feature of L<SQL::Abstract>).
+
+Say you want to run a complex custom query on your user data, here's what
+you have to add to your User class:
+
+  package My::Schema::User;
+  
+  use base qw/DBIx::Class/;
+  
+  # ->load_components, ->table, ->add_columns, etc.
+
+  # Make a new ResultSource based on the User class
+  my $source = __PACKAGE__->result_source_instance();
+  my $new_source = $source->new( $source );
+  $new_source->source_name( 'UserFriendsComplex' );
+  
+  # Hand in your query as a scalar reference
+  # It will be added as a sub-select after FROM,
+  # so pay attention to the surrounding brackets!
+  $new_source->name( \<<SQL );
+  ( SELECT u.* FROM user u 
+  INNER JOIN user_friends f ON u.id = f.user_id 
+  WHERE f.friend_user_id = ?
+  UNION 
+  SELECT u.* FROM user u 
+  INNER JOIN user_friends f ON u.id = f.friend_user_id 
+  WHERE f.user_id = ? )
+  SQL 
+
+  # Finally, register your new ResultSource with your Schema
+  My::Schema->register_source( 'UserFriendsComplex' => $new_source );
+
+Next, you can execute your complex query using bind parameters like this:
+
+  my $friends = [ $schema->resultset( 'UserFriendsComplex' )->search( {}, 
+    {
+      bind  => [ 12345, 12345 ]
+    }
+  ) ];
+  
+... and you'll get back a perfect L<DBIx::Class::ResultSet>.
+
 =head3 Using specific columns
 
 When you only want specific columns from a table, you can use
index df5b998..17586e4 100644 (file)
@@ -545,7 +545,7 @@ sub single {
     $attrs->{where}, $attrs
   );
 
-  return (@data ? ($self->_construct_object(@data))[0] : ());
+  return (@data ? ($self->_construct_object(@data))[0] : undef);
 }
 
 # _is_unique_query
@@ -740,7 +740,7 @@ sub next {
       ? @{delete $self->{stashed_row}}
       : $self->cursor->next
   );
-  return unless (@row);
+  return undef unless (@row);
   my ($row, @more) = $self->_construct_object(@row);
   $self->{stashed_objects} = \@more if @more;
   return $row;
@@ -1724,18 +1724,36 @@ sub related_resultset {
     my $join_count = $seen->{$rel};
     my $alias = ($join_count > 1 ? join('_', $rel, $join_count) : $rel);
 
-    $self->_source_handle->schema->resultset($rel_obj->{class})->search_rs(
-      undef, {
-        %{$self->{attrs}||{}},
-        join => undef,
-        prefetch => undef,
-        select => undef,
-        as => undef,
-        alias => $alias,
-        where => $self->{cond},
-        seen_join => $seen,
-        from => $from,
-    });
+    #XXX - temp fix for result_class bug. There likely is a more elegant fix -groditi
+    my %attrs = %{$self->{attrs}||{}};
+    delete $attrs{result_class};
+
+    my $new_cache;
+
+    if (my $cache = $self->get_cache) {
+      if ($cache->[0] && $cache->[0]->related_resultset($rel)->get_cache) {
+        $new_cache = [ map { @{$_->related_resultset($rel)->get_cache} }
+                        @$cache ];
+      }
+    }
+
+    my $new = $self->_source_handle
+                   ->schema
+                   ->resultset($rel_obj->{class})
+                   ->search_rs(
+                       undef, {
+                         %attrs,
+                         join => undef,
+                         prefetch => undef,
+                         select => undef,
+                         as => undef,
+                         alias => $alias,
+                         where => $self->{cond},
+                         seen_join => $seen,
+                         from => $from,
+                     });
+    $new->set_cache($new_cache) if $new_cache;
+    $new;
   };
 }
 
index f4d33cb..e4d885a 100644 (file)
@@ -142,6 +142,9 @@ sub insert {
     if $self->can('result_source_instance');
   $self->throw_exception("No result_source set on this object; can't insert")
     unless $source;
+  #use Data::Dumper; warn Dumper($self);
+  # Check if we stored uninserted relobjs here in new()
+  $source->storage->txn_begin if(!$self->{_rel_in_storage});
 
   # Check if we stored uninserted relobjs here in new()
   my %related_stuff = (%{$self->{_relationship_data} || {}}, 
@@ -402,6 +405,22 @@ sub get_dirty_columns {
            keys %{$self->{_dirty_columns}};
 }
 
+=head2 get_inflated_columns
+
+  my $inflated_data = $obj->get_inflated_columns;
+
+Similar to get_columns but objects are returned for inflated columns instead of their raw non-inflated values.
+
+=cut
+
+sub get_inflated_columns {
+  my $self = shift;
+  return map {
+    my $accessor = $self->column_info($_)->{'accessor'} || $_;
+    ($_ => $self->$accessor);
+  } $self->columns;
+}
+
 =head2 set_column
 
   $obj->set_column($col => $val);
@@ -542,6 +561,7 @@ sub inflate_result {
         $fetched = $pre_source->result_class->inflate_result(
                       $pre_source, @{$pre_val});
       }
+      $new->related_resultset($pre)->set_cache([ $fetched ]);
       my $accessor = $source->relationship_info($pre)->{attrs}{accessor};
       $class->throw_exception("No accessor for prefetched $pre")
        unless defined $accessor;
index 860cc36..c7ece60 100644 (file)
@@ -12,10 +12,10 @@ use DBIx::Class::Storage::Statistics;
 use IO::File;
 use Scalar::Util 'blessed';
 
-__PACKAGE__->mk_group_accessors(
-  'simple' =>
-    qw/_connect_info _dbh _sql_maker _sql_maker_opts _conn_pid _conn_tid
-       disable_sth_caching cursor on_connect_do transaction_depth/
+__PACKAGE__->mk_group_accessors('simple' =>
+    qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts
+       _conn_pid _conn_tid disable_sth_caching cursor on_connect_do
+       transaction_depth/
 );
 
 BEGIN {
@@ -464,9 +464,12 @@ sub connect_info {
   #  the new set of options
   $self->_sql_maker(undef);
   $self->_sql_maker_opts({});
+  $self->_connect_info($info_arg);
 
-  my $info = [ @$info_arg ]; # copy because we can alter it
-  my $last_info = $info->[-1];
+  my $dbi_info = [@$info_arg]; # copy for DBI
+  $self->_dbi_connect_info($dbi_info);
+
+  my $last_info = $dbi_info->[-1];
   if(ref $last_info eq 'HASH') {
     for my $storage_opt (qw/on_connect_do disable_sth_caching/) {
       if(my $value = delete $last_info->{$storage_opt}) {
@@ -480,29 +483,10 @@ sub connect_info {
     }
 
     # Get rid of any trailing empty hashref
-    pop(@$info) if !keys %$last_info;
-  }
-
-  if(ref $info->[0] ne 'CODE') {
-      # Extend to 3 arguments with undefs, if necessary
-      while(scalar(@$info) < 3) { push(@$info, undef) }
-
-      # Complain if 4th argument is defined and is not a HASH
-      if(defined $info->[3] && ref $info->[3] ne 'HASH') {
-          warn "4th argument of DBI connect info is defined "
-               . " but is not a hashref!";
-      }
-
-      # Set AutoCommit to 1 if not specified manually
-      else {
-          $info->[3] ||= {};
-          if(!defined $info->[3]->{AutoCommit}) {
-              $info->[3]->{AutoCommit} = 1;
-          }
-      }
+    pop(@$dbi_info) if !keys %$last_info;
   }
 
-  $self->_connect_info($info);
+  $info_arg;
 }
 
 =head2 on_connect_do
@@ -725,7 +709,7 @@ sub sql_maker {
 
 sub _populate_dbh {
   my ($self) = @_;
-  my @info = @{$self->_connect_info || []};
+  my @info = @{$self->_dbi_connect_info || []};
   $self->_dbh($self->_connect(@info));
 
   # Always set the transaction depth on connect, since
index 9dbe9e0..cd1f7da 100644 (file)
@@ -13,7 +13,9 @@ BEGIN {
   sub select {
     my ($self, $table, $fields, $where, $order, @rest) = @_;
 
-    $self->_oracle_joins($where, @{ $table });
+    if (ref($table) eq 'ARRAY') {
+      $where = $self->_oracle_joins($where, @{ $table });
+    }
 
     return $self->SUPER::select($table, $fields, $where, $order, @rest);
   }
@@ -39,12 +41,29 @@ BEGIN {
 
   sub _oracle_joins {
     my ($self, $where, $from, @join) = @_;
+    my $join_where = {};
+    $self->_recurse_oracle_joins($join_where, $from, @join);
+    if (keys %$join_where) {
+      if (!defined($where)) {
+        $where = $join_where;
+      } else {
+        if (ref($where) eq 'ARRAY') {
+          $where = { -or => $where };
+        }
+        $where = { -and => [ $join_where, $where ] };
+      }
+    }
+    return $where;
+  }
+
+  sub _recurse_oracle_joins {
+    my ($self, $where, $from, @join) = @_;
 
     foreach my $j (@join) {
       my ($to, $on) = @{ $j };
 
       if (ref $to eq 'ARRAY') {
-        $self->_oracle_joins($where, @{ $to });
+        $self->_recurse_oracle_joins($where, @{ $to });
       }
 
       my $to_jt      = ref $to eq 'ARRAY' ? $to->[0] : $to;
@@ -66,7 +85,7 @@ BEGIN {
       }
 
       foreach my $lhs (keys %{ $on }) {
-        $where->{$lhs . $left_join} = \" = $on->{ $lhs }$right_join";
+        $where->{$lhs . $left_join} = \"= $on->{ $lhs }$right_join";
       }
     }
   }
index aa30169..f853286 100644 (file)
@@ -5,8 +5,17 @@ use warnings;
 use Test::More;
 
 use lib qw(t/lib);
-use DBICTest::Plain;
 
-plan tests => 1;
+plan tests => 3;
 
+my @warnings;
+
+{
+  local $SIG{__WARN__} = sub { push(@warnings, $_[0]); };
+  require DBICTest::Plain;
+}
+
+like($warnings[0], qr/compose_connection deprecated as of 0\.08000/,
+      'deprecation warning emitted ok');
+cmp_ok(@warnings, '==', 1, 'no unexpected warnings');
 cmp_ok(DBICTest::Plain->resultset('Test')->count, '>', 0, 'count is valid');
index e8e22df..c9748b3 100644 (file)
@@ -2,11 +2,12 @@ use strict;
 use warnings;
 
 use Test::More;
-use DBIx::Class::Storage::DBI;
+#use DBIx::Class::Storage::DBI;
+use DBIx::Class::Storage::DBI::Oracle::WhereJoins;
 
-plan tests => 1;
+plan tests => 4;
 
-my $sa = new DBIC::SQL::Abstract;
+my $sa = new DBIC::SQL::Abstract::Oracle;
 
 $sa->limit_dialect('RowNum');
 
@@ -23,3 +24,45 @@ is($sa->select('rubbish',
 ) B
 WHERE r >= 4
 ', 'Munged stuff to make Oracle not explode');
+
+# test WhereJoins
+# search with undefined or empty $cond
+
+#  my ($self, $table, $fields, $where, $order, @rest) = @_;
+is($sa->select([
+        { me => "cd" },
+        [
+            { "-join_type" => "LEFT", artist => "artist" },
+            { "artist.artistid" => "me.artist" },
+        ],
+    ],
+    [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
+    undef,
+    undef),
+   'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( artist.artistid(+) = me.artist )', 'WhereJoins search with empty where clause');
+
+is($sa->select([
+        { me => "cd" },
+        [
+            { "-join_type" => "", artist => "artist" },
+            { "artist.artistid" => "me.artist" },
+        ],
+    ],
+    [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
+    { 'artist.artistid' => 3 },
+    undef),
+   'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( ( ( artist.artistid = me.artist ) AND ( artist.artistid = ? ) ) )', 'WhereJoins search with where clause');
+
+is($sa->select([
+        { me => "cd" },
+        [
+            { "-join_type" => "LEFT", artist => "artist" },
+            { "artist.artistid" => "me.artist" },
+        ],
+    ],
+    [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
+    [{ 'artist.artistid' => 3 }, { 'me.cdid' => 5 }],
+    undef),
+   'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( ( ( artist.artistid(+) = me.artist ) AND ( ( ( artist.artistid = ? ) OR ( me.cdid = ? ) ) ) ) )', 'WhereJoins search with or in where clause');
+
+
index 3eb80df..fc1bff2 100644 (file)
@@ -7,7 +7,7 @@ use DBICTest;
 
 my $schema = DBICTest->init_schema();
 
-plan tests => 64;
+plan tests => 77;
 
 # figure out if we've got a version of sqlite that is older than 3.2.6, in
 # which case COUNT(DISTINCT()) doesn't work
@@ -166,6 +166,7 @@ $new = $schema->resultset("Track")->new( {
   cd => 1,
   position => 4,
   title => 'Insert or Update',
+  last_updated_on => '1973-07-19 12:01:02'
 } );
 $new->update_or_insert;
 ok($new->in_storage, 'update_or_insert insert ok');
@@ -175,6 +176,17 @@ $new->pos(5);
 $new->update_or_insert;
 is( $schema->resultset("Track")->find(100)->pos, 5, 'update_or_insert update ok');
 
+# get_inflated_columns w/relation and accessor alias
+isa_ok($new->updated_date, 'DateTime', 'have inflated object via accessor');
+my %tdata = $new->get_inflated_columns;
+is($tdata{'trackid'}, 100, 'got id');
+isa_ok($tdata{'cd'}, 'DBICTest::CD', 'cd is CD object');
+is($tdata{'cd'}->id, 1, 'cd object is id 1');
+is($tdata{'position'}, 5, 'got position from pos');
+is($tdata{'title'}, 'Insert or Update');
+is($tdata{'last_updated_on'}, '1973-07-19T12:01:02');
+isa_ok($tdata{'last_updated_on'}, 'DateTime', 'inflated accessored column');
+
 eval { $schema->class("Track")->load_components('DoesNotExist'); };
 
 ok $@, $@;
@@ -306,3 +318,14 @@ ok(!$@, "stringify to false value doesn't cause error");
   ok(! exists $schema->source('CD')->_columns->{'year'}, 'year still exists in _columns');
 }
 
+# test get_inflated_columns with objects
+{
+    my $event = $schema->resultset('Event')->search->first;
+    my %edata = $event->get_inflated_columns;
+    is($edata{'id'}, $event->id, 'got id');
+    isa_ok($edata{'starts_at'}, 'DateTime', 'start_at is DateTime object');
+    isa_ok($edata{'created_on'}, 'DateTime', 'create_on DateTime object');
+    is($edata{'starts_at'}, $event->starts_at, 'got start date');
+    is($edata{'created_on'}, $event->created_on, 'got created date');
+}
+
diff --git a/t/61findnot.t b/t/61findnot.t
new file mode 100644 (file)
index 0000000..ee7b582
--- /dev/null
@@ -0,0 +1,46 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+my $schema = DBICTest->init_schema();
+
+plan tests => 17;
+
+my $art = $schema->resultset("Artist")->find(4);
+ok(!defined($art), 'Find on primary id: artist not found');
+my @cd = $schema->resultset("CD")->find(6);
+cmp_ok(@cd, '==', 1, 'Return something even in array context');
+ok(@cd && !defined($cd[0]), 'Array contains an undef as only element');
+
+$art = $schema->resultset("Artist")->find({artistid => '4'});
+ok(!defined($art), 'Find on unique constraint: artist not found');
+@cd = $schema->resultset("CD")->find({artist => '2', title => 'Lada-Di Lada-Da'});
+cmp_ok(@cd, '==', 1, 'Return something even in array context');
+ok(@cd && !defined($cd[0]), 'Array contains an undef as only element');
+
+$art = $schema->resultset("Artist")->search({name => 'The Jesus And Mary Chain'});
+isa_ok($art, 'DBIx::Class::ResultSet', 'get a DBIx::Class::ResultSet object');
+my $next = $art->next;
+ok(!defined($next), 'Nothing next in ResultSet');
+my $cd = $schema->resultset("CD")->search({title => 'Rubbersoul'});
+@cd = $cd->next;
+cmp_ok(@cd, '==', 1, 'Return something even in array context');
+ok(@cd && !defined($cd[0]), 'Array contains an undef as only element');
+
+$art = $schema->resultset("Artist")->single({name => 'Bikini Bottom Boys'});
+ok(!defined($art), 'Find on primary id: artist not found');
+@cd = $schema->resultset("CD")->single({title => 'The Singles 1962-2006'});
+cmp_ok(@cd, '==', 1, 'Return something even in array context');
+ok(@cd && !defined($cd[0]), 'Array contains an undef as only element');
+
+$art = $schema->resultset("Artist")->search({name => 'Random Girl Band'});
+isa_ok($art, 'DBIx::Class::ResultSet', 'get a DBIx::Class::ResultSet object');
+$next = $art->single;
+ok(!defined($next), 'Nothing next in ResultSet');
+$cd = $schema->resultset("CD")->search({title => 'Call of the West'});
+@cd = $cd->single;
+cmp_ok(@cd, '==', 1, 'Return something even in array context');
+ok(@cd && !defined($cd[0]), 'Array contains an undef as only element');
index 57a9ffc..c03df6b 100644 (file)
@@ -16,7 +16,7 @@ BEGIN {
     eval "use DBD::SQLite";
     plan $@
         ? ( skip_all => 'needs DBD::SQLite for testing' )
-        : ( tests => 53 );
+        : ( tests => 62 );
 }
 
 # figure out if we've got a version of sqlite that is older than 3.2.6, in
@@ -169,7 +169,7 @@ is(Dumper($attr), $attr_str, 'Attribute hash untouched after search()');
 cmp_ok($rs + 0, '==', 3, 'Correct number of records returned');
 
 my $queries = 0;
-$schema->storage->debugcb(sub { $queries++ });
+$schema->storage->debugcb(sub { $queries++; });
 $schema->storage->debug(1);
 
 my @cd = $rs->all;
@@ -222,12 +222,42 @@ is($queries, 1, 'nested prefetch ran exactly 1 select statement (excluding colum
 
 $queries = 0;
 
+is($tag->search_related('cd')->search_related('artist')->first->name,
+   'Caterwauler McCrae',
+   'chained belongs_to->belongs_to search_related ok');
+
+is($queries, 0, 'chained search_related after belontgs_to->belongs_to prefetch ran no queries');
+
+$queries = 0;
+
 $cd = $schema->resultset('CD')->find(1, { prefetch => 'artist' });
 
 is($cd->{_inflated_column}{artist}->name, 'Caterwauler McCrae', 'artist prefetched correctly on find');
 
 is($queries, 1, 'find with prefetch ran exactly 1 select statement (excluding column_info)');
 
+$queries = 0;
+
+$schema->storage->debugcb(sub { $queries++; });
+
+$cd = $schema->resultset('CD')->find(1, { prefetch => { cd_to_producer => 'producer' } });
+
+is($cd->producers->first->name, 'Matt S Trout', 'many_to_many accessor ok');
+
+TODO: {
+  local $TODO = 'use prefetched values for many_to_many accessor';
+
+  is($queries, 1, 'many_to_many accessor with nested prefetch ran exactly 1 query');
+}
+
+$queries = 0;
+
+my $producers = $cd->search_related('cd_to_producer')->search_related('producer');
+
+is($producers->first->name, 'Matt S Trout', 'chained many_to_many search_related ok');
+
+is($queries, 0, 'chained search_related after many_to_many prefetch ran no queries');
+
 $schema->storage->debug($orig_debug);
 $schema->storage->debugobj->callback(undef);
 
@@ -380,7 +410,8 @@ my $art_rs_pr = $art_rs->search(
     {},
     {
         join     => [ { cds => ['tracks'] } ],
-        prefetch => [ { cds => ['tracks'] } ]
+        prefetch => [ { cds => ['tracks'] } ],
+        cache    => 1 # last test needs this
     }
 );
 
@@ -405,8 +436,24 @@ sub make_hash_struc {
     return $struc;
 }
 
+$queries = 0;
+$schema->storage->debugcb(sub { $queries++ });
+$schema->storage->debug(1);
+
 my $prefetch_result = make_hash_struc($art_rs_pr);
+
+is($queries, 1, 'nested prefetch across has_many->has_many ran exactly 1 query');
+
 my $nonpre_result   = make_hash_struc($art_rs);
 
 is_deeply( $prefetch_result, $nonpre_result,
     'Compare 2 level prefetch result to non-prefetch result' );
+
+$queries = 0;
+
+is($art_rs_pr->search_related('cds')->search_related('tracks')->first->title,
+   'Fowlin',
+   'chained has_many->has_many search_related ok'
+  );
+
+is($queries, 0, 'chained search_related after has_many->has_many prefetch ran no queries');
diff --git a/t/97result_class.t b/t/97result_class.t
new file mode 100644 (file)
index 0000000..7921158
--- /dev/null
@@ -0,0 +1,44 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+my $schema = DBICTest->init_schema();
+
+plan tests => 9;
+
+{
+  my $cd_rc = $schema->resultset("CD")->result_class;
+  
+  my $artist_rs = $schema->resultset("Artist")
+    ->search_rs({}, {result_class => "IWillExplode"});
+  is($artist_rs->result_class, 'IWillExplode', 'Correct artist result_class');
+  
+  my $cd_rs = $artist_rs->related_resultset('cds');
+  is($cd_rs->result_class, $cd_rc, 'Correct cd result_class');
+
+  my $cd_rs2 = $schema->resultset("Artist")->search_rs({})->related_resultset('cds');
+  is($cd_rs->result_class, $cd_rc, 'Correct cd2 result_class');
+
+  my $cd_rs3 = $schema->resultset("Artist")->search_rs({},{})->related_resultset('cds');
+  is($cd_rs->result_class, $cd_rc, 'Correct cd3 result_class');
+  
+  isa_ok(eval{ $cd_rs->find(1) }, $cd_rc, 'Inflated into correct cd result_class');
+}
+
+
+{
+  my $cd_rc = $schema->resultset("CD")->result_class;
+  
+  my $artist_rs = $schema->resultset("Artist")
+    ->search_rs({}, {result_class => "IWillExplode"})->search({artistid => 1});
+  is($artist_rs->result_class, 'IWillExplode', 'Correct artist result_class');
+  
+  my $cd_rs = $artist_rs->related_resultset('cds');
+  is($cd_rs->result_class, $cd_rc, 'Correct cd result_class');
+  
+  isa_ok(eval{ $cd_rs->find(1) }, $cd_rc, 'Inflated into correct cd result_class');   
+  isa_ok(eval{ $cd_rs->search({ cdid => 1 })->first }, $cd_rc, 'Inflated into correct cd result_class');
+}
index d45e9f2..64eb0ee 100644 (file)
@@ -2,6 +2,7 @@ package # hide from PAUSE
     DBICTest::Schema::Track;
 
 use base 'DBIx::Class::Core';
+__PACKAGE__->load_components(qw/InflateColumn::DateTime/);
 
 __PACKAGE__->table('track');
 __PACKAGE__->add_columns(
@@ -20,6 +21,11 @@ __PACKAGE__->add_columns(
     data_type => 'varchar',
     size      => 100,
   },
+  last_updated_on => {
+    data_type => 'datetime',
+    accessor => 'updated_date',
+    is_nullable => 1
+  },
 );
 __PACKAGE__->set_primary_key('trackid');
 
index c9de968..5f17ebe 100644 (file)
@@ -108,7 +108,8 @@ CREATE TABLE track (
   trackid INTEGER PRIMARY KEY NOT NULL,
   cd integer NOT NULL,
   position integer NOT NULL,
-  title varchar(100) NOT NULL
+  title varchar(100) NOT NULL,
+  last_updated_on datetime NULL
 );
 
 --