X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSource%2FRowParser.pm;h=6fe946f38af5b41f78a8fd8d8e8077590c9617bb;hb=e2741c7fd695dca054614f297b01d351a45bbf38;hp=8ed29b3ff6765804bab396dc123e4c8a7a60504e;hpb=31dc2ecd10d6401d9f87efd2849b2187ebb60eed;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/ResultSource/RowParser.pm b/lib/DBIx/Class/ResultSource/RowParser.pm index 8ed29b3..6fe946f 100644 --- a/lib/DBIx/Class/ResultSource/RowParser.pm +++ b/lib/DBIx/Class/ResultSource/RowParser.pm @@ -6,9 +6,6 @@ use warnings; use base 'DBIx::Class'; -use Try::Tiny; -use List::Util qw(first max); - use DBIx::Class::ResultSource::RowParser::Util qw( assemble_simple_parser assemble_collapsing_parser @@ -122,8 +119,6 @@ sub _mk_row_parser { }, ); - my $check_null_columns; - my $src = (! $args->{collapse} ) ? assemble_simple_parser(\%common) : do { my $collapse_map = $self->_resolve_collapse ({ # FIXME @@ -141,9 +136,6 @@ sub _mk_row_parser { premultiplied => $args->{premultiplied}, }); - $check_null_columns = $collapse_map->{-identifying_columns} - if @{$collapse_map->{-identifying_columns}}; - assemble_collapsing_parser({ %common, collapse_map => $collapse_map, @@ -153,10 +145,7 @@ sub _mk_row_parser { utf8::upgrade($src) if DBIx::Class::_ENV_::STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE; - return ( - $args->{eval} ? ( eval "sub $src" || die $@ ) : $src, - $check_null_columns, - ); + $src; } @@ -178,13 +167,13 @@ sub _resolve_collapse { $args->{_is_top_level} = 1; }; - my ($my_cols, $rel_cols); + my ($my_cols, $rel_cols, $native_cols); for (keys %{$args->{as}}) { if ($_ =~ /^ ([^\.]+) \. (.+) /x) { $rel_cols->{$1}{$2} = 1; } else { - $my_cols->{$_} = {}; # important for ||='s below + $native_cols->{$_} = $my_cols->{$_} = {}; # important for ||='s below } } @@ -197,26 +186,12 @@ sub _resolve_collapse { is_single => ( $inf->{attrs}{accessor} && $inf->{attrs}{accessor} ne 'multi' ), is_inner => ( ( $inf->{attrs}{join_type} || '' ) !~ /^left/i), rsrc => $self->related_source($rel), + fk_map => $self->_resolve_relationship_condition( + rel_name => $rel, + self_alias => "\xFE", # irrelevant + foreign_alias => "\xFF", # irrelevant + )->{identity_map}, }; - - # FIME - need to use _resolve_cond here instead - my $cond = $inf->{cond}; - - if ( - ref $cond eq 'HASH' - and - keys %$cond - and - ! defined first { $_ !~ /^foreign\./ } (keys %$cond) - and - ! defined first { $_ !~ /^self\./ } (values %$cond) - ) { - for my $f (keys %$cond) { - my $s = $cond->{$f}; - $_ =~ s/^ (?: foreign | self ) \.//x for ($f, $s); - $relinfo->{$rel}{fk_map}{$s} = $f; - } - } } # inject non-left fk-bridges from *INNER-JOINED* children (if any) @@ -239,7 +214,7 @@ sub _resolve_collapse { if ( ! $args->{_parent_info}{underdefined} and ! $args->{_parent_info}{rev_rel_is_optional} ) { for my $col ( values %{$args->{_parent_info}{rel_condition} || {}} ) { next if exists $my_cols->{$col}; - $my_cols->{$col} = { via_collapse => $args->{_parent_info}{collapse_on_idcols} }; + $my_cols->{$col} = {}; $assumed_from_parent->{columns}{$col}++; } } @@ -254,9 +229,50 @@ sub _resolve_collapse { # first try to reuse the parent's collapser (i.e. reuse collapser over 1:1) # (makes for a leaner coderef later) - unless ($collapse_map->{-identifying_columns}) { + if( + ! $collapse_map->{-identifying_columns} + and + $args->{_parent_info}{collapser_reusable} + ) { $collapse_map->{-identifying_columns} = $args->{_parent_info}{collapse_on_idcols} - if $args->{_parent_info}{collapser_reusable}; + } + + # Still don't know how to collapse - in case we are a *single* relationship + # AND our parent is defined AND we have any *native* non-nullable pieces: then + # we are still good to go + # NOTE: it doesn't matter if the nonnullable set is unique or not - it will be + # made unique by the parents identifying cols + if( + ! $collapse_map->{-identifying_columns} + and + $args->{_parent_info}{is_single} + and + @{ $args->{_parent_info}{collapse_on_idcols} } + and + ( my @native_nonnull_cols = grep { + $native_cols->{$_}{colinfo} + and + ! $native_cols->{$_}{colinfo}{is_nullable} + } keys %$native_cols ) + ) { + + $collapse_map->{-identifying_columns} = [ __unique_numlist( + @{ $args->{_parent_info}{collapse_on_idcols}||[] }, + + # FIXME - we don't really need *all* of the columns, $our_nonnull_cols[0] + # is sufficient. However map the entire thing to engage the extra nonnull + # explicit checks, just to be on the safe side + # Remove some day in the future + (map + { + $common_args->{_as_fq_idx}{join ('.', + @{$args->{_rel_chain}}[1 .. $#{$args->{_rel_chain}}], + $_, + )} + } + @native_nonnull_cols + ), + )]; } # Still don't know how to collapse - try to resolve based on our columns (plus already inserted FK bridges) @@ -385,7 +401,14 @@ sub _resolve_collapse { # coderef later $collapse_map->{-identifying_columns} = []; $collapse_map->{-identifying_columns_variants} = [ sort { - (scalar @$a) <=> (scalar @$b) or max(@$a) <=> max(@$b) + (scalar @$a) <=> (scalar @$b) + or + ( + # Poor man's max() + ( sort { $b <=> $a } @$a )[0] + <=> + ( sort { $b <=> $a } @$b )[0] + ) } @collapse_sets ]; } } @@ -416,7 +439,6 @@ sub _resolve_collapse { @{ $collapse_map->{-identifying_columns} }, )]; - my @id_sets; for my $rel (sort keys %$relinfo) { $collapse_map->{$rel} = $relinfo->{$rel}{rsrc}->_resolve_collapse ({ @@ -430,9 +452,11 @@ sub _resolve_collapse { is_optional => ! $relinfo->{$rel}{is_inner}, + is_single => $relinfo->{$rel}{is_single}, + # if there is at least one *inner* reverse relationship which is HASH-based (equality only) # we can safely assume that the child can not exist without us - rev_rel_is_optional => ( first + rev_rel_is_optional => ( grep { ref $_->{cond} eq 'HASH' and ($_->{attrs}{join_type}||'') !~ /^left/i } values %{ $self->reverse_relationship_info($rel) }, ) ? 0 : 1,