Documentation cleanup
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSet.pm
CommitLineData
89c0a5a2 1package DBIx::Class::ResultSet;
2
3use strict;
4use warnings;
5use overload
ebaefbc2 6 '0+' => \&count,
a910dc57 7 'bool' => sub { 1; },
89c0a5a2 8 fallback => 1;
3c5b25c5 9use Data::Page;
ea20d0fd 10use Storable;
bcd26419 11use Scalar::Util qw/weaken/;
89c0a5a2 12
2bb7b40b 13use DBIx::Class::ResultSetColumn;
701da8c4 14use base qw/DBIx::Class/;
15__PACKAGE__->load_components(qw/AccessorGroup/);
a50bcd52 16__PACKAGE__->mk_group_accessors('simple' => qw/result_source result_class/);
701da8c4 17
ee38fa40 18=head1 NAME
19
bfab575a 20DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
ee38fa40 21
bfab575a 22=head1 SYNOPSIS
ee38fa40 23
a33df5d4 24 my $rs = $schema->resultset('User')->search(registered => 1);
24d67825 25 my @rows = $schema->resultset('CD')->search(year => 2005);
ee38fa40 26
27=head1 DESCRIPTION
28
bfab575a 29The resultset is also known as an iterator. It is responsible for handling
a33df5d4 30queries that may return an arbitrary number of rows, e.g. via L</search>
bfab575a 31or a C<has_many> relationship.
ee38fa40 32
a33df5d4 33In the examples below, the following table classes are used:
34
35 package MyApp::Schema::Artist;
36 use base qw/DBIx::Class/;
f4409169 37 __PACKAGE__->load_components(qw/Core/);
a33df5d4 38 __PACKAGE__->table('artist');
39 __PACKAGE__->add_columns(qw/artistid name/);
40 __PACKAGE__->set_primary_key('artistid');
41 __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
42 1;
43
44 package MyApp::Schema::CD;
45 use base qw/DBIx::Class/;
f4409169 46 __PACKAGE__->load_components(qw/Core/);
47 __PACKAGE__->table('cd');
a33df5d4 48 __PACKAGE__->add_columns(qw/cdid artist title year/);
49 __PACKAGE__->set_primary_key('cdid');
50 __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
51 1;
52
ee38fa40 53=head1 METHODS
54
75d07914 55=head2 new
87c4e602 56
27f01d1f 57=over 4
58
a031138b 59=item Arguments: $source, \%$attrs
60
61=item Return Value: $rs
62
27f01d1f 63=back
ee38fa40 64
a33df5d4 65The resultset constructor. Takes a source object (usually a
aa1088bf 66L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see
67L</ATTRIBUTES> below). Does not perform any queries -- these are
68executed as needed by the other methods.
a33df5d4 69
70Generally you won't need to construct a resultset manually. You'll
71automatically get one from e.g. a L</search> called in scalar context:
72
73 my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
ee38fa40 74
a031138b 75IMPORTANT: If called on an object, proxies to new_result instead so
76
77 my $cd = $schema->resultset('CD')->new({ title => 'Spoon' });
78
79will return a CD object, not a ResultSet.
80
ee38fa40 81=cut
82
89c0a5a2 83sub new {
fea3d045 84 my $class = shift;
f9db5527 85 return $class->new_result(@_) if ref $class;
5e8b1b2a 86
fea3d045 87 my ($source, $attrs) = @_;
bcd26419 88 weaken $source;
ea20d0fd 89 $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
bcd26419 90 #use Data::Dumper; warn Dumper($attrs);
6aeb9185 91 my $alias = ($attrs->{alias} ||= 'me');
5e8b1b2a 92
93 $attrs->{columns} ||= delete $attrs->{cols} if $attrs->{cols};
1c258fc1 94 delete $attrs->{as} if $attrs->{columns};
5e8b1b2a 95 $attrs->{columns} ||= [ $source->columns ] unless $attrs->{select};
aa1088bf 96 $attrs->{select} = [
97 map { m/\./ ? $_ : "${alias}.$_" } @{delete $attrs->{columns}}
98 ] if $attrs->{columns};
99 $attrs->{as} ||= [
100 map { m/^\Q$alias.\E(.+)$/ ? $1 : $_ } @{$attrs->{select}}
101 ];
5ac6a044 102 if (my $include = delete $attrs->{include_columns}) {
103 push(@{$attrs->{select}}, @$include);
223aea40 104 push(@{$attrs->{as}}, map { m/([^.]+)$/; $1; } @$include);
5ac6a044 105 }
976f3686 106 #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
5e8b1b2a 107
fea3d045 108 $attrs->{from} ||= [ { $alias => $source->from } ];
8fab5eef 109 $attrs->{seen_join} ||= {};
5e8b1b2a 110 my %seen;
b52e9bf8 111 if (my $join = delete $attrs->{join}) {
5e8b1b2a 112 foreach my $j (ref $join eq 'ARRAY' ? @$join : ($join)) {
c7ce65e6 113 if (ref $j eq 'HASH') {
114 $seen{$_} = 1 foreach keys %$j;
115 } else {
116 $seen{$j} = 1;
117 }
118 }
aa1088bf 119 push(@{$attrs->{from}}, $source->resolve_join(
120 $join, $attrs->{alias}, $attrs->{seen_join})
121 );
c7ce65e6 122 }
5e8b1b2a 123
54540863 124 $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
aa1088bf 125 $attrs->{order_by} = [ $attrs->{order_by} ] if
126 $attrs->{order_by} and !ref($attrs->{order_by});
a86b1efe 127 $attrs->{order_by} ||= [];
128
555af3d9 129 my $collapse = $attrs->{collapse} || {};
b3e8ac9b 130 if (my $prefetch = delete $attrs->{prefetch}) {
0f66a01b 131 my @pre_order;
5e8b1b2a 132 foreach my $p (ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch)) {
133 if ( ref $p eq 'HASH' ) {
b3e8ac9b 134 foreach my $key (keys %$p) {
135 push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
136 unless $seen{$key};
137 }
5e8b1b2a 138 } else {
b3e8ac9b 139 push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
140 unless $seen{$p};
141 }
a86b1efe 142 my @prefetch = $source->resolve_prefetch(
0f66a01b 143 $p, $attrs->{alias}, {}, \@pre_order, $collapse);
489709af 144 push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
145 push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
b3e8ac9b 146 }
0f66a01b 147 push(@{$attrs->{order_by}}, @pre_order);
fef5d100 148 }
555af3d9 149 $attrs->{collapse} = $collapse;
5e8b1b2a 150# use Data::Dumper; warn Dumper($collapse) if keys %{$collapse};
555af3d9 151
6aeb9185 152 if ($attrs->{page}) {
153 $attrs->{rows} ||= 10;
154 $attrs->{offset} ||= 0;
155 $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
156 }
0f66a01b 157
5e8b1b2a 158 bless {
701da8c4 159 result_source => $source,
a50bcd52 160 result_class => $attrs->{result_class} || $source->result_class,
89c0a5a2 161 cond => $attrs->{where},
0a3c5b43 162 from => $attrs->{from},
0f66a01b 163 collapse => $collapse,
3c5b25c5 164 count => undef,
93b004d3 165 page => delete $attrs->{page},
3c5b25c5 166 pager => undef,
5e8b1b2a 167 attrs => $attrs
168 }, $class;
89c0a5a2 169}
170
bfab575a 171=head2 search
0a3c5b43 172
b2f17732 173=over 4
174
a031138b 175=item Arguments: $cond, \%attrs?
b2f17732 176
a031138b 177=item Return Value: $resultset (scalar context), @row_objs (list context)
b2f17732 178
179=back
180
181 my @cds = $cd_rs->search({ year => 2001 }); # "... WHERE year = 2001"
182 my $new_rs = $cd_rs->search({ year => 2005 });
87f0da6a 183
a031138b 184 my $new_rs = $cd_rs->search([ { year => 2005 }, { year => 2004 } ]);
185 # year = 2005 OR year = 2004
186
6009260a 187If you need to pass in additional attributes but no additional condition,
2053ab2a 188call it as C<search(undef, \%attrs)>.
87f0da6a 189
24d67825 190 # "SELECT name, artistid FROM $artist_table"
191 my @all_artists = $schema->resultset('Artist')->search(undef, {
192 columns => [qw/name artistid/],
193 });
0a3c5b43 194
195=cut
196
197sub search {
198 my $self = shift;
199
ff7bb7a1 200 my $rs;
201 if( @_ ) {
202
203 my $attrs = { %{$self->{attrs}} };
8839560b 204 my $having = delete $attrs->{having};
223aea40 205 $attrs = { %$attrs, %{ pop(@_) } } if @_ > 1 and ref $_[$#_] eq 'HASH';
6009260a 206
3e0e9e27 207 my $where = (@_
208 ? ((@_ == 1 || ref $_[0] eq "HASH")
209 ? shift
210 : ((@_ % 2)
211 ? $self->throw_exception(
212 "Odd number of arguments to search")
213 : {@_}))
214 : undef());
ff7bb7a1 215 if (defined $where) {
223aea40 216 $attrs->{where} = (defined $attrs->{where}
ad3d2d7c 217 ? { '-and' =>
218 [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
219 $where, $attrs->{where} ] }
0a3c5b43 220 : $where);
ff7bb7a1 221 }
0a3c5b43 222
8839560b 223 if (defined $having) {
223aea40 224 $attrs->{having} = (defined $attrs->{having}
8839560b 225 ? { '-and' =>
226 [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
227 $having, $attrs->{having} ] }
228 : $having);
8839560b 229 }
230
ff7bb7a1 231 $rs = (ref $self)->new($self->result_source, $attrs);
232 }
233 else {
234 $rs = $self;
223aea40 235 $rs->reset;
ff7bb7a1 236 }
0a3c5b43 237 return (wantarray ? $rs->all : $rs);
238}
239
87f0da6a 240=head2 search_literal
241
b2f17732 242=over 4
243
a031138b 244=item Arguments: $sql_fragment, @bind_values
b2f17732 245
a031138b 246=item Return Value: $resultset (scalar context), @row_objs (list context)
b2f17732 247
248=back
249
250 my @cds = $cd_rs->search_literal('year = ? AND title = ?', qw/2001 Reload/);
251 my $newrs = $artist_rs->search_literal('name = ?', 'Metallica');
6009260a 252
253Pass a literal chunk of SQL to be added to the conditional part of the
b2f17732 254resultset query.
6009260a 255
bfab575a 256=cut
fd9f5466 257
6009260a 258sub search_literal {
259 my ($self, $cond, @vals) = @_;
260 my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
261 $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
262 return $self->search(\$cond, $attrs);
263}
0a3c5b43 264
87c4e602 265=head2 find
266
27f01d1f 267=over 4
268
ebc77b53 269=item Arguments: @values | \%cols, \%attrs?
27f01d1f 270
a031138b 271=item Return Value: $row_object
b2f17732 272
27f01d1f 273=back
87f0da6a 274
275Finds a row based on its primary key or unique constraint. For example:
276
87f0da6a 277 my $cd = $schema->resultset('CD')->find(5);
278
279Also takes an optional C<key> attribute, to search by a specific key or unique
280constraint. For example:
281
fd9f5466 282 my $cd = $schema->resultset('CD')->find(
87f0da6a 283 {
284 artist => 'Massive Attack',
285 title => 'Mezzanine',
286 },
287 { key => 'artist_title' }
288 );
289
7c193ab9 290If no C<key> is specified, it searches on all unique constraints defined on the
291source, including the primary key.
292
293If the C<key> is specified as C<primary>, it searches only on the primary key.
294
58b5bb8c 295See also L</find_or_create> and L</update_or_create>. For information on how to
296declare unique constraints, see
297L<DBIx::Class::ResultSource/add_unique_constraint>.
a33df5d4 298
87f0da6a 299=cut
716b3d29 300
301sub find {
302 my ($self, @vals) = @_;
303 my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
87f0da6a 304
8dc40f3e 305 my %unique_constraints = $self->result_source->unique_constraints;
306 $self->throw_exception(
307 "Can't find unless a primary key or unique constraint is defined"
308 ) unless %unique_constraints;
309
310 my @constraint_names = keys %unique_constraints;
87f0da6a 311 if (exists $attrs->{key}) {
aa1088bf 312 $self->throw_exception(
313 "Unknown key $attrs->{key} on '" . $self->result_source->name . "'"
8dc40f3e 314 ) unless exists $unique_constraints{$attrs->{key}};
315
316 @constraint_names = ($attrs->{key});
716b3d29 317 }
8dc40f3e 318
319 my @unique_hashes;
320 foreach my $name (@constraint_names) {
321 my @unique_cols = @{ $unique_constraints{$name} };
322 my %unique_hash;
323 if (ref $vals[0] eq 'HASH') {
eca4c979 324 # Stupid hack for CDBICompat
325 my %hash = %{ $vals[0] };
326 foreach my $key (keys %hash) {
327 $hash{lc $key} = delete $hash{$key};
328 }
329
8dc40f3e 330 %unique_hash =
eca4c979 331 map { $_ => $hash{$_} }
332 grep { exists $hash{$_} }
8dc40f3e 333 @unique_cols;
334 }
f64e05d2 335 elsif (@unique_cols == @vals) {
8dc40f3e 336 # Assume the argument order corresponds to the constraint definition
337 @unique_hash{@unique_cols} = @vals;
338 }
f64e05d2 339 elsif (@vals % 2 == 0) {
8dc40f3e 340 # Fix for CDBI calling with a hash
341 %unique_hash = @vals;
342 }
343
344 foreach my $key (grep { ! m/\./ } keys %unique_hash) {
345 $unique_hash{"$self->{attrs}{alias}.$key"} = delete $unique_hash{$key};
346 }
347
348 #use Data::Dumper; warn Dumper \@vals, \@unique_cols, \%unique_hash;
349 push @unique_hashes, \%unique_hash if %unique_hash;
01bc091e 350 }
8dc40f3e 351
352 # Handle cases where the ResultSet already defines the query
353 my $query = @unique_hashes ? \@unique_hashes : undef;
354
8389d433 355 if (keys %$attrs) {
43493e7e 356 my $rs = $self->search($query, $attrs);
8dc40f3e 357 return keys %{$rs->{collapse}} ? $rs->next : $rs->single;
43493e7e 358 }
359 else {
8dc40f3e 360 return keys %{$self->{collapse}}
361 ? $self->search($query)->next
362 : $self->single($query);
8389d433 363 }
716b3d29 364}
365
b52e9bf8 366=head2 search_related
367
b2f17732 368=over 4
369
a031138b 370=item Arguments: $cond, \%attrs?
b2f17732 371
a031138b 372=item Return Value: $new_resultset
b52e9bf8 373
b2f17732 374=back
375
376 $new_rs = $cd_rs->search_related('artist', {
377 name => 'Emo-R-Us',
378 });
379
2053ab2a 380Searches the specified relationship, optionally specifying a condition and
b2f17732 381attributes for matching records. See L</ATTRIBUTES> for more information.
a33df5d4 382
b52e9bf8 383=cut
384
6aeb9185 385sub search_related {
64acc2bc 386 return shift->related_resultset(shift)->search(@_);
6aeb9185 387}
b52e9bf8 388
bfab575a 389=head2 cursor
ee38fa40 390
b2f17732 391=over 4
392
a031138b 393=item Arguments: none
b2f17732 394
a031138b 395=item Return Value: $cursor
b2f17732 396
397=back
398
399Returns a storage-driven cursor to the given resultset. See
400L<DBIx::Class::Cursor> for more information.
ee38fa40 401
402=cut
403
73f58123 404sub cursor {
405 my ($self) = @_;
223aea40 406 my $attrs = { %{$self->{attrs}} };
73f58123 407 return $self->{cursor}
701da8c4 408 ||= $self->result_source->storage->select($self->{from}, $attrs->{select},
73f58123 409 $attrs->{where},$attrs);
410}
411
a04ab285 412=head2 single
413
b2f17732 414=over 4
415
a031138b 416=item Arguments: $cond?
b2f17732 417
a031138b 418=item Return Value: $row_object?
b2f17732 419
420=back
421
422 my $cd = $schema->resultset('CD')->single({ year => 2001 });
423
a031138b 424Inflates the first result without creating a cursor if the resultset has
58b5bb8c 425any records in it; if not returns nothing. Used by L</find> as an optimisation.
a04ab285 426
427=cut
428
429sub single {
223aea40 430 my ($self, $where) = @_;
431 my $attrs = { %{$self->{attrs}} };
432 if ($where) {
a04ab285 433 if (defined $attrs->{where}) {
434 $attrs->{where} = {
75d07914 435 '-and' =>
223aea40 436 [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
437 $where, delete $attrs->{where} ]
a04ab285 438 };
439 } else {
223aea40 440 $attrs->{where} = $where;
a04ab285 441 }
442 }
443 my @data = $self->result_source->storage->select_single(
444 $self->{from}, $attrs->{select},
445 $attrs->{where},$attrs);
446 return (@data ? $self->_construct_object(@data) : ());
447}
448
2bb7b40b 449=head2 get_column
450
451=over 4
452
453=item Arguments: $cond?
454
455=item Return Value: $resultsetcolumn
456
457=back
458
459 my $max_length = $rs->get_column('length')->max;
460
461Returns a ResultSetColumn instance for $column based on $self
462
463=cut
464
465sub get_column {
466 my ($self, $column) = @_;
467
468 my $new = DBIx::Class::ResultSetColumn->new($self, $column);
469 return $new;
470}
a04ab285 471
87f0da6a 472=head2 search_like
473
b2f17732 474=over 4
475
a031138b 476=item Arguments: $cond, \%attrs?
b2f17732 477
a031138b 478=item Return Value: $resultset (scalar context), @row_objs (list context)
b2f17732 479
480=back
481
482 # WHERE title LIKE '%blue%'
483 $cd_rs = $rs->search_like({ title => '%blue%'});
484
2053ab2a 485Performs a search, but uses C<LIKE> instead of C<=> as the condition. Note
b2f17732 486that this is simply a convenience method. You most likely want to use
a33df5d4 487L</search> with specific operators.
488
489For more information, see L<DBIx::Class::Manual::Cookbook>.
87f0da6a 490
491=cut
58a4bd18 492
493sub search_like {
223aea40 494 my $class = shift;
495 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
496 my $query = ref $_[0] eq 'HASH' ? { %{shift()} }: {@_};
58a4bd18 497 $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
498 return $class->search($query, { %$attrs });
499}
500
87c4e602 501=head2 slice
502
27f01d1f 503=over 4
504
a031138b 505=item Arguments: $first, $last
27f01d1f 506
a031138b 507=item Return Value: $resultset (scalar context), @row_objs (list context)
b2f17732 508
27f01d1f 509=back
ee38fa40 510
a031138b 511Returns a resultset or object list representing a subset of elements from the
2053ab2a 512resultset slice is called on. Indexes are from 0, i.e., to get the first
513three records, call:
a031138b 514
515 my ($one, $two, $three) = $rs->slice(0, 2);
ee38fa40 516
517=cut
518
89c0a5a2 519sub slice {
520 my ($self, $min, $max) = @_;
237f3e3b 521 my $attrs = {}; # = { %{ $self->{attrs} || {} } };
522 $attrs->{offset} = $self->{attrs}{offset} || 0;
6aeb9185 523 $attrs->{offset} += $min;
89c0a5a2 524 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
237f3e3b 525 return $self->search(undef(), $attrs);
526 #my $slice = (ref $self)->new($self->result_source, $attrs);
527 #return (wantarray ? $slice->all : $slice);
89c0a5a2 528}
529
87f0da6a 530=head2 next
ee38fa40 531
a031138b 532=over 4
533
534=item Arguments: none
535
536=item Return Value: $result?
537
538=back
539
a33df5d4 540Returns the next element in the resultset (C<undef> is there is none).
541
542Can be used to efficiently iterate over records in the resultset:
543
5e8b1b2a 544 my $rs = $schema->resultset('CD')->search;
a33df5d4 545 while (my $cd = $rs->next) {
546 print $cd->title;
547 }
ee38fa40 548
ea1eaf8d 549Note that you need to store the resultset object, and call C<next> on it.
550Calling C<< resultset('Table')->next >> repeatedly will always return the
551first record from the resultset.
552
ee38fa40 553=cut
554
89c0a5a2 555sub next {
556 my ($self) = @_;
223aea40 557 if (@{$self->{all_cache} || []}) {
64acc2bc 558 $self->{all_cache_position} ||= 0;
223aea40 559 return $self->{all_cache}->[$self->{all_cache_position}++];
64acc2bc 560 }
3e0e9e27 561 if ($self->{attrs}{cache}) {
0f66a01b 562 $self->{all_cache_position} = 1;
3e0e9e27 563 return ($self->all)[0];
564 }
aa1088bf 565 my @row = (exists $self->{stashed_row} ?
75d07914 566 @{delete $self->{stashed_row}} :
567 $self->cursor->next
aa1088bf 568 );
a953d8d9 569# warn Dumper(\@row); use Data::Dumper;
89c0a5a2 570 return unless (@row);
c7ce65e6 571 return $self->_construct_object(@row);
572}
573
574sub _construct_object {
575 my ($self, @row) = @_;
b3e8ac9b 576 my @as = @{ $self->{attrs}{as} };
223aea40 577
0f66a01b 578 my $info = $self->_collapse_result(\@as, \@row);
223aea40 579
a50bcd52 580 my $new = $self->result_class->inflate_result($self->result_source, @$info);
223aea40 581
33ce49d6 582 $new = $self->{attrs}{record_filter}->($new)
583 if exists $self->{attrs}{record_filter};
584 return $new;
89c0a5a2 585}
586
0f66a01b 587sub _collapse_result {
588 my ($self, $as, $row, $prefix) = @_;
589
590 my %const;
591
592 my @copy = @$row;
5a5bec6c 593 foreach my $this_as (@$as) {
594 my $val = shift @copy;
595 if (defined $prefix) {
596 if ($this_as =~ m/^\Q${prefix}.\E(.+)$/) {
597 my $remain = $1;
223aea40 598 $remain =~ /^(?:(.*)\.)?([^.]+)$/;
5a5bec6c 599 $const{$1||''}{$2} = $val;
600 }
601 } else {
223aea40 602 $this_as =~ /^(?:(.*)\.)?([^.]+)$/;
5a5bec6c 603 $const{$1||''}{$2} = $val;
0f66a01b 604 }
0f66a01b 605 }
606
0f66a01b 607 my $info = [ {}, {} ];
608 foreach my $key (keys %const) {
609 if (length $key) {
610 my $target = $info;
611 my @parts = split(/\./, $key);
612 foreach my $p (@parts) {
613 $target = $target->[1]->{$p} ||= [];
614 }
615 $target->[0] = $const{$key};
616 } else {
617 $info->[0] = $const{$key};
618 }
619 }
620
aa1088bf 621 my @collapse;
622 if (defined $prefix) {
623 @collapse = map {
75d07914 624 m/^\Q${prefix}.\E(.+)$/ ? ($1) : ()
d2c26f3f 625 } keys %{$self->{collapse}}
aa1088bf 626 } else {
627 @collapse = keys %{$self->{collapse}};
d2c26f3f 628 };
aa1088bf 629
5a5bec6c 630 if (@collapse) {
631 my ($c) = sort { length $a <=> length $b } @collapse;
0f66a01b 632 my $target = $info;
0f66a01b 633 foreach my $p (split(/\./, $c)) {
5a5bec6c 634 $target = $target->[1]->{$p} ||= [];
0f66a01b 635 }
5a5bec6c 636 my $c_prefix = (defined($prefix) ? "${prefix}.${c}" : $c);
637 my @co_key = @{$self->{collapse}{$c_prefix}};
0f66a01b 638 my %co_check = map { ($_, $target->[0]->{$_}); } @co_key;
5a5bec6c 639 my $tree = $self->_collapse_result($as, $row, $c_prefix);
0f66a01b 640 my (@final, @raw);
5a5bec6c 641 while ( !(grep {
aa1088bf 642 !defined($tree->[0]->{$_}) ||
75d07914 643 $co_check{$_} ne $tree->[0]->{$_}
5a5bec6c 644 } @co_key) ) {
0f66a01b 645 push(@final, $tree);
646 last unless (@raw = $self->cursor->next);
647 $row = $self->{stashed_row} = \@raw;
5a5bec6c 648 $tree = $self->_collapse_result($as, $row, $c_prefix);
649 #warn Data::Dumper::Dumper($tree, $row);
0f66a01b 650 }
223aea40 651 @$target = @final;
0f66a01b 652 }
653
0f66a01b 654 return $info;
655}
656
87c4e602 657=head2 result_source
701da8c4 658
a031138b 659=over 4
660
661=item Arguments: $result_source?
662
663=item Return Value: $result_source
664
665=back
666
667An accessor for the primary ResultSource object from which this ResultSet
668is derived.
701da8c4 669
670=cut
671
672
bfab575a 673=head2 count
ee38fa40 674
a031138b 675=over 4
676
ebc77b53 677=item Arguments: $cond, \%attrs??
a031138b 678
679=item Return Value: $count
680
681=back
682
bfab575a 683Performs an SQL C<COUNT> with the same query as the resultset was built
6009260a 684with to find the number of elements. If passed arguments, does a search
685on the resultset and counts the results of that.
ee38fa40 686
bda4c2b8 687Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
688using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
689not support C<DISTINCT> with multiple columns. If you are using such a
690database, you should only use columns from the main table in your C<group_by>
691clause.
692
ee38fa40 693=cut
694
89c0a5a2 695sub count {
6009260a 696 my $self = shift;
223aea40 697 return $self->search(@_)->count if @_ and defined $_[0];
84e3c114 698 return scalar @{ $self->get_cache } if @{ $self->get_cache };
15c382be 699
84e3c114 700 my $count = $self->_count;
701 return 0 unless $count;
15c382be 702
6aeb9185 703 $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
704 $count = $self->{attrs}{rows} if
223aea40 705 $self->{attrs}{rows} and $self->{attrs}{rows} < $count;
6aeb9185 706 return $count;
89c0a5a2 707}
708
84e3c114 709sub _count { # Separated out so pager can get the full count
710 my $self = shift;
711 my $select = { count => '*' };
712 my $attrs = { %{ $self->{attrs} } };
713 if (my $group_by = delete $attrs->{group_by}) {
714 delete $attrs->{having};
715 my @distinct = (ref $group_by ? @$group_by : ($group_by));
716 # todo: try CONCAT for multi-column pk
717 my @pk = $self->result_source->primary_columns;
718 if (@pk == 1) {
719 foreach my $column (@distinct) {
720 if ($column =~ qr/^(?:\Q$attrs->{alias}.\E)?$pk[0]$/) {
721 @distinct = ($column);
722 last;
723 }
75d07914 724 }
84e3c114 725 }
726
727 $select = { count => { distinct => \@distinct } };
728 #use Data::Dumper; die Dumper $select;
729 }
730
731 $attrs->{select} = $select;
732 $attrs->{as} = [qw/count/];
733
734 # offset, order by and page are not needed to count. record_filter is cdbi
735 delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
736
737 my ($count) = (ref $self)->new($self->result_source, $attrs)->cursor->next;
738 return $count;
739}
740
bfab575a 741=head2 count_literal
6009260a 742
a031138b 743=over 4
744
745=item Arguments: $sql_fragment, @bind_values
746
747=item Return Value: $count
748
749=back
750
b2f17732 751Counts the results in a literal query. Equivalent to calling L</search_literal>
752with the passed arguments, then L</count>.
6009260a 753
754=cut
755
756sub count_literal { shift->search_literal(@_)->count; }
757
bfab575a 758=head2 all
ee38fa40 759
a031138b 760=over 4
761
762=item Arguments: none
763
764=item Return Value: @objects
765
766=back
767
880a1a0c 768Returns all elements in the resultset. Called implicitly if the resultset
bfab575a 769is returned in list context.
ee38fa40 770
771=cut
772
89c0a5a2 773sub all {
774 my ($self) = @_;
223aea40 775 return @{ $self->get_cache } if @{ $self->get_cache };
5a5bec6c 776
777 my @obj;
778
779 if (keys %{$self->{collapse}}) {
780 # Using $self->cursor->all is really just an optimisation.
781 # If we're collapsing has_many prefetches it probably makes
782 # very little difference, and this is cleaner than hacking
783 # _construct_object to survive the approach
5a5bec6c 784 $self->cursor->reset;
479ed423 785 my @row = $self->cursor->next;
786 while (@row) {
5a5bec6c 787 push(@obj, $self->_construct_object(@row));
479ed423 788 @row = (exists $self->{stashed_row}
789 ? @{delete $self->{stashed_row}}
790 : $self->cursor->next);
5a5bec6c 791 }
792 } else {
223aea40 793 @obj = map { $self->_construct_object(@$_) } $self->cursor->all;
64acc2bc 794 }
5a5bec6c 795
223aea40 796 $self->set_cache(\@obj) if $self->{attrs}{cache};
5a5bec6c 797 return @obj;
89c0a5a2 798}
799
bfab575a 800=head2 reset
ee38fa40 801
a031138b 802=over 4
803
804=item Arguments: none
805
806=item Return Value: $self
807
808=back
809
bfab575a 810Resets the resultset's cursor, so you can iterate through the elements again.
ee38fa40 811
812=cut
813
89c0a5a2 814sub reset {
815 my ($self) = @_;
64acc2bc 816 $self->{all_cache_position} = 0;
73f58123 817 $self->cursor->reset;
89c0a5a2 818 return $self;
819}
820
bfab575a 821=head2 first
ee38fa40 822
a031138b 823=over 4
824
825=item Arguments: none
826
827=item Return Value: $object?
828
829=back
830
831Resets the resultset and returns an object for the first result (if the
2053ab2a 832resultset returns anything).
ee38fa40 833
834=cut
835
89c0a5a2 836sub first {
837 return $_[0]->reset->next;
838}
839
0f57d214 840# _cond_for_update_delete
841#
842# update/delete require the condition to be modified to handle
843# the differing SQL syntax available. This transforms the $self->{cond}
16b4fd26 844# appropriately, returning the new condition.
0f57d214 845
846sub _cond_for_update_delete {
847 my ($self) = @_;
848 my $cond = {};
849
850 if (!ref($self->{cond})) {
16b4fd26 851 # No-op. No condition, we're updating/deleting everything
0f57d214 852 }
853 elsif (ref $self->{cond} eq 'ARRAY') {
854 $cond = [
855 map {
856 my %hash;
857 foreach my $key (keys %{$_}) {
858 $key =~ /([^.]+)$/;
859 $hash{$1} = $_->{$key};
860 }
861 \%hash;
16b4fd26 862 } @{$self->{cond}}
0f57d214 863 ];
864 }
865 elsif (ref $self->{cond} eq 'HASH') {
866 if ((keys %{$self->{cond}})[0] eq '-and') {
16b4fd26 867 $cond->{-and} = [];
868
869 my @cond = @{$self->{cond}{-and}};
870 for (my $i = 0; $i < @cond - 1; $i++) {
871 my $entry = $cond[$i];
872
873 my %hash;
874 if (ref $entry eq 'HASH') {
875 foreach my $key (keys %{$entry}) {
0f57d214 876 $key =~ /([^.]+)$/;
16b4fd26 877 $hash{$1} = $entry->{$key};
0f57d214 878 }
16b4fd26 879 }
880 else {
881 $entry =~ /([^.]+)$/;
882 $hash{$entry} = $cond[++$i];
883 }
884
885 push @{$cond->{-and}}, \%hash;
886 }
0f57d214 887 }
888 else {
889 foreach my $key (keys %{$self->{cond}}) {
890 $key =~ /([^.]+)$/;
891 $cond->{$1} = $self->{cond}{$key};
892 }
893 }
894 }
895 else {
896 $self->throw_exception(
16b4fd26 897 "Can't update/delete on resultset with condition unless hash or array"
898 );
0f57d214 899 }
16b4fd26 900
0f57d214 901 return $cond;
902}
903
904
87c4e602 905=head2 update
906
27f01d1f 907=over 4
908
a031138b 909=item Arguments: \%values
910
911=item Return Value: $storage_rv
27f01d1f 912
913=back
c01ab172 914
a031138b 915Sets the specified columns in the resultset to the supplied values in a
916single query. Return value will be true if the update succeeded or false
917if no records were updated; exact type of success value is storage-dependent.
c01ab172 918
919=cut
920
921sub update {
922 my ($self, $values) = @_;
aa1088bf 923 $self->throw_exception("Values for update must be a hash")
924 unless ref $values eq 'HASH';
0f57d214 925
926 my $cond = $self->_cond_for_update_delete;
927
701da8c4 928 return $self->result_source->storage->update(
0f57d214 929 $self->result_source->from, $values, $cond
27f01d1f 930 );
c01ab172 931}
932
87c4e602 933=head2 update_all
934
27f01d1f 935=over 4
936
a031138b 937=item Arguments: \%values
938
939=item Return Value: 1
27f01d1f 940
941=back
c01ab172 942
2053ab2a 943Fetches all objects and updates them one at a time. Note that C<update_all>
944will run DBIC cascade triggers, while L</update> will not.
c01ab172 945
946=cut
947
948sub update_all {
949 my ($self, $values) = @_;
aa1088bf 950 $self->throw_exception("Values for update must be a hash")
951 unless ref $values eq 'HASH';
c01ab172 952 foreach my $obj ($self->all) {
953 $obj->set_columns($values)->update;
954 }
955 return 1;
956}
957
bfab575a 958=head2 delete
ee38fa40 959
a031138b 960=over 4
961
962=item Arguments: none
963
964=item Return Value: 1
965
966=back
967
b2f17732 968Deletes the contents of the resultset from its result source. Note that this
2053ab2a 969will not run DBIC cascade triggers. See L</delete_all> if you need triggers
970to run.
ee38fa40 971
972=cut
973
28927b50 974sub delete {
89c0a5a2 975 my ($self) = @_;
ca4b5ab7 976 my $del = {};
7ed3d6dc 977
0f57d214 978 my $cond = $self->_cond_for_update_delete;
7ed3d6dc 979
0f57d214 980 $self->result_source->storage->delete($self->result_source->from, $cond);
89c0a5a2 981 return 1;
982}
983
c01ab172 984=head2 delete_all
985
a031138b 986=over 4
987
988=item Arguments: none
989
990=item Return Value: 1
991
992=back
993
2053ab2a 994Fetches all objects and deletes them one at a time. Note that C<delete_all>
995will run DBIC cascade triggers, while L</delete> will not.
c01ab172 996
997=cut
998
999sub delete_all {
1000 my ($self) = @_;
1001 $_->delete for $self->all;
1002 return 1;
1003}
28927b50 1004
bfab575a 1005=head2 pager
ee38fa40 1006
a031138b 1007=over 4
1008
1009=item Arguments: none
1010
1011=item Return Value: $pager
1012
1013=back
1014
1015Return Value a L<Data::Page> object for the current resultset. Only makes
a33df5d4 1016sense for queries with a C<page> attribute.
ee38fa40 1017
1018=cut
1019
3c5b25c5 1020sub pager {
1021 my ($self) = @_;
1022 my $attrs = $self->{attrs};
aa1088bf 1023 $self->throw_exception("Can't create pager for non-paged rs")
1024 unless $self->{page};
6aeb9185 1025 $attrs->{rows} ||= 10;
6aeb9185 1026 return $self->{pager} ||= Data::Page->new(
84e3c114 1027 $self->_count, $attrs->{rows}, $self->{page});
3c5b25c5 1028}
1029
87c4e602 1030=head2 page
1031
27f01d1f 1032=over 4
1033
a031138b 1034=item Arguments: $page_number
1035
1036=item Return Value: $rs
27f01d1f 1037
1038=back
ee38fa40 1039
a031138b 1040Returns a resultset for the $page_number page of the resultset on which page
1041is called, where each page contains a number of rows equal to the 'rows'
2053ab2a 1042attribute set on the resultset (10 by default).
ee38fa40 1043
1044=cut
1045
3c5b25c5 1046sub page {
1047 my ($self, $page) = @_;
6aeb9185 1048 my $attrs = { %{$self->{attrs}} };
3c5b25c5 1049 $attrs->{page} = $page;
701da8c4 1050 return (ref $self)->new($self->result_source, $attrs);
fea3d045 1051}
1052
87c4e602 1053=head2 new_result
1054
27f01d1f 1055=over 4
1056
a031138b 1057=item Arguments: \%vals
1058
1059=item Return Value: $object
27f01d1f 1060
1061=back
fea3d045 1062
a031138b 1063Creates an object in the resultset's result class and returns it.
fea3d045 1064
1065=cut
1066
1067sub new_result {
1068 my ($self, $values) = @_;
701da8c4 1069 $self->throw_exception( "new_result needs a hash" )
fea3d045 1070 unless (ref $values eq 'HASH');
aa1088bf 1071 $self->throw_exception(
1072 "Can't abstract implicit construct, condition not a hash"
1073 ) if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
fea3d045 1074 my %new = %$values;
1075 my $alias = $self->{attrs}{alias};
1076 foreach my $key (keys %{$self->{cond}||{}}) {
223aea40 1077 $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:\Q${alias}.\E)?([^.]+)$/);
fea3d045 1078 }
a50bcd52 1079 my $obj = $self->result_class->new(\%new);
701da8c4 1080 $obj->result_source($self->result_source) if $obj->can('result_source');
223aea40 1081 return $obj;
fea3d045 1082}
1083
b3e1f1f5 1084=head2 find_or_new
1085
1086=over 4
1087
1088=item Arguments: \%vals, \%attrs?
1089
1090=item Return Value: $object
1091
1092=back
1093
1094Find an existing record from this resultset. If none exists, instantiate a new
1095result object and return it. The object will not be saved into your storage
58b5bb8c 1096until you call L<DBIx::Class::Row/insert> on it.
b3e1f1f5 1097
1098If you want objects to be saved immediately, use L</find_or_create> instead.
1099
1100=cut
1101
1102sub find_or_new {
1103 my $self = shift;
1104 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1105 my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
1106 my $exists = $self->find($hash, $attrs);
1107 return defined $exists ? $exists : $self->new_result($hash);
1108}
1109
87c4e602 1110=head2 create
1111
27f01d1f 1112=over 4
1113
a031138b 1114=item Arguments: \%vals
1115
1116=item Return Value: $object
27f01d1f 1117
1118=back
fea3d045 1119
a031138b 1120Inserts a record into the resultset and returns the object representing it.
fea3d045 1121
a33df5d4 1122Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
fea3d045 1123
1124=cut
1125
1126sub create {
1127 my ($self, $attrs) = @_;
aa1088bf 1128 $self->throw_exception( "create needs a hashref" )
1129 unless ref $attrs eq 'HASH';
fea3d045 1130 return $self->new_result($attrs)->insert;
3c5b25c5 1131}
1132
87c4e602 1133=head2 find_or_create
1134
27f01d1f 1135=over 4
1136
a031138b 1137=item Arguments: \%vals, \%attrs?
1138
1139=item Return Value: $object
27f01d1f 1140
1141=back
87f0da6a 1142
1143 $class->find_or_create({ key => $val, ... });
c2b15ecc 1144
fd9f5466 1145Searches for a record matching the search condition; if it doesn't find one,
1146creates one and returns that instead.
87f0da6a 1147
87f0da6a 1148 my $cd = $schema->resultset('CD')->find_or_create({
1149 cdid => 5,
1150 artist => 'Massive Attack',
1151 title => 'Mezzanine',
1152 year => 2005,
1153 });
1154
1155Also takes an optional C<key> attribute, to search by a specific key or unique
1156constraint. For example:
1157
1158 my $cd = $schema->resultset('CD')->find_or_create(
1159 {
1160 artist => 'Massive Attack',
1161 title => 'Mezzanine',
1162 },
1163 { key => 'artist_title' }
1164 );
1165
58b5bb8c 1166See also L</find> and L</update_or_create>. For information on how to declare
1167unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
87f0da6a 1168
c2b15ecc 1169=cut
1170
1171sub find_or_create {
1172 my $self = shift;
87f0da6a 1173 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
223aea40 1174 my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
87f0da6a 1175 my $exists = $self->find($hash, $attrs);
223aea40 1176 return defined $exists ? $exists : $self->create($hash);
c2b15ecc 1177}
1178
87f0da6a 1179=head2 update_or_create
1180
a031138b 1181=over 4
1182
1183=item Arguments: \%col_values, { key => $unique_constraint }?
1184
1185=item Return Value: $object
1186
1187=back
1188
1189 $class->update_or_create({ col => $val, ... });
87f0da6a 1190
2053ab2a 1191First, searches for an existing row matching one of the unique constraints
1192(including the primary key) on the source of this resultset. If a row is
1193found, updates it with the other given column values. Otherwise, creates a new
87f0da6a 1194row.
1195
1196Takes an optional C<key> attribute to search on a specific unique constraint.
1197For example:
1198
1199 # In your application
1200 my $cd = $schema->resultset('CD')->update_or_create(
1201 {
1202 artist => 'Massive Attack',
1203 title => 'Mezzanine',
1204 year => 1998,
1205 },
1206 { key => 'artist_title' }
1207 );
1208
1209If no C<key> is specified, it searches on all unique constraints defined on the
1210source, including the primary key.
1211
2053ab2a 1212If the C<key> is specified as C<primary>, it searches only on the primary key.
87f0da6a 1213
58b5bb8c 1214See also L</find> and L</find_or_create>. For information on how to declare
1215unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
a33df5d4 1216
87f0da6a 1217=cut
1218
1219sub update_or_create {
1220 my $self = shift;
87f0da6a 1221 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
223aea40 1222 my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
87f0da6a 1223
f64e05d2 1224 my $row = $self->find($hash, $attrs);
1225 if (defined $row) {
1226 $row->set_columns($hash);
1227 $row->update;
1228 return $row;
87f0da6a 1229 }
1230
223aea40 1231 return $self->create($hash);
87f0da6a 1232}
1233
64acc2bc 1234=head2 get_cache
1235
a031138b 1236=over 4
1237
1238=item Arguments: none
1239
1240=item Return Value: \@cache_objects?
1241
1242=back
1243
2053ab2a 1244Gets the contents of the cache for the resultset, if the cache is set.
64acc2bc 1245
1246=cut
1247
1248sub get_cache {
223aea40 1249 shift->{all_cache} || [];
64acc2bc 1250}
1251
1252=head2 set_cache
1253
a031138b 1254=over 4
1255
1256=item Arguments: \@cache_objects
1257
1258=item Return Value: \@cache_objects
1259
1260=back
1261
aa1088bf 1262Sets the contents of the cache for the resultset. Expects an arrayref
a031138b 1263of objects of the same class as those produced by the resultset. Note that
1264if the cache is set the resultset will return the cached objects rather
1265than re-querying the database even if the cache attr is not set.
64acc2bc 1266
1267=cut
1268
1269sub set_cache {
1270 my ( $self, $data ) = @_;
1271 $self->throw_exception("set_cache requires an arrayref")
1272 if ref $data ne 'ARRAY';
a50bcd52 1273 my $result_class = $self->result_class;
64acc2bc 1274 foreach( @$data ) {
aa1088bf 1275 $self->throw_exception(
1276 "cannot cache object of type '$_', expected '$result_class'"
1277 ) if ref $_ ne $result_class;
64acc2bc 1278 }
1279 $self->{all_cache} = $data;
1280}
1281
1282=head2 clear_cache
1283
a031138b 1284=over 4
1285
1286=item Arguments: none
1287
1288=item Return Value: []
1289
1290=back
1291
64acc2bc 1292Clears the cache for the resultset.
1293
1294=cut
1295
1296sub clear_cache {
223aea40 1297 shift->set_cache([]);
64acc2bc 1298}
1299
1300=head2 related_resultset
1301
a031138b 1302=over 4
1303
1304=item Arguments: $relationship_name
1305
1306=item Return Value: $resultset
1307
1308=back
1309
64acc2bc 1310Returns a related resultset for the supplied relationship name.
1311
24d67825 1312 $artist_rs = $schema->resultset('CD')->related_resultset('Artist');
64acc2bc 1313
1314=cut
1315
1316sub related_resultset {
a031138b 1317 my ( $self, $rel ) = @_;
64acc2bc 1318 $self->{related_resultsets} ||= {};
223aea40 1319 return $self->{related_resultsets}{$rel} ||= do {
1320 #warn "fetching related resultset for rel '$rel'";
1321 my $rel_obj = $self->result_source->relationship_info($rel);
1322 $self->throw_exception(
1323 "search_related: result source '" . $self->result_source->name .
1324 "' has no such relationship ${rel}")
1325 unless $rel_obj; #die Dumper $self->{attrs};
1326
1327 my $rs = $self->search(undef, { join => $rel });
1328 my $alias = defined $rs->{attrs}{seen_join}{$rel}
1329 && $rs->{attrs}{seen_join}{$rel} > 1
1330 ? join('_', $rel, $rs->{attrs}{seen_join}{$rel})
1331 : $rel;
1332
64acc2bc 1333 $self->result_source->schema->resultset($rel_obj->{class}
1334 )->search( undef,
1335 { %{$rs->{attrs}},
1336 alias => $alias,
223aea40 1337 select => undef,
1338 as => undef }
a031138b 1339 );
223aea40 1340 };
64acc2bc 1341}
1342
701da8c4 1343=head2 throw_exception
1344
a031138b 1345See L<DBIx::Class::Schema/throw_exception> for details.
701da8c4 1346
1347=cut
1348
1349sub throw_exception {
1350 my $self=shift;
1351 $self->result_source->schema->throw_exception(@_);
1352}
1353
a031138b 1354# XXX: FIXME: Attributes docs need clearing up
076652e8 1355
a031138b 1356=head1 ATTRIBUTES
27f01d1f 1357
a33df5d4 1358The resultset takes various attributes that modify its behavior. Here's an
1359overview of them:
bfab575a 1360
1361=head2 order_by
076652e8 1362
a031138b 1363=over 4
1364
1365=item Value: ($order_by | \@order_by)
1366
eaefb953 1367=back
1368
24d67825 1369Which column(s) to order the results by. This is currently passed
1370through directly to SQL, so you can give e.g. C<year DESC> for a
1371descending order on the column `year'.
076652e8 1372
5e8b1b2a 1373=head2 columns
87c4e602 1374
27f01d1f 1375=over 4
1376
a031138b 1377=item Value: \@columns
27f01d1f 1378
1379=back
976f3686 1380
a33df5d4 1381Shortcut to request a particular set of columns to be retrieved. Adds
1382C<me.> onto the start of any column without a C<.> in it and sets C<select>
5e8b1b2a 1383from that, then auto-populates C<as> from C<select> as normal. (You may also
1384use the C<cols> attribute, as in earlier versions of DBIC.)
976f3686 1385
87c4e602 1386=head2 include_columns
1387
27f01d1f 1388=over 4
1389
a031138b 1390=item Value: \@columns
27f01d1f 1391
1392=back
5ac6a044 1393
1394Shortcut to include additional columns in the returned results - for example
1395
24d67825 1396 $schema->resultset('CD')->search(undef, {
1397 include_columns => ['artist.name'],
1398 join => ['artist']
1399 });
5ac6a044 1400
24d67825 1401would return all CDs and include a 'name' column to the information
1402passed to object inflation
5ac6a044 1403
87c4e602 1404=head2 select
1405
27f01d1f 1406=over 4
1407
a031138b 1408=item Value: \@select_columns
27f01d1f 1409
1410=back
976f3686 1411
4a28c340 1412Indicates which columns should be selected from the storage. You can use
1413column names, or in the case of RDBMS back ends, function or stored procedure
1414names:
1415
24d67825 1416 $rs = $schema->resultset('Employee')->search(undef, {
1417 select => [
1418 'name',
1419 { count => 'employeeid' },
1420 { sum => 'salary' }
1421 ]
1422 });
4a28c340 1423
1424When you use function/stored procedure names and do not supply an C<as>
1425attribute, the column names returned are storage-dependent. E.g. MySQL would
24d67825 1426return a column named C<count(employeeid)> in the above example.
976f3686 1427
87c4e602 1428=head2 as
1429
27f01d1f 1430=over 4
1431
a031138b 1432=item Value: \@inflation_names
27f01d1f 1433
1434=back
076652e8 1435
4a28c340 1436Indicates column names for object inflation. This is used in conjunction with
1437C<select>, usually when C<select> contains one or more function or stored
1438procedure names:
1439
24d67825 1440 $rs = $schema->resultset('Employee')->search(undef, {
1441 select => [
1442 'name',
1443 { count => 'employeeid' }
1444 ],
a0638a7b 1445 as => ['name', 'employee_count'],
24d67825 1446 });
4a28c340 1447
24d67825 1448 my $employee = $rs->first(); # get the first Employee
4a28c340 1449
1450If the object against which the search is performed already has an accessor
1451matching a column name specified in C<as>, the value can be retrieved using
1452the accessor as normal:
1453
24d67825 1454 my $name = $employee->name();
4a28c340 1455
1456If on the other hand an accessor does not exist in the object, you need to
1457use C<get_column> instead:
1458
24d67825 1459 my $employee_count = $employee->get_column('employee_count');
4a28c340 1460
1461You can create your own accessors if required - see
1462L<DBIx::Class::Manual::Cookbook> for details.
ee38fa40 1463
bfab575a 1464=head2 join
ee38fa40 1465
a031138b 1466=over 4
1467
1468=item Value: ($rel_name | \@rel_names | \%rel_names)
1469
1470=back
1471
a33df5d4 1472Contains a list of relationships that should be joined for this query. For
1473example:
1474
1475 # Get CDs by Nine Inch Nails
1476 my $rs = $schema->resultset('CD')->search(
1477 { 'artist.name' => 'Nine Inch Nails' },
1478 { join => 'artist' }
1479 );
1480
1481Can also contain a hash reference to refer to the other relation's relations.
1482For example:
1483
1484 package MyApp::Schema::Track;
1485 use base qw/DBIx::Class/;
1486 __PACKAGE__->table('track');
1487 __PACKAGE__->add_columns(qw/trackid cd position title/);
1488 __PACKAGE__->set_primary_key('trackid');
1489 __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
1490 1;
1491
1492 # In your application
1493 my $rs = $schema->resultset('Artist')->search(
1494 { 'track.title' => 'Teardrop' },
1495 {
1496 join => { cd => 'track' },
1497 order_by => 'artist.name',
1498 }
1499 );
1500
2cb360cc 1501If the same join is supplied twice, it will be aliased to <rel>_2 (and
1502similarly for a third time). For e.g.
1503
24d67825 1504 my $rs = $schema->resultset('Artist')->search({
1505 'cds.title' => 'Down to Earth',
1506 'cds_2.title' => 'Popular',
1507 }, {
1508 join => [ qw/cds cds/ ],
1509 });
2cb360cc 1510
24d67825 1511will return a set of all artists that have both a cd with title 'Down
1512to Earth' and a cd with title 'Popular'.
2cb360cc 1513
1514If you want to fetch related objects from other tables as well, see C<prefetch>
ae1c90a1 1515below.
ee38fa40 1516
87c4e602 1517=head2 prefetch
1518
27f01d1f 1519=over 4
1520
a031138b 1521=item Value: ($rel_name | \@rel_names | \%rel_names)
27f01d1f 1522
1523=back
ee38fa40 1524
75d07914 1525Contains one or more relationships that should be fetched along with the main
bfab575a 1526query (when they are accessed afterwards they will have already been
a33df5d4 1527"prefetched"). This is useful for when you know you will need the related
ae1c90a1 1528objects, because it saves at least one query:
1529
1530 my $rs = $schema->resultset('Tag')->search(
5e8b1b2a 1531 undef,
ae1c90a1 1532 {
1533 prefetch => {
1534 cd => 'artist'
1535 }
1536 }
1537 );
1538
1539The initial search results in SQL like the following:
1540
1541 SELECT tag.*, cd.*, artist.* FROM tag
1542 JOIN cd ON tag.cd = cd.cdid
1543 JOIN artist ON cd.artist = artist.artistid
1544
1545L<DBIx::Class> has no need to go back to the database when we access the
1546C<cd> or C<artist> relationships, which saves us two SQL statements in this
1547case.
1548
2cb360cc 1549Simple prefetches will be joined automatically, so there is no need
1550for a C<join> attribute in the above search. If you're prefetching to
1551depth (e.g. { cd => { artist => 'label' } or similar), you'll need to
1552specify the join as well.
ae1c90a1 1553
1554C<prefetch> can be used with the following relationship types: C<belongs_to>,
2cb360cc 1555C<has_one> (or if you're using C<add_relationship>, any relationship declared
1556with an accessor type of 'single' or 'filter').
ee38fa40 1557
87c4e602 1558=head2 from
1559
27f01d1f 1560=over 4
1561
a031138b 1562=item Value: \@from_clause
27f01d1f 1563
1564=back
ee38fa40 1565
4a28c340 1566The C<from> attribute gives you manual control over the C<FROM> clause of SQL
1567statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
1568clauses.
ee38fa40 1569
a33df5d4 1570NOTE: Use this on your own risk. This allows you to shoot off your foot!
4a28c340 1571C<join> will usually do what you need and it is strongly recommended that you
1572avoid using C<from> unless you cannot achieve the desired result using C<join>.
1573
1574In simple terms, C<from> works as follows:
1575
1576 [
abaf89a9 1577 { <alias> => <table>, -join_type => 'inner|left|right' }
4a28c340 1578 [] # nested JOIN (optional)
493a7fb0 1579 { <table.column> => <foreign_table.foreign_key> }
4a28c340 1580 ]
1581
1582 JOIN
1583 <alias> <table>
1584 [JOIN ...]
1585 ON <table.column> = <foreign_table.foreign_key>
1586
1587An easy way to follow the examples below is to remember the following:
1588
1589 Anything inside "[]" is a JOIN
1590 Anything inside "{}" is a condition for the enclosing JOIN
1591
1592The following examples utilize a "person" table in a family tree application.
1593In order to express parent->child relationships, this table is self-joined:
1594
1595 # Person->belongs_to('father' => 'Person');
1596 # Person->belongs_to('mother' => 'Person');
1597
1598C<from> can be used to nest joins. Here we return all children with a father,
1599then search against all mothers of those children:
1600
1601 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1602 undef,
4a28c340 1603 {
1604 alias => 'mother', # alias columns in accordance with "from"
1605 from => [
1606 { mother => 'person' },
1607 [
1608 [
1609 { child => 'person' },
1610 [
1611 { father => 'person' },
1612 { 'father.person_id' => 'child.father_id' }
1613 ]
1614 ],
1615 { 'mother.person_id' => 'child.mother_id' }
fd9f5466 1616 ],
4a28c340 1617 ]
1618 },
1619 );
1620
1621 # Equivalent SQL:
1622 # SELECT mother.* FROM person mother
1623 # JOIN (
1624 # person child
1625 # JOIN person father
1626 # ON ( father.person_id = child.father_id )
1627 # )
1628 # ON ( mother.person_id = child.mother_id )
1629
1630The type of any join can be controlled manually. To search against only people
1631with a father in the person table, we could explicitly use C<INNER JOIN>:
1632
1633 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1634 undef,
4a28c340 1635 {
1636 alias => 'child', # alias columns in accordance with "from"
1637 from => [
1638 { child => 'person' },
1639 [
abaf89a9 1640 { father => 'person', -join_type => 'inner' },
4a28c340 1641 { 'father.id' => 'child.father_id' }
1642 ],
1643 ]
1644 },
1645 );
1646
1647 # Equivalent SQL:
1648 # SELECT child.* FROM person child
1649 # INNER JOIN person father ON child.father_id = father.id
ee38fa40 1650
bfab575a 1651=head2 page
076652e8 1652
27f01d1f 1653=over 4
1654
a031138b 1655=item Value: $page
27f01d1f 1656
1657=back
1658
a031138b 1659Makes the resultset paged and specifies the page to retrieve. Effectively
1660identical to creating a non-pages resultset and then calling ->page($page)
1661on it.
076652e8 1662
bfab575a 1663=head2 rows
076652e8 1664
27f01d1f 1665=over 4
1666
a031138b 1667=item Value: $rows
27f01d1f 1668
1669=back
1670
a031138b 1671Specifes the maximum number of rows for direct retrieval or the number of
1672rows per page if the page attribute or method is used.
076652e8 1673
87c4e602 1674=head2 group_by
1675
27f01d1f 1676=over 4
1677
a031138b 1678=item Value: \@columns
27f01d1f 1679
1680=back
54540863 1681
bda4c2b8 1682A arrayref of columns to group by. Can include columns of joined tables.
54540863 1683
675ce4a6 1684 group_by => [qw/ column1 column2 ... /]
1685
ea1eaf8d 1686=head2 having
1687
1688=over 4
1689
1690=item Value: $condition
1691
1692=back
1693
1694HAVING is a select statement attribute that is applied between GROUP BY and
1695ORDER BY. It is applied to the after the grouping calculations have been
1696done.
1697
1698 having => { 'count(employee)' => { '>=', 100 } }
1699
54540863 1700=head2 distinct
1701
a031138b 1702=over 4
1703
1704=item Value: (0 | 1)
1705
1706=back
1707
a33df5d4 1708Set to 1 to group by all columns.
1709
534ca143 1710=head2 cache
1711
1712Set to 1 to cache search results. This prevents extra SQL queries if you
1713revisit rows in your ResultSet:
1714
1715 my $resultset = $schema->resultset('Artist')->search( undef, { cache => 1 } );
1716
1717 while( my $artist = $resultset->next ) {
1718 ... do stuff ...
1719 }
1720
75d07914 1721 $rs->first; # without cache, this would issue a query
534ca143 1722
1723By default, searches are not cached.
1724
a33df5d4 1725For more examples of using these attributes, see
1726L<DBIx::Class::Manual::Cookbook>.
54540863 1727
bfab575a 1728=cut
076652e8 1729
89c0a5a2 17301;