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