[Dbix-class] order_by interfering with has_many fetch

Darin McBride darin.mcbride at shaw.ca
Mon Nov 16 20:18:58 GMT 2015


On Monday November 16 2015 7:20:17 PM Peter Rabbitson wrote:
> On 11/16/2015 07:16 PM, Darin McBride wrote:
> > On Monday November 16 2015 10:08:13 AM Peter Rabbitson wrote:
> >> On 11/16/2015 06:20 AM, Darin McBride wrote:
> >>> On Sunday November 15 2015 7:09:05 PM Darin McBride wrote:
> >>> So, the column is:
> >>> 
> >>> __PACKAGE__->add_columns(
> >>> 
> >>>       name                    => { data_type => 'varchar', size => 30,
> >>> 
> >>> is_nullable => 0 },
> >>> 
> >>> So, explicitly not nullable.
> >>> 
> >>> I've added this code as the next executable line after all the columns:
> >>> 
> >>> __PACKAGE__->add_unique_constraint(name => ['name']);
> >>> 
> >>> And now my search (which has grown since last time - I'm now prefetching
> >>> sitterauths, too, since I'm going to need a field from there for each
> >>> empire>
> >>> 
> >>> returned) looks like this:
> >>>           $planet_rs =
> >>>           
> >>>               Lacuna->db->resultset('Map::Body')->
> >>>               search(
> >>>               
> >>>                      {
> >>>                      
> >>>                          'sitterauths.sitter_id' => $real_empire->id,
> >>>                          'me.class' => { '!=' =>
> >>> 
> >>> 'Lacuna::DB::Result::Map::Body::Planet::Station' },
> >>> 
> >>>                      },
> >>>                      {
> >>>                      
> >>>                          join => { empire => 'sitterauths' },
> >>>                          prefetch => { 'empire', 'sitterauths' },
> >>>                          order_by => ['me.name'],
> >>>                      
> >>>                      });
> >> 
> >> Please use the resultset exactly as defined above, execute the following
> >> and get me its result:
> >> 
> >> 
> >> use Devel::Dwarn;
> >> $Data::Dumper::Maxdepth = 3;
> >> Dwarn [
> >> 
> >>    $planet_rs->result_source
> >>    
> >>               ->schema
> >>               
> >>                ->storage
> >>                
> >>                 ->_extract_colinfo_of_stable_main_source_order_by_portion
> >>                 (
> >>                 
> >>                   $planet_rs->_resolved_attrs
> >>                 
> >>                 )
> >> 
> >> ]
> 
> What does this say then:
> 
> Dwarn { $planet_rs->result_source->unique_constraints }
> 
> Something screwy is going on with the metadata layer...


{
  primary => [
    "id"
  ]
}

This makes it look like this line:

# tell DBIC that this is unique so it can be sorted properly when dealing
# with has_many, prefetch, and order_by
__PACKAGE__->add_unique_constraint(name => ['name']);

isn't doing anything.  Though, when I change it so the second parameter isn't 
an array reference anymore, I do get a nasty error message telling me I messed 
it up, and nothing else happens (it dies), so I'm pretty sure it's being 
called before the above Dwarn :)

As I'm reading the docs more, I also notice that prefetch is another name for 
join, so I'm removing the explicit join to just rely on the prefetch for 
telling DBIC to perform the join.  Not that this seems to affect the output at 
all, I'm just being clear so that if I paste the code in again in the future, 
you'll know why it has changed.

I also updated to DBIC 0.082820 on my dev system just in case it made any 
difference.  You probably knew it wouldn't, but it can't hurt.  (If it does 
make a difference, I'll have to upgrade the servers, too.)

> 
> > (It's not defined as a unique constraint in the db though, I was going to
> > add that later, since I suspect we'll get some minor speed improvement
> > from it.)
> It is not relevant whether the DB itself has it. It is perfectly fine to
> "lie" to DBIC as long as the thing exists logically.

That's what I figured, which is why I wasn't going to worry about it quite yet.  
I like consistency, but things like this are regularly not consistent while 
still developing :)




More information about the DBIx-Class mailing list