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