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