Rid of a wantarray
[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) = @_;
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) = @_;
223aea40 503 if (@{$self->{all_cache} || []}) {
64acc2bc 504 $self->{all_cache_position} ||= 0;
223aea40 505 return $self->{all_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);
595 #warn Data::Dumper::Dumper($tree, $row);
0f66a01b 596 }
223aea40 597 @$target = @final;
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];
84e3c114 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) = @_;
223aea40 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
87c4e602 786=head2 update
787
27f01d1f 788=over 4
789
a031138b 790=item Arguments: \%values
791
792=item Return Value: $storage_rv
27f01d1f 793
794=back
c01ab172 795
a031138b 796Sets the specified columns in the resultset to the supplied values in a
797single query. Return value will be true if the update succeeded or false
798if no records were updated; exact type of success value is storage-dependent.
c01ab172 799
800=cut
801
802sub update {
803 my ($self, $values) = @_;
aa1088bf 804 $self->throw_exception("Values for update must be a hash")
805 unless ref $values eq 'HASH';
701da8c4 806 return $self->result_source->storage->update(
27f01d1f 807 $self->result_source->from, $values, $self->{cond}
808 );
c01ab172 809}
810
87c4e602 811=head2 update_all
812
27f01d1f 813=over 4
814
a031138b 815=item Arguments: \%values
816
817=item Return Value: 1
27f01d1f 818
819=back
c01ab172 820
2053ab2a 821Fetches all objects and updates them one at a time. Note that C<update_all>
822will run DBIC cascade triggers, while L</update> will not.
c01ab172 823
824=cut
825
826sub update_all {
827 my ($self, $values) = @_;
aa1088bf 828 $self->throw_exception("Values for update must be a hash")
829 unless ref $values eq 'HASH';
c01ab172 830 foreach my $obj ($self->all) {
831 $obj->set_columns($values)->update;
832 }
833 return 1;
834}
835
bfab575a 836=head2 delete
ee38fa40 837
a031138b 838=over 4
839
840=item Arguments: none
841
842=item Return Value: 1
843
844=back
845
b2f17732 846Deletes the contents of the resultset from its result source. Note that this
2053ab2a 847will not run DBIC cascade triggers. See L</delete_all> if you need triggers
848to run.
ee38fa40 849
850=cut
851
28927b50 852sub delete {
89c0a5a2 853 my ($self) = @_;
ca4b5ab7 854 my $del = {};
7ed3d6dc 855
856 if (!ref($self->{cond})) {
857
858 # No-op. No condition, we're deleting everything
859
860 } elsif (ref $self->{cond} eq 'ARRAY') {
861
ca4b5ab7 862 $del = [ map { my %hash;
863 foreach my $key (keys %{$_}) {
223aea40 864 $key =~ /([^.]+)$/;
ca4b5ab7 865 $hash{$1} = $_->{$key};
866 }; \%hash; } @{$self->{cond}} ];
7ed3d6dc 867
868 } elsif (ref $self->{cond} eq 'HASH') {
869
870 if ((keys %{$self->{cond}})[0] eq '-and') {
871
872 $del->{-and} = [ map { my %hash;
873 foreach my $key (keys %{$_}) {
874 $key =~ /([^.]+)$/;
875 $hash{$1} = $_->{$key};
876 }; \%hash; } @{$self->{cond}{-and}} ];
877
878 } else {
879
880 foreach my $key (keys %{$self->{cond}}) {
223aea40 881 $key =~ /([^.]+)$/;
7ed3d6dc 882 $del->{$1} = $self->{cond}{$key};
883 }
ca4b5ab7 884 }
27f01d1f 885
7ed3d6dc 886 } else {
887 $self->throw_exception(
27f01d1f 888 "Can't delete on resultset with condition unless hash or array"
889 );
ca4b5ab7 890 }
7ed3d6dc 891
ca4b5ab7 892 $self->result_source->storage->delete($self->result_source->from, $del);
89c0a5a2 893 return 1;
894}
895
c01ab172 896=head2 delete_all
897
a031138b 898=over 4
899
900=item Arguments: none
901
902=item Return Value: 1
903
904=back
905
2053ab2a 906Fetches all objects and deletes them one at a time. Note that C<delete_all>
907will run DBIC cascade triggers, while L</delete> will not.
c01ab172 908
909=cut
910
911sub delete_all {
912 my ($self) = @_;
913 $_->delete for $self->all;
914 return 1;
915}
28927b50 916
bfab575a 917=head2 pager
ee38fa40 918
a031138b 919=over 4
920
921=item Arguments: none
922
923=item Return Value: $pager
924
925=back
926
927Return Value a L<Data::Page> object for the current resultset. Only makes
a33df5d4 928sense for queries with a C<page> attribute.
ee38fa40 929
930=cut
931
3c5b25c5 932sub pager {
933 my ($self) = @_;
934 my $attrs = $self->{attrs};
aa1088bf 935 $self->throw_exception("Can't create pager for non-paged rs")
936 unless $self->{page};
6aeb9185 937 $attrs->{rows} ||= 10;
6aeb9185 938 return $self->{pager} ||= Data::Page->new(
84e3c114 939 $self->_count, $attrs->{rows}, $self->{page});
3c5b25c5 940}
941
87c4e602 942=head2 page
943
27f01d1f 944=over 4
945
a031138b 946=item Arguments: $page_number
947
948=item Return Value: $rs
27f01d1f 949
950=back
ee38fa40 951
a031138b 952Returns a resultset for the $page_number page of the resultset on which page
953is called, where each page contains a number of rows equal to the 'rows'
2053ab2a 954attribute set on the resultset (10 by default).
ee38fa40 955
956=cut
957
3c5b25c5 958sub page {
959 my ($self, $page) = @_;
6aeb9185 960 my $attrs = { %{$self->{attrs}} };
3c5b25c5 961 $attrs->{page} = $page;
701da8c4 962 return (ref $self)->new($self->result_source, $attrs);
fea3d045 963}
964
87c4e602 965=head2 new_result
966
27f01d1f 967=over 4
968
a031138b 969=item Arguments: \%vals
970
971=item Return Value: $object
27f01d1f 972
973=back
fea3d045 974
a031138b 975Creates an object in the resultset's result class and returns it.
fea3d045 976
977=cut
978
979sub new_result {
980 my ($self, $values) = @_;
701da8c4 981 $self->throw_exception( "new_result needs a hash" )
fea3d045 982 unless (ref $values eq 'HASH');
aa1088bf 983 $self->throw_exception(
984 "Can't abstract implicit construct, condition not a hash"
985 ) if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
fea3d045 986 my %new = %$values;
987 my $alias = $self->{attrs}{alias};
988 foreach my $key (keys %{$self->{cond}||{}}) {
223aea40 989 $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:\Q${alias}.\E)?([^.]+)$/);
fea3d045 990 }
a50bcd52 991 my $obj = $self->result_class->new(\%new);
701da8c4 992 $obj->result_source($self->result_source) if $obj->can('result_source');
223aea40 993 return $obj;
fea3d045 994}
995
87c4e602 996=head2 create
997
27f01d1f 998=over 4
999
a031138b 1000=item Arguments: \%vals
1001
1002=item Return Value: $object
27f01d1f 1003
1004=back
fea3d045 1005
a031138b 1006Inserts a record into the resultset and returns the object representing it.
fea3d045 1007
a33df5d4 1008Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
fea3d045 1009
1010=cut
1011
1012sub create {
1013 my ($self, $attrs) = @_;
aa1088bf 1014 $self->throw_exception( "create needs a hashref" )
1015 unless ref $attrs eq 'HASH';
fea3d045 1016 return $self->new_result($attrs)->insert;
3c5b25c5 1017}
1018
87c4e602 1019=head2 find_or_create
1020
27f01d1f 1021=over 4
1022
a031138b 1023=item Arguments: \%vals, \%attrs?
1024
1025=item Return Value: $object
27f01d1f 1026
1027=back
87f0da6a 1028
1029 $class->find_or_create({ key => $val, ... });
c2b15ecc 1030
fd9f5466 1031Searches for a record matching the search condition; if it doesn't find one,
1032creates one and returns that instead.
87f0da6a 1033
87f0da6a 1034 my $cd = $schema->resultset('CD')->find_or_create({
1035 cdid => 5,
1036 artist => 'Massive Attack',
1037 title => 'Mezzanine',
1038 year => 2005,
1039 });
1040
1041Also takes an optional C<key> attribute, to search by a specific key or unique
1042constraint. For example:
1043
1044 my $cd = $schema->resultset('CD')->find_or_create(
1045 {
1046 artist => 'Massive Attack',
1047 title => 'Mezzanine',
1048 },
1049 { key => 'artist_title' }
1050 );
1051
1052See also L</find> and L</update_or_create>.
1053
c2b15ecc 1054=cut
1055
1056sub find_or_create {
1057 my $self = shift;
87f0da6a 1058 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
223aea40 1059 my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
87f0da6a 1060 my $exists = $self->find($hash, $attrs);
223aea40 1061 return defined $exists ? $exists : $self->create($hash);
c2b15ecc 1062}
1063
87f0da6a 1064=head2 update_or_create
1065
a031138b 1066=over 4
1067
1068=item Arguments: \%col_values, { key => $unique_constraint }?
1069
1070=item Return Value: $object
1071
1072=back
1073
1074 $class->update_or_create({ col => $val, ... });
87f0da6a 1075
2053ab2a 1076First, searches for an existing row matching one of the unique constraints
1077(including the primary key) on the source of this resultset. If a row is
1078found, updates it with the other given column values. Otherwise, creates a new
87f0da6a 1079row.
1080
1081Takes an optional C<key> attribute to search on a specific unique constraint.
1082For example:
1083
1084 # In your application
1085 my $cd = $schema->resultset('CD')->update_or_create(
1086 {
1087 artist => 'Massive Attack',
1088 title => 'Mezzanine',
1089 year => 1998,
1090 },
1091 { key => 'artist_title' }
1092 );
1093
1094If no C<key> is specified, it searches on all unique constraints defined on the
1095source, including the primary key.
1096
2053ab2a 1097If the C<key> is specified as C<primary>, it searches only on the primary key.
87f0da6a 1098
a33df5d4 1099See also L</find> and L</find_or_create>.
1100
87f0da6a 1101=cut
1102
1103sub update_or_create {
1104 my $self = shift;
87f0da6a 1105 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
223aea40 1106 my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
87f0da6a 1107
701da8c4 1108 my %unique_constraints = $self->result_source->unique_constraints;
87f0da6a 1109 my @constraint_names = (exists $attrs->{key}
1110 ? ($attrs->{key})
1111 : keys %unique_constraints);
1112
1113 my @unique_hashes;
1114 foreach my $name (@constraint_names) {
1115 my @unique_cols = @{ $unique_constraints{$name} };
1116 my %unique_hash =
1117 map { $_ => $hash->{$_} }
1118 grep { exists $hash->{$_} }
1119 @unique_cols;
1120
1121 push @unique_hashes, \%unique_hash
1122 if (scalar keys %unique_hash == scalar @unique_cols);
1123 }
1124
87f0da6a 1125 if (@unique_hashes) {
223aea40 1126 my $row = $self->single(\@unique_hashes);
1127 if (defined $row) {
87f0da6a 1128 $row->set_columns($hash);
1129 $row->update;
223aea40 1130 return $row;
87f0da6a 1131 }
1132 }
1133
223aea40 1134 return $self->create($hash);
87f0da6a 1135}
1136
64acc2bc 1137=head2 get_cache
1138
a031138b 1139=over 4
1140
1141=item Arguments: none
1142
1143=item Return Value: \@cache_objects?
1144
1145=back
1146
2053ab2a 1147Gets the contents of the cache for the resultset, if the cache is set.
64acc2bc 1148
1149=cut
1150
1151sub get_cache {
223aea40 1152 shift->{all_cache} || [];
64acc2bc 1153}
1154
1155=head2 set_cache
1156
a031138b 1157=over 4
1158
1159=item Arguments: \@cache_objects
1160
1161=item Return Value: \@cache_objects
1162
1163=back
1164
aa1088bf 1165Sets the contents of the cache for the resultset. Expects an arrayref
a031138b 1166of objects of the same class as those produced by the resultset. Note that
1167if the cache is set the resultset will return the cached objects rather
1168than re-querying the database even if the cache attr is not set.
64acc2bc 1169
1170=cut
1171
1172sub set_cache {
1173 my ( $self, $data ) = @_;
1174 $self->throw_exception("set_cache requires an arrayref")
1175 if ref $data ne 'ARRAY';
a50bcd52 1176 my $result_class = $self->result_class;
64acc2bc 1177 foreach( @$data ) {
aa1088bf 1178 $self->throw_exception(
1179 "cannot cache object of type '$_', expected '$result_class'"
1180 ) if ref $_ ne $result_class;
64acc2bc 1181 }
1182 $self->{all_cache} = $data;
1183}
1184
1185=head2 clear_cache
1186
a031138b 1187=over 4
1188
1189=item Arguments: none
1190
1191=item Return Value: []
1192
1193=back
1194
64acc2bc 1195Clears the cache for the resultset.
1196
1197=cut
1198
1199sub clear_cache {
223aea40 1200 shift->set_cache([]);
64acc2bc 1201}
1202
1203=head2 related_resultset
1204
a031138b 1205=over 4
1206
1207=item Arguments: $relationship_name
1208
1209=item Return Value: $resultset
1210
1211=back
1212
64acc2bc 1213Returns a related resultset for the supplied relationship name.
1214
24d67825 1215 $artist_rs = $schema->resultset('CD')->related_resultset('Artist');
64acc2bc 1216
1217=cut
1218
1219sub related_resultset {
a031138b 1220 my ( $self, $rel ) = @_;
64acc2bc 1221 $self->{related_resultsets} ||= {};
223aea40 1222 return $self->{related_resultsets}{$rel} ||= do {
1223 #warn "fetching related resultset for rel '$rel'";
1224 my $rel_obj = $self->result_source->relationship_info($rel);
1225 $self->throw_exception(
1226 "search_related: result source '" . $self->result_source->name .
1227 "' has no such relationship ${rel}")
1228 unless $rel_obj; #die Dumper $self->{attrs};
1229
1230 my $rs = $self->search(undef, { join => $rel });
1231 my $alias = defined $rs->{attrs}{seen_join}{$rel}
1232 && $rs->{attrs}{seen_join}{$rel} > 1
1233 ? join('_', $rel, $rs->{attrs}{seen_join}{$rel})
1234 : $rel;
1235
64acc2bc 1236 $self->result_source->schema->resultset($rel_obj->{class}
1237 )->search( undef,
1238 { %{$rs->{attrs}},
1239 alias => $alias,
223aea40 1240 select => undef,
1241 as => undef }
a031138b 1242 );
223aea40 1243 };
64acc2bc 1244}
1245
701da8c4 1246=head2 throw_exception
1247
a031138b 1248See L<DBIx::Class::Schema/throw_exception> for details.
701da8c4 1249
1250=cut
1251
1252sub throw_exception {
1253 my $self=shift;
1254 $self->result_source->schema->throw_exception(@_);
1255}
1256
a031138b 1257# XXX: FIXME: Attributes docs need clearing up
076652e8 1258
a031138b 1259=head1 ATTRIBUTES
27f01d1f 1260
a33df5d4 1261The resultset takes various attributes that modify its behavior. Here's an
1262overview of them:
bfab575a 1263
1264=head2 order_by
076652e8 1265
a031138b 1266=over 4
1267
1268=item Value: ($order_by | \@order_by)
1269
eaefb953 1270=back
1271
24d67825 1272Which column(s) to order the results by. This is currently passed
1273through directly to SQL, so you can give e.g. C<year DESC> for a
1274descending order on the column `year'.
076652e8 1275
5e8b1b2a 1276=head2 columns
87c4e602 1277
27f01d1f 1278=over 4
1279
a031138b 1280=item Value: \@columns
27f01d1f 1281
1282=back
976f3686 1283
a33df5d4 1284Shortcut to request a particular set of columns to be retrieved. Adds
1285C<me.> onto the start of any column without a C<.> in it and sets C<select>
5e8b1b2a 1286from that, then auto-populates C<as> from C<select> as normal. (You may also
1287use the C<cols> attribute, as in earlier versions of DBIC.)
976f3686 1288
87c4e602 1289=head2 include_columns
1290
27f01d1f 1291=over 4
1292
a031138b 1293=item Value: \@columns
27f01d1f 1294
1295=back
5ac6a044 1296
1297Shortcut to include additional columns in the returned results - for example
1298
24d67825 1299 $schema->resultset('CD')->search(undef, {
1300 include_columns => ['artist.name'],
1301 join => ['artist']
1302 });
5ac6a044 1303
24d67825 1304would return all CDs and include a 'name' column to the information
1305passed to object inflation
5ac6a044 1306
87c4e602 1307=head2 select
1308
27f01d1f 1309=over 4
1310
a031138b 1311=item Value: \@select_columns
27f01d1f 1312
1313=back
976f3686 1314
4a28c340 1315Indicates which columns should be selected from the storage. You can use
1316column names, or in the case of RDBMS back ends, function or stored procedure
1317names:
1318
24d67825 1319 $rs = $schema->resultset('Employee')->search(undef, {
1320 select => [
1321 'name',
1322 { count => 'employeeid' },
1323 { sum => 'salary' }
1324 ]
1325 });
4a28c340 1326
1327When you use function/stored procedure names and do not supply an C<as>
1328attribute, the column names returned are storage-dependent. E.g. MySQL would
24d67825 1329return a column named C<count(employeeid)> in the above example.
976f3686 1330
87c4e602 1331=head2 as
1332
27f01d1f 1333=over 4
1334
a031138b 1335=item Value: \@inflation_names
27f01d1f 1336
1337=back
076652e8 1338
4a28c340 1339Indicates column names for object inflation. This is used in conjunction with
1340C<select>, usually when C<select> contains one or more function or stored
1341procedure names:
1342
24d67825 1343 $rs = $schema->resultset('Employee')->search(undef, {
1344 select => [
1345 'name',
1346 { count => 'employeeid' }
1347 ],
a0638a7b 1348 as => ['name', 'employee_count'],
24d67825 1349 });
4a28c340 1350
24d67825 1351 my $employee = $rs->first(); # get the first Employee
4a28c340 1352
1353If the object against which the search is performed already has an accessor
1354matching a column name specified in C<as>, the value can be retrieved using
1355the accessor as normal:
1356
24d67825 1357 my $name = $employee->name();
4a28c340 1358
1359If on the other hand an accessor does not exist in the object, you need to
1360use C<get_column> instead:
1361
24d67825 1362 my $employee_count = $employee->get_column('employee_count');
4a28c340 1363
1364You can create your own accessors if required - see
1365L<DBIx::Class::Manual::Cookbook> for details.
ee38fa40 1366
bfab575a 1367=head2 join
ee38fa40 1368
a031138b 1369=over 4
1370
1371=item Value: ($rel_name | \@rel_names | \%rel_names)
1372
1373=back
1374
a33df5d4 1375Contains a list of relationships that should be joined for this query. For
1376example:
1377
1378 # Get CDs by Nine Inch Nails
1379 my $rs = $schema->resultset('CD')->search(
1380 { 'artist.name' => 'Nine Inch Nails' },
1381 { join => 'artist' }
1382 );
1383
1384Can also contain a hash reference to refer to the other relation's relations.
1385For example:
1386
1387 package MyApp::Schema::Track;
1388 use base qw/DBIx::Class/;
1389 __PACKAGE__->table('track');
1390 __PACKAGE__->add_columns(qw/trackid cd position title/);
1391 __PACKAGE__->set_primary_key('trackid');
1392 __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
1393 1;
1394
1395 # In your application
1396 my $rs = $schema->resultset('Artist')->search(
1397 { 'track.title' => 'Teardrop' },
1398 {
1399 join => { cd => 'track' },
1400 order_by => 'artist.name',
1401 }
1402 );
1403
2cb360cc 1404If the same join is supplied twice, it will be aliased to <rel>_2 (and
1405similarly for a third time). For e.g.
1406
24d67825 1407 my $rs = $schema->resultset('Artist')->search({
1408 'cds.title' => 'Down to Earth',
1409 'cds_2.title' => 'Popular',
1410 }, {
1411 join => [ qw/cds cds/ ],
1412 });
2cb360cc 1413
24d67825 1414will return a set of all artists that have both a cd with title 'Down
1415to Earth' and a cd with title 'Popular'.
2cb360cc 1416
1417If you want to fetch related objects from other tables as well, see C<prefetch>
ae1c90a1 1418below.
ee38fa40 1419
87c4e602 1420=head2 prefetch
1421
27f01d1f 1422=over 4
1423
a031138b 1424=item Value: ($rel_name | \@rel_names | \%rel_names)
27f01d1f 1425
1426=back
ee38fa40 1427
75d07914 1428Contains one or more relationships that should be fetched along with the main
bfab575a 1429query (when they are accessed afterwards they will have already been
a33df5d4 1430"prefetched"). This is useful for when you know you will need the related
ae1c90a1 1431objects, because it saves at least one query:
1432
1433 my $rs = $schema->resultset('Tag')->search(
5e8b1b2a 1434 undef,
ae1c90a1 1435 {
1436 prefetch => {
1437 cd => 'artist'
1438 }
1439 }
1440 );
1441
1442The initial search results in SQL like the following:
1443
1444 SELECT tag.*, cd.*, artist.* FROM tag
1445 JOIN cd ON tag.cd = cd.cdid
1446 JOIN artist ON cd.artist = artist.artistid
1447
1448L<DBIx::Class> has no need to go back to the database when we access the
1449C<cd> or C<artist> relationships, which saves us two SQL statements in this
1450case.
1451
2cb360cc 1452Simple prefetches will be joined automatically, so there is no need
1453for a C<join> attribute in the above search. If you're prefetching to
1454depth (e.g. { cd => { artist => 'label' } or similar), you'll need to
1455specify the join as well.
ae1c90a1 1456
1457C<prefetch> can be used with the following relationship types: C<belongs_to>,
2cb360cc 1458C<has_one> (or if you're using C<add_relationship>, any relationship declared
1459with an accessor type of 'single' or 'filter').
ee38fa40 1460
87c4e602 1461=head2 from
1462
27f01d1f 1463=over 4
1464
a031138b 1465=item Value: \@from_clause
27f01d1f 1466
1467=back
ee38fa40 1468
4a28c340 1469The C<from> attribute gives you manual control over the C<FROM> clause of SQL
1470statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
1471clauses.
ee38fa40 1472
a33df5d4 1473NOTE: Use this on your own risk. This allows you to shoot off your foot!
4a28c340 1474C<join> will usually do what you need and it is strongly recommended that you
1475avoid using C<from> unless you cannot achieve the desired result using C<join>.
1476
1477In simple terms, C<from> works as follows:
1478
1479 [
abaf89a9 1480 { <alias> => <table>, -join_type => 'inner|left|right' }
4a28c340 1481 [] # nested JOIN (optional)
493a7fb0 1482 { <table.column> => <foreign_table.foreign_key> }
4a28c340 1483 ]
1484
1485 JOIN
1486 <alias> <table>
1487 [JOIN ...]
1488 ON <table.column> = <foreign_table.foreign_key>
1489
1490An easy way to follow the examples below is to remember the following:
1491
1492 Anything inside "[]" is a JOIN
1493 Anything inside "{}" is a condition for the enclosing JOIN
1494
1495The following examples utilize a "person" table in a family tree application.
1496In order to express parent->child relationships, this table is self-joined:
1497
1498 # Person->belongs_to('father' => 'Person');
1499 # Person->belongs_to('mother' => 'Person');
1500
1501C<from> can be used to nest joins. Here we return all children with a father,
1502then search against all mothers of those children:
1503
1504 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1505 undef,
4a28c340 1506 {
1507 alias => 'mother', # alias columns in accordance with "from"
1508 from => [
1509 { mother => 'person' },
1510 [
1511 [
1512 { child => 'person' },
1513 [
1514 { father => 'person' },
1515 { 'father.person_id' => 'child.father_id' }
1516 ]
1517 ],
1518 { 'mother.person_id' => 'child.mother_id' }
fd9f5466 1519 ],
4a28c340 1520 ]
1521 },
1522 );
1523
1524 # Equivalent SQL:
1525 # SELECT mother.* FROM person mother
1526 # JOIN (
1527 # person child
1528 # JOIN person father
1529 # ON ( father.person_id = child.father_id )
1530 # )
1531 # ON ( mother.person_id = child.mother_id )
1532
1533The type of any join can be controlled manually. To search against only people
1534with a father in the person table, we could explicitly use C<INNER JOIN>:
1535
1536 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1537 undef,
4a28c340 1538 {
1539 alias => 'child', # alias columns in accordance with "from"
1540 from => [
1541 { child => 'person' },
1542 [
abaf89a9 1543 { father => 'person', -join_type => 'inner' },
4a28c340 1544 { 'father.id' => 'child.father_id' }
1545 ],
1546 ]
1547 },
1548 );
1549
1550 # Equivalent SQL:
1551 # SELECT child.* FROM person child
1552 # INNER JOIN person father ON child.father_id = father.id
ee38fa40 1553
bfab575a 1554=head2 page
076652e8 1555
27f01d1f 1556=over 4
1557
a031138b 1558=item Value: $page
27f01d1f 1559
1560=back
1561
a031138b 1562Makes the resultset paged and specifies the page to retrieve. Effectively
1563identical to creating a non-pages resultset and then calling ->page($page)
1564on it.
076652e8 1565
bfab575a 1566=head2 rows
076652e8 1567
27f01d1f 1568=over 4
1569
a031138b 1570=item Value: $rows
27f01d1f 1571
1572=back
1573
a031138b 1574Specifes the maximum number of rows for direct retrieval or the number of
1575rows per page if the page attribute or method is used.
076652e8 1576
87c4e602 1577=head2 group_by
1578
27f01d1f 1579=over 4
1580
a031138b 1581=item Value: \@columns
27f01d1f 1582
1583=back
54540863 1584
bda4c2b8 1585A arrayref of columns to group by. Can include columns of joined tables.
54540863 1586
675ce4a6 1587 group_by => [qw/ column1 column2 ... /]
1588
ea1eaf8d 1589=head2 having
1590
1591=over 4
1592
1593=item Value: $condition
1594
1595=back
1596
1597HAVING is a select statement attribute that is applied between GROUP BY and
1598ORDER BY. It is applied to the after the grouping calculations have been
1599done.
1600
1601 having => { 'count(employee)' => { '>=', 100 } }
1602
54540863 1603=head2 distinct
1604
a031138b 1605=over 4
1606
1607=item Value: (0 | 1)
1608
1609=back
1610
a33df5d4 1611Set to 1 to group by all columns.
1612
534ca143 1613=head2 cache
1614
1615Set to 1 to cache search results. This prevents extra SQL queries if you
1616revisit rows in your ResultSet:
1617
1618 my $resultset = $schema->resultset('Artist')->search( undef, { cache => 1 } );
1619
1620 while( my $artist = $resultset->next ) {
1621 ... do stuff ...
1622 }
1623
75d07914 1624 $rs->first; # without cache, this would issue a query
534ca143 1625
1626By default, searches are not cached.
1627
a33df5d4 1628For more examples of using these attributes, see
1629L<DBIx::Class::Manual::Cookbook>.
54540863 1630
bfab575a 1631=cut
076652e8 1632
89c0a5a2 16331;