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