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