reverted commit that should have gone on branches/subselect
[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
6789ebe3 1307Please note that if you have quoting enabled (see
1308L<DBIx::Class::Storage/quote_char>) you will need to do C<\'year DESC' > to
1309specify an order. (The scalar ref causes it to be passed as raw sql to the DB,
1310so you will need to manually quote things as appropriate.)
1311
5e8b1b2a 1312=head2 columns
87c4e602 1313
27f01d1f 1314=over 4
1315
a031138b 1316=item Value: \@columns
27f01d1f 1317
1318=back
976f3686 1319
a33df5d4 1320Shortcut to request a particular set of columns to be retrieved. Adds
1321C<me.> onto the start of any column without a C<.> in it and sets C<select>
5e8b1b2a 1322from that, then auto-populates C<as> from C<select> as normal. (You may also
1323use the C<cols> attribute, as in earlier versions of DBIC.)
976f3686 1324
87c4e602 1325=head2 include_columns
1326
27f01d1f 1327=over 4
1328
a031138b 1329=item Value: \@columns
27f01d1f 1330
1331=back
5ac6a044 1332
1333Shortcut to include additional columns in the returned results - for example
1334
24d67825 1335 $schema->resultset('CD')->search(undef, {
1336 include_columns => ['artist.name'],
1337 join => ['artist']
1338 });
5ac6a044 1339
24d67825 1340would return all CDs and include a 'name' column to the information
1341passed to object inflation
5ac6a044 1342
87c4e602 1343=head2 select
1344
27f01d1f 1345=over 4
1346
a031138b 1347=item Value: \@select_columns
27f01d1f 1348
1349=back
976f3686 1350
4a28c340 1351Indicates which columns should be selected from the storage. You can use
1352column names, or in the case of RDBMS back ends, function or stored procedure
1353names:
1354
24d67825 1355 $rs = $schema->resultset('Employee')->search(undef, {
1356 select => [
1357 'name',
1358 { count => 'employeeid' },
1359 { sum => 'salary' }
1360 ]
1361 });
4a28c340 1362
1363When you use function/stored procedure names and do not supply an C<as>
1364attribute, the column names returned are storage-dependent. E.g. MySQL would
24d67825 1365return a column named C<count(employeeid)> in the above example.
976f3686 1366
87c4e602 1367=head2 as
1368
27f01d1f 1369=over 4
1370
a031138b 1371=item Value: \@inflation_names
27f01d1f 1372
1373=back
076652e8 1374
4a28c340 1375Indicates column names for object inflation. This is used in conjunction with
1376C<select>, usually when C<select> contains one or more function or stored
1377procedure names:
1378
24d67825 1379 $rs = $schema->resultset('Employee')->search(undef, {
1380 select => [
1381 'name',
1382 { count => 'employeeid' }
1383 ],
a0638a7b 1384 as => ['name', 'employee_count'],
24d67825 1385 });
4a28c340 1386
24d67825 1387 my $employee = $rs->first(); # get the first Employee
4a28c340 1388
1389If the object against which the search is performed already has an accessor
1390matching a column name specified in C<as>, the value can be retrieved using
1391the accessor as normal:
1392
24d67825 1393 my $name = $employee->name();
4a28c340 1394
1395If on the other hand an accessor does not exist in the object, you need to
1396use C<get_column> instead:
1397
24d67825 1398 my $employee_count = $employee->get_column('employee_count');
4a28c340 1399
1400You can create your own accessors if required - see
1401L<DBIx::Class::Manual::Cookbook> for details.
ee38fa40 1402
e8e9e5c7 1403Please note: This will NOT insert an C<AS employee_count> into the SQL statement
1404produced, it is used for internal access only. Thus attempting to use the accessor
1405in an C<order_by> clause or similar will fail misrably.
1406
bfab575a 1407=head2 join
ee38fa40 1408
a031138b 1409=over 4
1410
1411=item Value: ($rel_name | \@rel_names | \%rel_names)
1412
1413=back
1414
a33df5d4 1415Contains a list of relationships that should be joined for this query. For
1416example:
1417
1418 # Get CDs by Nine Inch Nails
1419 my $rs = $schema->resultset('CD')->search(
1420 { 'artist.name' => 'Nine Inch Nails' },
1421 { join => 'artist' }
1422 );
1423
1424Can also contain a hash reference to refer to the other relation's relations.
1425For example:
1426
1427 package MyApp::Schema::Track;
1428 use base qw/DBIx::Class/;
1429 __PACKAGE__->table('track');
1430 __PACKAGE__->add_columns(qw/trackid cd position title/);
1431 __PACKAGE__->set_primary_key('trackid');
1432 __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
1433 1;
1434
1435 # In your application
1436 my $rs = $schema->resultset('Artist')->search(
1437 { 'track.title' => 'Teardrop' },
1438 {
1439 join => { cd => 'track' },
1440 order_by => 'artist.name',
1441 }
1442 );
1443
2cb360cc 1444If the same join is supplied twice, it will be aliased to <rel>_2 (and
1445similarly for a third time). For e.g.
1446
24d67825 1447 my $rs = $schema->resultset('Artist')->search({
1448 'cds.title' => 'Down to Earth',
1449 'cds_2.title' => 'Popular',
1450 }, {
1451 join => [ qw/cds cds/ ],
1452 });
2cb360cc 1453
24d67825 1454will return a set of all artists that have both a cd with title 'Down
1455to Earth' and a cd with title 'Popular'.
2cb360cc 1456
1457If you want to fetch related objects from other tables as well, see C<prefetch>
ae1c90a1 1458below.
ee38fa40 1459
87c4e602 1460=head2 prefetch
1461
27f01d1f 1462=over 4
1463
a031138b 1464=item Value: ($rel_name | \@rel_names | \%rel_names)
27f01d1f 1465
1466=back
ee38fa40 1467
75d07914 1468Contains one or more relationships that should be fetched along with the main
bfab575a 1469query (when they are accessed afterwards they will have already been
a33df5d4 1470"prefetched"). This is useful for when you know you will need the related
ae1c90a1 1471objects, because it saves at least one query:
1472
1473 my $rs = $schema->resultset('Tag')->search(
5e8b1b2a 1474 undef,
ae1c90a1 1475 {
1476 prefetch => {
1477 cd => 'artist'
1478 }
1479 }
1480 );
1481
1482The initial search results in SQL like the following:
1483
1484 SELECT tag.*, cd.*, artist.* FROM tag
1485 JOIN cd ON tag.cd = cd.cdid
1486 JOIN artist ON cd.artist = artist.artistid
1487
1488L<DBIx::Class> has no need to go back to the database when we access the
1489C<cd> or C<artist> relationships, which saves us two SQL statements in this
1490case.
1491
2cb360cc 1492Simple prefetches will be joined automatically, so there is no need
1493for a C<join> attribute in the above search. If you're prefetching to
1494depth (e.g. { cd => { artist => 'label' } or similar), you'll need to
1495specify the join as well.
ae1c90a1 1496
1497C<prefetch> can be used with the following relationship types: C<belongs_to>,
2cb360cc 1498C<has_one> (or if you're using C<add_relationship>, any relationship declared
1499with an accessor type of 'single' or 'filter').
ee38fa40 1500
8417f5ee 1501=head2 page
1502
1503=over 4
1504
1505=item Value: $page
1506
1507=back
1508
1509Makes the resultset paged and specifies the page to retrieve. Effectively
1510identical to creating a non-pages resultset and then calling ->page($page)
6789ebe3 1511on it.
1512
1513If L<rows> attribute is not specified it defualts to 10 rows per page.
8417f5ee 1514
1515=head2 rows
1516
1517=over 4
1518
1519=item Value: $rows
1520
1521=back
1522
1523Specifes the maximum number of rows for direct retrieval or the number of
1524rows per page if the page attribute or method is used.
1525
6789ebe3 1526=head2 offset
1527
1528=over 4
1529
1530=item Value: $offset
1531
1532=back
1533
1534Specifies the (zero-based) row number for the first row to be returned, or the
1535of the first row of the first page if paging is used.
1536
8417f5ee 1537=head2 group_by
1538
1539=over 4
1540
1541=item Value: \@columns
1542
1543=back
1544
1545A arrayref of columns to group by. Can include columns of joined tables.
1546
1547 group_by => [qw/ column1 column2 ... /]
1548
1549=head2 having
1550
1551=over 4
1552
1553=item Value: $condition
1554
1555=back
1556
1557HAVING is a select statement attribute that is applied between GROUP BY and
1558ORDER BY. It is applied to the after the grouping calculations have been
1559done.
1560
1561 having => { 'count(employee)' => { '>=', 100 } }
1562
1563=head2 distinct
1564
1565=over 4
1566
1567=item Value: (0 | 1)
1568
1569=back
1570
1571Set to 1 to group by all columns.
1572
1573=head2 cache
1574
1575Set to 1 to cache search results. This prevents extra SQL queries if you
1576revisit rows in your ResultSet:
1577
1578 my $resultset = $schema->resultset('Artist')->search( undef, { cache => 1 } );
1579
1580 while( my $artist = $resultset->next ) {
1581 ... do stuff ...
1582 }
1583
1584 $rs->first; # without cache, this would issue a query
1585
1586By default, searches are not cached.
1587
1588For more examples of using these attributes, see
1589L<DBIx::Class::Manual::Cookbook>.
1590
87c4e602 1591=head2 from
1592
27f01d1f 1593=over 4
1594
a031138b 1595=item Value: \@from_clause
27f01d1f 1596
1597=back
ee38fa40 1598
4a28c340 1599The C<from> attribute gives you manual control over the C<FROM> clause of SQL
1600statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
1601clauses.
ee38fa40 1602
a33df5d4 1603NOTE: Use this on your own risk. This allows you to shoot off your foot!
8417f5ee 1604
4a28c340 1605C<join> will usually do what you need and it is strongly recommended that you
1606avoid using C<from> unless you cannot achieve the desired result using C<join>.
8417f5ee 1607And we really do mean "cannot", not just tried and failed. Attempting to use
1608this because you're having problems with C<join> is like trying to use x86
1609ASM because you've got a syntax error in your C. Trust us on this.
1610
1611Now, if you're still really, really sure you need to use this (and if you're
1612not 100% sure, ask the mailing list first), here's an explanation of how this
1613works.
4a28c340 1614
8417f5ee 1615The syntax is as follows -
4a28c340 1616
8417f5ee 1617 [
1618 { <alias1> => <table1> },
4a28c340 1619 [
8417f5ee 1620 { <alias2> => <table2>, -join_type => 'inner|left|right' },
1621 [], # nested JOIN (optional)
1622 { <table1.column1> => <table2.column2>, ... (more conditions) },
1623 ],
1624 # More of the above [ ] may follow for additional joins
1625 ]
4a28c340 1626
8417f5ee 1627 <table1> <alias1>
1628 JOIN
1629 <table2> <alias2>
1630 [JOIN ...]
1631 ON <table1.column1> = <table2.column2>
1632 <more joins may follow>
4a28c340 1633
1634An easy way to follow the examples below is to remember the following:
1635
1636 Anything inside "[]" is a JOIN
1637 Anything inside "{}" is a condition for the enclosing JOIN
1638
1639The following examples utilize a "person" table in a family tree application.
1640In order to express parent->child relationships, this table is self-joined:
1641
1642 # Person->belongs_to('father' => 'Person');
1643 # Person->belongs_to('mother' => 'Person');
1644
1645C<from> can be used to nest joins. Here we return all children with a father,
1646then search against all mothers of those children:
1647
1648 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1649 undef,
4a28c340 1650 {
1651 alias => 'mother', # alias columns in accordance with "from"
1652 from => [
1653 { mother => 'person' },
1654 [
1655 [
1656 { child => 'person' },
1657 [
1658 { father => 'person' },
1659 { 'father.person_id' => 'child.father_id' }
1660 ]
1661 ],
1662 { 'mother.person_id' => 'child.mother_id' }
fd9f5466 1663 ],
4a28c340 1664 ]
1665 },
1666 );
1667
1668 # Equivalent SQL:
1669 # SELECT mother.* FROM person mother
1670 # JOIN (
1671 # person child
1672 # JOIN person father
1673 # ON ( father.person_id = child.father_id )
1674 # )
1675 # ON ( mother.person_id = child.mother_id )
1676
1677The type of any join can be controlled manually. To search against only people
1678with a father in the person table, we could explicitly use C<INNER JOIN>:
1679
1680 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1681 undef,
4a28c340 1682 {
1683 alias => 'child', # alias columns in accordance with "from"
1684 from => [
1685 { child => 'person' },
1686 [
abaf89a9 1687 { father => 'person', -join_type => 'inner' },
4a28c340 1688 { 'father.id' => 'child.father_id' }
1689 ],
1690 ]
1691 },
1692 );
1693
1694 # Equivalent SQL:
1695 # SELECT child.* FROM person child
1696 # INNER JOIN person father ON child.father_id = father.id
ee38fa40 1697
bfab575a 1698=cut
076652e8 1699
89c0a5a2 17001;