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