File Coverage

blib/lib/Fey/SQL/Select.pm
Criterion Covered Total %
statement 158 163 96.9
branch 66 72 91.6
condition 46 53 86.7
subroutine 36 37 97.3
pod 13 13 100.0
total 319 338 94.3


line stmt bran cond sub pod time code
1             package Fey::SQL::Select;
2              
3 27     27   141 use strict;
  27         47  
  27         1256  
4 27     27   143 use warnings;
  27         45  
  27         905  
5 27     27   130 use namespace::autoclean;
  27         42  
  27         236  
6              
7             our $VERSION = '0.43';
8              
9 27     27   2501 use Fey::Exceptions qw( param_error );
  27         49  
  27         1679  
10 27     27   135 use Fey::Literal;
  27         41  
  27         489  
11 27     27   9059 use Fey::Role::ColumnLike;
  27         1868  
  27         1607  
12 27     27   14473 use Fey::SQL::Fragment::Join;
  27         99  
  27         1410  
13             use Fey::Types
14 27     27   239 qw( ArrayRef Bool HashRef CanQuote GroupByElement SelectElement );
  27         40  
  27         191  
15 27     27   329948 use List::AllUtils qw( all );
  27         62  
  27         1857  
16 27     27   152 use Scalar::Util qw( blessed );
  27         48  
  27         1478  
17              
18 27     27   133 use Moose 2.1200;
  27         820  
  27         247  
19 27     27   175987 use MooseX::Params::Validate 0.21 qw( pos_validated_list );
  27         830  
  27         198  
20 27     27   5739 use MooseX::SemiAffordanceAccessor 0.03;
  27         525  
  27         187  
21 27     27   92893 use MooseX::StrictConstructor 0.13;
  27         620  
  27         181  
22              
23             with 'Fey::Role::Comparable',
24             'Fey::Role::Selectable',
25             'Fey::Role::SQL::HasOrderByClause',
26             'Fey::Role::SQL::HasLimitClause',
27             'Fey::Role::SQL::ReturnsData';
28              
29             with 'Fey::Role::SQL::HasWhereClause' => {
30             -excludes => 'bind_params',
31             -alias => { bind_params => '_where_clause_bind_params' },
32             };
33              
34             with 'Fey::Role::SQL::HasBindParams' => { -excludes => 'bind_params' };
35              
36             with 'Fey::Role::HasAliasName' => {
37             generated_alias_prefix => 'SUBSELECT',
38             sql_needs_parens => 1,
39             };
40              
41             has '_select' => (
42             traits => ['Array'],
43             is => 'bare',
44             isa => ArrayRef,
45             default => sub { [] },
46             handles => {
47             _add_select_element => 'push',
48             select_clause_elements => 'elements',
49             },
50             init_arg => undef,
51             );
52              
53             has 'is_distinct' => (
54             is => 'rw',
55             isa => Bool,
56             default => 0,
57             writer => '_set_is_distinct',
58             );
59              
60             has 'is_distinct_on' => (
61             is => 'rw',
62             does => 'Fey::Role::ColumnLike',
63             writer => '_set_is_distinct_on',
64             predicate => '_has_is_distinct_on',
65             );
66              
67             has '_from' => (
68             traits => ['Hash'],
69             is => 'bare',
70             isa => HashRef,
71             default => sub { {} },
72             handles => {
73             _get_from => 'get',
74             _set_from => 'set',
75             _from_ids => 'keys',
76             },
77             init_arg => undef,
78             );
79              
80             has '_group_by' => (
81             traits => ['Array'],
82             is => 'bare',
83             isa => ArrayRef,
84             default => sub { [] },
85             handles => {
86             _add_group_by_elements => 'push',
87             _has_group_by_elements => 'count',
88             _group_by => 'elements',
89             },
90             init_arg => undef,
91             );
92              
93             has '_having' => (
94             traits => ['Array'],
95             is => 'bare',
96             isa => ArrayRef,
97             default => sub { [] },
98             handles => {
99             _add_having_element => 'push',
100             _has_having_elements => 'count',
101             _last_having_element => [ 'get', -1 ],
102             _having => 'elements',
103             },
104             init_arg => undef,
105             );
106              
107             with 'Fey::Role::SQL::Cloneable';
108              
109             sub select {
110 92     92 1 5428 my $self = shift;
111              
112 92 50       276 my $count = @_ ? @_ : 1;
113 92         434 my (@select) = pos_validated_list(
114             \@_,
115             ( ( { isa => SelectElement } ) x $count ),
116             MX_PARAMS_VALIDATE_NO_CACHE => 1,
117             );
118              
119 92         2127 for my $elt (@select) {
120 95 100       2348 $self->_add_select_element(
121             blessed $elt ? $elt : Fey::Literal->new_from_scalar($elt) );
122             }
123              
124 92         436 return $self;
125             }
126              
127             sub distinct {
128 1 50   1 1 29 die 'Cannot call ->distinct and ->distinct_on'
129             if $_[0]->_has_is_distinct_on();
130              
131 1         33 $_[0]->_set_is_distinct(1);
132              
133 1         2 return $_[0];
134             }
135              
136             sub distinct_on {
137 0 0   0 1 0 die 'Cannot call ->distinct and ->distinct_on'
138             if $_[0]->is_distinct();
139              
140 0         0 $_[0]->_set_is_distinct_on( $_[1] );
141              
142 0         0 return $_[0];
143             }
144              
145             # XXX - need to handle subselect as if it were a table rather than as
146             # a special case
147             sub from {
148 117     117 1 10418 my $self = shift;
149              
150             # $t1, 'LEFT', $t2, ...
151 117   100     445 my $is_outer_join = @_ >= 3 && !blessed $_[1];
152              
153 117   100     397 my $is_inner_join = @_ >= 2 && !$is_outer_join;
154              
155             # gee, wouldn't multimethods be nice here?
156              
157             #<<<
158 117 100 100     2348 my $meth = (
    100 100        
    100 66        
    100 100        
    100 66        
    100 66        
    100 100        
    100 100        
    100 100        
    100 100        
159             @_ == 1
160             && blessed $_[0]
161             && $_[0]->can('is_joinable')
162             && $_[0]->is_joinable()
163             ? '_from_one_table'
164              
165             : @_ == 1
166             && blessed $_[0]
167             && $_[0]->can('does')
168             && $_[0]->does('Fey::Role::SQL::ReturnsData')
169             ? '_from_subselect'
170              
171             : $is_inner_join
172             && @_ == 4 && $_[3]->isa('Fey::SQL::Where')
173             ? '_join_with_where'
174              
175             : $is_inner_join
176             && @_ == 3 && $_[2]->isa('Fey::SQL::Where')
177             ? '_join_with_where'
178              
179             : $is_inner_join && @_ == 3 && $_[2]->isa('Fey::FK')
180             ? '_join'
181              
182             : $is_inner_join && @_ == 2
183             ? '_join'
184              
185             : $is_outer_join && @_ == 5
186             ? '_outer_join_with_where'
187              
188             : $is_outer_join
189             && @_ == 4
190             && $_[3]->isa('Fey::SQL::Where')
191             ? '_outer_join_with_where'
192              
193             : $is_outer_join && @_ == 4 && $_[3]->isa('Fey::FK')
194             ? '_outer_join'
195              
196             : $is_outer_join && @_ == 3
197             ? '_outer_join'
198              
199             : undef
200             );
201             #>>>
202              
203 117 100       4296 param_error "from() called with invalid parameters (@_)."
204             unless $meth;
205              
206 112         384 $self->$meth(@_);
207              
208 103         314 return $self;
209             }
210              
211             sub _from_one_table {
212 65     65   84 my $self = shift;
213              
214 65         1890 my $join = Fey::SQL::Fragment::Join->new( table1 => $_[0] );
215 65         232 $self->_set_from( $join->id() => $join );
216             }
217              
218             sub _from_subselect {
219 6     6   13 my $self = shift;
220              
221 6         10 my $subsel = $_[0];
222 6         26 $self->_set_from( $subsel->id() => $subsel );
223             }
224              
225             sub _join {
226 25     25   28 my $self = shift;
227              
228 25         65 _check_join_arguments(@_);
229              
230 21   66     142 my $fk = $_[2] || $self->_fk_for_join(@_);
231              
232 19         553 my $join = Fey::SQL::Fragment::Join->new(
233             table1 => $_[0],
234             table2 => $_[1],
235             fk => $fk,
236             );
237 19         66 $self->_set_from( $join->id() => $join );
238             }
239              
240             sub _join_with_where {
241 2     2   4 my $self = shift;
242              
243 2         5 _check_join_arguments(@_);
244              
245 2         8 my $where = pop;
246 2 100       7 my $fk = @_ == 3 ? pop : $self->_fk_for_join(@_);
247              
248 2         55 my $join = Fey::SQL::Fragment::Join->new(
249             table1 => $_[0],
250             table2 => $_[1],
251             fk => $fk,
252             where => $where,
253             );
254 2         9 $self->_set_from( $join->id() => $join );
255             }
256              
257             sub _check_join_arguments {
258             param_error
259             'the first two arguments to from() were not valid (not tables or something else joinable).'
260             unless
261 51 100 66 51   444 all { blessed $_ && $_->can('is_joinable') && $_->is_joinable() }
262 27 100   27   307 @_[ 0, 1 ];
263             }
264              
265             sub _fk_for_join {
266 29     29   42 my $self = shift;
267 29         64 my @tables = @_;
268              
269 29         622 my $s = $tables[0]->schema;
270 29         125 my @fk = $s->foreign_keys_between_tables(@tables);
271              
272 29 100       73 unless ( @fk == 1 ) {
273 2         5 my $names = join ' and ', sort map { $_->name() } @tables;
  4         74  
274              
275 2 100       11 param_error
276             "You specified a join for two tables that do not share a foreign key ($names)."
277             unless @fk;
278              
279 1         9 param_error
280             "You specified a join for two tables with more than one foreign key ($names)"
281             . ', so you must specify which foreign key to use for the join.';
282             }
283              
284 27         105 return $fk[0];
285             }
286              
287             sub _outer_join {
288 11     11   17 my $self = shift;
289              
290 11         26 _check_outer_join_arguments(@_);
291              
292             # I used to have ...
293             #
294             # $_[3] || $self->_fk_for_join( @_[0, 2] )
295             #
296             # but this ends up reducing code coverage because it's not
297             # possible (I hope) to have a situation where both are false.
298 8         14 my $fk = $_[3];
299 8 100       36 $fk = $self->_fk_for_join( @_[ 0, 2 ] )
300             unless $fk;
301              
302 8         237 my $join = Fey::SQL::Fragment::Join->new(
303             table1 => $_[0],
304             table2 => $_[2],
305             fk => $fk,
306             outer_type => lc $_[1],
307             );
308 8         30 $self->_set_from( $join->id() => $join );
309             }
310              
311             sub _outer_join_with_where {
312 3     3   6 my $self = shift;
313              
314 3         9 _check_outer_join_arguments(@_);
315              
316 3         4 my $fk;
317 3 100       74 $fk = $_[3]->isa('Fey::FK') ? $_[3] : $self->_fk_for_join( @_[ 0, 2 ] );
318              
319 3 100       11 my $where = $_[4] ? $_[4] : $_[3];
320              
321 3         108 my $join = Fey::SQL::Fragment::Join->new(
322             table1 => $_[0],
323             table2 => $_[2],
324             fk => $fk,
325             outer_type => lc $_[1],
326             where => $where,
327             );
328 3         11 $self->_set_from( $join->id() => $join );
329             }
330              
331             sub _check_outer_join_arguments {
332 14 100   14   95 param_error
333             'invalid outer join type, must be one of out left, right, or full.'
334             unless $_[1] =~ /^(?:left|right|full)$/i;
335              
336 13 100 66     106 param_error 'from() was called with invalid arguments'
      100        
      66        
337             unless $_[0]->can('is_joinable')
338             && $_[0]->is_joinable()
339             && $_[2]->can('is_joinable')
340             && $_[2]->is_joinable();
341             }
342              
343             sub group_by {
344 7     7 1 250 my $self = shift;
345              
346 7 100       18 my $count = @_ ? @_ : 1;
347 7         39 my (@by) = pos_validated_list(
348             \@_,
349             ( ( { isa => GroupByElement } ) x $count ),
350             MX_PARAMS_VALIDATE_NO_CACHE => 1,
351             );
352              
353 5         328 $self->_add_group_by_elements(@by);
354              
355 5         14 return $self;
356             }
357              
358             sub having {
359 27     27 1 1950 my $self = shift;
360              
361 27         80 $self->_condition( 'having', @_ );
362              
363 23         41 return $self;
364             }
365              
366             sub id {
367 3     3 1 13 return $_[0]->sql('Fey::FakeDBI');
368             }
369              
370             sub sql {
371 77     77 1 129 my $self = shift;
372 77         317 my ($dbh) = pos_validated_list( \@_, { isa => CanQuote } );
373              
374             return (
375 77         2881 join q{ },
376             $self->select_clause($dbh),
377             $self->from_clause($dbh),
378             $self->where_clause($dbh),
379             $self->group_by_clause($dbh),
380             $self->having_clause($dbh),
381             $self->order_by_clause($dbh),
382             $self->limit_clause($dbh),
383             );
384             }
385              
386             sub select_clause {
387 87     87 1 1003 my $self = shift;
388 87         106 my $dbh = shift;
389              
390 87         124 my $sql = 'SELECT ';
391              
392 87 100       2446 if ( $self->is_distinct() ) {
    50          
393 1         3 $sql .= 'DISTINCT ';
394             }
395             elsif ( $self->_has_is_distinct_on() ) {
396 0         0 $sql .= 'DISTINCT ON ('
397             . $self->is_distinct_on()->sql_or_alias($dbh) . ') ';
398             }
399              
400             $sql .= (
401 92 100       1156 join ', ',
402             map {
403 87         2734 $_->can('sql_for_select_clause')
404             ? $_->sql_for_select_clause($dbh)
405             : $_->sql_with_alias($dbh)
406             } $self->select_clause_elements()
407             );
408              
409 87         2104 return $sql;
410             }
411              
412             sub from_clause {
413 102     102 1 267 my $self = shift;
414 102         139 my $dbh = shift;
415              
416 102         126 my @from;
417              
418             my %seen;
419              
420             # We lower case the test for correctly skipping already-seen tables.
421 102         3287 for my $frag (
  16         327  
422             $self->_get_from( sort { lc($a) cmp lc($b) } $self->_from_ids() ) ) {
423 115         519 my $join_sql = $frag->sql_with_alias( $dbh, \%seen );
424              
425             # the fragment could be a Fey::SQL::Select itself
426 115 100       4715 my @tables = $frag->can('tables') ? $frag->tables() : ();
427              
428 115         2388 $seen{ $_->id() } = 1 for @tables;
429              
430 115 100       293 next unless length $join_sql;
431              
432 113         287 push @from, $join_sql;
433             }
434              
435 102         173 my $sql = 'FROM ';
436              
437             # This is a sort of manual join() call special-cased to add a
438             # comma as needed.
439 102         292 for ( my $i = 0; $i < @from; $i++ ) {
440 113         192 $sql .= $from[$i];
441              
442 113 50 100     1178 if ( $sql =~ /\)^/ ) {
    100          
    100          
443 0         0 $sql .= q{ };
444             }
445             elsif ( ( $from[ $i + 1 ] || '' ) =~ /^[\w\s]*JOIN/ ) {
446 8         24 $sql .= q{ };
447             }
448             elsif ( $from[ $i + 1 ] ) {
449 3         10 $sql .= q{, };
450             }
451             }
452              
453 102         582 return $sql;
454             }
455              
456             sub group_by_clause {
457 82     82 1 119 my $self = shift;
458 82         129 my $dbh = shift;
459              
460 82 100       2788 return unless $self->_has_group_by_elements();
461              
462             return (
463 6         116 'GROUP BY '
464             . (
465             join ', ',
466 5         152 map { $_->sql_or_alias($dbh) } $self->_group_by()
467             )
468             );
469             }
470              
471             sub having_clause {
472 94     94 1 157 my $self = shift;
473 94         120 my $dbh = shift;
474              
475 94 100       2916 return unless $self->_has_having_elements();
476              
477             return (
478 23         71 'HAVING '
479             . (
480             join ' ',
481 17         467 map { $_->sql($dbh) } $self->_having()
482             )
483             );
484             }
485              
486             sub bind_params {
487 29     29 1 64 my $self = shift;
488              
489             return (
490             (
491 1         4 map { $_->bind_params() }
  16         545  
492 18         74 grep { $_->can('bind_params') }
493             $self->select_clause_elements()
494             ),
495              
496             (
497 18         91 map { $_->bind_params() }
498 18         678 grep { $_->can('bind_params') }
499 3         9 map { $self->_get_from($_) }
500             sort $self->_from_ids()
501             ),
502              
503             $self->_where_clause_bind_params(),
504              
505             (
506 3         12 map { $_->bind_params() }
507 29         1218 grep { $_->can('bind_params') } $self->_having()
508             ),
509             );
510             }
511              
512             __PACKAGE__->meta()->make_immutable();
513              
514             1;
515              
516             # ABSTRACT: Represents a SELECT query
517              
518             __END__
519              
520             =pod
521              
522             =head1 NAME
523              
524             Fey::SQL::Select - Represents a SELECT query
525              
526             =head1 VERSION
527              
528             version 0.43
529              
530             =head1 SYNOPSIS
531              
532             my $sql = Fey::SQL->new_select();
533              
534             # SELECT Part.part_id, Part.part_name
535             # FROM Part JOIN MachinePart
536             # ON Part.part_id = MachinePart.part_id
537             # WHERE MachinePart.machine_id = $value
538             # ORDER BY Part.name DESC
539             # LIMIT 10
540             $sql->select( $part_id, $part_name );
541             $sql->from( $Part, $MachinePart );
542             $sql->where( $machine_id, '=', $value );
543             $sql->order_by( $part_Name, 'DESC' );
544             $sql->limit(10);
545              
546             print $sql->sql($dbh);
547              
548             =head1 DESCRIPTION
549              
550             This class represents a C<SELECT> query.
551              
552             =head1 METHODS
553              
554             This class provides the following methods:
555              
556             =head2 Constructor
557              
558             To construct an object of this class, call C<< $query->select() >> on
559             a C<Fey::SQL> object.
560              
561             =head2 $select->select(...)
562              
563             This method accepts a list of parameters, which are the things being
564             selected.
565              
566             The list can include the following types of elements:
567              
568             =over 4
569              
570             =item * plain scalars, including C<undef>
571              
572             These will be passed to C<< Fey::Literal->new_from_scalar() >>.
573              
574             =item * C<Fey::Table> objects
575              
576             If a table is passed, then all of its columns will be included in the
577             C<SELECT> clause.
578              
579             =item * C<Fey::Column> objects, and aliases
580              
581             This specifies an individual column (possibly aliased) to include in
582             the select.
583              
584             The C<< $column->is_selectable() >> method must return true for these
585             objects.
586              
587             This method can be called multiple times with different elements each
588             time.
589              
590             =item * C<Fey::Literal> objects
591              
592             Any type of literal can be included in a C<SELECT> clause.
593              
594             =back
595              
596             =head2 $select->distinct()
597              
598             If this is called, the generated SQL will start with C<SELECT DISTINCT>. You
599             cannot call both C<< $select->distinct() >> and C<< $select->distinct_on() >>
600             for the same query.
601              
602             =head2 $select->distinct_on($column)
603              
604             If this is called, the generated SQL will start with C<SELECT DISTINCT ON
605             (Table.column)>. You cannot call both C<< $select->distinct() >> and C<<
606             $select->distinct_on() >> for the same query.
607              
608             =head2 $select->from(...)
609              
610             This method specifies the C<FROM> clause of the query. It can accept a
611             variety of argument lists.
612              
613             =over 4
614              
615             =item * ($table_or_alias)
616              
617             If called with a single C<Fey::Table> or table alias object, that
618             table is included in the C<FROM> clause.
619              
620             FROM Part
621              
622             FROM Part as Part0
623              
624             =item * ($select_query)
625              
626             If called with a single C<Fey::SQL::Select> object, that object's SQL
627             will be included in the C<FROM> clause as a subselect.
628              
629             FROM (SELECT part_id FROM Part) AS SUBSELECT0
630              
631             =item * ($table1, $table2)
632              
633             If two tables (or aliases) are passed to this method, these two tables
634             are included and joined together. The foreign key between these two
635             tables will be looked up in the C<Fey::Schema> object for the
636             tables. However, if the tables do not have a foreign key between them,
637             or have more than one foreign key, an exception is thrown.
638              
639             FROM Part, MachinePart
640             ON Part.part_id = MachinePart.part_id
641              
642             =item * ($table1, $table2, $fk)
643              
644             When joining two tables, you can manually specify the foreign key
645             which should be used to join them. This is necessary when there are
646             multiple foreign keys between two tables.
647              
648             You can also use this to "fake" a foreign key between two tables which
649             don't really have one, but where it makes sense to join them
650             anyway. If this paragraph doesn't make sense, don't worry about it ;)
651              
652             =item * ($table1, $table2, $where_clause)
653              
654             =item * ($table1, $table2, $fk, $where_clause)
655              
656             If you want to specify a C<WHERE> clause as part of an inner join, include this
657             as the last argument when calling C<< $select->from() >>.
658              
659             To create a standalone C<WHERE> clause suitable for passing to this
660             method, use the C<Fey::SQL::Where> class.
661              
662             =item * ($table1, 'left', $table2)
663              
664             If you want to do an outer join between two tables, pass the two
665             tables, separated by one of the following string:
666              
667             =over 8
668              
669             =item * left
670              
671             =item * right
672              
673             =item * full
674              
675             =back
676              
677             This will generate the appropriate outer join SQL in the C<FROM>
678             clause.
679              
680             FROM Part
681             LEFT OUTER JOIN MachinePart
682             ON Part.part_id = MachinePart.part_id
683              
684             Just as with a normal join, the C<<$select->from() >> will attempt to
685             automatically find a foreign key between the two tables.
686              
687             =item * ($table1, 'left', $table2, $fk)
688              
689             Just as with a normal join, you can manually specify the foreign key
690             to use for an outer join as well.
691              
692             =item * ($table1, 'left', $table2, $where_clause)
693              
694             If you want to specify a C<WHERE> clause as part of an outer join,
695             include this as the fourth argument when calling C<< $select->from()
696             >>.
697              
698             FROM Part
699             LEFT OUTER JOIN MachinePart
700             ON Part.part_id = MachinePart.part_id
701             AND MachinePart.machine_id = ?
702              
703             To create a standalone C<WHERE> clause suitable for passing to this
704             method, use the C<Fey::SQL::Where> class.
705              
706             =item * ($table1, 'left', $table2, $fk, $where_clause)
707              
708             You can manually specify a foreign key I<and> include a where clause
709             in an outer join.
710              
711             =back
712              
713             The C<< $select->from() >> method can be called multiple times with
714             different join options. If you call the method with arguments that it
715             has already seen, then it will effectively ignore that call.
716              
717             =head2 $select->where(...)
718              
719             See the L<Fey::SQL section on WHERE Clauses|Fey::SQL/WHERE Clauses>
720             for more details.
721              
722             =head2 $select->group_by(...)
723              
724             This method accepts a list of elements. Each element can be a
725             C<Fey::Column> object, a column alias, or a literal function or term.
726              
727             =head2 $select->having(...)
728              
729             The C<< $select->having() >> method accepts exactly the same arguments
730             as the C<< $select->where() >> method.
731              
732             =head2 $select->order_by(...)
733              
734             See the L<Fey::SQL section on ORDER BY Clauses|Fey::SQL/ORDER BY
735             Clauses> for more details.
736              
737             =head2 $select->limit(...)
738              
739             See the L<Fey::SQL section on LIMIT Clauses|Fey::SQL/LIMIT Clauses>
740             for more details.
741              
742             =head2 $select->sql($dbh)
743              
744             Returns the full SQL statement which this object represents. A DBI
745             handle must be passed so that identifiers can be properly quoted.
746              
747             =head2 $select->bind_params()
748              
749             See the L<Fey::SQL section on Bind Parameters|Fey::SQL/Bind
750             Parameters> for more details.
751              
752             =head2 $select->select_clause_elements
753              
754             Returns a list of objects, one for each element in the C<SELECT>
755             clause. These can be C<Fey::Column>s, C<Fey::Column::Alias>es, or any
756             type of C<Fey::Literal>.
757              
758             These items are returned in the order in which they will be included
759             in the C<SELECT> clause.
760              
761             =head2 $select->select_clause()
762              
763             Returns the C<SELECT> clause portion of the SQL statement as a string.
764              
765             =head2 $select->from_clause()
766              
767             Returns the C<FROM> clause portion of the SQL statement as a string.
768              
769             =head2 $select->where_clause()
770              
771             Returns the C<WHERE> clause portion of the SQL statement as a string.
772              
773             =head2 $select->order_by_clause()
774              
775             Returns the C<ORDER BY> clause portion of the SQL statement as a
776             string.
777              
778             =head2 $select->group_by_clause()
779              
780             Returns the C<GROUP BY> clause portion of the SQL statement as a
781             string.
782              
783             =head2 $select->having_clause()
784              
785             Returns the C<HAVING> clause portion of the SQL statement as a string.
786              
787             =head2 $select->limit_clause()
788              
789             Returns the C<LIMIT> clause portion of the SQL statement as a string.
790              
791             =head2 $select->sql_or_alias()
792              
793             =head2 $select->sql_with_alias()
794              
795             Returns the appropriate SQL snippet. See L<Fey::Role::HasAliasName>.
796              
797             =head2 $select->id()
798              
799             Returns a unique identifier for the select.
800              
801             =head1 ROLES
802              
803             =over 4
804              
805             =item * L<Fey::Role::SQL::HasBindParams>
806              
807             =item * L<Fey::Role::SQL::HasWhereClause>
808              
809             =item * L<Fey::Role::SQL::HasOrderByClause>
810              
811             =item * L<Fey::Role::SQL::HasLimitClause>
812              
813             =item * L<Fey::Role::SQL::HasAliasName>
814              
815             =item * L<Fey::Role::SQL::Comparable>
816              
817             This role allows a C<Fey::SQL::Select> object to be used as a
818             subselect in C<WHERE> clauses.
819              
820             =item * L<Fey::Role::SQL::Cloneable>
821              
822             =back
823              
824             =head1 BUGS
825              
826             See L<Fey> for details on how to report bugs.
827              
828             =head1 AUTHOR
829              
830             Dave Rolsky <autarch@urth.org>
831              
832             =head1 COPYRIGHT AND LICENSE
833              
834             This software is Copyright (c) 2011 - 2015 by Dave Rolsky.
835              
836             This is free software, licensed under:
837              
838             The Artistic License 2.0 (GPL Compatible)
839              
840             =cut