From: Peter Rabbitson Date: Thu, 14 Oct 2010 05:06:28 +0000 (+0200) Subject: Fix spotty handling of complex order_by relationship attrs while prefetching X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d2fcb9b3612958ecc794acae77520f3da06d3c5b;p=dbsrgits%2FDBIx-Class-Historic.git Fix spotty handling of complex order_by relationship attrs while prefetching --- diff --git a/Changes b/Changes index 8da3ec5..6e593da 100644 --- a/Changes +++ b/Changes @@ -58,6 +58,7 @@ Revision history for DBIx::Class on DateTime::Format::Pg (RT#61503) - Fix dirtyness detection on source-less objects - Fix incorrect limit_dialect assignment on Replicated pool members + - Fix invalid sql on relationship attr order_by with prefetch * Misc - Refactored capability handling in Storage::DBI, allows for diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index e2f6e13..075c331 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -1545,13 +1545,33 @@ sub _resolve_prefetch { # in ResultSet->_collapse_result my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); } keys %{$rel_info->{cond}}; - my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY' - ? @{$rel_info->{attrs}{order_by}} + push @$order, map { "${as}.$_" } @key; - : (defined $rel_info->{attrs}{order_by} - ? ($rel_info->{attrs}{order_by}) - : ())); - push(@$order, map { "${as}.$_" } (@key, @ord)); + if (my $rel_order = $rel_info->{attrs}{order_by}) { + # this is kludgy and incomplete, I am well aware + # but the parent method is going away entirely anyway + # so sod it + my $sql_maker = $self->storage->sql_maker; + my ($orig_ql, $orig_qr) = $sql_maker->_quote_chars; + my $sep = $sql_maker->name_sep; + + # install our own quoter, so we can catch unqualified stuff + local $sql_maker->{quote_char} = ["\x00", "\xFF"]; + + my $quoted_prefix = "\x00${as}\xFF"; + + for my $chunk ( $sql_maker->_order_by_chunks ($rel_order) ) { + my @bind; + ($chunk, @bind) = @$chunk if ref $chunk; + + $chunk = "${quoted_prefix}${sep}${chunk}" + unless $chunk =~ /\Q$sep/; + + $chunk =~ s/\x00/$orig_ql/g; + $chunk =~ s/\xFF/$orig_qr/g; + push @$order, \[$chunk, @bind]; + } + } } return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] } diff --git a/lib/DBIx/Class/Storage/DBIHacks.pm b/lib/DBIx/Class/Storage/DBIHacks.pm index 23b528b..d4a9df8 100644 --- a/lib/DBIx/Class/Storage/DBIHacks.pm +++ b/lib/DBIx/Class/Storage/DBIHacks.pm @@ -245,7 +245,6 @@ sub _resolve_aliastypes_from_select_args { my ($lquote, $rquote, $sep) = map { quotemeta $_ } ($sql_maker->_quote_chars, $sql_maker->name_sep); - # generate sql chunks my $to_scan = { restricting => [ diff --git a/t/lib/DBICTest/Schema/Artist.pm b/t/lib/DBICTest/Schema/Artist.pm index dd5028e..fdecea3 100644 --- a/t/lib/DBICTest/Schema/Artist.pm +++ b/t/lib/DBICTest/Schema/Artist.pm @@ -39,7 +39,7 @@ __PACKAGE__->mk_classdata('field_name_for', { __PACKAGE__->has_many( cds => 'DBICTest::Schema::CD', undef, - { order_by => 'year' }, + { order_by => { -asc => 'year'} }, ); __PACKAGE__->has_many( cds_unordered => 'DBICTest::Schema::CD' diff --git a/t/prefetch/join_type.t b/t/prefetch/join_type.t index 6a21f22..7b90c87 100644 --- a/t/prefetch/join_type.t +++ b/t/prefetch/join_type.t @@ -39,7 +39,7 @@ is_same_sql_bind ( JOIN artist artist ON artist.artistid = me.artist LEFT JOIN cd cds ON cds.artist = artist.artistid LEFT JOIN artist artist_2 ON artist_2.artistid = cds.artist - ORDER BY cds.artist, cds.year + ORDER BY cds.artist, cds.year ASC )', [], );