couple bugfixes
[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
75d07914 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,
2053ab2a 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;
ff7bb7a1 198
8c91c8fe 199 my $attrs = { %{$self->{attrs}} };
200 my $having = delete $attrs->{having};
201 $attrs = { %$attrs, %{ pop(@_) } } if @_ > 1 and ref $_[$#_] eq 'HASH';
202
203 my $where = (@_
204 ? ((@_ == 1 || ref $_[0] eq "HASH")
205 ? shift
206 : ((@_ % 2)
207 ? $self->throw_exception(
208 "Odd number of arguments to search")
209 : {@_}))
210 : undef());
211 if (defined $where) {
212 $attrs->{where} = (defined $attrs->{where}
213 ? { '-and' =>
214 [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
215 $where, $attrs->{where} ] }
216 : $where);
217 }
8839560b 218
8c91c8fe 219 if (defined $having) {
220 $attrs->{having} = (defined $attrs->{having}
221 ? { '-and' =>
222 [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
223 $having, $attrs->{having} ] }
224 : $having);
ff7bb7a1 225 }
8c91c8fe 226
227 my $rs = (ref $self)->new($self->result_source, $attrs);
228
765f5b7b 229 unless (@_) { # no search, effectively just a clone
230 my $rows = $self->get_cache;
0823196c 231 if ($rows) {
765f5b7b 232 $rs->set_cache($rows);
233 }
ff7bb7a1 234 }
8c91c8fe 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}} ?
75d07914 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
2053ab2a 348Searches the specified relationship, optionally specifying a condition and
b2f17732 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} = {
75d07914 403 '-and' =>
223aea40 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
2053ab2a 431Performs a search, but uses C<LIKE> instead of C<=> as the condition. Note
b2f17732 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
2053ab2a 458resultset slice is called on. Indexes are from 0, i.e., to get the first
459three records, call:
a031138b 460
461 my ($one, $two, $three) = $rs->slice(0, 2);
ee38fa40 462
463=cut
464
89c0a5a2 465sub slice {
466 my ($self, $min, $max) = @_;
237f3e3b 467 my $attrs = {}; # = { %{ $self->{attrs} || {} } };
468 $attrs->{offset} = $self->{attrs}{offset} || 0;
6aeb9185 469 $attrs->{offset} += $min;
89c0a5a2 470 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
237f3e3b 471 return $self->search(undef(), $attrs);
472 #my $slice = (ref $self)->new($self->result_source, $attrs);
473 #return (wantarray ? $slice->all : $slice);
89c0a5a2 474}
475
87f0da6a 476=head2 next
ee38fa40 477
a031138b 478=over 4
479
480=item Arguments: none
481
482=item Return Value: $result?
483
484=back
485
a33df5d4 486Returns the next element in the resultset (C<undef> is there is none).
487
488Can be used to efficiently iterate over records in the resultset:
489
5e8b1b2a 490 my $rs = $schema->resultset('CD')->search;
a33df5d4 491 while (my $cd = $rs->next) {
492 print $cd->title;
493 }
ee38fa40 494
ea1eaf8d 495Note that you need to store the resultset object, and call C<next> on it.
496Calling C<< resultset('Table')->next >> repeatedly will always return the
497first record from the resultset.
498
ee38fa40 499=cut
500
89c0a5a2 501sub next {
502 my ($self) = @_;
0823196c 503 if (my $cache = $self->get_cache) {
64acc2bc 504 $self->{all_cache_position} ||= 0;
0823196c 505 return $cache->[$self->{all_cache_position}++];
64acc2bc 506 }
3e0e9e27 507 if ($self->{attrs}{cache}) {
0f66a01b 508 $self->{all_cache_position} = 1;
3e0e9e27 509 return ($self->all)[0];
510 }
aa1088bf 511 my @row = (exists $self->{stashed_row} ?
75d07914 512 @{delete $self->{stashed_row}} :
513 $self->cursor->next
aa1088bf 514 );
a953d8d9 515# warn Dumper(\@row); use Data::Dumper;
89c0a5a2 516 return unless (@row);
c7ce65e6 517 return $self->_construct_object(@row);
518}
519
520sub _construct_object {
521 my ($self, @row) = @_;
b3e8ac9b 522 my @as = @{ $self->{attrs}{as} };
223aea40 523
0f66a01b 524 my $info = $self->_collapse_result(\@as, \@row);
223aea40 525
a50bcd52 526 my $new = $self->result_class->inflate_result($self->result_source, @$info);
223aea40 527
33ce49d6 528 $new = $self->{attrs}{record_filter}->($new)
529 if exists $self->{attrs}{record_filter};
530 return $new;
89c0a5a2 531}
532
0f66a01b 533sub _collapse_result {
534 my ($self, $as, $row, $prefix) = @_;
535
536 my %const;
537
538 my @copy = @$row;
5a5bec6c 539 foreach my $this_as (@$as) {
540 my $val = shift @copy;
541 if (defined $prefix) {
542 if ($this_as =~ m/^\Q${prefix}.\E(.+)$/) {
543 my $remain = $1;
223aea40 544 $remain =~ /^(?:(.*)\.)?([^.]+)$/;
5a5bec6c 545 $const{$1||''}{$2} = $val;
546 }
547 } else {
223aea40 548 $this_as =~ /^(?:(.*)\.)?([^.]+)$/;
5a5bec6c 549 $const{$1||''}{$2} = $val;
0f66a01b 550 }
0f66a01b 551 }
552
0f66a01b 553 my $info = [ {}, {} ];
554 foreach my $key (keys %const) {
555 if (length $key) {
556 my $target = $info;
557 my @parts = split(/\./, $key);
558 foreach my $p (@parts) {
559 $target = $target->[1]->{$p} ||= [];
560 }
561 $target->[0] = $const{$key};
562 } else {
563 $info->[0] = $const{$key};
564 }
565 }
566
aa1088bf 567 my @collapse;
568 if (defined $prefix) {
569 @collapse = map {
75d07914 570 m/^\Q${prefix}.\E(.+)$/ ? ($1) : ()
d2c26f3f 571 } keys %{$self->{collapse}}
aa1088bf 572 } else {
573 @collapse = keys %{$self->{collapse}};
d2c26f3f 574 };
aa1088bf 575
5a5bec6c 576 if (@collapse) {
577 my ($c) = sort { length $a <=> length $b } @collapse;
0f66a01b 578 my $target = $info;
0f66a01b 579 foreach my $p (split(/\./, $c)) {
5a5bec6c 580 $target = $target->[1]->{$p} ||= [];
0f66a01b 581 }
5a5bec6c 582 my $c_prefix = (defined($prefix) ? "${prefix}.${c}" : $c);
583 my @co_key = @{$self->{collapse}{$c_prefix}};
0f66a01b 584 my %co_check = map { ($_, $target->[0]->{$_}); } @co_key;
5a5bec6c 585 my $tree = $self->_collapse_result($as, $row, $c_prefix);
0f66a01b 586 my (@final, @raw);
5a5bec6c 587 while ( !(grep {
aa1088bf 588 !defined($tree->[0]->{$_}) ||
75d07914 589 $co_check{$_} ne $tree->[0]->{$_}
5a5bec6c 590 } @co_key) ) {
0f66a01b 591 push(@final, $tree);
592 last unless (@raw = $self->cursor->next);
593 $row = $self->{stashed_row} = \@raw;
5a5bec6c 594 $tree = $self->_collapse_result($as, $row, $c_prefix);
0f66a01b 595 }
0823196c 596 @$target = (@final ? @final : [ {}, {} ]);
597 # single empty result to indicate an empty prefetched has_many
0f66a01b 598 }
599
0f66a01b 600 return $info;
601}
602
87c4e602 603=head2 result_source
701da8c4 604
a031138b 605=over 4
606
607=item Arguments: $result_source?
608
609=item Return Value: $result_source
610
611=back
612
613An accessor for the primary ResultSource object from which this ResultSet
614is derived.
701da8c4 615
616=cut
617
618
bfab575a 619=head2 count
ee38fa40 620
a031138b 621=over 4
622
ebc77b53 623=item Arguments: $cond, \%attrs??
a031138b 624
625=item Return Value: $count
626
627=back
628
bfab575a 629Performs an SQL C<COUNT> with the same query as the resultset was built
6009260a 630with to find the number of elements. If passed arguments, does a search
631on the resultset and counts the results of that.
ee38fa40 632
bda4c2b8 633Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
634using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
635not support C<DISTINCT> with multiple columns. If you are using such a
636database, you should only use columns from the main table in your C<group_by>
637clause.
638
ee38fa40 639=cut
640
89c0a5a2 641sub count {
6009260a 642 my $self = shift;
223aea40 643 return $self->search(@_)->count if @_ and defined $_[0];
0823196c 644 return scalar @{ $self->get_cache } if $self->get_cache;
15c382be 645
84e3c114 646 my $count = $self->_count;
647 return 0 unless $count;
15c382be 648
6aeb9185 649 $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
650 $count = $self->{attrs}{rows} if
223aea40 651 $self->{attrs}{rows} and $self->{attrs}{rows} < $count;
6aeb9185 652 return $count;
89c0a5a2 653}
654
84e3c114 655sub _count { # Separated out so pager can get the full count
656 my $self = shift;
657 my $select = { count => '*' };
658 my $attrs = { %{ $self->{attrs} } };
659 if (my $group_by = delete $attrs->{group_by}) {
660 delete $attrs->{having};
661 my @distinct = (ref $group_by ? @$group_by : ($group_by));
662 # todo: try CONCAT for multi-column pk
663 my @pk = $self->result_source->primary_columns;
664 if (@pk == 1) {
665 foreach my $column (@distinct) {
666 if ($column =~ qr/^(?:\Q$attrs->{alias}.\E)?$pk[0]$/) {
667 @distinct = ($column);
668 last;
669 }
75d07914 670 }
84e3c114 671 }
672
673 $select = { count => { distinct => \@distinct } };
674 #use Data::Dumper; die Dumper $select;
675 }
676
677 $attrs->{select} = $select;
678 $attrs->{as} = [qw/count/];
679
680 # offset, order by and page are not needed to count. record_filter is cdbi
681 delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
682
683 my ($count) = (ref $self)->new($self->result_source, $attrs)->cursor->next;
684 return $count;
685}
686
bfab575a 687=head2 count_literal
6009260a 688
a031138b 689=over 4
690
691=item Arguments: $sql_fragment, @bind_values
692
693=item Return Value: $count
694
695=back
696
b2f17732 697Counts the results in a literal query. Equivalent to calling L</search_literal>
698with the passed arguments, then L</count>.
6009260a 699
700=cut
701
702sub count_literal { shift->search_literal(@_)->count; }
703
bfab575a 704=head2 all
ee38fa40 705
a031138b 706=over 4
707
708=item Arguments: none
709
710=item Return Value: @objects
711
712=back
713
880a1a0c 714Returns all elements in the resultset. Called implicitly if the resultset
bfab575a 715is returned in list context.
ee38fa40 716
717=cut
718
89c0a5a2 719sub all {
720 my ($self) = @_;
0823196c 721 return @{ $self->get_cache } if $self->get_cache;
5a5bec6c 722
723 my @obj;
724
725 if (keys %{$self->{collapse}}) {
726 # Using $self->cursor->all is really just an optimisation.
727 # If we're collapsing has_many prefetches it probably makes
728 # very little difference, and this is cleaner than hacking
729 # _construct_object to survive the approach
5a5bec6c 730 $self->cursor->reset;
479ed423 731 my @row = $self->cursor->next;
732 while (@row) {
5a5bec6c 733 push(@obj, $self->_construct_object(@row));
479ed423 734 @row = (exists $self->{stashed_row}
735 ? @{delete $self->{stashed_row}}
736 : $self->cursor->next);
5a5bec6c 737 }
738 } else {
223aea40 739 @obj = map { $self->_construct_object(@$_) } $self->cursor->all;
64acc2bc 740 }
5a5bec6c 741
223aea40 742 $self->set_cache(\@obj) if $self->{attrs}{cache};
5a5bec6c 743 return @obj;
89c0a5a2 744}
745
bfab575a 746=head2 reset
ee38fa40 747
a031138b 748=over 4
749
750=item Arguments: none
751
752=item Return Value: $self
753
754=back
755
bfab575a 756Resets the resultset's cursor, so you can iterate through the elements again.
ee38fa40 757
758=cut
759
89c0a5a2 760sub reset {
761 my ($self) = @_;
64acc2bc 762 $self->{all_cache_position} = 0;
73f58123 763 $self->cursor->reset;
89c0a5a2 764 return $self;
765}
766
bfab575a 767=head2 first
ee38fa40 768
a031138b 769=over 4
770
771=item Arguments: none
772
773=item Return Value: $object?
774
775=back
776
777Resets the resultset and returns an object for the first result (if the
2053ab2a 778resultset returns anything).
ee38fa40 779
780=cut
781
89c0a5a2 782sub first {
783 return $_[0]->reset->next;
784}
785
0f57d214 786# _cond_for_update_delete
787#
788# update/delete require the condition to be modified to handle
789# the differing SQL syntax available. This transforms the $self->{cond}
16b4fd26 790# appropriately, returning the new condition.
0f57d214 791
792sub _cond_for_update_delete {
793 my ($self) = @_;
794 my $cond = {};
795
796 if (!ref($self->{cond})) {
16b4fd26 797 # No-op. No condition, we're updating/deleting everything
0f57d214 798 }
799 elsif (ref $self->{cond} eq 'ARRAY') {
800 $cond = [
801 map {
802 my %hash;
803 foreach my $key (keys %{$_}) {
804 $key =~ /([^.]+)$/;
805 $hash{$1} = $_->{$key};
806 }
807 \%hash;
16b4fd26 808 } @{$self->{cond}}
0f57d214 809 ];
810 }
811 elsif (ref $self->{cond} eq 'HASH') {
812 if ((keys %{$self->{cond}})[0] eq '-and') {
16b4fd26 813 $cond->{-and} = [];
814
815 my @cond = @{$self->{cond}{-and}};
816 for (my $i = 0; $i < @cond - 1; $i++) {
817 my $entry = $cond[$i];
818
819 my %hash;
820 if (ref $entry eq 'HASH') {
821 foreach my $key (keys %{$entry}) {
0f57d214 822 $key =~ /([^.]+)$/;
16b4fd26 823 $hash{$1} = $entry->{$key};
0f57d214 824 }
16b4fd26 825 }
826 else {
827 $entry =~ /([^.]+)$/;
828 $hash{$entry} = $cond[++$i];
829 }
830
831 push @{$cond->{-and}}, \%hash;
832 }
0f57d214 833 }
834 else {
835 foreach my $key (keys %{$self->{cond}}) {
836 $key =~ /([^.]+)$/;
837 $cond->{$1} = $self->{cond}{$key};
838 }
839 }
840 }
841 else {
842 $self->throw_exception(
16b4fd26 843 "Can't update/delete on resultset with condition unless hash or array"
844 );
0f57d214 845 }
16b4fd26 846
0f57d214 847 return $cond;
848}
849
850
87c4e602 851=head2 update
852
27f01d1f 853=over 4
854
a031138b 855=item Arguments: \%values
856
857=item Return Value: $storage_rv
27f01d1f 858
859=back
c01ab172 860
a031138b 861Sets the specified columns in the resultset to the supplied values in a
862single query. Return value will be true if the update succeeded or false
863if no records were updated; exact type of success value is storage-dependent.
c01ab172 864
865=cut
866
867sub update {
868 my ($self, $values) = @_;
aa1088bf 869 $self->throw_exception("Values for update must be a hash")
870 unless ref $values eq 'HASH';
0f57d214 871
872 my $cond = $self->_cond_for_update_delete;
873
701da8c4 874 return $self->result_source->storage->update(
0f57d214 875 $self->result_source->from, $values, $cond
27f01d1f 876 );
c01ab172 877}
878
87c4e602 879=head2 update_all
880
27f01d1f 881=over 4
882
a031138b 883=item Arguments: \%values
884
885=item Return Value: 1
27f01d1f 886
887=back
c01ab172 888
2053ab2a 889Fetches all objects and updates them one at a time. Note that C<update_all>
890will run DBIC cascade triggers, while L</update> will not.
c01ab172 891
892=cut
893
894sub update_all {
895 my ($self, $values) = @_;
aa1088bf 896 $self->throw_exception("Values for update must be a hash")
897 unless ref $values eq 'HASH';
c01ab172 898 foreach my $obj ($self->all) {
899 $obj->set_columns($values)->update;
900 }
901 return 1;
902}
903
bfab575a 904=head2 delete
ee38fa40 905
a031138b 906=over 4
907
908=item Arguments: none
909
910=item Return Value: 1
911
912=back
913
b2f17732 914Deletes the contents of the resultset from its result source. Note that this
2053ab2a 915will not run DBIC cascade triggers. See L</delete_all> if you need triggers
916to run.
ee38fa40 917
918=cut
919
28927b50 920sub delete {
89c0a5a2 921 my ($self) = @_;
ca4b5ab7 922 my $del = {};
7ed3d6dc 923
0f57d214 924 my $cond = $self->_cond_for_update_delete;
7ed3d6dc 925
0f57d214 926 $self->result_source->storage->delete($self->result_source->from, $cond);
89c0a5a2 927 return 1;
928}
929
c01ab172 930=head2 delete_all
931
a031138b 932=over 4
933
934=item Arguments: none
935
936=item Return Value: 1
937
938=back
939
2053ab2a 940Fetches all objects and deletes them one at a time. Note that C<delete_all>
941will run DBIC cascade triggers, while L</delete> will not.
c01ab172 942
943=cut
944
945sub delete_all {
946 my ($self) = @_;
947 $_->delete for $self->all;
948 return 1;
949}
28927b50 950
bfab575a 951=head2 pager
ee38fa40 952
a031138b 953=over 4
954
955=item Arguments: none
956
957=item Return Value: $pager
958
959=back
960
961Return Value a L<Data::Page> object for the current resultset. Only makes
a33df5d4 962sense for queries with a C<page> attribute.
ee38fa40 963
964=cut
965
3c5b25c5 966sub pager {
967 my ($self) = @_;
968 my $attrs = $self->{attrs};
aa1088bf 969 $self->throw_exception("Can't create pager for non-paged rs")
970 unless $self->{page};
6aeb9185 971 $attrs->{rows} ||= 10;
6aeb9185 972 return $self->{pager} ||= Data::Page->new(
84e3c114 973 $self->_count, $attrs->{rows}, $self->{page});
3c5b25c5 974}
975
87c4e602 976=head2 page
977
27f01d1f 978=over 4
979
a031138b 980=item Arguments: $page_number
981
982=item Return Value: $rs
27f01d1f 983
984=back
ee38fa40 985
a031138b 986Returns a resultset for the $page_number page of the resultset on which page
987is called, where each page contains a number of rows equal to the 'rows'
2053ab2a 988attribute set on the resultset (10 by default).
ee38fa40 989
990=cut
991
3c5b25c5 992sub page {
993 my ($self, $page) = @_;
6aeb9185 994 my $attrs = { %{$self->{attrs}} };
3c5b25c5 995 $attrs->{page} = $page;
701da8c4 996 return (ref $self)->new($self->result_source, $attrs);
fea3d045 997}
998
87c4e602 999=head2 new_result
1000
27f01d1f 1001=over 4
1002
a031138b 1003=item Arguments: \%vals
1004
1005=item Return Value: $object
27f01d1f 1006
1007=back
fea3d045 1008
a031138b 1009Creates an object in the resultset's result class and returns it.
fea3d045 1010
1011=cut
1012
1013sub new_result {
1014 my ($self, $values) = @_;
701da8c4 1015 $self->throw_exception( "new_result needs a hash" )
fea3d045 1016 unless (ref $values eq 'HASH');
aa1088bf 1017 $self->throw_exception(
1018 "Can't abstract implicit construct, condition not a hash"
1019 ) if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
fea3d045 1020 my %new = %$values;
1021 my $alias = $self->{attrs}{alias};
1022 foreach my $key (keys %{$self->{cond}||{}}) {
223aea40 1023 $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:\Q${alias}.\E)?([^.]+)$/);
fea3d045 1024 }
a50bcd52 1025 my $obj = $self->result_class->new(\%new);
701da8c4 1026 $obj->result_source($self->result_source) if $obj->can('result_source');
223aea40 1027 return $obj;
fea3d045 1028}
1029
87c4e602 1030=head2 create
1031
27f01d1f 1032=over 4
1033
a031138b 1034=item Arguments: \%vals
1035
1036=item Return Value: $object
27f01d1f 1037
1038=back
fea3d045 1039
a031138b 1040Inserts a record into the resultset and returns the object representing it.
fea3d045 1041
a33df5d4 1042Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
fea3d045 1043
1044=cut
1045
1046sub create {
1047 my ($self, $attrs) = @_;
aa1088bf 1048 $self->throw_exception( "create needs a hashref" )
1049 unless ref $attrs eq 'HASH';
fea3d045 1050 return $self->new_result($attrs)->insert;
3c5b25c5 1051}
1052
87c4e602 1053=head2 find_or_create
1054
27f01d1f 1055=over 4
1056
a031138b 1057=item Arguments: \%vals, \%attrs?
1058
1059=item Return Value: $object
27f01d1f 1060
1061=back
87f0da6a 1062
1063 $class->find_or_create({ key => $val, ... });
c2b15ecc 1064
fd9f5466 1065Searches for a record matching the search condition; if it doesn't find one,
1066creates one and returns that instead.
87f0da6a 1067
87f0da6a 1068 my $cd = $schema->resultset('CD')->find_or_create({
1069 cdid => 5,
1070 artist => 'Massive Attack',
1071 title => 'Mezzanine',
1072 year => 2005,
1073 });
1074
1075Also takes an optional C<key> attribute, to search by a specific key or unique
1076constraint. For example:
1077
1078 my $cd = $schema->resultset('CD')->find_or_create(
1079 {
1080 artist => 'Massive Attack',
1081 title => 'Mezzanine',
1082 },
1083 { key => 'artist_title' }
1084 );
1085
1086See also L</find> and L</update_or_create>.
1087
c2b15ecc 1088=cut
1089
1090sub find_or_create {
1091 my $self = shift;
87f0da6a 1092 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
223aea40 1093 my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
87f0da6a 1094 my $exists = $self->find($hash, $attrs);
223aea40 1095 return defined $exists ? $exists : $self->create($hash);
c2b15ecc 1096}
1097
87f0da6a 1098=head2 update_or_create
1099
a031138b 1100=over 4
1101
1102=item Arguments: \%col_values, { key => $unique_constraint }?
1103
1104=item Return Value: $object
1105
1106=back
1107
1108 $class->update_or_create({ col => $val, ... });
87f0da6a 1109
2053ab2a 1110First, searches for an existing row matching one of the unique constraints
1111(including the primary key) on the source of this resultset. If a row is
1112found, updates it with the other given column values. Otherwise, creates a new
87f0da6a 1113row.
1114
1115Takes an optional C<key> attribute to search on a specific unique constraint.
1116For example:
1117
1118 # In your application
1119 my $cd = $schema->resultset('CD')->update_or_create(
1120 {
1121 artist => 'Massive Attack',
1122 title => 'Mezzanine',
1123 year => 1998,
1124 },
1125 { key => 'artist_title' }
1126 );
1127
1128If no C<key> is specified, it searches on all unique constraints defined on the
1129source, including the primary key.
1130
2053ab2a 1131If the C<key> is specified as C<primary>, it searches only on the primary key.
87f0da6a 1132
a33df5d4 1133See also L</find> and L</find_or_create>.
1134
87f0da6a 1135=cut
1136
1137sub update_or_create {
1138 my $self = shift;
87f0da6a 1139 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
223aea40 1140 my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
87f0da6a 1141
701da8c4 1142 my %unique_constraints = $self->result_source->unique_constraints;
87f0da6a 1143 my @constraint_names = (exists $attrs->{key}
1144 ? ($attrs->{key})
1145 : keys %unique_constraints);
1146
1147 my @unique_hashes;
1148 foreach my $name (@constraint_names) {
1149 my @unique_cols = @{ $unique_constraints{$name} };
1150 my %unique_hash =
1151 map { $_ => $hash->{$_} }
1152 grep { exists $hash->{$_} }
1153 @unique_cols;
1154
1155 push @unique_hashes, \%unique_hash
1156 if (scalar keys %unique_hash == scalar @unique_cols);
1157 }
1158
87f0da6a 1159 if (@unique_hashes) {
223aea40 1160 my $row = $self->single(\@unique_hashes);
1161 if (defined $row) {
87f0da6a 1162 $row->set_columns($hash);
1163 $row->update;
223aea40 1164 return $row;
87f0da6a 1165 }
1166 }
1167
223aea40 1168 return $self->create($hash);
87f0da6a 1169}
1170
64acc2bc 1171=head2 get_cache
1172
a031138b 1173=over 4
1174
1175=item Arguments: none
1176
1177=item Return Value: \@cache_objects?
1178
1179=back
1180
2053ab2a 1181Gets the contents of the cache for the resultset, if the cache is set.
64acc2bc 1182
1183=cut
1184
1185sub get_cache {
0823196c 1186 shift->{all_cache};
64acc2bc 1187}
1188
1189=head2 set_cache
1190
a031138b 1191=over 4
1192
1193=item Arguments: \@cache_objects
1194
1195=item Return Value: \@cache_objects
1196
1197=back
1198
aa1088bf 1199Sets the contents of the cache for the resultset. Expects an arrayref
a031138b 1200of objects of the same class as those produced by the resultset. Note that
1201if the cache is set the resultset will return the cached objects rather
1202than re-querying the database even if the cache attr is not set.
64acc2bc 1203
1204=cut
1205
1206sub set_cache {
1207 my ( $self, $data ) = @_;
1208 $self->throw_exception("set_cache requires an arrayref")
0823196c 1209 if defined($data) && (ref $data ne 'ARRAY');
64acc2bc 1210 $self->{all_cache} = $data;
1211}
1212
1213=head2 clear_cache
1214
a031138b 1215=over 4
1216
1217=item Arguments: none
1218
1219=item Return Value: []
1220
1221=back
1222
64acc2bc 1223Clears the cache for the resultset.
1224
1225=cut
1226
1227sub clear_cache {
0823196c 1228 shift->set_cache(undef);
64acc2bc 1229}
1230
1231=head2 related_resultset
1232
a031138b 1233=over 4
1234
1235=item Arguments: $relationship_name
1236
1237=item Return Value: $resultset
1238
1239=back
1240
64acc2bc 1241Returns a related resultset for the supplied relationship name.
1242
24d67825 1243 $artist_rs = $schema->resultset('CD')->related_resultset('Artist');
64acc2bc 1244
1245=cut
1246
1247sub related_resultset {
a031138b 1248 my ( $self, $rel ) = @_;
64acc2bc 1249 $self->{related_resultsets} ||= {};
223aea40 1250 return $self->{related_resultsets}{$rel} ||= do {
1251 #warn "fetching related resultset for rel '$rel'";
1252 my $rel_obj = $self->result_source->relationship_info($rel);
1253 $self->throw_exception(
1254 "search_related: result source '" . $self->result_source->name .
1255 "' has no such relationship ${rel}")
1256 unless $rel_obj; #die Dumper $self->{attrs};
1257
1258 my $rs = $self->search(undef, { join => $rel });
1259 my $alias = defined $rs->{attrs}{seen_join}{$rel}
1260 && $rs->{attrs}{seen_join}{$rel} > 1
1261 ? join('_', $rel, $rs->{attrs}{seen_join}{$rel})
1262 : $rel;
1263
64acc2bc 1264 $self->result_source->schema->resultset($rel_obj->{class}
1265 )->search( undef,
1266 { %{$rs->{attrs}},
1267 alias => $alias,
223aea40 1268 select => undef,
1269 as => undef }
a031138b 1270 );
223aea40 1271 };
64acc2bc 1272}
1273
701da8c4 1274=head2 throw_exception
1275
a031138b 1276See L<DBIx::Class::Schema/throw_exception> for details.
701da8c4 1277
1278=cut
1279
1280sub throw_exception {
1281 my $self=shift;
1282 $self->result_source->schema->throw_exception(@_);
1283}
1284
a031138b 1285# XXX: FIXME: Attributes docs need clearing up
076652e8 1286
a031138b 1287=head1 ATTRIBUTES
27f01d1f 1288
a33df5d4 1289The resultset takes various attributes that modify its behavior. Here's an
1290overview of them:
bfab575a 1291
1292=head2 order_by
076652e8 1293
a031138b 1294=over 4
1295
1296=item Value: ($order_by | \@order_by)
1297
eaefb953 1298=back
1299
24d67825 1300Which column(s) to order the results by. This is currently passed
1301through directly to SQL, so you can give e.g. C<year DESC> for a
1302descending order on the column `year'.
076652e8 1303
5e8b1b2a 1304=head2 columns
87c4e602 1305
27f01d1f 1306=over 4
1307
a031138b 1308=item Value: \@columns
27f01d1f 1309
1310=back
976f3686 1311
a33df5d4 1312Shortcut to request a particular set of columns to be retrieved. Adds
1313C<me.> onto the start of any column without a C<.> in it and sets C<select>
5e8b1b2a 1314from that, then auto-populates C<as> from C<select> as normal. (You may also
1315use the C<cols> attribute, as in earlier versions of DBIC.)
976f3686 1316
87c4e602 1317=head2 include_columns
1318
27f01d1f 1319=over 4
1320
a031138b 1321=item Value: \@columns
27f01d1f 1322
1323=back
5ac6a044 1324
1325Shortcut to include additional columns in the returned results - for example
1326
24d67825 1327 $schema->resultset('CD')->search(undef, {
1328 include_columns => ['artist.name'],
1329 join => ['artist']
1330 });
5ac6a044 1331
24d67825 1332would return all CDs and include a 'name' column to the information
1333passed to object inflation
5ac6a044 1334
87c4e602 1335=head2 select
1336
27f01d1f 1337=over 4
1338
a031138b 1339=item Value: \@select_columns
27f01d1f 1340
1341=back
976f3686 1342
4a28c340 1343Indicates which columns should be selected from the storage. You can use
1344column names, or in the case of RDBMS back ends, function or stored procedure
1345names:
1346
24d67825 1347 $rs = $schema->resultset('Employee')->search(undef, {
1348 select => [
1349 'name',
1350 { count => 'employeeid' },
1351 { sum => 'salary' }
1352 ]
1353 });
4a28c340 1354
1355When you use function/stored procedure names and do not supply an C<as>
1356attribute, the column names returned are storage-dependent. E.g. MySQL would
24d67825 1357return a column named C<count(employeeid)> in the above example.
976f3686 1358
87c4e602 1359=head2 as
1360
27f01d1f 1361=over 4
1362
a031138b 1363=item Value: \@inflation_names
27f01d1f 1364
1365=back
076652e8 1366
4a28c340 1367Indicates column names for object inflation. This is used in conjunction with
1368C<select>, usually when C<select> contains one or more function or stored
1369procedure names:
1370
24d67825 1371 $rs = $schema->resultset('Employee')->search(undef, {
1372 select => [
1373 'name',
1374 { count => 'employeeid' }
1375 ],
a0638a7b 1376 as => ['name', 'employee_count'],
24d67825 1377 });
4a28c340 1378
24d67825 1379 my $employee = $rs->first(); # get the first Employee
4a28c340 1380
1381If the object against which the search is performed already has an accessor
1382matching a column name specified in C<as>, the value can be retrieved using
1383the accessor as normal:
1384
24d67825 1385 my $name = $employee->name();
4a28c340 1386
1387If on the other hand an accessor does not exist in the object, you need to
1388use C<get_column> instead:
1389
24d67825 1390 my $employee_count = $employee->get_column('employee_count');
4a28c340 1391
1392You can create your own accessors if required - see
1393L<DBIx::Class::Manual::Cookbook> for details.
ee38fa40 1394
bfab575a 1395=head2 join
ee38fa40 1396
a031138b 1397=over 4
1398
1399=item Value: ($rel_name | \@rel_names | \%rel_names)
1400
1401=back
1402
a33df5d4 1403Contains a list of relationships that should be joined for this query. For
1404example:
1405
1406 # Get CDs by Nine Inch Nails
1407 my $rs = $schema->resultset('CD')->search(
1408 { 'artist.name' => 'Nine Inch Nails' },
1409 { join => 'artist' }
1410 );
1411
1412Can also contain a hash reference to refer to the other relation's relations.
1413For example:
1414
1415 package MyApp::Schema::Track;
1416 use base qw/DBIx::Class/;
1417 __PACKAGE__->table('track');
1418 __PACKAGE__->add_columns(qw/trackid cd position title/);
1419 __PACKAGE__->set_primary_key('trackid');
1420 __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
1421 1;
1422
1423 # In your application
1424 my $rs = $schema->resultset('Artist')->search(
1425 { 'track.title' => 'Teardrop' },
1426 {
1427 join => { cd => 'track' },
1428 order_by => 'artist.name',
1429 }
1430 );
1431
2cb360cc 1432If the same join is supplied twice, it will be aliased to <rel>_2 (and
1433similarly for a third time). For e.g.
1434
24d67825 1435 my $rs = $schema->resultset('Artist')->search({
1436 'cds.title' => 'Down to Earth',
1437 'cds_2.title' => 'Popular',
1438 }, {
1439 join => [ qw/cds cds/ ],
1440 });
2cb360cc 1441
24d67825 1442will return a set of all artists that have both a cd with title 'Down
1443to Earth' and a cd with title 'Popular'.
2cb360cc 1444
1445If you want to fetch related objects from other tables as well, see C<prefetch>
ae1c90a1 1446below.
ee38fa40 1447
87c4e602 1448=head2 prefetch
1449
27f01d1f 1450=over 4
1451
a031138b 1452=item Value: ($rel_name | \@rel_names | \%rel_names)
27f01d1f 1453
1454=back
ee38fa40 1455
75d07914 1456Contains one or more relationships that should be fetched along with the main
bfab575a 1457query (when they are accessed afterwards they will have already been
a33df5d4 1458"prefetched"). This is useful for when you know you will need the related
ae1c90a1 1459objects, because it saves at least one query:
1460
1461 my $rs = $schema->resultset('Tag')->search(
5e8b1b2a 1462 undef,
ae1c90a1 1463 {
1464 prefetch => {
1465 cd => 'artist'
1466 }
1467 }
1468 );
1469
1470The initial search results in SQL like the following:
1471
1472 SELECT tag.*, cd.*, artist.* FROM tag
1473 JOIN cd ON tag.cd = cd.cdid
1474 JOIN artist ON cd.artist = artist.artistid
1475
1476L<DBIx::Class> has no need to go back to the database when we access the
1477C<cd> or C<artist> relationships, which saves us two SQL statements in this
1478case.
1479
2cb360cc 1480Simple prefetches will be joined automatically, so there is no need
1481for a C<join> attribute in the above search. If you're prefetching to
1482depth (e.g. { cd => { artist => 'label' } or similar), you'll need to
1483specify the join as well.
ae1c90a1 1484
1485C<prefetch> can be used with the following relationship types: C<belongs_to>,
2cb360cc 1486C<has_one> (or if you're using C<add_relationship>, any relationship declared
1487with an accessor type of 'single' or 'filter').
ee38fa40 1488
87c4e602 1489=head2 from
1490
27f01d1f 1491=over 4
1492
a031138b 1493=item Value: \@from_clause
27f01d1f 1494
1495=back
ee38fa40 1496
4a28c340 1497The C<from> attribute gives you manual control over the C<FROM> clause of SQL
1498statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
1499clauses.
ee38fa40 1500
a33df5d4 1501NOTE: Use this on your own risk. This allows you to shoot off your foot!
4a28c340 1502C<join> will usually do what you need and it is strongly recommended that you
1503avoid using C<from> unless you cannot achieve the desired result using C<join>.
1504
1505In simple terms, C<from> works as follows:
1506
1507 [
abaf89a9 1508 { <alias> => <table>, -join_type => 'inner|left|right' }
4a28c340 1509 [] # nested JOIN (optional)
493a7fb0 1510 { <table.column> => <foreign_table.foreign_key> }
4a28c340 1511 ]
1512
1513 JOIN
1514 <alias> <table>
1515 [JOIN ...]
1516 ON <table.column> = <foreign_table.foreign_key>
1517
1518An easy way to follow the examples below is to remember the following:
1519
1520 Anything inside "[]" is a JOIN
1521 Anything inside "{}" is a condition for the enclosing JOIN
1522
1523The following examples utilize a "person" table in a family tree application.
1524In order to express parent->child relationships, this table is self-joined:
1525
1526 # Person->belongs_to('father' => 'Person');
1527 # Person->belongs_to('mother' => 'Person');
1528
1529C<from> can be used to nest joins. Here we return all children with a father,
1530then search against all mothers of those children:
1531
1532 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1533 undef,
4a28c340 1534 {
1535 alias => 'mother', # alias columns in accordance with "from"
1536 from => [
1537 { mother => 'person' },
1538 [
1539 [
1540 { child => 'person' },
1541 [
1542 { father => 'person' },
1543 { 'father.person_id' => 'child.father_id' }
1544 ]
1545 ],
1546 { 'mother.person_id' => 'child.mother_id' }
fd9f5466 1547 ],
4a28c340 1548 ]
1549 },
1550 );
1551
1552 # Equivalent SQL:
1553 # SELECT mother.* FROM person mother
1554 # JOIN (
1555 # person child
1556 # JOIN person father
1557 # ON ( father.person_id = child.father_id )
1558 # )
1559 # ON ( mother.person_id = child.mother_id )
1560
1561The type of any join can be controlled manually. To search against only people
1562with a father in the person table, we could explicitly use C<INNER JOIN>:
1563
1564 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1565 undef,
4a28c340 1566 {
1567 alias => 'child', # alias columns in accordance with "from"
1568 from => [
1569 { child => 'person' },
1570 [
abaf89a9 1571 { father => 'person', -join_type => 'inner' },
4a28c340 1572 { 'father.id' => 'child.father_id' }
1573 ],
1574 ]
1575 },
1576 );
1577
1578 # Equivalent SQL:
1579 # SELECT child.* FROM person child
1580 # INNER JOIN person father ON child.father_id = father.id
ee38fa40 1581
bfab575a 1582=head2 page
076652e8 1583
27f01d1f 1584=over 4
1585
a031138b 1586=item Value: $page
27f01d1f 1587
1588=back
1589
a031138b 1590Makes the resultset paged and specifies the page to retrieve. Effectively
1591identical to creating a non-pages resultset and then calling ->page($page)
1592on it.
076652e8 1593
bfab575a 1594=head2 rows
076652e8 1595
27f01d1f 1596=over 4
1597
a031138b 1598=item Value: $rows
27f01d1f 1599
1600=back
1601
a031138b 1602Specifes the maximum number of rows for direct retrieval or the number of
1603rows per page if the page attribute or method is used.
076652e8 1604
87c4e602 1605=head2 group_by
1606
27f01d1f 1607=over 4
1608
a031138b 1609=item Value: \@columns
27f01d1f 1610
1611=back
54540863 1612
bda4c2b8 1613A arrayref of columns to group by. Can include columns of joined tables.
54540863 1614
675ce4a6 1615 group_by => [qw/ column1 column2 ... /]
1616
ea1eaf8d 1617=head2 having
1618
1619=over 4
1620
1621=item Value: $condition
1622
1623=back
1624
1625HAVING is a select statement attribute that is applied between GROUP BY and
1626ORDER BY. It is applied to the after the grouping calculations have been
1627done.
1628
1629 having => { 'count(employee)' => { '>=', 100 } }
1630
54540863 1631=head2 distinct
1632
a031138b 1633=over 4
1634
1635=item Value: (0 | 1)
1636
1637=back
1638
a33df5d4 1639Set to 1 to group by all columns.
1640
534ca143 1641=head2 cache
1642
1643Set to 1 to cache search results. This prevents extra SQL queries if you
1644revisit rows in your ResultSet:
1645
1646 my $resultset = $schema->resultset('Artist')->search( undef, { cache => 1 } );
1647
1648 while( my $artist = $resultset->next ) {
1649 ... do stuff ...
1650 }
1651
75d07914 1652 $rs->first; # without cache, this would issue a query
534ca143 1653
1654By default, searches are not cached.
1655
a33df5d4 1656For more examples of using these attributes, see
1657L<DBIx::Class::Manual::Cookbook>.
54540863 1658
bfab575a 1659=cut
076652e8 1660
89c0a5a2 16611;