Fix spotty handling of complex order_by relationship attrs while prefetching
Peter Rabbitson [Thu, 14 Oct 2010 05:06:28 +0000 (07:06 +0200)]
Changes
lib/DBIx/Class/ResultSource.pm
lib/DBIx/Class/Storage/DBIHacks.pm
t/lib/DBICTest/Schema/Artist.pm
t/prefetch/join_type.t

diff --git a/Changes b/Changes
index 8da3ec5..6e593da 100644 (file)
--- 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
index e2f6e13..075c331 100644 (file)
@@ -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}.$_", ] }
index 23b528b..d4a9df8 100644 (file)
@@ -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 => [
index dd5028e..fdecea3 100644 (file)
@@ -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'
index 6a21f22..7b90c87 100644 (file)
@@ -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
   )',
   [],
 );