File Coverage

blib/lib/ActiveRecord/Simple/Find.pm
Criterion Covered Total %
statement 277 368 75.2
branch 82 150 54.6
condition 36 64 56.2
subroutine 29 35 82.8
pod 18 19 94.7
total 442 636 69.5


line stmt bran cond sub pod time code
1             package ActiveRecord::Simple::Find;
2              
3 12     12   156 use 5.010;
  12         30  
4 12     12   53 use strict;
  12         31  
  12         217  
5 12     12   43 use warnings;
  12         34  
  12         286  
6 12     12   66 use vars qw/$AUTOLOAD/;
  12         25  
  12         405  
7              
8 12     12   56 use Carp;
  12         23  
  12         585  
9              
10 12     12   761 use parent 'ActiveRecord::Simple';
  12         513  
  12         56  
11              
12 12     12   4338 use ActiveRecord::Simple::Utils qw/load_module/;
  12         24  
  12         40732  
13              
14              
15             our $MAXIMUM_LIMIT = 100_000_000_000;
16              
17              
18             sub new {
19 86     86 1 173 my ($self_class, $class, @param) = @_;
20              
21             #my $self = $class->new();
22 86         195 my $self = bless { class => $class } => $self_class;
23              
24 86 50       2106 my $table_name = ($self->{class}->can('_get_table_name')) ? $self->{class}->_get_table_name : undef;
25 86 50       1593 my $pkey = ($self->{class}->can('_get_primary_key')) ? $self->{class}->_get_primary_key : undef;
26              
27 86 50       199 croak 'can not get table_name for class ' . $self->{class} unless $table_name;
28             #croak 'can not get primary_key for class ' . $self->{class} unless $pkey;
29              
30 86   50     361 $self->{prep_select_fields} //= [];
31 86   50     271 $self->{prep_select_from} //= [];
32 86   50     269 $self->{prep_select_where} //= [];
33              
34 86         121 my ($fields, $from, $where);
35              
36 86 100 100     437 if (!ref $param[0] && scalar @param == 1) {
    100 100        
    100 100        
    100 66        
37 22         49 $fields = qq/"$table_name".*/;
38 22         37 $from = qq/"$table_name"/;
39 22         48 $where = qq/"$table_name"."$pkey" = ?/;
40              
41             $self->{BIND} = \@param
42 22         43 }
43             elsif (!ref $param[0] && scalar @param == 0) {
44 33         61 $fields = qq/"$table_name".*/;
45 33         52 $from = qq/"$table_name"/;
46              
47 33         49 $self->{BIND} = undef;
48             }
49             elsif (ref $param[0] && ref $param[0] eq 'HASH') {
50             # find many by params
51 23         57 my ($bind, $condition_pairs) = $self->_parse_hash($param[0]);
52              
53 23         51 my $where_str = join q/ AND /, @$condition_pairs;
54              
55 23         42 $fields = qq/"$table_name".*/;
56 23         57 $from = qq/"$table_name"/;
57 23         40 $where = $where_str;
58              
59 23         43 $self->{BIND} = $bind;
60             }
61             elsif (ref $param[0] && ref $param[0] eq 'ARRAY') {
62             # find many by primary keys
63 2         4 my $whereinstr = join ', ', @{ $param[0] };
  2         7  
64              
65 2         7 $fields = qq/"$table_name".*/;
66 2         3 $from = qq/"$table_name"/;
67 2         6 $where = qq/"$table_name"."$pkey" IN ($whereinstr)/;
68              
69 2         4 $self->{BIND} = undef;
70             }
71             else {
72             # find many by condition
73 6         14 my $wherestr = shift @param;
74              
75 6         17 $fields = qq/"$table_name".*/;
76 6         13 $from = qq/"$table_name"/;
77 6         10 $where = $wherestr;
78              
79 6         13 $self->{BIND} = \@param;
80             }
81              
82 86 50       151 push @{ $self->{prep_select_fields} }, $fields if $fields;
  86         170  
83 86 50       136 push @{ $self->{prep_select_from} }, $from if $from;
  86         120  
84 86 100       125 push @{ $self->{prep_select_where} }, $where if $where;
  53         103  
85              
86 86         252 return $self;
87             }
88              
89             sub count {
90 8     8 1 16 my $inv = shift;
91 8 50       17 my $self = ref $inv ? $inv : $inv->new(@_);
92 8         20 $self->{prep_select_fields} = [ 'COUNT(*)' ];
93 8 100       10 if (@{ $self->{prep_group_by} || [] }) {
  8 100       35  
94 2         37 my $table_name = $self->{class}->_get_table_name;
95 2         4 push @{ $self->{prep_select_fields} }, map qq/"$table_name".$_/, @{ $self->{prep_group_by} };
  2         3  
  2         7  
96 2         3 my @group_by = @{ $self->{prep_group_by} };
  2         4  
97 2         7 s/"//g foreach @group_by;
98 2         4 my @results;
99 2         4 foreach my $item ($self->fetch) {
100 7         11 push my @line, (count => $item->{'COUNT(*)'}), map { $_ => $item->{$_} } @group_by;
  7         17  
101 7         19 push @results, { @line };
102             }
103 2         12 return @results;
104             }
105             else {
106 6         17 return $self->fetch->{'COUNT(*)'};
107             }
108             }
109              
110             sub first {
111 6     6 1 12 my ($self, $limit) = @_;
112              
113 6   100     21 $limit //= 1;
114              
115 6 50       19 $self->{class}->can('_get_primary_key') or croak 'Can\'t use "first" without primary key';
116 6         108 my $primary_key = $self->{class}->_get_primary_key;
117              
118 6         14 return $self->order_by($primary_key)->limit($limit)->fetch;
119             }
120              
121             sub last {
122 3     3 1 15 my ($self, $limit) = @_;
123              
124 3 50       13 $self->{class}->can('_get_primary_key') or croak 'Can\'t use "first" without primary key';
125 3         54 my $primary_key = $self->{class}->_get_primary_key;
126 3   50     13 $limit //= 1;
127              
128 3         8 return $self->order_by($primary_key)->desc->limit($limit)->fetch;
129             }
130              
131             sub only {
132 7     7 1 16 my ($self, @fields) = @_;
133              
134 7 50       16 scalar @fields > 0 or croak 'Not defined fields for method "only"';
135 7 50       16 ref $self or croak 'Create an object abstraction before using the modifiers. Use methods like `find`, `first`, `last` at the beginning';
136              
137 7 50       21 if ($self->{class}->can('_get_primary_key')) {
138 7         121 my $pk = $self->{class}->_get_primary_key;
139 7 100       13 push @fields, $pk if ! grep { $_ eq $pk } @fields;
  9         35  
140             }
141              
142 7         117 my $table_name = $self->{class}->_get_table_name;
143 7 100       109 my $mixins = $self->{class}->can('_get_mixins') ? $self->{class}->_get_mixins : undef;
144              
145             my @filtered_prep_select_fields =
146 7         10 grep { $_ ne qq/"$table_name".*/ } @{ $self->{prep_select_fields} };
  7         18  
  7         14  
147 7         15 for my $fld (@fields) {
148 10 100 100     32 if ($mixins && grep { $_ eq $fld } keys %$mixins) {
  8         25  
149 1         4 my $mixin = $mixins->{$fld}->($self->{class});
150 1 50       6 $mixin .= qq/ AS $fld/ unless $mixin =~ /as\s+\w+$/i;
151 1         3 push @filtered_prep_select_fields, $mixin;
152             }
153             else {
154 9         27 push @filtered_prep_select_fields, qq/"$table_name"."$fld"/;
155             }
156             }
157              
158 7         12 $self->{prep_select_fields} = \@filtered_prep_select_fields;
159              
160 7         22 return $self;
161             }
162              
163             # alias to only:
164 1     1 1 3 sub fields { shift->only(@_) }
165              
166             sub order_by {
167 20     20 1 44 my ($self, @param) = @_;
168              
169             #return if not defined $self->{SQL}; ### TODO: die
170 20   100     80 $self->{prep_order_by} ||= [];
171 20         27 push @{$self->{prep_order_by}}, map qq/"$_"/, @param;
  20         72  
172 20         30 delete $self->{prep_asc_desc};
173              
174 20         48 return $self;
175             }
176              
177             sub desc {
178 7     7 1 18 return shift->_order_by_direction('DESC');
179             }
180              
181             sub asc {
182 2     2 1 4 return shift->_order_by_direction('ASC');
183             }
184              
185             sub group_by {
186 3     3 1 7 my ($self, @param) = @_;
187              
188 3   50     12 $self->{prep_group_by} ||= [];
189 3         6 push @{$self->{prep_group_by}}, map qq/"$_"/, @param;
  3         11  
190 3         29 return $self;
191             }
192              
193             sub limit {
194 12     12 1 17 my ($self, $limit) = @_;
195              
196             #return if not defined $self->{SQL};
197 12 50       25 return $self if exists $self->{prep_limit};
198              
199 12         22 $self->{prep_limit} = $limit; ### TODO: move $limit to $self->{BIND}
200              
201 12         23 return $self;
202             }
203              
204             sub offset {
205 3     3 1 6 my ($self, $offset) = @_;
206              
207             #return if not defined $self->{SQL};
208 3 50       9 return $self if exists $self->{prep_offset};
209              
210 3         4 $self->{prep_offset} = $offset; ### TODO: move $offset to $self->{BIND}
211              
212 3         9 return $self;
213             }
214              
215             sub fetch {
216 78     78 1 138 my ($self, $param) = @_;
217              
218 78         105 my ($read_only, $limit);
219 78 50       135 if (ref $param eq 'HASH') {
220 0         0 $limit = $param->{limit};
221 0         0 $read_only = $param->{read_only};
222             }
223             else {
224 78         93 $limit = $param;
225             }
226              
227 78 50       152 return $self->_get_slice($limit) if $self->{_objects};
228              
229 78         172 $self->_finish_sql_stmt();
230 78         170 $self->_quote_sql_stmt();
231              
232 78         110 my $class = $self->{class};
233 78 50       149 my $sth = $self->dbh->prepare($self->{SQL}) or croak $self->dbh->errstr;
234              
235 78 50       4239 $sth->execute(@{ $self->{BIND} }) or croak $self->dbh->errstr;
  78         1354  
236 78 100       212 if (wantarray) {
237 29         41 my @objects;
238 29         39 my $i = 0;
239 29         504 while (my $object_data = $sth->fetchrow_hashref()) {
240 80         132 $i++;
241 80         190 my $obj = $class->new($object_data);
242 80         191 $self->_finish_object_representation($obj, $object_data, $read_only);
243 80         105 push @objects, $obj;
244              
245 80 50 33     974 last if $limit && $i == $limit;
246             }
247 29         76 delete $self->{has_joined_table};
248              
249 29         345 return @objects;
250             }
251             else {
252 49 50       624 my $object_data = $sth->fetchrow_hashref() or return;
253 49         233 my $obj = $class->new($object_data);
254 49         129 $self->_finish_object_representation($obj, $object_data, $read_only);
255 49         72 delete $self->{has_joined_table};
256              
257 49         538 return $obj;
258             }
259             }
260              
261             sub upload {
262 1     1 0 6 my ($self, $param) = @_;
263              
264 1         3 my $o = $self->fetch($param);
265 1         2 $_[0] = $o;
266              
267 1         6 return $_[0];
268             }
269              
270             sub next {
271 7     7 1 1766 my ($self, $n) = @_;
272              
273 7   100     23 $n ||= 1;
274              
275 7         10 $self->{prep_limit} = $n;
276 7 100       15 $self->{prep_offset} = 0 unless defined $self->{prep_offset};
277 7         15 my @result = $self->fetch;
278              
279 7         14 $self->{prep_offset} += $n;
280              
281 7 100       21 return wantarray ? @result : $result[0];
282             }
283              
284             sub with {
285 0     0 1 0 my ($self, @rels) = @_;
286              
287 0 0       0 return $self if exists $self->{prep_left_joins};
288 0 0       0 return $self unless @rels;
289              
290 0 0       0 $self->{class}->can('_get_relations')
291             or die "Class doesn't have any relations";
292              
293 0         0 my $table_name = $self->{class}->_get_table_name;
294              
295 0         0 $self->{prep_left_joins} = [];
296 0         0 $self->{with} = \@rels;
297              
298             RELATION:
299 0         0 for my $rel_name (@rels) {
300 0 0       0 my $relation = $self->{class}->_get_relations->{$rel_name}
301             or next RELATION;
302              
303 0 0       0 next RELATION unless grep { $_ eq $relation->{type} } qw/one only/;
  0         0  
304 0         0 my $rel_table_name = $relation->{class}->_get_table_name;
305 0         0 my $rel_columns = $relation->{class}->_get_columns;
306              
307             REL_COLUMN:
308 0         0 for (@$rel_columns) {
309 0 0       0 next REL_COLUMN if ref $_;
310 0         0 push @{ $self->{prep_select_fields} }, qq/"$rel_table_name"."$_" AS "JOINED_$rel_name\_$_"/;
  0         0  
311             }
312              
313 0 0       0 if ($relation->{type} eq 'one') {
314 0         0 my $join_sql = qq/LEFT JOIN "$rel_table_name" ON /;
315 0         0 $join_sql .= qq/"$rel_table_name"."$relation->{params}{pk}"/;
316 0         0 $join_sql .= qq/ = "$table_name"."$relation->{params}{fk}"/;
317              
318 0         0 push @{ $self->{prep_left_joins} }, $join_sql;
  0         0  
319             }
320             }
321              
322 0         0 return $self;
323             }
324              
325 0     0 1 0 sub left_join { shift->with(@_) }
326              
327             sub to_sql {
328 0     0 1 0 my ($self) = @_;
329              
330 0         0 $self->_finish_sql_stmt();
331 0         0 $self->_quote_sql_stmt();
332              
333 0 0       0 return wantarray ? ($self->{SQL}, $self->{BIND}) : $self->{SQL};
334             }
335              
336             sub exists {
337 7     7 1 15 my ($self) = @_;
338              
339 7         16 $self->{prep_select_fields} = ['1'];
340 7         17 $self->_finish_sql_stmt;
341 7         17 $self->_quote_sql_stmt;
342              
343 7         16 my $sth = $self->dbh->prepare($self->{SQL});
344 7         411 $sth->execute(@{ $self->{BIND} });
  7         99  
345              
346 7         102 return $sth->fetchrow_arrayref();
347             }
348              
349              
350             ### Private
351              
352             sub _find_many_to_many {
353 14     14   25 my ($self_class, $class, $param) = @_;
354              
355 14 50 33     30 return unless $self_class->dbh && $class && $param;
      33        
356              
357 14         19 my $mc_fkey;
358 14         24 my $class_opts = {};
359 14         18 my $root_class_opts = {};
360              
361 14 50       26 if ($param->{m_class}) {
362             #eval { load $param->{m_class} };
363             #if (!is_loaded $param->{m_class}) {
364             # load $param->{m_class};
365             # mark_as_loaded
366             #}
367 0         0 load_module $param->{m_class};
368              
369              
370 0         0 for my $opts ( values %{ $param->{m_class}->_get_relations } ) {
  0         0  
371 0 0       0 if ($opts->{class} eq $param->{root_class}) {
    0          
372 0         0 $root_class_opts = $opts;
373             }
374             elsif ($opts->{class} eq $class) {
375 0         0 $class_opts = $opts;
376             }
377             }
378              
379 0         0 my $self = $self_class->new($class, @{ $param->{where_statement} });
  0         0  
380              
381 0         0 my $connected_table_name = $class->_get_table_name;
382 0         0 $self->{prep_select_from} = [ $param->{m_class}->_get_table_name ];
383              
384 0         0 push @{ $self->{prep_left_joins} },
385             'JOIN ' . $connected_table_name . ' ON ' . $connected_table_name . '.' . $class->_get_primary_key . ' = '
386 0         0 . $param->{m_class}->_get_table_name . '.' . $class_opts->{params}{fk};
387              
388 0         0 push @{ $self->{prep_select_where} },
389 0         0 $root_class_opts->{params}{fk} . ' = ' . $param->{self}->{ $param->{root_class}->_get_primary_key };
390              
391 0         0 return $self;
392             }
393             else {
394 14         21 my $self = $self_class->new($class, @{ $param->{where_statement} });
  14         44  
395              
396 14         246 my $connected_table_name = $class->_get_table_name;
397 14         35 $self->{prep_select_from} = [ $param->{via_table} ];
398 14         33 my $fk = ActiveRecord::Simple::Utils::class_to_table_name($class);
399 14         24 $fk .= '_id';
400              
401 14         236 push @{ $self->{prep_left_joins} },
402             'JOIN ' . $connected_table_name . ' ON ' . $connected_table_name . '.' . $class->_get_primary_key . ' = '
403 14         17 . $param->{via_table} . '.' . $fk;
404              
405 14         29 my $fk2 = ActiveRecord::Simple::Utils::class_to_table_name($param->{root_class}) . '_id';
406              
407 14         226 push @{ $self->{prep_select_where} },
408 14         17 $fk2 . ' = ' . $param->{self}->{ $param->{root_class}->_get_primary_key };
409              
410 14         65 return $self;
411             }
412              
413             }
414              
415             sub _get_slice {
416 0     0   0 my ($self, $time) = @_;
417              
418             return unless $self->{_objects}
419             && ref $self->{_objects} eq 'ARRAY'
420 0 0 0     0 && scalar @{ $self->{_objects} } > 0;
  0   0     0  
421              
422 0 0       0 if (wantarray) {
423 0   0     0 $time ||= scalar @{ $self->{_objects} };
  0         0  
424 0         0 return splice @{ $self->{_objects} }, 0, $time;
  0         0  
425             }
426             else {
427 0         0 return shift @{ $self->{_objects} };
  0         0  
428             }
429             }
430              
431             sub _quote_sql_stmt {
432 85     85   116 my ($self) = @_;
433              
434 85 50 33     271 return unless $self->{SQL} && $self->dbh;
435              
436 85         204 my $driver_name = $self->dbh->{Driver}{Name};
437 85   50     245 $driver_name //= 'Pg';
438 85         237 my $quotes_map = {
439             Pg => q/"/,
440             mysql => q/`/,
441             SQLite => q/`/,
442             };
443 85         134 my $quote = $quotes_map->{$driver_name};
444              
445 85         399 $self->{SQL} =~ s/"/$quote/g;
446              
447 85         202 return $self;
448             }
449              
450             sub _finish_object_representation {
451 129     129   211 my ($self, $obj, $object_data, $read_only) = @_;
452              
453 129 100       244 if ($self->{has_joined_table}) {
454             RELATION:
455 27         64 for my $rel_name (@{ $self->{with} }) {
  27         71  
456 0 0       0 my $relation = $self->{class}->_get_relations->{$rel_name} or next RELATION;
457 0         0 my %pairs = map { $_, $object_data->{$_} } grep { $_ =~ /^JOINED\_$rel_name\_/ } keys %$object_data;
  0         0  
  0         0  
458 0 0       0 next RELATION unless %pairs;
459              
460 0         0 for my $key (keys %pairs) {
461 0         0 my $val = delete $pairs{$key};
462 0         0 $key =~ s/^JOINED\_$rel_name\_//;
463 0         0 $pairs{$key} = $val;
464             }
465 0         0 $obj->{"relation_instance_$rel_name"} = $relation->{class}->new(\%pairs);
466              
467 0         0 $obj->_delete_keys(qr/^JOINED\_$rel_name/);
468             }
469              
470             }
471              
472 129 50       205 $obj->{read_only} = 1 if defined $read_only;
473 129         196 $obj->{isin_database} = 1;
474              
475 129         164 return $obj;
476             }
477              
478             sub _finish_sql_stmt {
479 85     85   119 my ($self) = @_;
480              
481 85 50       171 ref $self->{prep_select_fields} or croak 'Invalid prepare SQL statement';
482 85 50       141 ref $self->{prep_select_from} or croak 'Invalid prepare SQL statement';
483              
484 85         1521 my $table_name = $self->{class}->_get_table_name;
485 85 100       108 my @add = grep { $_ !~~ $self->{prep_select_fields} } map qq/"$table_name".$_/, @{ $self->{prep_group_by}||[] };
  4         58  
  85         300  
486 85         124 push @{ $self->{prep_select_fields} }, @add;
  85         135  
487              
488 85         100 $self->{SQL} = "SELECT " . (join q/, /, @{ $self->{prep_select_fields} }) . "\n";
  85         244  
489 85         116 $self->{SQL} .= "FROM " . (join q/, /, @{ $self->{prep_select_from} }) . "\n";
  85         185  
490              
491 85 100       195 if (defined $self->{prep_left_joins}) {
492 14         20 $self->{SQL} .= "$_\n" for @{ $self->{prep_left_joins} };
  14         39  
493 14         29 $self->{has_joined_table} = 1;
494             }
495              
496 85 50       100 if (@{ $self->{prep_select_where}||[] }) {
  85 100       204  
497 58         85 $self->{SQL} .= "WHERE\n";
498 58         73 $self->{SQL} .= join " AND ", @{ $self->{prep_select_where} };
  58         108  
499             }
500              
501 85 100       104 if (@{ $self->{prep_group_by}||[] }) {
  85 100       270  
502 3         3 $self->{SQL} .= ' GROUP BY ';
503 3         4 $self->{SQL} .= join q/, /, @{ $self->{prep_group_by} };
  3         7  
504             }
505              
506 85 100       106 if (@{ $self->{prep_order_by}||[] }) {
  85 100       218  
507 21         37 $self->{SQL} .= ' ORDER BY ';
508 21         28 $self->{SQL} .= join q/, /, @{ $self->{prep_order_by} };
  21         31  
509             }
510              
511 85   66     258 $self->{SQL} .= ' LIMIT ' . ($self->{prep_limit} // $MAXIMUM_LIMIT);
512 85   100     229 $self->{SQL} .= ' OFFSET '. ($self->{prep_offset} // 0);
513              
514 85         136 return $self;
515             }
516              
517             sub _parse_hash {
518 23     23   40 my ($self, $param_hash) = @_;
519 23         67 my $class = $self->{class};
520 23 50       441 my $table_name = ($self->{class}->can('_get_table_name')) ? $self->{class}->_get_table_name : undef;
521 23         47 my ($bind, $condition_pairs) = ([],[]);
522 23         33 for my $param_name (keys %{ $param_hash }) {
  23         92  
523 23 50 33     111 if (ref $param_hash->{$param_name} eq 'ARRAY' and !ref $param_hash->{$param_name}[0]) {
    100          
524 0         0 my $instr = join q/, /, map { '?' } @{ $param_hash->{$param_name} };
  0         0  
  0         0  
525 0         0 push @$condition_pairs, qq/"$table_name"."$param_name" IN ($instr)/;
526 0         0 push @$bind, @{ $param_hash->{$param_name} };
  0         0  
527             }
528             elsif (ref $param_hash->{$param_name}) {
529 2 50       8 next if !$class->can('_get_relations');
530 2 50       32 my $relation = $class->_get_relations->{$param_name} or next;
531              
532 2 50       6 next if $relation->{type} ne 'one';
533 2         3 my $fk = $relation->{params}{fk};
534 2         3 my $pk = $relation->{params}{pk};
535              
536 2 50       6 if (ref $param_hash->{$param_name} eq __PACKAGE__) {
537 0         0 my $object = $param_hash->{$param_name};
538              
539 0         0 my $tmp_table = qq/tmp_table_/ . sprintf("%x", $object);
540 0         0 my $request_table = $object->{class}->_get_table_name;
541              
542 0         0 $object->{prep_select_fields} = [qq/"$request_table"."$pk"/];
543 0         0 $object->_finish_sql_stmt;
544              
545 0         0 push @$condition_pairs, qq/"$table_name"."$fk" IN (SELECT "$tmp_table"."$pk" from ($object->{SQL}) as $tmp_table)/;
546 0 0       0 push @$bind, @{ $object->{BIND} } if ref $object->{BIND} eq 'ARRAY';
  0         0  
547             }
548             else {
549 2         2 my $object = $param_hash->{$param_name};
550              
551 2 50       6 if (ref $object eq 'ARRAY') {
552 0         0 push @$bind, map $_->$pk, @$object;
553 0         0 push @$condition_pairs, qq/"$table_name"."$fk" IN (@{[ join ', ', map "?", @$object ]})/;
  0         0  
554             }
555             else {
556 2         6 push @$condition_pairs, qq/"$table_name"."$fk" = ?/;
557 2         32 push @$bind, $object->$pk;
558             }
559             }
560             }
561             else {
562 21 50       39 if (defined $param_hash->{$param_name}) {
563 21         59 push @$condition_pairs, qq/"$table_name"."$param_name" = ?/;
564 21         41 push @$bind, $param_hash->{$param_name};
565             }
566             else {
567             # is NULL
568 0         0 push @$condition_pairs, qq/"$table_name"."$param_name" IS NULL/;
569             }
570             }
571             }
572 23         55 return ($bind, $condition_pairs);
573             }
574              
575             sub _order_by_direction {
576 9     9   15 my ($self, $direction) = @_;
577              
578             # There are no fields for order yet
579 9 50 33     26 return unless ref $self->{prep_order_by} eq 'ARRAY' and scalar @{ $self->{prep_order_by} } > 0;
  9         23  
580              
581             # asc/desc is called before: ->asc->desc
582 9 50       19 return if defined $self->{prep_asc_desc};
583              
584             # $direction should be ASC/DESC
585 9 50       33 return unless $direction =~ /^(ASC|DESC)$/i;
586              
587             # Add $direction to the latest field
588 9         14 @{$self->{prep_order_by}}[-1] .= " $direction";
  9         21  
589 9         15 $self->{prep_asc_desc} = 1;
590              
591 9         21 return $self;
592             }
593              
594       0     sub DESTROY { }
595              
596             sub AUTOLOAD {
597 0     0     my $call = $AUTOLOAD;
598 0           my $self = shift;
599 0           my $class = ref $self;
600              
601 0           $call =~ s/.*:://;
602 0           my $error = "Can't call method `$call` on class $class.\nPerhaps you have forgotten to fetch your object?";
603              
604 0           croak $error;
605             }
606              
607             1;
608              
609             __END__;