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