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