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