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