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