[Dbix-class] Controlling column order

Will Hawes info at whawes.co.uk
Thu Jan 12 22:12:07 CET 2006


Matt S Trout wrote:
> On Thu, Jan 12, 2006 at 07:08:16PM +0000, Will Hawes wrote:
>> Matt S Trout wrote:
>>> On Thu, Jan 12, 2006 at 10:33:56AM +0000, Will Hawes wrote:
>>>> Matt S Trout wrote:
>>>>> On Wed, Jan 11, 2006 at 01:16:12PM -0600, Brandon Black wrote:
>>>>>> On 1/11/06, Will Hawes <info at whawes.co.uk> wrote:
>>>>>>> Is it possible to control the order in which columns are returned from 
>>>>>>> a
>>>>>>> DBIx::Class object?
>>>>>>>
>>>>>> You mean from DBIx::Class::Table->columns?  Perhaps this should be an
>>>>>> optional column_info attribute (sort_order?) that ->columns looks at.
>>>>> or maybe just make the internal hash an IxHash like primaries do. Not 
>>>>> sure
>>>>> what the performance impact of this would be though.
>>>>>
>>>> I thought something along the lines of the attached patch (to SVN 
>>>> revision 462) might be useful here.
>>> Why the classaccessor rather than creating _ordered_columns as part of the
>>> simple group along with everything else?
>> I did try that, but for some reason it made several of the cdbi tests 
>> crap out.
> 
> Back to the drawing board and try to figure out why then :)
> 
> It's probably down to the way CDBI handles column grouping/ordering;
> emulating it was "enertaining", let us say.
> 
> Making it a class-level accessor definitely isn't the answer, since
> DBIx::Class::Table is no longer something any of your record classes inherit
> from - instead they have an instance of it as classdata accessible via
> $object->result_source. If you update your branch to latest you should also
> find that most of this stuff is now in ResultSource.pm, rather than Table
> - if you could add it there, please?
> 

I've run svn update and I'm no longer able to reproduce the failed tests 
- looks like you've released some more pre-emptive fixes :)

Attached are patches to ResultSource.pm to add the ordered_columns() 
accessor, this time using mk_group_accessors(), and 01core.tl to add a 
test for said accessor.
-------------- next part --------------
--- lib\DBIx\Class\ResultSource.pm.orig	Thu Jan 12 20:10:09 2006
+++ lib\DBIx\Class\ResultSource.pm	Thu Jan 12 20:33:01 2006
@@ -11,7 +11,7 @@
 __PACKAGE__->load_components(qw/AccessorGroup/);
 
 __PACKAGE__->mk_group_accessors('simple' =>
-  qw/_columns _primaries name resultset_class result_class schema from/);
+  qw/_ordered_columns _columns _primaries name resultset_class result_class schema from/);
 
 =head1 NAME
 
@@ -33,6 +33,7 @@
   $class = ref $class if ref $class;
   my $new = bless({ %{$attrs || {}} }, $class);
   $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
+  $new->{_ordered_columns} ||= [];
   $new->{_columns} ||= {};
   $new->{name} ||= "!!NAME NOT SET!!";
   return $new;
@@ -40,6 +41,9 @@
 
 sub add_columns {
   my ($self, @cols) = @_;
+  $self->_ordered_columns( \@cols )
+    if !$self->_ordered_columns;
+  push @{ $self->_ordered_columns }, @cols;
   while (my $col = shift @cols) {
     $self->_columns->{$col} = (ref $cols[0] ? shift : {});
   }
@@ -105,6 +109,19 @@
 sub columns {
   croak "columns() is a read-only accessor, did you mean add_columns()?" if (@_ > 1);
   return keys %{shift->_columns};
+}
+
+=head2 ordered_columns
+
+  my @column_names = $obj->ordered_columns;
+
+Like columns(), but returns column names using the order in which they were
+originally supplied to add_columns().
+
+=cut
+
+sub ordered_columns {
+  return @{shift->{ordered_columns}};
 }
 
 =head2 set_primary_key(@cols)
-------------- next part --------------
--- t\run\01core.tl.orig	Thu Jan 12 21:01:36 2006
+++ t\run\01core.tl	Thu Jan 12 21:01:52 2006
@@ -1,6 +1,6 @@
 sub run_tests {
 
-plan tests => 33;
+plan tests => 34;
 
 my @art = DBICTest->class("Artist")->search({ }, { order_by => 'name DESC'});
 
@@ -89,6 +89,11 @@
 is($cd->year, 2005, 'set_columns ok');
 
 $cd->discard_changes;
+
+# check whether ResultSource->ordered_columns returns columns in order originally supplied
+my @cd = DBICTest->class("CD")->find(1)->result_source->ordered_columns;
+
+is_deeply( \@cd, [qw/cdid artist title year/], 'ordered_columns');
 
 $cd = DBICTest->class("CD")->search({ title => 'Spoonful of bees' }, { cols => ['title'] })->next;
 is($cd->title, 'Spoonful of bees', 'subset of columns returned correctly');


More information about the Dbix-class mailing list