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