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