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