Revision history for DBIx::Class\r
\r
+0.03\r
+ - Paging support\r
+\r
0.02 2005-08-12 18:00:00\r
- Test fixes.\r
- Performance improvements.\r
#use Data::Dumper; warn Dumper(@_);
$it_class = ref $it_class if ref $it_class;
$attrs = { %{ $attrs || {} } };
+ my %seen;
+ $attrs->{cols} ||= [ map { "me.$_" } $db_class->_select_columns ];
+ $attrs->{from} ||= [ { 'me' => $db_class->_table_name } ];
if ($attrs->{join}) {
- $attrs->{from} = [ { 'me' => $db_class->_table_name },
- $db_class->_resolve_join($attrs->{join}, 'me') ];
- $attrs->{cols} = [ map { "me.$_" } $db_class->_select_columns ];
+ foreach my $j (ref $attrs->{join} eq 'ARRAY'
+ ? (@{$attrs->{join}}) : ($attrs->{join})) {
+ if (ref $j eq 'HASH') {
+ $seen{$_} = 1 foreach keys %$j;
+ } else {
+ $seen{$j} = 1;
+ }
+ }
+ push(@{$attrs->{from}}, $db_class->_resolve_join($attrs->{join}, 'me'));
+ }
+ foreach my $pre (@{$attrs->{prefetch} || []}) {
+ push(@{$attrs->{from}}, $db_class->_resolve_join($pre, 'me'))
+ unless $seen{$pre};
+ push(@{$attrs->{cols}},
+ map { "$pre.$_" }
+ $db_class->_relationships->{$pre}->{class}->columns);
}
my $new = {
class => $db_class,
my ($self) = @_;
my @row = $self->cursor->next;
return unless (@row);
- return $self->{class}->_row_to_object($self->{cols}, \@row);
+ return $self->_construct_object(@row);
+}
+
+sub _construct_object {
+ my ($self, @row) = @_;
+ my @cols = $self->{class}->_select_columns;
+ unless ($self->{attrs}{prefetch}) {
+ return $self->{class}->_row_to_object(\@cols, \@row);
+ } else {
+ my @main = splice(@row, 0, scalar @cols);
+ my $new = $self->{class}->_row_to_object(\@cols, \@main);
+ PRE: foreach my $pre (@{$self->{attrs}{prefetch}}) {
+ my $rel_obj = $self->{class}->_relationships->{$pre};
+ my @pre_cols = $rel_obj->{class}->columns;
+ my @vals = splice(@row, 0, scalar @pre_cols);
+ my $fetched = $rel_obj->{class}->_row_to_object(\@pre_cols, \@vals);
+ $self->{class}->throw("No accessor for prefetched $pre")
+ unless defined $rel_obj->{attrs}{accessor};
+ if ($rel_obj->{attrs}{accessor} eq 'single') {
+ foreach my $pri ($rel_obj->{class}->primary_columns) {
+ next PRE unless defined $fetched->get_column($pri);
+ }
+ $new->{_relationship_data}{$pre} = $fetched;
+ } elsif ($rel_obj->{attrs}{accessor} eq 'filter') {
+ $new->{_inflated_column}{$pre} = $fetched;
+ } else {
+ $self->{class}->throw("Don't know to to store prefetched $pre");
+ }
+ }
+ return $new;
+ }
}
sub count {
sub all {
my ($self) = @_;
- return map { $self->{class}->_row_to_object($self->{cols}, $_); }
+ return map { $self->_construct_object(@$_); }
$self->cursor->all;
}
sub _row_to_object {
my ($class, $cols, $row) = @_;
my %vals;
- foreach my $pos (0..$#$cols) {
- my $c = $cols->[$pos];
- $c =~ s/^me\.//;
- $vals{$c} = $row->[$pos];
- }
+ $vals{$cols->[$_]} = $row->[$_] for 0 .. $#$cols;
my $new = $class->new(\%vals);
$new->in_storage(1);
return $new;
=head1 DESCRIPTION
-This provides a simple base class for DBIx::Class tests using SQLite.
-Each class for the test should inherit from this, provide a create_sql()
-method which returns a string representing the SQL used to create the
-table for the class, and then call set_table() to create the table, and
-tie it to the class.
+This provides a simple base class for DBIx::Class::CDBICompat tests using
+SQLite. Each class for the test should inherit from this, provide a
+create_sql() method which returns a string representing the SQL used to
+create the table for the class, and then call set_table() to create the
+table, and tie it to the class.
=cut
eval "use DBD::SQLite";
plan $@
? ( skip_all => 'needs DBD::SQLite for testing' )
- : ( tests => 12 );
+ : ( tests => 17 );
}
use lib qw(t/lib);
my $rs = DBICTest::CD->search(
{ 'year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
- { from => [ { 'cd' => 'cd' },
+ { from => [ { 'me' => 'cd' },
[
{ artist => 'artist' },
- { 'cd.artist' => 'artist.artistid' }
+ { 'me.artist' => 'artist.artistid' }
] ] }
);
cmp_ok( $rs->count, '==', 1, "Single record in resultset");
is($rs->first->name, 'We Are Goth', 'Correct record returned');
+
+DBICTest::Schema::CD->add_relationship(
+ artist => 'DBICTest::Schema::Artist',
+ { 'foreign.artistid' => 'self.artist' },
+ { accessor => 'filter' },
+);
+
+DBICTest::Schema::CD->add_relationship(
+ liner_notes => 'DBICTest::Schema::LinerNotes',
+ { 'foreign.liner_id' => 'self.cdid' },
+ { join_type => 'LEFT', accessor => 'single' });
+
+
+$rs = DBICTest::CD->search(
+ { 'artist.name' => 'Caterwauler McCrae' },
+ { prefetch => [ qw/artist liner_notes/ ],
+ order_by => 'me.cdid' });
+
+cmp_ok($rs->count, '==', 3, 'Correct number of records returned');
+
+my @cd = $rs->all;
+
+is($cd[0]->title, 'Spoonful of bees', 'First record returned ok');
+
+ok(!exists $cd[0]->{_relationship_data}{liner_notes}, 'No prefetch for NULL LEFT JOIN');
+
+is($cd[1]->{_relationship_data}{liner_notes}->notes, 'Buy Whiskey!', 'Prefetch for present LEFT JOIN');
+
+is($cd[2]->{_inflated_column}{artist}->name, 'Caterwauler McCrae', 'Prefetch on parent object ok');
DBICTest::Schema::CD->set_primary_key('cdid');
DBICTest::Schema::CD->add_relationship(
artist => 'DBICTest::Schema::Artist',
- { 'foreign.artistid' => 'self.artist' }
+ { 'foreign.artistid' => 'self.artist' },
);
DBICTest::Schema::CD->add_relationship(
tracks => 'DBICTest::Schema::Track',