X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBIHacks.pm;fp=lib%2FDBIx%2FClass%2FStorage%2FDBIHacks.pm;h=ec6a32f779ec45e0f66766b7c119c926759f4679;hb=656524408f86cf27df8c70a900f452421be9c4e4;hp=3f3662bcb9e509edd3a0aa428e34306f01687607;hpb=2268474f6427676f69515a0ea47d638eaa6b497c;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBIHacks.pm b/lib/DBIx/Class/Storage/DBIHacks.pm index 3f3662b..ec6a32f 100644 --- a/lib/DBIx/Class/Storage/DBIHacks.pm +++ b/lib/DBIx/Class/Storage/DBIHacks.pm @@ -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;