Add myself to the contributors list ;)
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSet.pm
CommitLineData
89c0a5a2 1package DBIx::Class::ResultSet;
2
3use strict;
4use warnings;
aa562407 5use Carp qw/croak/;
89c0a5a2 6use overload
7 '0+' => 'count',
a910dc57 8 'bool' => sub { 1; },
89c0a5a2 9 fallback => 1;
3c5b25c5 10use Data::Page;
ea20d0fd 11use Storable;
89c0a5a2 12
ee38fa40 13=head1 NAME
14
bfab575a 15DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
ee38fa40 16
bfab575a 17=head1 SYNOPSIS
ee38fa40 18
a33df5d4 19 my $rs = $schema->resultset('User')->search(registered => 1);
20 my @rows = $schema->resultset('Foo')->search(bar => 'baz');
ee38fa40 21
22=head1 DESCRIPTION
23
bfab575a 24The resultset is also known as an iterator. It is responsible for handling
a33df5d4 25queries that may return an arbitrary number of rows, e.g. via L</search>
bfab575a 26or a C<has_many> relationship.
ee38fa40 27
a33df5d4 28In the examples below, the following table classes are used:
29
30 package MyApp::Schema::Artist;
31 use base qw/DBIx::Class/;
32 __PACKAGE__->table('artist');
33 __PACKAGE__->add_columns(qw/artistid name/);
34 __PACKAGE__->set_primary_key('artistid');
35 __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
36 1;
37
38 package MyApp::Schema::CD;
39 use base qw/DBIx::Class/;
40 __PACKAGE__->table('artist');
41 __PACKAGE__->add_columns(qw/cdid artist title year/);
42 __PACKAGE__->set_primary_key('cdid');
43 __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
44 1;
45
ee38fa40 46=head1 METHODS
47
976f3686 48=head2 new($source, \%$attrs)
ee38fa40 49
a33df5d4 50The resultset constructor. Takes a source object (usually a
51L<DBIx::Class::TableInstance>) and an attribute hash (see L</ATRRIBUTES>
52below). Does not perform any queries -- these are executed as needed by the
53other methods.
54
55Generally you won't need to construct a resultset manually. You'll
56automatically get one from e.g. a L</search> called in scalar context:
57
58 my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
ee38fa40 59
60=cut
61
89c0a5a2 62sub new {
fea3d045 63 my $class = shift;
f9db5527 64 return $class->new_result(@_) if ref $class;
fea3d045 65 my ($source, $attrs) = @_;
b98e75f6 66 #use Data::Dumper; warn Dumper($attrs);
ea20d0fd 67 $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
c7ce65e6 68 my %seen;
6aeb9185 69 my $alias = ($attrs->{alias} ||= 'me');
a9433341 70 if ($attrs->{cols} || !$attrs->{select}) {
71 delete $attrs->{as} if $attrs->{cols};
976f3686 72 my @cols = ($attrs->{cols}
73 ? @{delete $attrs->{cols}}
a9433341 74 : $source->columns);
6aeb9185 75 $attrs->{select} = [ map { m/\./ ? $_ : "${alias}.$_" } @cols ];
976f3686 76 }
6aeb9185 77 $attrs->{as} ||= [ map { m/^$alias\.(.*)$/ ? $1 : $_ } @{$attrs->{select}} ];
976f3686 78 #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
fea3d045 79 $attrs->{from} ||= [ { $alias => $source->from } ];
b52e9bf8 80 if (my $join = delete $attrs->{join}) {
81 foreach my $j (ref $join eq 'ARRAY'
82 ? (@{$join}) : ($join)) {
c7ce65e6 83 if (ref $j eq 'HASH') {
84 $seen{$_} = 1 foreach keys %$j;
85 } else {
86 $seen{$j} = 1;
87 }
88 }
8452e496 89 push(@{$attrs->{from}}, $source->resolve_join($join, $attrs->{alias}));
c7ce65e6 90 }
54540863 91 $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
b52e9bf8 92 foreach my $pre (@{delete $attrs->{prefetch} || []}) {
8452e496 93 push(@{$attrs->{from}}, $source->resolve_join($pre, $attrs->{alias}))
c7ce65e6 94 unless $seen{$pre};
976f3686 95 my @pre =
c7ce65e6 96 map { "$pre.$_" }
f9db5527 97 $source->related_source($pre)->columns;
976f3686 98 push(@{$attrs->{select}}, @pre);
99 push(@{$attrs->{as}}, @pre);
fef5d100 100 }
6aeb9185 101 if ($attrs->{page}) {
102 $attrs->{rows} ||= 10;
103 $attrs->{offset} ||= 0;
104 $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
105 }
89c0a5a2 106 my $new = {
cda04c3a 107 source => $source,
89c0a5a2 108 cond => $attrs->{where},
0a3c5b43 109 from => $attrs->{from},
3c5b25c5 110 count => undef,
93b004d3 111 page => delete $attrs->{page},
3c5b25c5 112 pager => undef,
89c0a5a2 113 attrs => $attrs };
2f5911b2 114 bless ($new, $class);
9229f20a 115 return $new;
89c0a5a2 116}
117
bfab575a 118=head2 search
0a3c5b43 119
87f0da6a 120 my @obj = $rs->search({ foo => 3 }); # "... WHERE foo = 3"
121 my $new_rs = $rs->search({ foo => 3 });
122
6009260a 123If you need to pass in additional attributes but no additional condition,
a33df5d4 124call it as C<search({}, \%attrs);>.
87f0da6a 125
a33df5d4 126 # "SELECT foo, bar FROM $class_table"
127 my @all = $class->search({}, { cols => [qw/foo bar/] });
0a3c5b43 128
129=cut
130
131sub search {
132 my $self = shift;
133
6009260a 134 #use Data::Dumper;warn Dumper(@_);
135
0a3c5b43 136 my $attrs = { %{$self->{attrs}} };
137 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
6aeb9185 138 $attrs = { %$attrs, %{ pop(@_) } };
0a3c5b43 139 }
140
6aeb9185 141 my $where = (@_ ? ((@_ == 1 || ref $_[0] eq "HASH") ? shift : {@_}) : undef());
0a3c5b43 142 if (defined $where) {
143 $where = (defined $attrs->{where}
ad3d2d7c 144 ? { '-and' =>
145 [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
146 $where, $attrs->{where} ] }
0a3c5b43 147 : $where);
148 $attrs->{where} = $where;
149 }
150
fea3d045 151 my $rs = (ref $self)->new($self->{source}, $attrs);
0a3c5b43 152
153 return (wantarray ? $rs->all : $rs);
154}
155
87f0da6a 156=head2 search_literal
157
6009260a 158 my @obj = $rs->search_literal($literal_where_cond, @bind);
159 my $new_rs = $rs->search_literal($literal_where_cond, @bind);
160
161Pass a literal chunk of SQL to be added to the conditional part of the
87f0da6a 162resultset.
6009260a 163
bfab575a 164=cut
165
6009260a 166sub search_literal {
167 my ($self, $cond, @vals) = @_;
168 my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
169 $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
170 return $self->search(\$cond, $attrs);
171}
0a3c5b43 172
87f0da6a 173=head2 find(@colvalues), find(\%cols, \%attrs?)
174
175Finds a row based on its primary key or unique constraint. For example:
176
87f0da6a 177 my $cd = $schema->resultset('CD')->find(5);
178
179Also takes an optional C<key> attribute, to search by a specific key or unique
180constraint. For example:
181
182 my $cd = $schema->resultset('CD')->find_or_create(
183 {
184 artist => 'Massive Attack',
185 title => 'Mezzanine',
186 },
187 { key => 'artist_title' }
188 );
189
a33df5d4 190See also L</find_or_create> and L</update_or_create>.
191
87f0da6a 192=cut
716b3d29 193
194sub find {
195 my ($self, @vals) = @_;
196 my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
87f0da6a 197
198 my @cols = $self->{source}->primary_columns;
199 if (exists $attrs->{key}) {
200 my %uniq = $self->{source}->unique_constraints;
201 $self->( "Unknown key " . $attrs->{key} . " on " . $self->name )
202 unless exists $uniq{$attrs->{key}};
203 @cols = @{ $uniq{$attrs->{key}} };
204 }
205 #use Data::Dumper; warn Dumper($attrs, @vals, @cols);
206 $self->{source}->result_class->throw( "Can't find unless a primary key or unique constraint is defined" )
207 unless @cols;
208
716b3d29 209 my $query;
210 if (ref $vals[0] eq 'HASH') {
211 $query = $vals[0];
87f0da6a 212 } elsif (@cols == @vals) {
716b3d29 213 $query = {};
87f0da6a 214 @{$query}{@cols} = @vals;
716b3d29 215 } else {
216 $query = {@vals};
217 }
218 #warn Dumper($query);
219 # Useless -> disabled
220 #$self->{source}->result_class->throw( "Can't find unless all primary keys are specified" )
221 # unless (keys %$query >= @pk); # If we check 'em we run afoul of uc/lc
222 # column names etc. Not sure what to do yet
223 return $self->search($query)->next;
224}
225
b52e9bf8 226=head2 search_related
227
228 $rs->search_related('relname', $cond?, $attrs?);
229
a33df5d4 230Search the specified relationship. Optionally specify a condition for matching
231records.
232
b52e9bf8 233=cut
234
6aeb9185 235sub search_related {
236 my ($self, $rel, @rest) = @_;
f9db5527 237 my $rel_obj = $self->{source}->relationship_info($rel);
6aeb9185 238 $self->{source}->result_class->throw(
239 "No such relationship ${rel} in search_related")
240 unless $rel_obj;
6aeb9185 241 my $rs = $self->search(undef, { join => $rel });
ea20d0fd 242 return $self->{source}->schema->resultset($rel_obj->{class}
243 )->search( undef,
244 { %{$rs->{attrs}},
245 alias => $rel,
246 select => undef(),
247 as => undef() }
6aeb9185 248 )->search(@rest);
249}
b52e9bf8 250
bfab575a 251=head2 cursor
ee38fa40 252
bfab575a 253Returns a storage-driven cursor to the given resultset.
ee38fa40 254
255=cut
256
73f58123 257sub cursor {
258 my ($self) = @_;
2f5911b2 259 my ($source, $attrs) = @{$self}{qw/source attrs/};
6aeb9185 260 $attrs = { %$attrs };
73f58123 261 return $self->{cursor}
976f3686 262 ||= $source->storage->select($self->{from}, $attrs->{select},
73f58123 263 $attrs->{where},$attrs);
264}
265
87f0da6a 266=head2 search_like
267
a33df5d4 268Perform a search, but use C<LIKE> instead of equality as the condition. Note
269that this is simply a convenience method; you most likely want to use
270L</search> with specific operators.
271
272For more information, see L<DBIx::Class::Manual::Cookbook>.
87f0da6a 273
274=cut
58a4bd18 275
276sub search_like {
277 my $class = shift;
278 my $attrs = { };
279 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
280 $attrs = pop(@_);
281 }
282 my $query = ref $_[0] eq "HASH" ? { %{shift()} }: {@_};
283 $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
284 return $class->search($query, { %$attrs });
285}
286
bfab575a 287=head2 slice($first, $last)
ee38fa40 288
bfab575a 289Returns a subset of elements from the resultset.
ee38fa40 290
291=cut
292
89c0a5a2 293sub slice {
294 my ($self, $min, $max) = @_;
295 my $attrs = { %{ $self->{attrs} || {} } };
6aeb9185 296 $attrs->{offset} ||= 0;
297 $attrs->{offset} += $min;
89c0a5a2 298 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
fea3d045 299 my $slice = (ref $self)->new($self->{source}, $attrs);
89c0a5a2 300 return (wantarray ? $slice->all : $slice);
301}
302
87f0da6a 303=head2 next
ee38fa40 304
a33df5d4 305Returns the next element in the resultset (C<undef> is there is none).
306
307Can be used to efficiently iterate over records in the resultset:
308
309 my $rs = $schema->resultset('CD')->search({});
310 while (my $cd = $rs->next) {
311 print $cd->title;
312 }
ee38fa40 313
314=cut
315
89c0a5a2 316sub next {
317 my ($self) = @_;
73f58123 318 my @row = $self->cursor->next;
a953d8d9 319# warn Dumper(\@row); use Data::Dumper;
89c0a5a2 320 return unless (@row);
c7ce65e6 321 return $self->_construct_object(@row);
322}
323
324sub _construct_object {
325 my ($self, @row) = @_;
976f3686 326 my @cols = @{ $self->{attrs}{as} };
327 #warn "@cols -> @row";
b52e9bf8 328 my (%me, %pre);
329 foreach my $col (@cols) {
330 if ($col =~ /([^\.]+)\.([^\.]+)/) {
6aeb9185 331 $pre{$1}[0]{$2} = shift @row;
b52e9bf8 332 } else {
333 $me{$col} = shift @row;
c7ce65e6 334 }
c7ce65e6 335 }
c01ab172 336 my $new = $self->{source}->result_class->inflate_result(
337 $self->{source}, \%me, \%pre);
33ce49d6 338 $new = $self->{attrs}{record_filter}->($new)
339 if exists $self->{attrs}{record_filter};
340 return $new;
89c0a5a2 341}
342
bfab575a 343=head2 count
ee38fa40 344
bfab575a 345Performs an SQL C<COUNT> with the same query as the resultset was built
6009260a 346with to find the number of elements. If passed arguments, does a search
347on the resultset and counts the results of that.
ee38fa40 348
349=cut
350
89c0a5a2 351sub count {
6009260a 352 my $self = shift;
353 return $self->search(@_)->count if @_ && defined $_[0];
aa562407 354 croak "Unable to ->count with a GROUP BY" if defined $self->{attrs}{group_by};
6aeb9185 355 unless (defined $self->{count}) {
976f3686 356 my $attrs = { %{ $self->{attrs} },
54540863 357 select => { 'count' => '*' },
358 as => [ 'count' ] };
ea20d0fd 359 # offset, order by and page are not needed to count. record_filter is cdbi
360 delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
3c5b25c5 361
fea3d045 362 ($self->{count}) = (ref $self)->new($self->{source}, $attrs)->cursor->next;
3c5b25c5 363 }
364 return 0 unless $self->{count};
6aeb9185 365 my $count = $self->{count};
366 $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
367 $count = $self->{attrs}{rows} if
368 ($self->{attrs}{rows} && $self->{attrs}{rows} < $count);
369 return $count;
89c0a5a2 370}
371
bfab575a 372=head2 count_literal
6009260a 373
a33df5d4 374Calls L</search_literal> with the passed arguments, then L</count>.
6009260a 375
376=cut
377
378sub count_literal { shift->search_literal(@_)->count; }
379
bfab575a 380=head2 all
ee38fa40 381
bfab575a 382Returns all elements in the resultset. Called implictly if the resultset
383is returned in list context.
ee38fa40 384
385=cut
386
89c0a5a2 387sub all {
388 my ($self) = @_;
c7ce65e6 389 return map { $self->_construct_object(@$_); }
73f58123 390 $self->cursor->all;
89c0a5a2 391}
392
bfab575a 393=head2 reset
ee38fa40 394
bfab575a 395Resets the resultset's cursor, so you can iterate through the elements again.
ee38fa40 396
397=cut
398
89c0a5a2 399sub reset {
400 my ($self) = @_;
73f58123 401 $self->cursor->reset;
89c0a5a2 402 return $self;
403}
404
bfab575a 405=head2 first
ee38fa40 406
bfab575a 407Resets the resultset and returns the first element.
ee38fa40 408
409=cut
410
89c0a5a2 411sub first {
412 return $_[0]->reset->next;
413}
414
c01ab172 415=head2 update(\%values)
416
a33df5d4 417Sets the specified columns in the resultset to the supplied values.
c01ab172 418
419=cut
420
421sub update {
422 my ($self, $values) = @_;
aa562407 423 croak "Values for update must be a hash" unless ref $values eq 'HASH';
c01ab172 424 return $self->{source}->storage->update(
425 $self->{source}->from, $values, $self->{cond});
426}
427
428=head2 update_all(\%values)
429
a33df5d4 430Fetches all objects and updates them one at a time. Note that C<update_all>
431will run cascade triggers while L</update> will not.
c01ab172 432
433=cut
434
435sub update_all {
436 my ($self, $values) = @_;
aa562407 437 croak "Values for update must be a hash" unless ref $values eq 'HASH';
c01ab172 438 foreach my $obj ($self->all) {
439 $obj->set_columns($values)->update;
440 }
441 return 1;
442}
443
bfab575a 444=head2 delete
ee38fa40 445
c01ab172 446Deletes the contents of the resultset from its result source.
ee38fa40 447
448=cut
449
28927b50 450sub delete {
89c0a5a2 451 my ($self) = @_;
c01ab172 452 $self->{source}->storage->delete($self->{source}->from, $self->{cond});
89c0a5a2 453 return 1;
454}
455
c01ab172 456=head2 delete_all
457
a33df5d4 458Fetches all objects and deletes them one at a time. Note that C<delete_all>
459will run cascade triggers while L</delete> will not.
c01ab172 460
461=cut
462
463sub delete_all {
464 my ($self) = @_;
465 $_->delete for $self->all;
466 return 1;
467}
28927b50 468
bfab575a 469=head2 pager
ee38fa40 470
471Returns a L<Data::Page> object for the current resultset. Only makes
a33df5d4 472sense for queries with a C<page> attribute.
ee38fa40 473
474=cut
475
3c5b25c5 476sub pager {
477 my ($self) = @_;
478 my $attrs = $self->{attrs};
aa562407 479 croak "Can't create pager for non-paged rs" unless $self->{page};
6aeb9185 480 $attrs->{rows} ||= 10;
481 $self->count;
482 return $self->{pager} ||= Data::Page->new(
93b004d3 483 $self->{count}, $attrs->{rows}, $self->{page});
3c5b25c5 484}
485
bfab575a 486=head2 page($page_num)
ee38fa40 487
bfab575a 488Returns a new resultset for the specified page.
ee38fa40 489
490=cut
491
3c5b25c5 492sub page {
493 my ($self, $page) = @_;
6aeb9185 494 my $attrs = { %{$self->{attrs}} };
3c5b25c5 495 $attrs->{page} = $page;
fea3d045 496 return (ref $self)->new($self->{source}, $attrs);
497}
498
499=head2 new_result(\%vals)
500
87f0da6a 501Creates a result in the resultset's result class.
fea3d045 502
503=cut
504
505sub new_result {
506 my ($self, $values) = @_;
507 $self->{source}->result_class->throw( "new_result needs a hash" )
508 unless (ref $values eq 'HASH');
509 $self->{source}->result_class->throw( "Can't abstract implicit construct, condition not a hash" )
510 if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
511 my %new = %$values;
512 my $alias = $self->{attrs}{alias};
513 foreach my $key (keys %{$self->{cond}||{}}) {
514 $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:$alias\.)?([^\.]+)$/);
515 }
097d3227 516 my $obj = $self->{source}->result_class->new(\%new);
517 $obj->result_source($self->{source}) if $obj->can('result_source');
518 $obj;
fea3d045 519}
520
521=head2 create(\%vals)
522
87f0da6a 523Inserts a record into the resultset and returns the object.
fea3d045 524
a33df5d4 525Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
fea3d045 526
527=cut
528
529sub create {
530 my ($self, $attrs) = @_;
531 $self->{source}->result_class->throw( "create needs a hashref" ) unless ref $attrs eq 'HASH';
532 return $self->new_result($attrs)->insert;
3c5b25c5 533}
534
87f0da6a 535=head2 find_or_create(\%vals, \%attrs?)
536
537 $class->find_or_create({ key => $val, ... });
c2b15ecc 538
c2b15ecc 539Searches for a record matching the search condition; if it doesn't find one,
540creates one and returns that instead.
87f0da6a 541
87f0da6a 542 my $cd = $schema->resultset('CD')->find_or_create({
543 cdid => 5,
544 artist => 'Massive Attack',
545 title => 'Mezzanine',
546 year => 2005,
547 });
548
549Also takes an optional C<key> attribute, to search by a specific key or unique
550constraint. For example:
551
552 my $cd = $schema->resultset('CD')->find_or_create(
553 {
554 artist => 'Massive Attack',
555 title => 'Mezzanine',
556 },
557 { key => 'artist_title' }
558 );
559
560See also L</find> and L</update_or_create>.
561
c2b15ecc 562=cut
563
564sub find_or_create {
565 my $self = shift;
87f0da6a 566 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
567 my $hash = ref $_[0] eq "HASH" ? shift : {@_};
568 my $exists = $self->find($hash, $attrs);
c2b15ecc 569 return defined($exists) ? $exists : $self->create($hash);
570}
571
87f0da6a 572=head2 update_or_create
573
574 $class->update_or_create({ key => $val, ... });
575
576First, search for an existing row matching one of the unique constraints
577(including the primary key) on the source of this resultset. If a row is
578found, update it with the other given column values. Otherwise, create a new
579row.
580
581Takes an optional C<key> attribute to search on a specific unique constraint.
582For example:
583
584 # In your application
585 my $cd = $schema->resultset('CD')->update_or_create(
586 {
587 artist => 'Massive Attack',
588 title => 'Mezzanine',
589 year => 1998,
590 },
591 { key => 'artist_title' }
592 );
593
594If no C<key> is specified, it searches on all unique constraints defined on the
595source, including the primary key.
596
597If the C<key> is specified as C<primary>, search only on the primary key.
598
a33df5d4 599See also L</find> and L</find_or_create>.
600
87f0da6a 601=cut
602
603sub update_or_create {
604 my $self = shift;
605
606 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
607 my $hash = ref $_[0] eq "HASH" ? shift : {@_};
608
609 my %unique_constraints = $self->{source}->unique_constraints;
610 my @constraint_names = (exists $attrs->{key}
611 ? ($attrs->{key})
612 : keys %unique_constraints);
613
614 my @unique_hashes;
615 foreach my $name (@constraint_names) {
616 my @unique_cols = @{ $unique_constraints{$name} };
617 my %unique_hash =
618 map { $_ => $hash->{$_} }
619 grep { exists $hash->{$_} }
620 @unique_cols;
621
622 push @unique_hashes, \%unique_hash
623 if (scalar keys %unique_hash == scalar @unique_cols);
624 }
625
626 my $row;
627 if (@unique_hashes) {
628 $row = $self->search(\@unique_hashes, { rows => 1 })->first;
629 if ($row) {
630 $row->set_columns($hash);
631 $row->update;
632 }
633 }
634
635 unless ($row) {
636 $row = $self->create($hash);
637 }
638
639 return $row;
640}
641
40dbc108 642=head1 ATTRIBUTES
076652e8 643
a33df5d4 644The resultset takes various attributes that modify its behavior. Here's an
645overview of them:
bfab575a 646
647=head2 order_by
076652e8 648
a33df5d4 649Which column(s) to order the results by. This is currently passed through
650directly to SQL, so you can give e.g. C<foo DESC> for a descending order.
076652e8 651
976f3686 652=head2 cols (arrayref)
653
a33df5d4 654Shortcut to request a particular set of columns to be retrieved. Adds
655C<me.> onto the start of any column without a C<.> in it and sets C<select>
656from that, then auto-populates C<as> from C<select> as normal.
976f3686 657
658=head2 select (arrayref)
659
a33df5d4 660Indicates which columns should be selected from the storage.
976f3686 661
662=head2 as (arrayref)
076652e8 663
a33df5d4 664Indicates column names for object inflation.
ee38fa40 665
bfab575a 666=head2 join
ee38fa40 667
a33df5d4 668Contains a list of relationships that should be joined for this query. For
669example:
670
671 # Get CDs by Nine Inch Nails
672 my $rs = $schema->resultset('CD')->search(
673 { 'artist.name' => 'Nine Inch Nails' },
674 { join => 'artist' }
675 );
676
677Can also contain a hash reference to refer to the other relation's relations.
678For example:
679
680 package MyApp::Schema::Track;
681 use base qw/DBIx::Class/;
682 __PACKAGE__->table('track');
683 __PACKAGE__->add_columns(qw/trackid cd position title/);
684 __PACKAGE__->set_primary_key('trackid');
685 __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
686 1;
687
688 # In your application
689 my $rs = $schema->resultset('Artist')->search(
690 { 'track.title' => 'Teardrop' },
691 {
692 join => { cd => 'track' },
693 order_by => 'artist.name',
694 }
695 );
696
697If you want to fetch the columns from the related table as well, see
698C<prefetch> below.
ee38fa40 699
bfab575a 700=head2 prefetch
ee38fa40 701
bfab575a 702Contains a list of relationships that should be fetched along with the main
703query (when they are accessed afterwards they will have already been
a33df5d4 704"prefetched"). This is useful for when you know you will need the related
705objects, because it saves a query. Currently limited to prefetching
bfab575a 706one relationship deep, so unlike C<join>, prefetch must be an arrayref.
ee38fa40 707
bfab575a 708=head2 from
ee38fa40 709
a33df5d4 710This attribute can contain a arrayref of elements. Each element can be another
ee38fa40 711arrayref, to nest joins, or it can be a hash which represents the two sides
712of the join.
713
a33df5d4 714NOTE: Use this on your own risk. This allows you to shoot off your foot!
ee38fa40 715
bfab575a 716=head2 page
076652e8 717
a33df5d4 718For a paged resultset, specifies which page to retrieve. Leave unset
bfab575a 719for an unpaged resultset.
076652e8 720
bfab575a 721=head2 rows
076652e8 722
a33df5d4 723For a paged resultset, how many rows per page. Can also be used to simulate an
724SQL C<LIMIT>.
076652e8 725
a33df5d4 726=head2 group_by (arrayref)
54540863 727
a33df5d4 728A arrayref of columns to group by (note that L</count> doesn't work on grouped
729resultsets).
54540863 730
675ce4a6 731 group_by => [qw/ column1 column2 ... /]
732
54540863 733=head2 distinct
734
a33df5d4 735Set to 1 to group by all columns.
736
737For more examples of using these attributes, see
738L<DBIx::Class::Manual::Cookbook>.
54540863 739
bfab575a 740=cut
076652e8 741
89c0a5a2 7421;