Update find docs re: key attribute
[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
87c4e602 1082=head2 create
1083
27f01d1f 1084=over 4
1085
a031138b 1086=item Arguments: \%vals
1087
1088=item Return Value: $object
27f01d1f 1089
1090=back
fea3d045 1091
a031138b 1092Inserts a record into the resultset and returns the object representing it.
fea3d045 1093
a33df5d4 1094Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
fea3d045 1095
1096=cut
1097
1098sub create {
1099 my ($self, $attrs) = @_;
aa1088bf 1100 $self->throw_exception( "create needs a hashref" )
1101 unless ref $attrs eq 'HASH';
fea3d045 1102 return $self->new_result($attrs)->insert;
3c5b25c5 1103}
1104
87c4e602 1105=head2 find_or_create
1106
27f01d1f 1107=over 4
1108
a031138b 1109=item Arguments: \%vals, \%attrs?
1110
1111=item Return Value: $object
27f01d1f 1112
1113=back
87f0da6a 1114
1115 $class->find_or_create({ key => $val, ... });
c2b15ecc 1116
fd9f5466 1117Searches for a record matching the search condition; if it doesn't find one,
1118creates one and returns that instead.
87f0da6a 1119
87f0da6a 1120 my $cd = $schema->resultset('CD')->find_or_create({
1121 cdid => 5,
1122 artist => 'Massive Attack',
1123 title => 'Mezzanine',
1124 year => 2005,
1125 });
1126
1127Also takes an optional C<key> attribute, to search by a specific key or unique
1128constraint. For example:
1129
1130 my $cd = $schema->resultset('CD')->find_or_create(
1131 {
1132 artist => 'Massive Attack',
1133 title => 'Mezzanine',
1134 },
1135 { key => 'artist_title' }
1136 );
1137
1138See also L</find> and L</update_or_create>.
1139
c2b15ecc 1140=cut
1141
1142sub find_or_create {
1143 my $self = shift;
87f0da6a 1144 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
223aea40 1145 my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
87f0da6a 1146 my $exists = $self->find($hash, $attrs);
223aea40 1147 return defined $exists ? $exists : $self->create($hash);
c2b15ecc 1148}
1149
87f0da6a 1150=head2 update_or_create
1151
a031138b 1152=over 4
1153
1154=item Arguments: \%col_values, { key => $unique_constraint }?
1155
1156=item Return Value: $object
1157
1158=back
1159
1160 $class->update_or_create({ col => $val, ... });
87f0da6a 1161
2053ab2a 1162First, searches for an existing row matching one of the unique constraints
1163(including the primary key) on the source of this resultset. If a row is
1164found, updates it with the other given column values. Otherwise, creates a new
87f0da6a 1165row.
1166
1167Takes an optional C<key> attribute to search on a specific unique constraint.
1168For example:
1169
1170 # In your application
1171 my $cd = $schema->resultset('CD')->update_or_create(
1172 {
1173 artist => 'Massive Attack',
1174 title => 'Mezzanine',
1175 year => 1998,
1176 },
1177 { key => 'artist_title' }
1178 );
1179
1180If no C<key> is specified, it searches on all unique constraints defined on the
1181source, including the primary key.
1182
2053ab2a 1183If the C<key> is specified as C<primary>, it searches only on the primary key.
87f0da6a 1184
a33df5d4 1185See also L</find> and L</find_or_create>.
1186
87f0da6a 1187=cut
1188
1189sub update_or_create {
1190 my $self = shift;
87f0da6a 1191 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
223aea40 1192 my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
87f0da6a 1193
f64e05d2 1194 my $row = $self->find($hash, $attrs);
1195 if (defined $row) {
1196 $row->set_columns($hash);
1197 $row->update;
1198 return $row;
87f0da6a 1199 }
1200
223aea40 1201 return $self->create($hash);
87f0da6a 1202}
1203
64acc2bc 1204=head2 get_cache
1205
a031138b 1206=over 4
1207
1208=item Arguments: none
1209
1210=item Return Value: \@cache_objects?
1211
1212=back
1213
2053ab2a 1214Gets the contents of the cache for the resultset, if the cache is set.
64acc2bc 1215
1216=cut
1217
1218sub get_cache {
223aea40 1219 shift->{all_cache} || [];
64acc2bc 1220}
1221
1222=head2 set_cache
1223
a031138b 1224=over 4
1225
1226=item Arguments: \@cache_objects
1227
1228=item Return Value: \@cache_objects
1229
1230=back
1231
aa1088bf 1232Sets the contents of the cache for the resultset. Expects an arrayref
a031138b 1233of objects of the same class as those produced by the resultset. Note that
1234if the cache is set the resultset will return the cached objects rather
1235than re-querying the database even if the cache attr is not set.
64acc2bc 1236
1237=cut
1238
1239sub set_cache {
1240 my ( $self, $data ) = @_;
1241 $self->throw_exception("set_cache requires an arrayref")
1242 if ref $data ne 'ARRAY';
a50bcd52 1243 my $result_class = $self->result_class;
64acc2bc 1244 foreach( @$data ) {
aa1088bf 1245 $self->throw_exception(
1246 "cannot cache object of type '$_', expected '$result_class'"
1247 ) if ref $_ ne $result_class;
64acc2bc 1248 }
1249 $self->{all_cache} = $data;
1250}
1251
1252=head2 clear_cache
1253
a031138b 1254=over 4
1255
1256=item Arguments: none
1257
1258=item Return Value: []
1259
1260=back
1261
64acc2bc 1262Clears the cache for the resultset.
1263
1264=cut
1265
1266sub clear_cache {
223aea40 1267 shift->set_cache([]);
64acc2bc 1268}
1269
1270=head2 related_resultset
1271
a031138b 1272=over 4
1273
1274=item Arguments: $relationship_name
1275
1276=item Return Value: $resultset
1277
1278=back
1279
64acc2bc 1280Returns a related resultset for the supplied relationship name.
1281
24d67825 1282 $artist_rs = $schema->resultset('CD')->related_resultset('Artist');
64acc2bc 1283
1284=cut
1285
1286sub related_resultset {
a031138b 1287 my ( $self, $rel ) = @_;
64acc2bc 1288 $self->{related_resultsets} ||= {};
223aea40 1289 return $self->{related_resultsets}{$rel} ||= do {
1290 #warn "fetching related resultset for rel '$rel'";
1291 my $rel_obj = $self->result_source->relationship_info($rel);
1292 $self->throw_exception(
1293 "search_related: result source '" . $self->result_source->name .
1294 "' has no such relationship ${rel}")
1295 unless $rel_obj; #die Dumper $self->{attrs};
1296
1297 my $rs = $self->search(undef, { join => $rel });
1298 my $alias = defined $rs->{attrs}{seen_join}{$rel}
1299 && $rs->{attrs}{seen_join}{$rel} > 1
1300 ? join('_', $rel, $rs->{attrs}{seen_join}{$rel})
1301 : $rel;
1302
64acc2bc 1303 $self->result_source->schema->resultset($rel_obj->{class}
1304 )->search( undef,
1305 { %{$rs->{attrs}},
1306 alias => $alias,
223aea40 1307 select => undef,
1308 as => undef }
a031138b 1309 );
223aea40 1310 };
64acc2bc 1311}
1312
701da8c4 1313=head2 throw_exception
1314
a031138b 1315See L<DBIx::Class::Schema/throw_exception> for details.
701da8c4 1316
1317=cut
1318
1319sub throw_exception {
1320 my $self=shift;
1321 $self->result_source->schema->throw_exception(@_);
1322}
1323
a031138b 1324# XXX: FIXME: Attributes docs need clearing up
076652e8 1325
a031138b 1326=head1 ATTRIBUTES
27f01d1f 1327
a33df5d4 1328The resultset takes various attributes that modify its behavior. Here's an
1329overview of them:
bfab575a 1330
1331=head2 order_by
076652e8 1332
a031138b 1333=over 4
1334
1335=item Value: ($order_by | \@order_by)
1336
eaefb953 1337=back
1338
24d67825 1339Which column(s) to order the results by. This is currently passed
1340through directly to SQL, so you can give e.g. C<year DESC> for a
1341descending order on the column `year'.
076652e8 1342
5e8b1b2a 1343=head2 columns
87c4e602 1344
27f01d1f 1345=over 4
1346
a031138b 1347=item Value: \@columns
27f01d1f 1348
1349=back
976f3686 1350
a33df5d4 1351Shortcut to request a particular set of columns to be retrieved. Adds
1352C<me.> onto the start of any column without a C<.> in it and sets C<select>
5e8b1b2a 1353from that, then auto-populates C<as> from C<select> as normal. (You may also
1354use the C<cols> attribute, as in earlier versions of DBIC.)
976f3686 1355
87c4e602 1356=head2 include_columns
1357
27f01d1f 1358=over 4
1359
a031138b 1360=item Value: \@columns
27f01d1f 1361
1362=back
5ac6a044 1363
1364Shortcut to include additional columns in the returned results - for example
1365
24d67825 1366 $schema->resultset('CD')->search(undef, {
1367 include_columns => ['artist.name'],
1368 join => ['artist']
1369 });
5ac6a044 1370
24d67825 1371would return all CDs and include a 'name' column to the information
1372passed to object inflation
5ac6a044 1373
87c4e602 1374=head2 select
1375
27f01d1f 1376=over 4
1377
a031138b 1378=item Value: \@select_columns
27f01d1f 1379
1380=back
976f3686 1381
4a28c340 1382Indicates which columns should be selected from the storage. You can use
1383column names, or in the case of RDBMS back ends, function or stored procedure
1384names:
1385
24d67825 1386 $rs = $schema->resultset('Employee')->search(undef, {
1387 select => [
1388 'name',
1389 { count => 'employeeid' },
1390 { sum => 'salary' }
1391 ]
1392 });
4a28c340 1393
1394When you use function/stored procedure names and do not supply an C<as>
1395attribute, the column names returned are storage-dependent. E.g. MySQL would
24d67825 1396return a column named C<count(employeeid)> in the above example.
976f3686 1397
87c4e602 1398=head2 as
1399
27f01d1f 1400=over 4
1401
a031138b 1402=item Value: \@inflation_names
27f01d1f 1403
1404=back
076652e8 1405
4a28c340 1406Indicates column names for object inflation. This is used in conjunction with
1407C<select>, usually when C<select> contains one or more function or stored
1408procedure names:
1409
24d67825 1410 $rs = $schema->resultset('Employee')->search(undef, {
1411 select => [
1412 'name',
1413 { count => 'employeeid' }
1414 ],
a0638a7b 1415 as => ['name', 'employee_count'],
24d67825 1416 });
4a28c340 1417
24d67825 1418 my $employee = $rs->first(); # get the first Employee
4a28c340 1419
1420If the object against which the search is performed already has an accessor
1421matching a column name specified in C<as>, the value can be retrieved using
1422the accessor as normal:
1423
24d67825 1424 my $name = $employee->name();
4a28c340 1425
1426If on the other hand an accessor does not exist in the object, you need to
1427use C<get_column> instead:
1428
24d67825 1429 my $employee_count = $employee->get_column('employee_count');
4a28c340 1430
1431You can create your own accessors if required - see
1432L<DBIx::Class::Manual::Cookbook> for details.
ee38fa40 1433
bfab575a 1434=head2 join
ee38fa40 1435
a031138b 1436=over 4
1437
1438=item Value: ($rel_name | \@rel_names | \%rel_names)
1439
1440=back
1441
a33df5d4 1442Contains a list of relationships that should be joined for this query. For
1443example:
1444
1445 # Get CDs by Nine Inch Nails
1446 my $rs = $schema->resultset('CD')->search(
1447 { 'artist.name' => 'Nine Inch Nails' },
1448 { join => 'artist' }
1449 );
1450
1451Can also contain a hash reference to refer to the other relation's relations.
1452For example:
1453
1454 package MyApp::Schema::Track;
1455 use base qw/DBIx::Class/;
1456 __PACKAGE__->table('track');
1457 __PACKAGE__->add_columns(qw/trackid cd position title/);
1458 __PACKAGE__->set_primary_key('trackid');
1459 __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
1460 1;
1461
1462 # In your application
1463 my $rs = $schema->resultset('Artist')->search(
1464 { 'track.title' => 'Teardrop' },
1465 {
1466 join => { cd => 'track' },
1467 order_by => 'artist.name',
1468 }
1469 );
1470
2cb360cc 1471If the same join is supplied twice, it will be aliased to <rel>_2 (and
1472similarly for a third time). For e.g.
1473
24d67825 1474 my $rs = $schema->resultset('Artist')->search({
1475 'cds.title' => 'Down to Earth',
1476 'cds_2.title' => 'Popular',
1477 }, {
1478 join => [ qw/cds cds/ ],
1479 });
2cb360cc 1480
24d67825 1481will return a set of all artists that have both a cd with title 'Down
1482to Earth' and a cd with title 'Popular'.
2cb360cc 1483
1484If you want to fetch related objects from other tables as well, see C<prefetch>
ae1c90a1 1485below.
ee38fa40 1486
87c4e602 1487=head2 prefetch
1488
27f01d1f 1489=over 4
1490
a031138b 1491=item Value: ($rel_name | \@rel_names | \%rel_names)
27f01d1f 1492
1493=back
ee38fa40 1494
75d07914 1495Contains one or more relationships that should be fetched along with the main
bfab575a 1496query (when they are accessed afterwards they will have already been
a33df5d4 1497"prefetched"). This is useful for when you know you will need the related
ae1c90a1 1498objects, because it saves at least one query:
1499
1500 my $rs = $schema->resultset('Tag')->search(
5e8b1b2a 1501 undef,
ae1c90a1 1502 {
1503 prefetch => {
1504 cd => 'artist'
1505 }
1506 }
1507 );
1508
1509The initial search results in SQL like the following:
1510
1511 SELECT tag.*, cd.*, artist.* FROM tag
1512 JOIN cd ON tag.cd = cd.cdid
1513 JOIN artist ON cd.artist = artist.artistid
1514
1515L<DBIx::Class> has no need to go back to the database when we access the
1516C<cd> or C<artist> relationships, which saves us two SQL statements in this
1517case.
1518
2cb360cc 1519Simple prefetches will be joined automatically, so there is no need
1520for a C<join> attribute in the above search. If you're prefetching to
1521depth (e.g. { cd => { artist => 'label' } or similar), you'll need to
1522specify the join as well.
ae1c90a1 1523
1524C<prefetch> can be used with the following relationship types: C<belongs_to>,
2cb360cc 1525C<has_one> (or if you're using C<add_relationship>, any relationship declared
1526with an accessor type of 'single' or 'filter').
ee38fa40 1527
87c4e602 1528=head2 from
1529
27f01d1f 1530=over 4
1531
a031138b 1532=item Value: \@from_clause
27f01d1f 1533
1534=back
ee38fa40 1535
4a28c340 1536The C<from> attribute gives you manual control over the C<FROM> clause of SQL
1537statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
1538clauses.
ee38fa40 1539
a33df5d4 1540NOTE: Use this on your own risk. This allows you to shoot off your foot!
4a28c340 1541C<join> will usually do what you need and it is strongly recommended that you
1542avoid using C<from> unless you cannot achieve the desired result using C<join>.
1543
1544In simple terms, C<from> works as follows:
1545
1546 [
abaf89a9 1547 { <alias> => <table>, -join_type => 'inner|left|right' }
4a28c340 1548 [] # nested JOIN (optional)
493a7fb0 1549 { <table.column> => <foreign_table.foreign_key> }
4a28c340 1550 ]
1551
1552 JOIN
1553 <alias> <table>
1554 [JOIN ...]
1555 ON <table.column> = <foreign_table.foreign_key>
1556
1557An easy way to follow the examples below is to remember the following:
1558
1559 Anything inside "[]" is a JOIN
1560 Anything inside "{}" is a condition for the enclosing JOIN
1561
1562The following examples utilize a "person" table in a family tree application.
1563In order to express parent->child relationships, this table is self-joined:
1564
1565 # Person->belongs_to('father' => 'Person');
1566 # Person->belongs_to('mother' => 'Person');
1567
1568C<from> can be used to nest joins. Here we return all children with a father,
1569then search against all mothers of those children:
1570
1571 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1572 undef,
4a28c340 1573 {
1574 alias => 'mother', # alias columns in accordance with "from"
1575 from => [
1576 { mother => 'person' },
1577 [
1578 [
1579 { child => 'person' },
1580 [
1581 { father => 'person' },
1582 { 'father.person_id' => 'child.father_id' }
1583 ]
1584 ],
1585 { 'mother.person_id' => 'child.mother_id' }
fd9f5466 1586 ],
4a28c340 1587 ]
1588 },
1589 );
1590
1591 # Equivalent SQL:
1592 # SELECT mother.* FROM person mother
1593 # JOIN (
1594 # person child
1595 # JOIN person father
1596 # ON ( father.person_id = child.father_id )
1597 # )
1598 # ON ( mother.person_id = child.mother_id )
1599
1600The type of any join can be controlled manually. To search against only people
1601with a father in the person table, we could explicitly use C<INNER JOIN>:
1602
1603 $rs = $schema->resultset('Person')->search(
5e8b1b2a 1604 undef,
4a28c340 1605 {
1606 alias => 'child', # alias columns in accordance with "from"
1607 from => [
1608 { child => 'person' },
1609 [
abaf89a9 1610 { father => 'person', -join_type => 'inner' },
4a28c340 1611 { 'father.id' => 'child.father_id' }
1612 ],
1613 ]
1614 },
1615 );
1616
1617 # Equivalent SQL:
1618 # SELECT child.* FROM person child
1619 # INNER JOIN person father ON child.father_id = father.id
ee38fa40 1620
bfab575a 1621=head2 page
076652e8 1622
27f01d1f 1623=over 4
1624
a031138b 1625=item Value: $page
27f01d1f 1626
1627=back
1628
a031138b 1629Makes the resultset paged and specifies the page to retrieve. Effectively
1630identical to creating a non-pages resultset and then calling ->page($page)
1631on it.
076652e8 1632
bfab575a 1633=head2 rows
076652e8 1634
27f01d1f 1635=over 4
1636
a031138b 1637=item Value: $rows
27f01d1f 1638
1639=back
1640
a031138b 1641Specifes the maximum number of rows for direct retrieval or the number of
1642rows per page if the page attribute or method is used.
076652e8 1643
87c4e602 1644=head2 group_by
1645
27f01d1f 1646=over 4
1647
a031138b 1648=item Value: \@columns
27f01d1f 1649
1650=back
54540863 1651
bda4c2b8 1652A arrayref of columns to group by. Can include columns of joined tables.
54540863 1653
675ce4a6 1654 group_by => [qw/ column1 column2 ... /]
1655
ea1eaf8d 1656=head2 having
1657
1658=over 4
1659
1660=item Value: $condition
1661
1662=back
1663
1664HAVING is a select statement attribute that is applied between GROUP BY and
1665ORDER BY. It is applied to the after the grouping calculations have been
1666done.
1667
1668 having => { 'count(employee)' => { '>=', 100 } }
1669
54540863 1670=head2 distinct
1671
a031138b 1672=over 4
1673
1674=item Value: (0 | 1)
1675
1676=back
1677
a33df5d4 1678Set to 1 to group by all columns.
1679
534ca143 1680=head2 cache
1681
1682Set to 1 to cache search results. This prevents extra SQL queries if you
1683revisit rows in your ResultSet:
1684
1685 my $resultset = $schema->resultset('Artist')->search( undef, { cache => 1 } );
1686
1687 while( my $artist = $resultset->next ) {
1688 ... do stuff ...
1689 }
1690
75d07914 1691 $rs->first; # without cache, this would issue a query
534ca143 1692
1693By default, searches are not cached.
1694
a33df5d4 1695For more examples of using these attributes, see
1696L<DBIx::Class::Manual::Cookbook>.
54540863 1697
bfab575a 1698=cut
076652e8 1699
89c0a5a2 17001;