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