* Fixed a bug: did not create the underlying resultset if neither ->next or ->reset...
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSetColumn.pm
CommitLineData
2bb7b40b 1package DBIx::Class::ResultSetColumn;
2use strict;
3use warnings;
4use base 'DBIx::Class';
66521001 5use List::Util;
2bb7b40b 6
7=head1 NAME
8
9 DBIx::Class::ResultSetColumn - helpful methods for messing
10 with a single column of the resultset
11
12=head1 SYNOPSIS
13
14 $rs = $schema->resultset('CD')->search({ artist => 'Tool' });
15 $rs_column = $rs->get_column('year');
16 $max_year = $rs_column->max; #returns latest year
17
18=head1 DESCRIPTION
19
eb98561c 20A convenience class used to perform operations on a specific column of
21a resultset.
2bb7b40b 22
23=cut
24
25=head1 METHODS
26
27=head2 new
28
29 my $obj = DBIx::Class::ResultSetColumn->new($rs, $column);
30
eb98561c 31Creates a new resultset column object from the resultset and column
32passed as params. Used internally by L<DBIx::Class::ResultSet/get_column>.
2bb7b40b 33
34=cut
35
36sub new {
37 my ($class, $rs, $column) = @_;
38 $class = ref $class if ref $class;
3f6cc7e4 39 my $new_parent_rs = $rs->search_rs; # we don't want to mess up the original, so clone it
5d1fc7dc 40 my $attrs = $new_parent_rs->_resolved_attrs;
41 $new_parent_rs->{attrs}->{$_} = undef for qw(prefetch include_columns +select +as); # prefetch, include_columns, +select, +as cause additional columns to be fetched
42 my ($select, $as) =
43 map { defined $_ ? ($attrs->{select}->[$_], $attrs->{as}->[$_]) : ($column, $column) }
66521001 44 List::Util::first { ($attrs->{as} || [])->[$_] eq $column }
5d1fc7dc 45 0..$#{$attrs->{as} || []};
46 my $new = bless { _select => $select, _as => $as, _parent_resultset => $new_parent_rs }, $class;
6b051e14 47 $new->throw_exception("column must be supplied") unless $column;
2bb7b40b 48 return $new;
49}
50
51=head2 next
52
53=over 4
54
55=item Arguments: none
56
57=item Return Value: $value
58
59=back
60
eb98561c 61Returns the next value of the column in the resultset (or C<undef> if
62there is none).
2bb7b40b 63
eb98561c 64Much like L<DBIx::Class::ResultSet/next> but just returning the
65one value.
2bb7b40b 66
67=cut
68
69sub next {
70 my $self = shift;
66521001 71 my ($row) = $self->_resultset->cursor->next;
2bb7b40b 72 return $row;
73}
74
75=head2 all
76
77=over 4
78
79=item Arguments: none
80
81=item Return Value: @values
82
83=back
84
eb98561c 85Returns all values of the column in the resultset (or C<undef> if
86there are none).
2bb7b40b 87
eb98561c 88Much like L<DBIx::Class::ResultSet/all> but returns values rather
89than row objects.
2bb7b40b 90
91=cut
92
93sub all {
94 my $self = shift;
66521001 95 return map { $_->[0] } $self->_resultset->cursor->all;
96}
97
98=head2 reset
99
100=over 4
101
102=item Arguments: none
103
104=item Return Value: $self
105
106=back
107
108Resets the underlying resultset's cursor, so you can iterate through the
109elements of the column again.
110
111Much like L<DBIx::Class::ResultSet/reset>.
112
113=cut
114
115sub reset {
116 my $self = shift;
117 $self->_resultset->cursor->reset;
118 return $self;
119}
120
121=head2 first
122
123=over 4
124
125=item Arguments: none
126
127=item Return Value: $value
128
129=back
130
131Resets the underlying resultset and returns the next value of the column in the
132resultset (or C<undef> if there is none).
133
134Much like L<DBIx::Class::ResultSet/first> but just returning the one value.
135
136=cut
137
138sub first {
139 my $self = shift;
3484603a 140 my ($row) = $self->_resultset->cursor->reset->next;
66521001 141 return $row;
2bb7b40b 142}
143
144=head2 min
145
146=over 4
147
148=item Arguments: none
149
150=item Return Value: $lowest_value
151
152=back
153
eb98561c 154 my $first_year = $year_col->min();
155
156Wrapper for ->func. Returns the lowest value of the column in the
157resultset (or C<undef> if there are none).
2bb7b40b 158
159=cut
160
161sub min {
6b051e14 162 return shift->func('MIN');
2bb7b40b 163}
164
165=head2 max
166
167=over 4
168
169=item Arguments: none
170
171=item Return Value: $highest_value
172
173=back
174
eb98561c 175 my $last_year = $year_col->max();
176
177Wrapper for ->func. Returns the highest value of the column in the
178resultset (or C<undef> if there are none).
2bb7b40b 179
180=cut
181
182sub max {
6b051e14 183 return shift->func('MAX');
2bb7b40b 184}
185
186=head2 sum
187
188=over 4
189
190=item Arguments: none
191
192=item Return Value: $sum_of_values
193
194=back
195
eb98561c 196 my $total = $prices_col->sum();
197
198Wrapper for ->func. Returns the sum of all the values in the column of
199the resultset. Use on varchar-like columns at your own risk.
2bb7b40b 200
201=cut
202
203sub sum {
6b051e14 204 return shift->func('SUM');
2bb7b40b 205}
206
207=head2 func
208
209=over 4
210
211=item Arguments: $function
212
213=item Return Value: $function_return_value
214
215=back
216
e8419341 217 $rs = $schema->resultset("CD")->search({});
218 $length = $rs->get_column('title')->func('LENGTH');
2bb7b40b 219
eb98561c 220Runs a query using the function on the column and returns the
221value. Produces the following SQL:
222
223 SELECT LENGTH( title ) FROM cd me
2bb7b40b 224
225=cut
226
227sub func {
6b051e14 228 my ($self,$function) = @_;
5d1fc7dc 229 my $cursor = $self->{_parent_resultset}->search(undef, {select => {$function => $self->{_select}}, as => [$self->{_as}]})->cursor;
5d62876f 230
231 if( wantarray ) {
232 return map { $_->[ 0 ] } $cursor->all;
233 }
234
235 return ( $cursor->next )[ 0 ];
2bb7b40b 236}
237
5d1fc7dc 238=head2 throw_exception
239
240See L<DBIx::Class::Schema/throw_exception> for details.
241
242=cut
243
244sub throw_exception {
245 my $self=shift;
246 if (ref $self && $self->{_parent_resultset}) {
247 $self->{_parent_resultset}->throw_exception(@_)
248 } else {
249 croak(@_);
250 }
251}
252
66521001 253=head2 _resultset
254
255=over 4
256
257=item Arguments: none
258
259=item Return Value: $resultset
260
261=back
262
263 $year_col->_resultset->next
264
265Returns the underlying resultset. Creates it from the parent resultset if
266necessary.
267
268=cut
269
270sub _resultset {
271 my $self = shift;
272
273 return $self->{_resultset} ||= $self->{_parent_resultset}->search(undef,
274 {
275 select => [$self->{_select}],
276 as => [$self->{_as}]
277 }
278 );
279}
280
5d1fc7dc 281
2bb7b40b 2821;
283
284=head1 AUTHORS
285
286Luke Saunders <luke.saunders@gmail.com>
287
eb98561c 288Jess Robinson
289
2bb7b40b 290=head1 LICENSE
291
292You may distribute this code under the same terms as Perl itself.
293
294=cut