X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBIHacks.pm;h=ec6a32f779ec45e0f66766b7c119c926759f4679;hb=5f11e54f1dc812354b8d160d5b286502cc227cbf;hp=66790f48ac9ff8cce9cc87d7c80d5e92c287d74a;hpb=7cec43565df63cdbf6320721c7d7c33cb6ce6e96;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBIHacks.pm b/lib/DBIx/Class/Storage/DBIHacks.pm index 66790f4..ec6a32f 100644 --- a/lib/DBIx/Class/Storage/DBIHacks.pm +++ b/lib/DBIx/Class/Storage/DBIHacks.pm @@ -77,7 +77,7 @@ sub _adjust_select_args_for_complex_prefetch { my $outer_attrs = { %$attrs }; delete $outer_attrs->{$_} for qw/where bind rows offset group_by having/; - my $inner_attrs = { %$attrs }; + my $inner_attrs = { %$attrs, _is_internal_subuery => 1 }; delete $inner_attrs->{$_} for qw/for collapse _prefetch_selector_range _collapse_order_by select as/; @@ -681,11 +681,12 @@ sub _extract_order_criteria { } sub _order_by_is_stable { - my ($self, $ident, $order_by) = @_; + my ($self, $ident, $order_by, $where) = @_; - my $colinfo = $self->_resolve_column_info( - $ident, [ map { $_->[0] } $self->_extract_order_criteria($order_by) ] - ); + my $colinfo = $self->_resolve_column_info($ident, [ + (map { $_->[0] } $self->_extract_order_criteria($order_by)), + $where ? @{$self->_extract_fixed_condition_columns($where)} :(), + ]); return undef unless keys %$colinfo; @@ -700,4 +701,41 @@ sub _order_by_is_stable { return undef; } +# returns an arrayref of column names which *definitely* have som +# sort of non-nullable equality requested in the given condition +# specification. This is used to figure out if a resultset is +# constrained to a column which is part of a unique constraint, +# which in turn allows us to better predict how ordering will behave +# etc. +# +# this is a rudimentary, incomplete, and error-prone extractor +# however this is OK - it is conservative, and if we can not find +# something that is in fact there - the stack will recover gracefully +# Also - DQ and the mst it rode in on will save us all RSN!!! +sub _extract_fixed_condition_columns { + my ($self, $where, $nested) = @_; + + return unless ref $where eq 'HASH'; + + my @cols; + for my $lhs (keys %$where) { + if ($lhs =~ /^\-and$/i) { + push @cols, ref $where->{$lhs} eq 'ARRAY' + ? ( map { $self->_extract_fixed_condition_columns($_, 1) } @{$where->{$lhs}} ) + : $self->_extract_fixed_condition_columns($where->{$lhs}, 1) + ; + } + elsif ($lhs !~ /^\-/) { + my $val = $where->{$lhs}; + + push @cols, $lhs if (defined $val and ( + ! ref $val + or + (ref $val eq 'HASH' and keys %$val == 1 and defined $val->{'='}) + )); + } + } + return $nested ? @cols : \@cols; +} + 1;