Changeset 1410

Show
Ignore:
Timestamp:
02/26/08 07:57:59 (5 months ago)
Author:
bchoate
Message:

Changes to nextprev method to leverage database order by clause to select adjacent object. BugId:68994

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/release-30/lib/MT/Object.pm

    r1174 r1410  
    513513 
    514514    my ($id, $ts) = ($obj->id, $obj->$by_field()); 
    515     local @$args{qw( sort direction range_incl )} 
    516         = ($by_field, $next ? 'ascend' : 'descend', { $by_field => 1 }); 
    517     my $iter = $class->load_iter({ 
     515    local @$args{qw( sort range_incl )} 
     516        = ( [ { column => $by_field, desc => $next ? 'ASC' : 'DESC' }, 
     517            { column => 'id', desc => $next ? 'ASC' : 'DESC' } ], 
     518            { $by_field => 1 }); 
     519 
     520    my $obj = $class->load({ 
    518521        $by_field => ($next ? [ $ts, undef ] : [ undef, $ts ]), 
     522        'id' => $id, 
    519523        %{$terms} 
    520     }, $args); 
    521  
    522     # This selection should always succeed, but handle situation if 
    523     # it fails by returning undef. 
    524     return unless $iter; 
    525  
    526     # The 'same' array will hold any entries that have matching 
    527     # timestamps; we will then sort those by id to find the correct 
    528     # adjacent object. 
    529     my @same;  
    530     while (my $e = $iter->()) { 
    531         # Don't consider the object that is 'current' 
    532         next if $e->id == $id; 
    533         my $e_ts = $e->$by_field(); 
    534         if ($e_ts eq $ts) { 
    535             # An object with the same timestamp should only be 
    536             # considered if the id is in the scope we're looking for 
    537             # (greater than for the 'next' object; less than for 
    538             # the 'previous' object). 
    539             push @same, $e 
    540                 if $next && $e->id > $id or !$next && $e->id < $id; 
    541         } else { 
    542             # We found an object with a timestamp different than 
    543             # the 'current' object. 
    544             if (!@same) { 
    545                 push @same, $e; 
    546                 # We should check to see if this new timestamped object also 
    547                 # has entries adjacent to _it_ that have the same timestamp. 
    548                 while (my $e = $iter->()) { 
    549                     push(@same, $e), next if $e->$by_field() eq $e_ts; 
    550                     $iter->('finish'), last; 
    551                 } 
    552             } else { 
    553                 $iter->('finish'); 
    554             } 
    555             return $e unless @same; 
    556             last; 
    557         } 
    558     } 
    559     if (@same) { 
    560         # If we only have 1 element in @same, return that. 
    561         return $same[0] if @same == 1; 
    562         # Sort remaining elements in @same by id. 
    563         @same = sort { $a->id <=> $b->id } @same; 
    564         # Return front of list (smallest id) if selecting 'next' 
    565         # object. Return tail of list (largest id) if selection 'previous'. 
    566         return $same[$next ? 0 : $#same]; 
    567     } 
    568     return; 
     524    }, { not => { 'id' => 1 }, limit => 1, %$args }); 
     525 
     526    return $obj; 
    569527} 
    570528 
  • branches/release-30/lib/MT/ObjectDriver/Driver/DBI.pm

    r1174 r1410  
    348348        if ($args->{sort} || $args->{direction}) { 
    349349            my $order = $args->{sort} || 'id'; 
    350             my $dir = $args->{direction} && 
    351                       $args->{direction} eq 'descend' ? 'DESC' : 'ASC'; 
    352             $stmt->order({ 
    353                 column => $dbd->db_column_name($tbl, $order), 
    354                 desc   => $dir, 
    355             }); 
     350            if (! ref($order)) { 
     351                my $dir = $args->{direction} && 
     352                          $args->{direction} eq 'descend' ? 'DESC' : 'ASC'; 
     353                $stmt->order({ 
     354                    column => $dbd->db_column_name($tbl, $order), 
     355                    desc   => $dir, 
     356                }); 
     357            } else { 
     358                my @order; 
     359                foreach my $ord (@$order) { 
     360                    push @order, { 
     361                        column => $dbd->db_column_name($tbl, $ord->{column}), 
     362                        desc => $ord->{desc}, 
     363                    }; 
     364                } 
     365                $stmt->order(\@order); 
     366            } 
    356367        } 
    357368    } 
     
    433444        ## TODO: support complex primary keys 
    434445        my $col = $args->{sort} || $class->primary_key; 
    435         $col = $driver->_decorate_column_name($class, $col); 
     446        if (ref $col eq 'ARRAY') { 
     447            if (ref $col->[0] eq 'HASH') { 
     448                # complex 'sort' array/hash structure 
     449                foreach (@$col) { 
     450                    $_->{column} = $driver->_decorate_column_name($class, $_->{column}); 
     451                } 
     452            } else { 
     453                # primary key as array of column names 
     454                foreach (@$col) { 
     455                    $_ = $driver->_decorate_column_name($class, $_); 
     456                } 
     457            } 
     458        } else { 
     459            $col = $driver->_decorate_column_name($class, $col); 
     460        } 
    436461        my $op = $args->{direction} eq 'descend' ? '<' : '>'; 
    437462        $stmt->add_where($col, { value => $start_val, op => $op });