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