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