Codebase list libdbix-class-perl / upstream/0.08118
[svn-upgrade] Integrating new upstream version, libdbix-class-perl (0.08118) Jonathan Yu 14 years ago
16 changed file(s) with 251 addition(s) and 189 deletion(s). Raw diff Collapse all Expand all
00 Revision history for DBIx::Class
1
2 0.08118 2010-02-08 11:53:00 (UTC)
3 - Fix a bug causing UTF8 columns not to be decoded (RT#54395)
4 - Fix bug in One->Many->One prefetch-collapse handling (RT#54039)
5 - Cleanup handling of relationship accessor types
16
27 0.08117 2010-02-05 17:10:00 (UTC)
38 - Perl 5.8.1 is now the minimum supported version
442442 t/prefetch/incomplete.t
443443 t/prefetch/join_type.t
444444 t/prefetch/multiple_hasmany.t
445 t/prefetch/one_to_many_to_one.t
445446 t/prefetch/standard.t
446447 t/prefetch/via_search_related.t
447448 t/prefetch/with_limit.t
451452 t/relationship/update_or_create_multi.t
452453 t/relationship/update_or_create_single.t
453454 t/resultset/as_query.t
455 t/resultset/as_subselect_rs.t
454456 t/resultset/is_paged.t
455457 t/resultset/nulls_only.t
456458 t/resultset/plus_select.t
5555 MailingList: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
5656 license: http://dev.perl.org/licenses/
5757 repository: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
58 version: 0.08117
58 version: 0.08118
7878 $self->throw_exception("inflate_column needs attr hashref")
7979 unless ref $attrs eq 'HASH';
8080 $self->column_info($col)->{_inflate_info} = $attrs;
81 $self->mk_group_accessors('inflated_column' => [$self->column_info($col)->{accessor} || $col, $col]);
81 my $acc = $self->column_info($col)->{accessor};
82 $self->mk_group_accessors('inflated_column' => [ (defined $acc ? $acc : $col), $col]);
8283 return 1;
8384 }
8485
2828 =back
2929
3030 __PACKAGE__->add_relationship('relname', 'Foreign::Class', $cond, $attrs);
31
32 =head3 condition
3133
3234 The condition needs to be an L<SQL::Abstract>-style representation of the
3335 join between the tables. When resolving the condition for use in a C<JOIN>,
6668 To add an C<OR>ed condition, use an arrayref of hashrefs. See the
6769 L<SQL::Abstract> documentation for more details.
6870
69 In addition to the
70 L<standard ResultSet attributes|DBIx::Class::ResultSet/ATTRIBUTES>,
71 the following attributes are also valid:
71 =head3 attributes
72
73 The L<standard ResultSet attributes|DBIx::Class::ResultSet/ATTRIBUTES> may
74 be used as relationship attributes. In particular, the 'where' attribute is
75 useful for filtering relationships:
76
77 __PACKAGE__->has_many( 'valid_users', 'MyApp::Schema::User',
78 { 'foreign.user_id' => 'self.user_id' },
79 { where => { valid => 1 } }
80 );
81
82 The following attributes are also valid:
7283
7384 =over 4
7485
194205 if ($cond eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION) {
195206 my $reverse = $source->reverse_relationship_info($rel);
196207 foreach my $rev_rel (keys %$reverse) {
197 if ($reverse->{$rev_rel}{attrs}{accessor} eq 'multi') {
208 if ($reverse->{$rev_rel}{attrs}{accessor} && $reverse->{$rev_rel}{attrs}{accessor} eq 'multi') {
198209 $attrs->{related_objects}{$rev_rel} = [ $self ];
199210 Scalar::Util::weaken($attrs->{related_object}{$rev_rel}[0]);
200211 } else {
3838 my @cascade = grep { $rels{$_}{attrs}{cascade_update} } keys %rels;
3939 foreach my $rel (@cascade) {
4040 next if (
41 $rels{$rel}{attrs}{accessor}
42 &&
4143 $rels{$rel}{attrs}{accessor} eq 'single'
42 && !exists($self->{_relationship_data}{$rel})
44 &&
45 !exists($self->{_relationship_data}{$rel})
4346 );
4447 $_->update for grep defined, $self->$rel;
4548 }
25012501 ->relname_to_table_alias($rel, $join_count);
25022502
25032503 # since this is search_related, and we already slid the select window inwards
2504 # (the select/as attrs were deleted in the beginning), we need to flip all
2504 # (the select/as attrs were deleted in the beginning), we need to flip all
25052505 # left joins to inner, so we get the expected results
25062506 # read the comment on top of the actual function to see what this does
25072507 $attrs->{from} = $rsrc->schema->storage->_straight_join_to_node ($attrs->{from}, $alias);
25852585 my ($self) = @_;
25862586
25872587 return ($self->{attrs} || {})->{alias} || 'me';
2588 }
2589
2590 =head2 as_subselect_rs
2591
2592 =over 4
2593
2594 =item Arguments: none
2595
2596 =item Return Value: $resultset
2597
2598 =back
2599
2600 Act as a barrier to SQL symbols. The resultset provided will be made into a
2601 "virtual view" by including it as a subquery within the from clause. From this
2602 point on, any joined tables are inaccessible to ->search on the resultset (as if
2603 it were simply where-filtered without joins). For example:
2604
2605 my $rs = $schema->resultset('Bar')->search({'x.name' => 'abc'},{ join => 'x' });
2606
2607 # 'x' now pollutes the query namespace
2608
2609 # So the following works as expected
2610 my $ok_rs = $rs->search({'x.other' => 1});
2611
2612 # But this doesn't: instead of finding a 'Bar' related to two x rows (abc and
2613 # def) we look for one row with contradictory terms and join in another table
2614 # (aliased 'x_2') which we never use
2615 my $broken_rs = $rs->search({'x.name' => 'def'});
2616
2617 my $rs2 = $rs->as_subselect_rs;
2618
2619 # doesn't work - 'x' is no longer accessible in $rs2, having been sealed away
2620 my $not_joined_rs = $rs2->search({'x.other' => 1});
2621
2622 # works as expected: finds a 'table' row related to two x rows (abc and def)
2623 my $correctly_joined_rs = $rs2->search({'x.name' => 'def'});
2624
2625 Another example of when one might use this would be to select a subset of
2626 columns in a group by clause:
2627
2628 my $rs = $schema->resultset('Bar')->search(undef, {
2629 group_by => [qw{ id foo_id baz_id }],
2630 })->as_subselect_rs->search(undef, {
2631 columns => [qw{ id foo_id }]
2632 });
2633
2634 In the above example normally columns would have to be equal to the group by,
2635 but because we isolated the group by into a subselect the above works.
2636
2637 =cut
2638
2639 sub as_subselect_rs {
2640 my $self = shift;
2641
2642 return $self->result_source->resultset->search( undef, {
2643 alias => $self->current_source_alias,
2644 from => [{
2645 $self->current_source_alias => $self->as_query,
2646 -alias => $self->current_source_alias,
2647 -source_handle => $self->result_source->handle,
2648 }]
2649 });
25882650 }
25892651
25902652 # This code is called by search_related, and makes sure there
11871187 return $found;
11881188 }
11891189
1190 sub resolve_join {
1191 carp 'resolve_join is a private method, stop calling it';
1192 my $self = shift;
1193 $self->_resolve_join (@_);
1194 }
1195
11961190 # Returns the {from} structure used to express JOIN conditions
11971191 sub _resolve_join {
11981192 my ($self, $join, $alias, $seen, $jpath, $parent_force_left) = @_;
12611255 : $rel_info->{attrs}{join_type}
12621256 ,
12631257 -join_path => [@$jpath, { $join => $as } ],
1264 -is_single => (List::Util::first { $rel_info->{attrs}{accessor} eq $_ } (qw/single filter/) ),
1258 -is_single => (
1259 $rel_info->{attrs}{accessor}
1260 &&
1261 List::Util::first { $rel_info->{attrs}{accessor} eq $_ } (qw/single filter/)
1262 ),
12651263 -alias => $as,
12661264 -relation_chain_depth => $seen->{-relation_chain_depth} || 0,
12671265 },
13721370 }
13731371 }
13741372
1375 # Legacy code, needs to go entirely away (fully replaced by _resolve_prefetch)
1376 sub resolve_prefetch {
1377 carp 'resolve_prefetch is a private method, stop calling it';
1378
1379 my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
1380 $seen ||= {};
1381 if( ref $pre eq 'ARRAY' ) {
1373
1374 # Accepts one or more relationships for the current source and returns an
1375 # array of column names for each of those relationships. Column names are
1376 # prefixed relative to the current source, in accordance with where they appear
1377 # in the supplied relationships.
1378
1379 sub _resolve_prefetch {
1380 my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
1381 $pref_path ||= [];
1382
1383 if (not defined $pre) {
1384 return ();
1385 }
1386 elsif( ref $pre eq 'ARRAY' ) {
13821387 return
1383 map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
1388 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
13841389 @$pre;
13851390 }
13861391 elsif( ref $pre eq 'HASH' ) {
13871392 my @ret =
13881393 map {
1389 $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
1390 $self->related_source($_)->resolve_prefetch(
1391 $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
1394 $self->_resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
1395 $self->related_source($_)->_resolve_prefetch(
1396 $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
13921397 } keys %$pre;
13931398 return @ret;
13941399 }
13971402 "don't know how to resolve prefetch reftype ".ref($pre));
13981403 }
13991404 else {
1400 my $count = ++$seen->{$pre};
1401 my $as = ($count > 1 ? "${pre}_${count}" : $pre);
1405 my $p = $alias_map;
1406 $p = $p->{$_} for (@$pref_path, $pre);
1407
1408 $self->throw_exception (
1409 "Unable to resolve prefetch '$pre' - join alias map does not contain an entry for path: "
1410 . join (' -> ', @$pref_path, $pre)
1411 ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
1412
1413 my $as = shift @{$p->{-join_aliases}};
1414
14021415 my $rel_info = $self->relationship_info( $pre );
14031416 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
14041417 unless $rel_info;
14051418 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
14061419 my $rel_source = $self->related_source($pre);
14071420
1408 if (exists $rel_info->{attrs}{accessor}
1409 && $rel_info->{attrs}{accessor} eq 'multi') {
1421 if ($rel_info->{attrs}{accessor} && $rel_info->{attrs}{accessor} eq 'multi') {
14101422 $self->throw_exception(
14111423 "Can't prefetch has_many ${pre} (join cond too complex)")
14121424 unless ref($rel_info->{cond}) eq 'HASH';
14331445 keys %{$rel_info->{cond}};
14341446 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
14351447 ? @{$rel_info->{attrs}{order_by}}
1436 : (defined $rel_info->{attrs}{order_by}
1437 ? ($rel_info->{attrs}{order_by})
1438 : ()));
1439 push(@$order, map { "${as}.$_" } (@key, @ord));
1440 }
1441
1442 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
1443 $rel_source->columns;
1444 }
1445 }
1446
1447 # Accepts one or more relationships for the current source and returns an
1448 # array of column names for each of those relationships. Column names are
1449 # prefixed relative to the current source, in accordance with where they appear
1450 # in the supplied relationships.
1451
1452 sub _resolve_prefetch {
1453 my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
1454 $pref_path ||= [];
1455
1456 if (not defined $pre) {
1457 return ();
1458 }
1459 elsif( ref $pre eq 'ARRAY' ) {
1460 return
1461 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
1462 @$pre;
1463 }
1464 elsif( ref $pre eq 'HASH' ) {
1465 my @ret =
1466 map {
1467 $self->_resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
1468 $self->related_source($_)->_resolve_prefetch(
1469 $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
1470 } keys %$pre;
1471 return @ret;
1472 }
1473 elsif( ref $pre ) {
1474 $self->throw_exception(
1475 "don't know how to resolve prefetch reftype ".ref($pre));
1476 }
1477 else {
1478 my $p = $alias_map;
1479 $p = $p->{$_} for (@$pref_path, $pre);
1480
1481 $self->throw_exception (
1482 "Unable to resolve prefetch '$pre' - join alias map does not contain an entry for path: "
1483 . join (' -> ', @$pref_path, $pre)
1484 ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
1485
1486 my $as = shift @{$p->{-join_aliases}};
1487
1488 my $rel_info = $self->relationship_info( $pre );
1489 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
1490 unless $rel_info;
1491 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
1492 my $rel_source = $self->related_source($pre);
1493
1494 if (exists $rel_info->{attrs}{accessor}
1495 && $rel_info->{attrs}{accessor} eq 'multi') {
1496 $self->throw_exception(
1497 "Can't prefetch has_many ${pre} (join cond too complex)")
1498 unless ref($rel_info->{cond}) eq 'HASH';
1499 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1500 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1501 keys %{$collapse}) {
1502 my ($last) = ($fail =~ /([^\.]+)$/);
1503 carp (
1504 "Prefetching multiple has_many rels ${last} and ${pre} "
1505 .(length($as_prefix)
1506 ? "at the same level (${as_prefix}) "
1507 : "at top level "
1508 )
1509 . 'will explode the number of row objects retrievable via ->next or ->all. '
1510 . 'Use at your own risk.'
1511 );
1512 }
1513 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1514 # values %{$rel_info->{cond}};
1515 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
1516 # action at a distance. prepending the '.' allows simpler code
1517 # in ResultSet->_collapse_result
1518 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
1519 keys %{$rel_info->{cond}};
1520 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1521 ? @{$rel_info->{attrs}{order_by}}
1522 : (defined $rel_info->{attrs}{order_by}
1448
1449 : (defined $rel_info->{attrs}{order_by}
15231450 ? ($rel_info->{attrs}{order_by})
15241451 : ()));
15251452 push(@$order, map { "${as}.$_" } (@key, @ord));
170170 $new->throw_exception("Can't do multi-create without result source")
171171 unless $source;
172172 my $info = $source->relationship_info($key);
173 if ($info && $info->{attrs}{accessor}
174 && $info->{attrs}{accessor} eq 'single')
175 {
173 my $acc_type = $info->{attrs}{accessor} || '';
174 if ($acc_type eq 'single') {
176175 my $rel_obj = delete $attrs->{$key};
177176 if(!Scalar::Util::blessed($rel_obj)) {
178177 $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
187186
188187 $related->{$key} = $rel_obj;
189188 next;
190 } elsif ($info && $info->{attrs}{accessor}
191 && $info->{attrs}{accessor} eq 'multi'
192 && ref $attrs->{$key} eq 'ARRAY') {
189 }
190 elsif ($acc_type eq 'multi' && ref $attrs->{$key} eq 'ARRAY' ) {
193191 my $others = delete $attrs->{$key};
194192 my $total = @$others;
195193 my @objects;
209207 }
210208 $related->{$key} = \@objects;
211209 next;
212 } elsif ($info && $info->{attrs}{accessor}
213 && $info->{attrs}{accessor} eq 'filter')
214 {
210 }
211 elsif ($acc_type eq 'filter') {
215212 ## 'filter' should disappear and get merged in with 'single' above!
216213 my $rel_obj = delete $attrs->{$key};
217214 if(!Scalar::Util::blessed($rel_obj)) {
762759 for my $col (keys %loaded_colinfo) {
763760 if (exists $loaded_colinfo{$col}{accessor}) {
764761 my $acc = $loaded_colinfo{$col}{accessor};
765 if (defined $acc) {
766 $inflated{$col} = $self->$acc;
767 }
762 $inflated{$col} = $self->$acc if defined $acc;
768763 }
769764 else {
770765 $inflated{$col} = $self->$col;
916911 foreach my $key (keys %$upd) {
917912 if (ref $upd->{$key}) {
918913 my $info = $self->relationship_info($key);
919 if ($info && $info->{attrs}{accessor}
920 && $info->{attrs}{accessor} eq 'single')
921 {
914 my $acc_type = $info->{attrs}{accessor} || '';
915 if ($acc_type eq 'single') {
922916 my $rel = delete $upd->{$key};
923917 $self->set_from_related($key => $rel);
924918 $self->{_relationship_data}{$key} = $rel;
925 } elsif ($info && $info->{attrs}{accessor}
926 && $info->{attrs}{accessor} eq 'multi') {
927 $self->throw_exception(
928 "Recursive update is not supported over relationships of type multi ($key)"
929 );
930919 }
931 elsif ($self->has_column($key)
932 && exists $self->column_info($key)->{_inflate_info})
933 {
920 elsif ($acc_type eq 'multi') {
921 $self->throw_exception(
922 "Recursive update is not supported over relationships of type '$acc_type' ($key)"
923 );
924 }
925 elsif ($self->has_column($key) && exists $self->column_info($key)->{_inflate_info}) {
934926 $self->set_inflated_column($key, delete $upd->{$key});
935927 }
936928 }
10691061 my ($source_handle) = $source;
10701062
10711063 if ($source->isa('DBIx::Class::ResultSourceHandle')) {
1072 $source = $source_handle->resolve
1073 } else {
1074 $source_handle = $source->handle
1064 $source = $source_handle->resolve
1065 }
1066 else {
1067 $source_handle = $source->handle
10751068 }
10761069
10771070 my $new = {
10801073 };
10811074 bless $new, (ref $class || $class);
10821075
1083 my $schema;
10841076 foreach my $pre (keys %{$prefetch||{}}) {
1085 my $pre_val = $prefetch->{$pre};
1086 my $pre_source = $source->related_source($pre);
1087 $class->throw_exception("Can't prefetch non-existent relationship ${pre}")
1088 unless $pre_source;
1089 if (ref($pre_val->[0]) eq 'ARRAY') { # multi
1090 my @pre_objects;
1091
1092 for my $me_pref (@$pre_val) {
1093
1077
1078 my $pre_source = $source->related_source($pre)
1079 or $class->throw_exception("Can't prefetch non-existent relationship ${pre}");
1080
1081 my $accessor = $source->relationship_info($pre)->{attrs}{accessor}
1082 or $class->throw_exception("No accessor for prefetched $pre");
1083
1084 my @pre_vals;
1085 if (ref $prefetch->{$pre}[0] eq 'ARRAY') {
1086 @pre_vals = @{$prefetch->{$pre}};
1087 }
1088 elsif ($accessor eq 'multi') {
1089 $class->throw_exception("Implicit prefetch (via select/columns) not supported with accessor 'multi'");
1090 }
1091 else {
1092 @pre_vals = $prefetch->{$pre};
1093 }
1094
1095 my @pre_objects;
1096 for my $me_pref (@pre_vals) {
1097
1098 # FIXME - this should not be necessary
10941099 # the collapser currently *could* return bogus elements with all
10951100 # columns set to undef
10961101 my $has_def;
11051110 push @pre_objects, $pre_source->result_class->inflate_result(
11061111 $pre_source, @$me_pref
11071112 );
1108 }
1109
1110 $new->related_resultset($pre)->set_cache(\@pre_objects);
1111 } elsif (defined $pre_val->[0]) {
1112 my $fetched;
1113 unless ($pre_source->primary_columns == grep { exists $pre_val->[0]{$_}
1114 and !defined $pre_val->[0]{$_} } $pre_source->primary_columns)
1115 {
1116 $fetched = $pre_source->result_class->inflate_result(
1117 $pre_source, @{$pre_val});
1118 }
1119 my $accessor = $source->relationship_info($pre)->{attrs}{accessor};
1120 $class->throw_exception("No accessor for prefetched $pre")
1121 unless defined $accessor;
1122 if ($accessor eq 'single') {
1123 $new->{_relationship_data}{$pre} = $fetched;
1124 } elsif ($accessor eq 'filter') {
1125 $new->{_inflated_column}{$pre} = $fetched;
1126 } else {
1127 $class->throw_exception("Implicit prefetch (via select/columns) not supported with accessor '$accessor'");
1128 }
1129 $new->related_resultset($pre)->set_cache([ $fetched ]);
1130 }
1113 }
1114
1115 if ($accessor eq 'single') {
1116 $new->{_relationship_data}{$pre} = $pre_objects[0];
1117 }
1118 elsif ($accessor eq 'filter') {
1119 $new->{_inflated_column}{$pre} = $pre_objects[0];
1120 }
1121
1122 $new->related_resultset($pre)->set_cache(\@pre_objects);
11311123 }
11321124
11331125 $new->in_storage (1);
11 use strict;
22 use warnings;
33 use base qw/DBIx::Class/;
4 use utf8;
54
65 __PACKAGE__->mk_classdata( '_utf8_columns' );
76
113112
114113 # override this if you want to force everything to be encoded/decoded
115114 sub _is_utf8_column {
116 return (shift->utf8_columns || {})->{shift};
115 return (shift->utf8_columns || {})->{shift @_};
117116 }
118117
119118 =head1 AUTHORS
2424 # Always remember to do all digits for the version even if they're 0
2525 # i.e. first release of 0.XX *must* be 0.XX000. This avoids fBSD ports
2626 # brain damage and presumably various other packaging systems too
27 $VERSION = '0.08117';
27 $VERSION = '0.08118';
2828
2929 $VERSION = eval $VERSION; # numify for warning-free dev releases
3030
420420
421421 # make sure we got rid of the compat shims
422422 SKIP: {
423 skip "Remove in 0.09", 5 if $DBIx::Class::VERSION < 0.09;
424
425 for (qw/compare_relationship_keys pk_depends_on resolve_condition resolve_join resolve_prefetch/) {
423 skip "Remove in 0.082", 3 if $DBIx::Class::VERSION < 0.082;
424
425 for (qw/compare_relationship_keys pk_depends_on resolve_condition/) {
426426 ok (! DBIx::Class::ResultSource->can ($_), "$_ no longer provided by DBIx::Class::ResultSource");
427427 }
428428 }
44 use Test::Warn;
55 use lib qw(t/lib);
66 use DBICTest;
7 use utf8;
87
98 warning_like (
109 sub {
2726 DBICTest::Schema::CD->utf8_columns('title');
2827 Class::C3->reinitialize();
2928
30 my $cd = $schema->resultset('CD')->create( { artist => 1, title => 'øni', year => '2048' } );
31 my $utf8_char = 'uniuni';
32
29 my $cd = $schema->resultset('CD')->create( { artist => 1, title => "weird\x{466}stuff", year => '2048' } );
3330
3431 ok( utf8::is_utf8( $cd->title ), 'got title with utf8 flag' );
32 ok(! utf8::is_utf8( $cd->{_column_data}{title} ), 'store title without utf8' );
33
3534 ok(! utf8::is_utf8( $cd->year ), 'got year without utf8 flag' );
35 ok(! utf8::is_utf8( $cd->{_column_data}{year} ), 'store year without utf8' );
3636
37 utf8::decode($utf8_char);
38 $cd->title($utf8_char);
37 $cd->title('nonunicode');
38 ok(! utf8::is_utf8( $cd->title ), 'got title without utf8 flag' );
3939 ok(! utf8::is_utf8( $cd->{_column_data}{title} ), 'store utf8-less chars' );
4040
4141
7171 ],
7272 });
7373 },
74 qr/Recursive update is not supported over relationships of type multi/,
74 qr/Recursive update is not supported over relationships of type 'multi'/,
7575 'create via update of multi relationships throws an exception'
7676 );
7777
0 use strict;
1 use warnings;
2
3 use Test::More;
4 use Test::Exception;
5
6 use lib qw(t/lib);
7 use DBICTest;
8
9 my $schema = DBICTest->init_schema();
10
11 my $artist = $schema->resultset ('Artist')->find ({artistid => 1});
12 is ($artist->cds->count, 3, 'Correct number of CDs');
13 is ($artist->cds->search_related ('genre')->count, 1, 'Only one of the cds has a genre');
14
15 my $queries = 0;
16 my $orig_cb = $schema->storage->debugcb;
17 $schema->storage->debugcb(sub { $queries++ });
18 $schema->storage->debug(1);
19
20
21 my $pref = $schema->resultset ('Artist')
22 ->search ({ 'me.artistid' => $artist->id }, { prefetch => { cds => 'genre' } })
23 ->next;
24
25 is ($pref->cds->count, 3, 'Correct number of CDs prefetched');
26 is ($pref->cds->search_related ('genre')->count, 1, 'Only one of the prefetched cds has a prefetched genre');
27
28
29 is ($queries, 1, 'All happened within one query only');
30 $schema->storage->debugcb($orig_cb);
31 $schema->storage->debug(0);
32
33
34 done_testing;
0 use strict;
1 use warnings;
2
3 use Test::More;
4 use Test::Exception;
5
6 use lib qw(t/lib);
7 use DBICTest;
8 use DBIC::SqlMakerTest;
9
10 my $schema = DBICTest->init_schema();
11
12 my $new_rs = $schema->resultset('Artist')->search({
13 'artwork_to_artist.artist_id' => 1
14 }, {
15 join => 'artwork_to_artist'
16 });
17 lives_ok { $new_rs->count } 'regular search works';
18 lives_ok { $new_rs->search({ 'artwork_to_artist.artwork_cd_id' => 1})->count }
19 '... and chaining off that using join works';
20 lives_ok { $new_rs->search({ 'artwork_to_artist.artwork_cd_id' => 1})->as_subselect_rs->count }
21 '... and chaining off the virtual view works';
22 dies_ok { $new_rs->as_subselect_rs->search({'artwork_to_artist.artwork_cd_id'=> 1})->count }
23 q{... but chaining off of a virtual view using join doesn't work};
24 done_testing;