[Bast-commits] r6311 - in DBIx-Class/0.08/trunk: . lib/DBIx/Class
t/prefetch
ribasushi at dev.catalyst.perl.org
ribasushi at dev.catalyst.perl.org
Mon May 18 21:05:10 GMT 2009
Author: ribasushi
Date: 2009-05-18 21:05:10 +0000 (Mon, 18 May 2009)
New Revision: 6311
Added:
DBIx-Class/0.08/trunk/t/prefetch/diamond.t
Modified:
DBIx-Class/0.08/trunk/
DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm
DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSource.pm
Log:
r6157 at Thesaurus (orig r6156): ribasushi | 2009-05-07 10:28:14 +0200
new branch for the diamond join/prefetch bug
r6158 at Thesaurus (orig r6157): ribasushi | 2009-05-07 11:12:41 +0200
Add failing test by gheift
r6294 at Thesaurus (orig r6293): ribasushi | 2009-05-18 01:10:22 +0200
Fixes for the diamond-relationship prefetch/join problem
The core of the issue was that resolve_prefetch calculated duplicate join alias numbers separate from resolve_join
In order to solve this, now the only join alias calculation happens in resolve_join (with prefetch being always merged as extra joins), and each join arrayref in from is labeled with the full relationship chain from me to the particular join. Then resolve_prefetch has to walk this chain and pull the necessary alias in order to generate the correct select
r6296 at Thesaurus (orig r6295): ribasushi | 2009-05-18 14:05:31 +0200
Add a comment about a small resolve_join omission
Property changes on: DBIx-Class/0.08/trunk
___________________________________________________________________
Name: svk:merge
- 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/resultsetcolumn_custom_columns:5160
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/sqla_1.50_compat:5414
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/trunk:5969
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_column_attr:10946
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_trunk:11142
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/belongs_to_null_col_fix:5244
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/column_attr:5074
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/count_distinct:6218
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/fix-update-and-delete-as_query:6162
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/multi_stuff:5565
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle-tweaks:6222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch:5699
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/rt_bug_41083:5437
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sqla_1.50_compat:5321
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-tweaks:6262
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subclassed_rsset:5930
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subquery:5617
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase:5651
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_mssql:6125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/views:5585
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510
+ 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/resultsetcolumn_custom_columns:5160
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/sqla_1.50_compat:5414
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/trunk:5969
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_column_attr:10946
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_trunk:11142
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/belongs_to_null_col_fix:5244
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/column_attr:5074
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/count_distinct:6218
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/diamond_relationships:6310
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/fix-update-and-delete-as_query:6162
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/multi_stuff:5565
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle-tweaks:6222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch:5699
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/rt_bug_41083:5437
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sqla_1.50_compat:5321
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-tweaks:6262
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subclassed_rsset:5930
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subquery:5617
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase:5651
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_mssql:6125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/views:5585
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510
Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm 2009-05-18 21:04:47 UTC (rev 6310)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm 2009-05-18 21:05:10 UTC (rev 6311)
@@ -2243,7 +2243,7 @@
"search_related: result source '" . $self->result_source->source_name .
"' has no such relationship $rel")
unless $rel_obj;
-
+
my ($from,$seen) = $self->_resolve_from($rel);
my $join_count = $seen->{$rel};
@@ -2336,29 +2336,34 @@
return ($self->{attrs} || {})->{alias} || 'me';
}
+# This code is called by search_related, and makes sure there
+# is clear separation between the joins before, during, and
+# after the relationship. This information is needed later
+# in order to properly resolve prefetch aliases (any alias
+# with a relation_chain_depth less than the depth of the
+# current prefetch is not considered)
sub _resolve_from {
my ($self, $extra_join) = @_;
my $source = $self->result_source;
my $attrs = $self->{attrs};
-
+
my $from = $attrs->{from}
|| [ { $attrs->{alias} => $source->from } ];
my $seen = { %{$attrs->{seen_join}||{}} };
- my $join = ($attrs->{join}
- ? [ $attrs->{join}, $extra_join ]
- : $extra_join);
-
# we need to take the prefetch the attrs into account before we
# ->resolve_join as otherwise they get lost - captainL
- my $merged = $self->_merge_attr( $join, $attrs->{prefetch} );
+ my $merged = $self->_merge_attr( $attrs->{join}, $attrs->{prefetch} );
- $from = [
- @$from,
- ($join ? $source->resolve_join($merged, $attrs->{alias}, $seen) : ()),
- ];
+ push @$from, $source->resolve_join($merged, $attrs->{alias}, $seen) if ($merged);
+ ++$seen->{-relation_chain_depth};
+
+ push @$from, $source->resolve_join($extra_join, $attrs->{alias}, $seen);
+
+ ++$seen->{-relation_chain_depth};
+
return ($from,$seen);
}
@@ -2479,12 +2484,12 @@
if ( my $prefetch = delete $attrs->{prefetch} ) {
$prefetch = $self->_merge_attr( {}, $prefetch );
my @pre_order;
- my $seen = { %{ $attrs->{seen_join} || {} } };
foreach my $p ( ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch) ) {
# bring joins back to level of current class
+ my $join_map = $self->_joinpath_aliases ($attrs->{from}, $attrs->{seen_join});
my @prefetch =
- $source->resolve_prefetch( $p, $alias, $seen, \@pre_order, $collapse );
+ $source->resolve_prefetch( $p, $alias, $join_map, \@pre_order, $collapse );
push( @{ $attrs->{select} }, map { $_->[0] } @prefetch );
push( @{ $attrs->{as} }, map { $_->[1] } @prefetch );
}
@@ -2500,6 +2505,25 @@
return $self->{_attrs} = $attrs;
}
+sub _joinpath_aliases {
+ my ($self, $fromspec, $seen) = @_;
+
+ my $paths = {};
+ return $paths unless ref $fromspec eq 'ARRAY';
+
+ for my $j (@$fromspec) {
+
+ next if ref $j ne 'ARRAY';
+ next if $j->[0]{-relation_chain_depth} < ( $seen->{-relation_chain_depth} || 0);
+
+ my $p = $paths;
+ $p = $p->{$_} ||= {} for @{$j->[0]{-join_path}};
+ push @{$p->{-join_aliases} }, $j->[0]{-join_alias};
+ }
+
+ return $paths;
+}
+
sub _rollout_attr {
my ($self, $attr) = @_;
Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSource.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSource.pm 2009-05-18 21:04:47 UTC (rev 6310)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSource.pm 2009-05-18 21:05:10 UTC (rev 6311)
@@ -1085,32 +1085,46 @@
=cut
sub resolve_join {
- my ($self, $join, $alias, $seen, $force_left) = @_;
- $seen ||= {};
+ my ($self, $join, $alias, $seen, $force_left, $jpath) = @_;
+
+ # we need a supplied one, because we do in-place modifications, no returns
+ $self->throw_exception ('You must supply a seen hashref as the 3rd argument to resolve_join')
+ unless $seen;
+
$force_left ||= { force => 0 };
+
+ # This isn't quite right, we should actually dive into $seen and reconstruct
+ # the entire path (the reference entry point would be the join conditional
+ # with depth == current_depth - 1. At this point however nothing depends on
+ # having the entire path, transcending related_resultset, so just leave it
+ # as is, hairy enough already.
+ $jpath ||= [];
+
if (ref $join eq 'ARRAY') {
return
map {
local $force_left->{force} = $force_left->{force};
- $self->resolve_join($_, $alias, $seen, $force_left);
+ $self->resolve_join($_, $alias, $seen, $force_left, [@$jpath]);
} @$join;
} elsif (ref $join eq 'HASH') {
return
map {
- my $as = ($seen->{$_} ? $_.'_'.($seen->{$_}+1) : $_);
+ my $as = ($seen->{$_} ? join ('_', $_, $seen->{$_} + 1) : $_); # the actual seen value will be incremented below
local $force_left->{force} = $force_left->{force};
(
- $self->resolve_join($_, $alias, $seen, $force_left),
+ $self->resolve_join($_, $alias, $seen, $force_left, [@$jpath]),
$self->related_source($_)->resolve_join(
- $join->{$_}, $as, $seen, $force_left
+ $join->{$_}, $as, $seen, $force_left, [@$jpath, $_]
)
);
} keys %$join;
} elsif (ref $join) {
$self->throw_exception("No idea how to resolve join reftype ".ref $join);
} else {
+
my $count = ++$seen->{$join};
my $as = ($count > 1 ? "${join}_${count}" : $join);
+
my $rel_info = $self->relationship_info($join);
$self->throw_exception("No such relationship ${join}") unless $rel_info;
my $type;
@@ -1121,7 +1135,11 @@
$force_left->{force} = 1 if lc($type) eq 'left';
}
return [ { $as => $self->related_source($join)->from,
- -join_type => $type },
+ -join_type => $type,
+ -join_path => [@$jpath, $join],
+ -join_alias => $as,
+ -relation_chain_depth => $seen->{-relation_chain_depth} || 0,
+ },
$self->resolve_condition($rel_info->{cond}, $as, $alias) ];
}
}
@@ -1284,19 +1302,20 @@
=cut
sub resolve_prefetch {
- my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
- $seen ||= {};
+ my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
+ $pref_path ||= [];
+
if( ref $pre eq 'ARRAY' ) {
return
- map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
+ map { $self->resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
@$pre;
}
elsif( ref $pre eq 'HASH' ) {
my @ret =
map {
- $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
+ $self->resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
$self->related_source($_)->resolve_prefetch(
- $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
+ $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
} keys %$pre;
return @ret;
}
@@ -1305,8 +1324,17 @@
"don't know how to resolve prefetch reftype ".ref($pre));
}
else {
- my $count = ++$seen->{$pre};
- my $as = ($count > 1 ? "${pre}_${count}" : $pre);
+
+ my $p = $alias_map;
+ $p = $p->{$_} for (@$pref_path, $pre);
+
+ $self->throw_exception (
+ "Unable to resolve prefetch $pre - join alias map does not contain an entry for path "
+ . join (' -> ', @$pref_path, $pre)
+ ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
+
+ my $as = shift @{$p->{-join_aliases}};
+
my $rel_info = $self->relationship_info( $pre );
$self->throw_exception( $self->name . " has no such relationship '$pre'" )
unless $rel_info;
Added: DBIx-Class/0.08/trunk/t/prefetch/diamond.t
===================================================================
--- DBIx-Class/0.08/trunk/t/prefetch/diamond.t (rev 0)
+++ DBIx-Class/0.08/trunk/t/prefetch/diamond.t 2009-05-18 21:05:10 UTC (rev 6311)
@@ -0,0 +1,107 @@
+# Test if prefetch and join in diamond relationship fetching the correct rows
+use strict;
+use warnings;
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+my $schema = DBICTest->init_schema();
+
+$schema->populate('Artwork', [
+ [ qw/cd_id/ ],
+ [ 1 ],
+]);
+
+$schema->populate('Artwork_to_Artist', [
+ [ qw/artwork_cd_id artist_id/ ],
+ [ 1, 2 ],
+]);
+
+my $ars = $schema->resultset ('Artwork');
+
+# The relationship diagram here is:
+#
+# $ars --> artwork_to_artist
+# | |
+# | |
+# V V
+# cd ------> artist
+#
+# The current artwork belongs to a cd by artist1
+# but the artwork itself is painted by artist2
+#
+# What we try is all possible permutations of join/prefetch
+# combinations in both directions, while always expecting to
+# arrive at the specific artist at the end of each path.
+
+
+my $cd_paths = {
+ 'no cd' => [],
+ 'cd' => ['cd'],
+ 'cd->artist1' => [{'cd' => 'artist'}]
+};
+my $a2a_paths = {
+ 'no a2a' => [],
+ 'a2a' => ['artwork_to_artist'],
+ 'a2a->artist2' => [{'artwork_to_artist' => 'artist'}]
+};
+
+my %tests;
+
+foreach my $cd_path (keys %$cd_paths) {
+
+ foreach my $a2a_path (keys %$a2a_paths) {
+
+
+ $tests{sprintf "join %s, %s", $cd_path, $a2a_path} = $ars->search({}, {
+ 'join' => [
+ @{ $cd_paths->{$cd_path} },
+ @{ $a2a_paths->{$a2a_path} },
+ ],
+ 'prefetch' => [
+ ],
+ });
+
+
+ $tests{sprintf "prefetch %s, %s", $cd_path, $a2a_path} = $ars->search({}, {
+ 'join' => [
+ ],
+ 'prefetch' => [
+ @{ $cd_paths->{$cd_path} },
+ @{ $a2a_paths->{$a2a_path} },
+ ],
+ });
+
+
+ $tests{sprintf "join %s, prefetch %s", $cd_path, $a2a_path} = $ars->search({}, {
+ 'join' => [
+ @{ $cd_paths->{$cd_path} },
+ ],
+ 'prefetch' => [
+ @{ $a2a_paths->{$a2a_path} },
+ ],
+ });
+
+
+ $tests{sprintf "join %s, prefetch %s", $a2a_path, $cd_path} = $ars->search({}, {
+ 'join' => [
+ @{ $a2a_paths->{$a2a_path} },
+ ],
+ 'prefetch' => [
+ @{ $cd_paths->{$cd_path} },
+ ],
+ });
+
+ }
+}
+
+plan tests => (scalar (keys %tests) * 3);
+
+foreach my $name (keys %tests) {
+ foreach my $artwork ($tests{$name}->all()) {
+ is($artwork->id, 1, $name . ', correct artwork');
+ is($artwork->cd->artist->artistid, 1, $name . ', correct artist_id over cd');
+ is($artwork->artwork_to_artist->first->artist->artistid, 2, $name . ', correct artist_id over A2A');
+ }
+}
\ No newline at end of file
More information about the Bast-commits
mailing list