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