Added as_query to ResultSet with a couple tests
[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
b6e85b48 42
152002c4 43 # If $column can be found in the 'as' list of the parent resultset, use the
44 # corresponding element of its 'select' list (to keep any custom column
45 # definition set up with 'select' or '+select' attrs), otherwise use $column
46 # (to create a new column definition on-the-fly).
b6e85b48 47 my $as_list = $attrs->{as} || [];
48 my $select_list = $attrs->{select} || [];
49 my $as_index = List::Util::first { ($as_list->[$_] || "") eq $column } 0..$#$as_list;
b6e85b48 50 my $select = defined $as_index ? $select_list->[$as_index] : $column;
51
52 my $new = bless { _select => $select, _as => $column, _parent_resultset => $new_parent_rs }, $class;
6b051e14 53 $new->throw_exception("column must be supplied") unless $column;
2bb7b40b 54 return $new;
55}
56
57=head2 next
58
59=over 4
60
61=item Arguments: none
62
63=item Return Value: $value
64
65=back
66
eb98561c 67Returns the next value of the column in the resultset (or C<undef> if
68there is none).
2bb7b40b 69
eb98561c 70Much like L<DBIx::Class::ResultSet/next> but just returning the
71one value.
2bb7b40b 72
73=cut
74
75sub next {
76 my $self = shift;
66521001 77 my ($row) = $self->_resultset->cursor->next;
2bb7b40b 78 return $row;
79}
80
81=head2 all
82
83=over 4
84
85=item Arguments: none
86
87=item Return Value: @values
88
89=back
90
eb98561c 91Returns all values of the column in the resultset (or C<undef> if
92there are none).
2bb7b40b 93
eb98561c 94Much like L<DBIx::Class::ResultSet/all> but returns values rather
95than row objects.
2bb7b40b 96
97=cut
98
99sub all {
100 my $self = shift;
66521001 101 return map { $_->[0] } $self->_resultset->cursor->all;
102}
103
104=head2 reset
105
106=over 4
107
108=item Arguments: none
109
110=item Return Value: $self
111
112=back
113
114Resets the underlying resultset's cursor, so you can iterate through the
115elements of the column again.
116
117Much like L<DBIx::Class::ResultSet/reset>.
118
119=cut
120
121sub reset {
122 my $self = shift;
123 $self->_resultset->cursor->reset;
124 return $self;
125}
126
127=head2 first
128
129=over 4
130
131=item Arguments: none
132
133=item Return Value: $value
134
135=back
136
137Resets the underlying resultset and returns the next value of the column in the
138resultset (or C<undef> if there is none).
139
140Much like L<DBIx::Class::ResultSet/first> but just returning the one value.
141
142=cut
143
144sub first {
145 my $self = shift;
3484603a 146 my ($row) = $self->_resultset->cursor->reset->next;
66521001 147 return $row;
2bb7b40b 148}
149
150=head2 min
151
152=over 4
153
154=item Arguments: none
155
156=item Return Value: $lowest_value
157
158=back
159
eb98561c 160 my $first_year = $year_col->min();
161
162Wrapper for ->func. Returns the lowest value of the column in the
163resultset (or C<undef> if there are none).
2bb7b40b 164
165=cut
166
167sub min {
6b051e14 168 return shift->func('MIN');
2bb7b40b 169}
170
171=head2 max
172
173=over 4
174
175=item Arguments: none
176
177=item Return Value: $highest_value
178
179=back
180
eb98561c 181 my $last_year = $year_col->max();
182
183Wrapper for ->func. Returns the highest value of the column in the
184resultset (or C<undef> if there are none).
2bb7b40b 185
186=cut
187
188sub max {
6b051e14 189 return shift->func('MAX');
2bb7b40b 190}
191
192=head2 sum
193
194=over 4
195
196=item Arguments: none
197
198=item Return Value: $sum_of_values
199
200=back
201
eb98561c 202 my $total = $prices_col->sum();
203
204Wrapper for ->func. Returns the sum of all the values in the column of
205the resultset. Use on varchar-like columns at your own risk.
2bb7b40b 206
207=cut
208
209sub sum {
6b051e14 210 return shift->func('SUM');
2bb7b40b 211}
212
213=head2 func
214
215=over 4
216
217=item Arguments: $function
218
219=item Return Value: $function_return_value
220
221=back
222
e8419341 223 $rs = $schema->resultset("CD")->search({});
224 $length = $rs->get_column('title')->func('LENGTH');
2bb7b40b 225
eb98561c 226Runs a query using the function on the column and returns the
227value. Produces the following SQL:
228
229 SELECT LENGTH( title ) FROM cd me
2bb7b40b 230
231=cut
232
233sub func {
6b051e14 234 my ($self,$function) = @_;
5d1fc7dc 235 my $cursor = $self->{_parent_resultset}->search(undef, {select => {$function => $self->{_select}}, as => [$self->{_as}]})->cursor;
5d62876f 236
237 if( wantarray ) {
238 return map { $_->[ 0 ] } $cursor->all;
239 }
240
241 return ( $cursor->next )[ 0 ];
2bb7b40b 242}
243
5d1fc7dc 244=head2 throw_exception
245
246See L<DBIx::Class::Schema/throw_exception> for details.
247
248=cut
249
250sub throw_exception {
251 my $self=shift;
252 if (ref $self && $self->{_parent_resultset}) {
253 $self->{_parent_resultset}->throw_exception(@_)
254 } else {
255 croak(@_);
256 }
257}
258
b6e85b48 259# _resultset
260#
261# Arguments: none
262#
263# Return Value: $resultset
264#
265# $year_col->_resultset->next
266#
267# Returns the underlying resultset. Creates it from the parent resultset if
268# necessary.
269#
66521001 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