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