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