missing svk add
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSet.pm
CommitLineData
89c0a5a2 1package DBIx::Class::ResultSet;
2
3use strict;
4use warnings;
5use overload
6 '0+' => 'count',
a910dc57 7 'bool' => sub { 1; },
89c0a5a2 8 fallback => 1;
3c5b25c5 9use Data::Page;
ea20d0fd 10use Storable;
89c0a5a2 11
701da8c4 12use base qw/DBIx::Class/;
13__PACKAGE__->load_components(qw/AccessorGroup/);
14__PACKAGE__->mk_group_accessors('simple' => 'result_source');
15
ee38fa40 16=head1 NAME
17
bfab575a 18DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
ee38fa40 19
bfab575a 20=head1 SYNOPSIS
ee38fa40 21
a33df5d4 22 my $rs = $schema->resultset('User')->search(registered => 1);
23 my @rows = $schema->resultset('Foo')->search(bar => 'baz');
ee38fa40 24
25=head1 DESCRIPTION
26
bfab575a 27The resultset is also known as an iterator. It is responsible for handling
a33df5d4 28queries that may return an arbitrary number of rows, e.g. via L</search>
bfab575a 29or a C<has_many> relationship.
ee38fa40 30
a33df5d4 31In the examples below, the following table classes are used:
32
33 package MyApp::Schema::Artist;
34 use base qw/DBIx::Class/;
35 __PACKAGE__->table('artist');
36 __PACKAGE__->add_columns(qw/artistid name/);
37 __PACKAGE__->set_primary_key('artistid');
38 __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
39 1;
40
41 package MyApp::Schema::CD;
42 use base qw/DBIx::Class/;
43 __PACKAGE__->table('artist');
44 __PACKAGE__->add_columns(qw/cdid artist title year/);
45 __PACKAGE__->set_primary_key('cdid');
46 __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
47 1;
48
ee38fa40 49=head1 METHODS
50
976f3686 51=head2 new($source, \%$attrs)
ee38fa40 52
a33df5d4 53The resultset constructor. Takes a source object (usually a
80c90f5d 54L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see L</ATRRIBUTES>
a33df5d4 55below). Does not perform any queries -- these are executed as needed by the
56other methods.
57
58Generally you won't need to construct a resultset manually. You'll
59automatically get one from e.g. a L</search> called in scalar context:
60
61 my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
ee38fa40 62
63=cut
64
89c0a5a2 65sub new {
fea3d045 66 my $class = shift;
f9db5527 67 return $class->new_result(@_) if ref $class;
fea3d045 68 my ($source, $attrs) = @_;
b98e75f6 69 #use Data::Dumper; warn Dumper($attrs);
ea20d0fd 70 $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
c7ce65e6 71 my %seen;
6aeb9185 72 my $alias = ($attrs->{alias} ||= 'me');
a9433341 73 if ($attrs->{cols} || !$attrs->{select}) {
74 delete $attrs->{as} if $attrs->{cols};
976f3686 75 my @cols = ($attrs->{cols}
76 ? @{delete $attrs->{cols}}
a9433341 77 : $source->columns);
6aeb9185 78 $attrs->{select} = [ map { m/\./ ? $_ : "${alias}.$_" } @cols ];
976f3686 79 }
6aeb9185 80 $attrs->{as} ||= [ map { m/^$alias\.(.*)$/ ? $1 : $_ } @{$attrs->{select}} ];
5ac6a044 81 if (my $include = delete $attrs->{include_columns}) {
82 push(@{$attrs->{select}}, @$include);
83 push(@{$attrs->{as}}, map { m/([^\.]+)$/; $1; } @$include);
84 }
976f3686 85 #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
fea3d045 86 $attrs->{from} ||= [ { $alias => $source->from } ];
b52e9bf8 87 if (my $join = delete $attrs->{join}) {
88 foreach my $j (ref $join eq 'ARRAY'
89 ? (@{$join}) : ($join)) {
c7ce65e6 90 if (ref $j eq 'HASH') {
91 $seen{$_} = 1 foreach keys %$j;
92 } else {
93 $seen{$j} = 1;
94 }
95 }
8452e496 96 push(@{$attrs->{from}}, $source->resolve_join($join, $attrs->{alias}));
c7ce65e6 97 }
54540863 98 $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
b3e8ac9b 99
100 if (my $prefetch = delete $attrs->{prefetch}) {
101 foreach my $p (ref $prefetch eq 'ARRAY'
102 ? (@{$prefetch}) : ($prefetch)) {
103 if( ref $p eq 'HASH' ) {
104 foreach my $key (keys %$p) {
105 push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
106 unless $seen{$key};
107 }
108 }
109 else {
110 push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
111 unless $seen{$p};
112 }
489709af 113 my @prefetch = $source->resolve_prefetch($p, $attrs->{alias});
b3e8ac9b 114 #die Dumper \@cols;
489709af 115 push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
116 push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
b3e8ac9b 117 }
fef5d100 118 }
b3e8ac9b 119
6aeb9185 120 if ($attrs->{page}) {
121 $attrs->{rows} ||= 10;
122 $attrs->{offset} ||= 0;
123 $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
124 }
89c0a5a2 125 my $new = {
701da8c4 126 result_source => $source,
89c0a5a2 127 cond => $attrs->{where},
0a3c5b43 128 from => $attrs->{from},
3c5b25c5 129 count => undef,
93b004d3 130 page => delete $attrs->{page},
3c5b25c5 131 pager => undef,
89c0a5a2 132 attrs => $attrs };
2f5911b2 133 bless ($new, $class);
9229f20a 134 return $new;
89c0a5a2 135}
136
bfab575a 137=head2 search
0a3c5b43 138
87f0da6a 139 my @obj = $rs->search({ foo => 3 }); # "... WHERE foo = 3"
140 my $new_rs = $rs->search({ foo => 3 });
141
6009260a 142If you need to pass in additional attributes but no additional condition,
a33df5d4 143call it as C<search({}, \%attrs);>.
87f0da6a 144
a33df5d4 145 # "SELECT foo, bar FROM $class_table"
146 my @all = $class->search({}, { cols => [qw/foo bar/] });
0a3c5b43 147
148=cut
149
150sub search {
151 my $self = shift;
152
6009260a 153 #use Data::Dumper;warn Dumper(@_);
154
0a3c5b43 155 my $attrs = { %{$self->{attrs}} };
156 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
6aeb9185 157 $attrs = { %$attrs, %{ pop(@_) } };
0a3c5b43 158 }
159
6aeb9185 160 my $where = (@_ ? ((@_ == 1 || ref $_[0] eq "HASH") ? shift : {@_}) : undef());
0a3c5b43 161 if (defined $where) {
162 $where = (defined $attrs->{where}
ad3d2d7c 163 ? { '-and' =>
164 [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
165 $where, $attrs->{where} ] }
0a3c5b43 166 : $where);
167 $attrs->{where} = $where;
168 }
169
701da8c4 170 my $rs = (ref $self)->new($self->result_source, $attrs);
0a3c5b43 171
172 return (wantarray ? $rs->all : $rs);
173}
174
87f0da6a 175=head2 search_literal
176
6009260a 177 my @obj = $rs->search_literal($literal_where_cond, @bind);
178 my $new_rs = $rs->search_literal($literal_where_cond, @bind);
179
180Pass a literal chunk of SQL to be added to the conditional part of the
87f0da6a 181resultset.
6009260a 182
bfab575a 183=cut
184
6009260a 185sub search_literal {
186 my ($self, $cond, @vals) = @_;
187 my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
188 $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
189 return $self->search(\$cond, $attrs);
190}
0a3c5b43 191
87f0da6a 192=head2 find(@colvalues), find(\%cols, \%attrs?)
193
194Finds a row based on its primary key or unique constraint. For example:
195
87f0da6a 196 my $cd = $schema->resultset('CD')->find(5);
197
198Also takes an optional C<key> attribute, to search by a specific key or unique
199constraint. For example:
200
201 my $cd = $schema->resultset('CD')->find_or_create(
202 {
203 artist => 'Massive Attack',
204 title => 'Mezzanine',
205 },
206 { key => 'artist_title' }
207 );
208
a33df5d4 209See also L</find_or_create> and L</update_or_create>.
210
87f0da6a 211=cut
716b3d29 212
213sub find {
214 my ($self, @vals) = @_;
215 my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
87f0da6a 216
701da8c4 217 my @cols = $self->result_source->primary_columns;
87f0da6a 218 if (exists $attrs->{key}) {
701da8c4 219 my %uniq = $self->result_source->unique_constraints;
87f0da6a 220 $self->( "Unknown key " . $attrs->{key} . " on " . $self->name )
221 unless exists $uniq{$attrs->{key}};
222 @cols = @{ $uniq{$attrs->{key}} };
223 }
224 #use Data::Dumper; warn Dumper($attrs, @vals, @cols);
701da8c4 225 $self->throw_exception( "Can't find unless a primary key or unique constraint is defined" )
87f0da6a 226 unless @cols;
227
716b3d29 228 my $query;
229 if (ref $vals[0] eq 'HASH') {
01bc091e 230 $query = { %{$vals[0]} };
87f0da6a 231 } elsif (@cols == @vals) {
716b3d29 232 $query = {};
87f0da6a 233 @{$query}{@cols} = @vals;
716b3d29 234 } else {
235 $query = {@vals};
236 }
01bc091e 237 foreach (keys %$query) {
238 next if m/\./;
239 $query->{$self->{attrs}{alias}.'.'.$_} = delete $query->{$_};
240 }
716b3d29 241 #warn Dumper($query);
c5b7d799 242 return $self->search($query,$attrs)->next;
716b3d29 243}
244
b52e9bf8 245=head2 search_related
246
247 $rs->search_related('relname', $cond?, $attrs?);
248
a33df5d4 249Search the specified relationship. Optionally specify a condition for matching
250records.
251
b52e9bf8 252=cut
253
6aeb9185 254sub search_related {
255 my ($self, $rel, @rest) = @_;
701da8c4 256 my $rel_obj = $self->result_source->relationship_info($rel);
257 $self->throw_exception(
6aeb9185 258 "No such relationship ${rel} in search_related")
259 unless $rel_obj;
6aeb9185 260 my $rs = $self->search(undef, { join => $rel });
701da8c4 261 return $self->result_source->schema->resultset($rel_obj->{class}
ea20d0fd 262 )->search( undef,
263 { %{$rs->{attrs}},
264 alias => $rel,
265 select => undef(),
266 as => undef() }
6aeb9185 267 )->search(@rest);
268}
b52e9bf8 269
bfab575a 270=head2 cursor
ee38fa40 271
bfab575a 272Returns a storage-driven cursor to the given resultset.
ee38fa40 273
274=cut
275
73f58123 276sub cursor {
277 my ($self) = @_;
701da8c4 278 my ($attrs) = $self->{attrs};
6aeb9185 279 $attrs = { %$attrs };
73f58123 280 return $self->{cursor}
701da8c4 281 ||= $self->result_source->storage->select($self->{from}, $attrs->{select},
73f58123 282 $attrs->{where},$attrs);
283}
284
87f0da6a 285=head2 search_like
286
a33df5d4 287Perform a search, but use C<LIKE> instead of equality as the condition. Note
288that this is simply a convenience method; you most likely want to use
289L</search> with specific operators.
290
291For more information, see L<DBIx::Class::Manual::Cookbook>.
87f0da6a 292
293=cut
58a4bd18 294
295sub search_like {
296 my $class = shift;
297 my $attrs = { };
298 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
299 $attrs = pop(@_);
300 }
301 my $query = ref $_[0] eq "HASH" ? { %{shift()} }: {@_};
302 $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
303 return $class->search($query, { %$attrs });
304}
305
bfab575a 306=head2 slice($first, $last)
ee38fa40 307
bfab575a 308Returns a subset of elements from the resultset.
ee38fa40 309
310=cut
311
89c0a5a2 312sub slice {
313 my ($self, $min, $max) = @_;
314 my $attrs = { %{ $self->{attrs} || {} } };
6aeb9185 315 $attrs->{offset} ||= 0;
316 $attrs->{offset} += $min;
89c0a5a2 317 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
701da8c4 318 my $slice = (ref $self)->new($self->result_source, $attrs);
89c0a5a2 319 return (wantarray ? $slice->all : $slice);
320}
321
87f0da6a 322=head2 next
ee38fa40 323
a33df5d4 324Returns the next element in the resultset (C<undef> is there is none).
325
326Can be used to efficiently iterate over records in the resultset:
327
328 my $rs = $schema->resultset('CD')->search({});
329 while (my $cd = $rs->next) {
330 print $cd->title;
331 }
ee38fa40 332
333=cut
334
89c0a5a2 335sub next {
336 my ($self) = @_;
73f58123 337 my @row = $self->cursor->next;
a953d8d9 338# warn Dumper(\@row); use Data::Dumper;
89c0a5a2 339 return unless (@row);
c7ce65e6 340 return $self->_construct_object(@row);
341}
342
343sub _construct_object {
344 my ($self, @row) = @_;
b3e8ac9b 345 my @as = @{ $self->{attrs}{as} };
976f3686 346 #warn "@cols -> @row";
b3e8ac9b 347 my $info = [ {}, {} ];
348 foreach my $as (@as) {
349 my $target = $info;
350 my @parts = split(/\./, $as);
351 my $col = pop(@parts);
352 foreach my $p (@parts) {
353 $target = $target->[1]->{$p} ||= [];
c7ce65e6 354 }
b3e8ac9b 355 $target->[0]->{$col} = shift @row;
c7ce65e6 356 }
b3e8ac9b 357 #use Data::Dumper; warn Dumper(\@as, $info);
701da8c4 358 my $new = $self->result_source->result_class->inflate_result(
359 $self->result_source, @$info);
33ce49d6 360 $new = $self->{attrs}{record_filter}->($new)
361 if exists $self->{attrs}{record_filter};
362 return $new;
89c0a5a2 363}
364
701da8c4 365=head2 result_source
366
367Returns a reference to the result source for this recordset.
368
369=cut
370
371
bfab575a 372=head2 count
ee38fa40 373
bfab575a 374Performs an SQL C<COUNT> with the same query as the resultset was built
6009260a 375with to find the number of elements. If passed arguments, does a search
376on the resultset and counts the results of that.
ee38fa40 377
bda4c2b8 378Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
379using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
380not support C<DISTINCT> with multiple columns. If you are using such a
381database, you should only use columns from the main table in your C<group_by>
382clause.
383
ee38fa40 384=cut
385
89c0a5a2 386sub count {
6009260a 387 my $self = shift;
388 return $self->search(@_)->count if @_ && defined $_[0];
6aeb9185 389 unless (defined $self->{count}) {
15c382be 390 my $group_by;
391 my $select = { 'count' => '*' };
392 if( $group_by = delete $self->{attrs}{group_by} ) {
393 my @distinct = @$group_by;
394 # todo: try CONCAT for multi-column pk
395 my @pk = $self->result_source->primary_columns;
396 if( scalar(@pk) == 1 ) {
397 my $pk = shift(@pk);
398 my $alias = $self->{attrs}{alias};
399 my $re = qr/^($alias\.)?$pk$/;
400 foreach my $column ( @$group_by ) {
401 if( $column =~ $re ) {
402 @distinct = ( $column );
403 last;
404 }
405 }
406 }
407
408 $select = { count => { 'distinct' => \@distinct } };
409 #use Data::Dumper; die Dumper $select;
410 }
411
976f3686 412 my $attrs = { %{ $self->{attrs} },
15c382be 413 select => $select,
54540863 414 as => [ 'count' ] };
ea20d0fd 415 # offset, order by and page are not needed to count. record_filter is cdbi
416 delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
3c5b25c5 417
701da8c4 418 ($self->{count}) = (ref $self)->new($self->result_source, $attrs)->cursor->next;
15c382be 419 $self->{attrs}{group_by} = $group_by;
3c5b25c5 420 }
421 return 0 unless $self->{count};
6aeb9185 422 my $count = $self->{count};
423 $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
424 $count = $self->{attrs}{rows} if
425 ($self->{attrs}{rows} && $self->{attrs}{rows} < $count);
426 return $count;
89c0a5a2 427}
428
bfab575a 429=head2 count_literal
6009260a 430
a33df5d4 431Calls L</search_literal> with the passed arguments, then L</count>.
6009260a 432
433=cut
434
435sub count_literal { shift->search_literal(@_)->count; }
436
bfab575a 437=head2 all
ee38fa40 438
bfab575a 439Returns all elements in the resultset. Called implictly if the resultset
440is returned in list context.
ee38fa40 441
442=cut
443
89c0a5a2 444sub all {
445 my ($self) = @_;
c7ce65e6 446 return map { $self->_construct_object(@$_); }
73f58123 447 $self->cursor->all;
89c0a5a2 448}
449
bfab575a 450=head2 reset
ee38fa40 451
bfab575a 452Resets the resultset's cursor, so you can iterate through the elements again.
ee38fa40 453
454=cut
455
89c0a5a2 456sub reset {
457 my ($self) = @_;
73f58123 458 $self->cursor->reset;
89c0a5a2 459 return $self;
460}
461
bfab575a 462=head2 first
ee38fa40 463
bfab575a 464Resets the resultset and returns the first element.
ee38fa40 465
466=cut
467
89c0a5a2 468sub first {
469 return $_[0]->reset->next;
470}
471
c01ab172 472=head2 update(\%values)
473
a33df5d4 474Sets the specified columns in the resultset to the supplied values.
c01ab172 475
476=cut
477
478sub update {
479 my ($self, $values) = @_;
701da8c4 480 $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
481 return $self->result_source->storage->update(
482 $self->result_source->from, $values, $self->{cond});
c01ab172 483}
484
485=head2 update_all(\%values)
486
a33df5d4 487Fetches all objects and updates them one at a time. Note that C<update_all>
488will run cascade triggers while L</update> will not.
c01ab172 489
490=cut
491
492sub update_all {
493 my ($self, $values) = @_;
701da8c4 494 $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
c01ab172 495 foreach my $obj ($self->all) {
496 $obj->set_columns($values)->update;
497 }
498 return 1;
499}
500
bfab575a 501=head2 delete
ee38fa40 502
c01ab172 503Deletes the contents of the resultset from its result source.
ee38fa40 504
505=cut
506
28927b50 507sub delete {
89c0a5a2 508 my ($self) = @_;
701da8c4 509 $self->result_source->storage->delete($self->result_source->from, $self->{cond});
89c0a5a2 510 return 1;
511}
512
c01ab172 513=head2 delete_all
514
a33df5d4 515Fetches all objects and deletes them one at a time. Note that C<delete_all>
516will run cascade triggers while L</delete> will not.
c01ab172 517
518=cut
519
520sub delete_all {
521 my ($self) = @_;
522 $_->delete for $self->all;
523 return 1;
524}
28927b50 525
bfab575a 526=head2 pager
ee38fa40 527
528Returns a L<Data::Page> object for the current resultset. Only makes
a33df5d4 529sense for queries with a C<page> attribute.
ee38fa40 530
531=cut
532
3c5b25c5 533sub pager {
534 my ($self) = @_;
535 my $attrs = $self->{attrs};
701da8c4 536 $self->throw_exception("Can't create pager for non-paged rs") unless $self->{page};
6aeb9185 537 $attrs->{rows} ||= 10;
538 $self->count;
539 return $self->{pager} ||= Data::Page->new(
93b004d3 540 $self->{count}, $attrs->{rows}, $self->{page});
3c5b25c5 541}
542
bfab575a 543=head2 page($page_num)
ee38fa40 544
bfab575a 545Returns a new resultset for the specified page.
ee38fa40 546
547=cut
548
3c5b25c5 549sub page {
550 my ($self, $page) = @_;
6aeb9185 551 my $attrs = { %{$self->{attrs}} };
3c5b25c5 552 $attrs->{page} = $page;
701da8c4 553 return (ref $self)->new($self->result_source, $attrs);
fea3d045 554}
555
556=head2 new_result(\%vals)
557
87f0da6a 558Creates a result in the resultset's result class.
fea3d045 559
560=cut
561
562sub new_result {
563 my ($self, $values) = @_;
701da8c4 564 $self->throw_exception( "new_result needs a hash" )
fea3d045 565 unless (ref $values eq 'HASH');
701da8c4 566 $self->throw_exception( "Can't abstract implicit construct, condition not a hash" )
fea3d045 567 if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
568 my %new = %$values;
569 my $alias = $self->{attrs}{alias};
570 foreach my $key (keys %{$self->{cond}||{}}) {
571 $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:$alias\.)?([^\.]+)$/);
572 }
701da8c4 573 my $obj = $self->result_source->result_class->new(\%new);
574 $obj->result_source($self->result_source) if $obj->can('result_source');
097d3227 575 $obj;
fea3d045 576}
577
578=head2 create(\%vals)
579
87f0da6a 580Inserts a record into the resultset and returns the object.
fea3d045 581
a33df5d4 582Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
fea3d045 583
584=cut
585
586sub create {
587 my ($self, $attrs) = @_;
701da8c4 588 $self->throw_exception( "create needs a hashref" ) unless ref $attrs eq 'HASH';
fea3d045 589 return $self->new_result($attrs)->insert;
3c5b25c5 590}
591
87f0da6a 592=head2 find_or_create(\%vals, \%attrs?)
593
594 $class->find_or_create({ key => $val, ... });
c2b15ecc 595
c2b15ecc 596Searches for a record matching the search condition; if it doesn't find one,
cf7b40ed 597creates one and returns that instead.
87f0da6a 598
87f0da6a 599 my $cd = $schema->resultset('CD')->find_or_create({
600 cdid => 5,
601 artist => 'Massive Attack',
602 title => 'Mezzanine',
603 year => 2005,
604 });
605
606Also takes an optional C<key> attribute, to search by a specific key or unique
607constraint. For example:
608
609 my $cd = $schema->resultset('CD')->find_or_create(
610 {
611 artist => 'Massive Attack',
612 title => 'Mezzanine',
613 },
614 { key => 'artist_title' }
615 );
616
617See also L</find> and L</update_or_create>.
618
c2b15ecc 619=cut
620
621sub find_or_create {
622 my $self = shift;
87f0da6a 623 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
624 my $hash = ref $_[0] eq "HASH" ? shift : {@_};
625 my $exists = $self->find($hash, $attrs);
c2b15ecc 626 return defined($exists) ? $exists : $self->create($hash);
627}
628
87f0da6a 629=head2 update_or_create
630
631 $class->update_or_create({ key => $val, ... });
632
633First, search for an existing row matching one of the unique constraints
634(including the primary key) on the source of this resultset. If a row is
635found, update it with the other given column values. Otherwise, create a new
636row.
637
638Takes an optional C<key> attribute to search on a specific unique constraint.
639For example:
640
641 # In your application
642 my $cd = $schema->resultset('CD')->update_or_create(
643 {
644 artist => 'Massive Attack',
645 title => 'Mezzanine',
646 year => 1998,
647 },
648 { key => 'artist_title' }
649 );
650
651If no C<key> is specified, it searches on all unique constraints defined on the
652source, including the primary key.
653
654If the C<key> is specified as C<primary>, search only on the primary key.
655
a33df5d4 656See also L</find> and L</find_or_create>.
657
87f0da6a 658=cut
659
660sub update_or_create {
661 my $self = shift;
662
663 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
664 my $hash = ref $_[0] eq "HASH" ? shift : {@_};
665
701da8c4 666 my %unique_constraints = $self->result_source->unique_constraints;
87f0da6a 667 my @constraint_names = (exists $attrs->{key}
668 ? ($attrs->{key})
669 : keys %unique_constraints);
670
671 my @unique_hashes;
672 foreach my $name (@constraint_names) {
673 my @unique_cols = @{ $unique_constraints{$name} };
674 my %unique_hash =
675 map { $_ => $hash->{$_} }
676 grep { exists $hash->{$_} }
677 @unique_cols;
678
679 push @unique_hashes, \%unique_hash
680 if (scalar keys %unique_hash == scalar @unique_cols);
681 }
682
683 my $row;
684 if (@unique_hashes) {
685 $row = $self->search(\@unique_hashes, { rows => 1 })->first;
686 if ($row) {
687 $row->set_columns($hash);
688 $row->update;
689 }
690 }
691
692 unless ($row) {
693 $row = $self->create($hash);
694 }
695
696 return $row;
697}
698
701da8c4 699=head2 throw_exception
700
701See Schema's throw_exception
702
703=cut
704
705sub throw_exception {
706 my $self=shift;
707 $self->result_source->schema->throw_exception(@_);
708}
709
40dbc108 710=head1 ATTRIBUTES
076652e8 711
a33df5d4 712The resultset takes various attributes that modify its behavior. Here's an
713overview of them:
bfab575a 714
715=head2 order_by
076652e8 716
a33df5d4 717Which column(s) to order the results by. This is currently passed through
718directly to SQL, so you can give e.g. C<foo DESC> for a descending order.
076652e8 719
976f3686 720=head2 cols (arrayref)
721
a33df5d4 722Shortcut to request a particular set of columns to be retrieved. Adds
723C<me.> onto the start of any column without a C<.> in it and sets C<select>
724from that, then auto-populates C<as> from C<select> as normal.
976f3686 725
5ac6a044 726=head2 include_columns (arrayref)
727
728Shortcut to include additional columns in the returned results - for example
729
730 { include_columns => ['foo.name'], join => ['foo'] }
731
732would add a 'name' column to the information passed to object inflation
733
976f3686 734=head2 select (arrayref)
735
4a28c340 736Indicates which columns should be selected from the storage. You can use
737column names, or in the case of RDBMS back ends, function or stored procedure
738names:
739
740 $rs = $schema->resultset('Foo')->search(
741 {},
742 {
cf7b40ed 743 select => [
4a28c340 744 'column_name',
745 { count => 'column_to_count' },
746 { sum => 'column_to_sum' }
cf7b40ed 747 ]
4a28c340 748 }
749 );
750
751When you use function/stored procedure names and do not supply an C<as>
752attribute, the column names returned are storage-dependent. E.g. MySQL would
753return a column named C<count(column_to_count)> in the above example.
976f3686 754
755=head2 as (arrayref)
076652e8 756
4a28c340 757Indicates column names for object inflation. This is used in conjunction with
758C<select>, usually when C<select> contains one or more function or stored
759procedure names:
760
761 $rs = $schema->resultset('Foo')->search(
762 {},
763 {
cf7b40ed 764 select => [
4a28c340 765 'column1',
766 { count => 'column2' }
cf7b40ed 767 ],
4a28c340 768 as => [qw/ column1 column2_count /]
769 }
770 );
771
772 my $foo = $rs->first(); # get the first Foo
773
774If the object against which the search is performed already has an accessor
775matching a column name specified in C<as>, the value can be retrieved using
776the accessor as normal:
777
778 my $column1 = $foo->column1();
779
780If on the other hand an accessor does not exist in the object, you need to
781use C<get_column> instead:
782
783 my $column2_count = $foo->get_column('column2_count');
784
785You can create your own accessors if required - see
786L<DBIx::Class::Manual::Cookbook> for details.
ee38fa40 787
bfab575a 788=head2 join
ee38fa40 789
a33df5d4 790Contains a list of relationships that should be joined for this query. For
791example:
792
793 # Get CDs by Nine Inch Nails
794 my $rs = $schema->resultset('CD')->search(
795 { 'artist.name' => 'Nine Inch Nails' },
796 { join => 'artist' }
797 );
798
799Can also contain a hash reference to refer to the other relation's relations.
800For example:
801
802 package MyApp::Schema::Track;
803 use base qw/DBIx::Class/;
804 __PACKAGE__->table('track');
805 __PACKAGE__->add_columns(qw/trackid cd position title/);
806 __PACKAGE__->set_primary_key('trackid');
807 __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
808 1;
809
810 # In your application
811 my $rs = $schema->resultset('Artist')->search(
812 { 'track.title' => 'Teardrop' },
813 {
814 join => { cd => 'track' },
815 order_by => 'artist.name',
816 }
817 );
818
ae1c90a1 819If you want to fetch columns from related tables as well, see C<prefetch>
820below.
ee38fa40 821
ae1c90a1 822=head2 prefetch arrayref/hashref
ee38fa40 823
ae1c90a1 824Contains one or more relationships that should be fetched along with the main
bfab575a 825query (when they are accessed afterwards they will have already been
a33df5d4 826"prefetched"). This is useful for when you know you will need the related
ae1c90a1 827objects, because it saves at least one query:
828
829 my $rs = $schema->resultset('Tag')->search(
830 {},
831 {
832 prefetch => {
833 cd => 'artist'
834 }
835 }
836 );
837
838The initial search results in SQL like the following:
839
840 SELECT tag.*, cd.*, artist.* FROM tag
841 JOIN cd ON tag.cd = cd.cdid
842 JOIN artist ON cd.artist = artist.artistid
843
844L<DBIx::Class> has no need to go back to the database when we access the
845C<cd> or C<artist> relationships, which saves us two SQL statements in this
846case.
847
848Any prefetched relationship will be joined automatically, so there is no need
849for a C<join> attribute in the above search.
850
851C<prefetch> can be used with the following relationship types: C<belongs_to>,
852C<has_one>.
ee38fa40 853
4a28c340 854=head2 from (arrayref)
ee38fa40 855
4a28c340 856The C<from> attribute gives you manual control over the C<FROM> clause of SQL
857statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
858clauses.
ee38fa40 859
a33df5d4 860NOTE: Use this on your own risk. This allows you to shoot off your foot!
4a28c340 861C<join> will usually do what you need and it is strongly recommended that you
862avoid using C<from> unless you cannot achieve the desired result using C<join>.
863
864In simple terms, C<from> works as follows:
865
866 [
867 { <alias> => <table>, -join-type => 'inner|left|right' }
868 [] # nested JOIN (optional)
869 { <table.column> = <foreign_table.foreign_key> }
870 ]
871
872 JOIN
873 <alias> <table>
874 [JOIN ...]
875 ON <table.column> = <foreign_table.foreign_key>
876
877An easy way to follow the examples below is to remember the following:
878
879 Anything inside "[]" is a JOIN
880 Anything inside "{}" is a condition for the enclosing JOIN
881
882The following examples utilize a "person" table in a family tree application.
883In order to express parent->child relationships, this table is self-joined:
884
885 # Person->belongs_to('father' => 'Person');
886 # Person->belongs_to('mother' => 'Person');
887
888C<from> can be used to nest joins. Here we return all children with a father,
889then search against all mothers of those children:
890
891 $rs = $schema->resultset('Person')->search(
892 {},
893 {
894 alias => 'mother', # alias columns in accordance with "from"
895 from => [
896 { mother => 'person' },
897 [
898 [
899 { child => 'person' },
900 [
901 { father => 'person' },
902 { 'father.person_id' => 'child.father_id' }
903 ]
904 ],
905 { 'mother.person_id' => 'child.mother_id' }
906 ],
907 ]
908 },
909 );
910
911 # Equivalent SQL:
912 # SELECT mother.* FROM person mother
913 # JOIN (
914 # person child
915 # JOIN person father
916 # ON ( father.person_id = child.father_id )
917 # )
918 # ON ( mother.person_id = child.mother_id )
919
920The type of any join can be controlled manually. To search against only people
921with a father in the person table, we could explicitly use C<INNER JOIN>:
922
923 $rs = $schema->resultset('Person')->search(
924 {},
925 {
926 alias => 'child', # alias columns in accordance with "from"
927 from => [
928 { child => 'person' },
929 [
930 { father => 'person', -join-type => 'inner' },
931 { 'father.id' => 'child.father_id' }
932 ],
933 ]
934 },
935 );
936
937 # Equivalent SQL:
938 # SELECT child.* FROM person child
939 # INNER JOIN person father ON child.father_id = father.id
ee38fa40 940
bfab575a 941=head2 page
076652e8 942
a33df5d4 943For a paged resultset, specifies which page to retrieve. Leave unset
bfab575a 944for an unpaged resultset.
076652e8 945
bfab575a 946=head2 rows
076652e8 947
4a28c340 948For a paged resultset, how many rows per page:
949
950 rows => 10
951
952Can also be used to simulate an SQL C<LIMIT>.
076652e8 953
a33df5d4 954=head2 group_by (arrayref)
54540863 955
bda4c2b8 956A arrayref of columns to group by. Can include columns of joined tables.
54540863 957
675ce4a6 958 group_by => [qw/ column1 column2 ... /]
959
54540863 960=head2 distinct
961
a33df5d4 962Set to 1 to group by all columns.
963
964For more examples of using these attributes, see
965L<DBIx::Class::Manual::Cookbook>.
54540863 966
bfab575a 967=cut
076652e8 968
89c0a5a2 9691;