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   136 use strict;
  27         43  
  27         1178  
4 27     27   127 use warnings;
  27         42  
  27         824  
5 27     27   121 use namespace::autoclean;
  27         42  
  27         224  
6              
7             our $VERSION = '0.42';
8              
9 27     27   2295 use Fey::Exceptions qw( param_error );
  27         45  
  27         1527  
10 27     27   172 use Fey::Literal;
  27         40  
  27         551  
11 27     27   8946 use Fey::Role::ColumnLike;
  27         1279  
  27         1300  
12 27     27   12775 use Fey::SQL::Fragment::Join;
  27         83  
  27         1177  
13             use Fey::Types
14 27     27   197 qw( ArrayRef Bool HashRef CanQuote GroupByElement SelectElement );
  27         36  
  27         168  
15 27     27   292963 use List::AllUtils qw( all );
  27         59  
  27         1667  
16 27     27   129 use Scalar::Util qw( blessed );
  27         41  
  27         1296  
17              
18 27     27   123 use Moose 0.90;
  27         706  
  27         209  
19 27     27   142096 use MooseX::Params::Validate 0.08 qw( pos_validated_list );
  27         652  
  27         206  
20 27     27   5034 use MooseX::SemiAffordanceAccessor 0.03;
  27         435  
  27         171  
21 27     27   81354 use MooseX::StrictConstructor 0.07;
  27         581  
  27         173  
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 5034 my $self = shift;
111              
112 92 50       265 my $count = @_ ? @_ : 1;
113 92         380 my (@select) = pos_validated_list(
114             \@_,
115             ( ( { isa => SelectElement } ) x $count ),
116             MX_PARAMS_VALIDATE_NO_CACHE => 1,
117             );
118              
119 92         1994 for my $elt (@select) {
120 95 100       2594 $self->_add_select_element(
121             blessed $elt ? $elt : Fey::Literal->new_from_scalar($elt) );
122             }
123              
124 92         401 return $self;
125             }
126              
127             sub distinct {
128 1 50   1 1 34 die 'Cannot call ->distinct and ->distinct_on'
129             if $_[0]->_has_is_distinct_on();
130              
131 1         27 $_[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 10082 my $self = shift;
149              
150             # $t1, 'LEFT', $t2, ...
151 117   100     469 my $is_outer_join = @_ >= 3 && !blessed $_[1];
152              
153 117   100     351 my $is_inner_join = @_ >= 2 && !$is_outer_join;
154              
155             # gee, wouldn't multimethods be nice here?
156              
157             #<<<
158 117 100 100     2358 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       4070 param_error "from() called with invalid parameters (@_)."
204             unless $meth;
205              
206 112         382 $self->$meth(@_);
207              
208 103         309 return $self;
209             }
210              
211             sub _from_one_table {
212 65     65   77 my $self = shift;
213              
214 65         1807 my $join = Fey::SQL::Fragment::Join->new( table1 => $_[0] );
215 65         208 $self->_set_from( $join->id() => $join );
216             }
217              
218             sub _from_subselect {
219 6     6   12 my $self = shift;
220              
221 6         12 my $subsel = $_[0];
222 6         26 $self->_set_from( $subsel->id() => $subsel );
223             }
224              
225             sub _join {
226 25     25   35 my $self = shift;
227              
228 25         87 _check_join_arguments(@_);
229              
230 21   66     167 my $fk = $_[2] || $self->_fk_for_join(@_);
231              
232 19         579 my $join = Fey::SQL::Fragment::Join->new(
233             table1 => $_[0],
234             table2 => $_[1],
235             fk => $fk,
236             );
237 19         76 $self->_set_from( $join->id() => $join );
238             }
239              
240             sub _join_with_where {
241 2     2   5 my $self = shift;
242              
243 2         7 _check_join_arguments(@_);
244              
245 2         9 my $where = pop;
246 2 100       10 my $fk = @_ == 3 ? pop : $self->_fk_for_join(@_);
247              
248 2         61 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   534 all { blessed $_ && $_->can('is_joinable') && $_->is_joinable() }
262 27 100   27   288 @_[ 0, 1 ];
263             }
264              
265             sub _fk_for_join {
266 29     29   66 my $self = shift;
267 29         59 my @tables = @_;
268              
269 29         630 my $s = $tables[0]->schema;
270 29         139 my @fk = $s->foreign_keys_between_tables(@tables);
271              
272 29 100       102 unless ( @fk == 1 ) {
273 2         5 my $names = join ' and ', sort map { $_->name() } @tables;
  4         74  
274              
275 2 100       12 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         124 return $fk[0];
285             }
286              
287             sub _outer_join {
288 11     11   20 my $self = shift;
289              
290 11         39 _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         17 my $fk = $_[3];
299 8 100       38 $fk = $self->_fk_for_join( @_[ 0, 2 ] )
300             unless $fk;
301              
302 8         278 my $join = Fey::SQL::Fragment::Join->new(
303             table1 => $_[0],
304             table2 => $_[2],
305             fk => $fk,
306             outer_type => lc $_[1],
307             );
308 8         37 $self->_set_from( $join->id() => $join );
309             }
310              
311             sub _outer_join_with_where {
312 3     3   6 my $self = shift;
313              
314 3         11 _check_outer_join_arguments(@_);
315              
316 3         6 my $fk;
317 3 100       34 $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         103 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   110 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     141 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 195 my $self = shift;
345              
346 7 100       16 my $count = @_ ? @_ : 1;
347 7         26 my (@by) = pos_validated_list(
348             \@_,
349             ( ( { isa => GroupByElement } ) x $count ),
350             MX_PARAMS_VALIDATE_NO_CACHE => 1,
351             );
352              
353 5         266 $self->_add_group_by_elements(@by);
354              
355 5         13 return $self;
356             }
357              
358             sub having {
359 27     27 1 2076 my $self = shift;
360              
361 27         75 $self->_condition( 'having', @_ );
362              
363 23         44 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 122 my $self = shift;
372 77         294 my ($dbh) = pos_validated_list( \@_, { isa => CanQuote } );
373              
374             return (
375 77         2733 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 853 my $self = shift;
388 87         86 my $dbh = shift;
389              
390 87         109 my $sql = 'SELECT ';
391              
392 87 100       2372 if ( $self->is_distinct() ) {
    50          
393 1         2 $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       1122 join ', ',
402             map {
403 87         2756 $_->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         1890 return $sql;
410             }
411              
412             sub from_clause {
413 102     102 1 306 my $self = shift;
414 102         116 my $dbh = shift;
415              
416 102         133 my @from;
417              
418             my %seen;
419              
420             # We lower case the test for correctly skipping already-seen tables.
421 102         3110 for my $frag (
  15         352  
422             $self->_get_from( sort { lc($a) cmp lc($b) } $self->_from_ids() ) ) {
423 115         464 my $join_sql = $frag->sql_with_alias( $dbh, \%seen );
424              
425             # the fragment could be a Fey::SQL::Select itself
426 115 100       4612 my @tables = $frag->can('tables') ? $frag->tables() : ();
427              
428 115         2245 $seen{ $_->id() } = 1 for @tables;
429              
430 115 100       327 next unless length $join_sql;
431              
432 113         254 push @from, $join_sql;
433             }
434              
435 102         165 my $sql = 'FROM ';
436              
437             # This is a sort of manual join() call special-cased to add a
438             # comma as needed.
439 102         299 for ( my $i = 0; $i < @from; $i++ ) {
440 113         179 $sql .= $from[$i];
441              
442 113 50 100     1066 if ( $sql =~ /\)^/ ) {
    100          
    100          
443 0         0 $sql .= q{ };
444             }
445             elsif ( ( $from[ $i + 1 ] || '' ) =~ /^[\w\s]*JOIN/ ) {
446 8         25 $sql .= q{ };
447             }
448             elsif ( $from[ $i + 1 ] ) {
449 3         8 $sql .= q{, };
450             }
451             }
452              
453 102         580 return $sql;
454             }
455              
456             sub group_by_clause {
457 82     82 1 106 my $self = shift;
458 82         107 my $dbh = shift;
459              
460 82 100       2730 return unless $self->_has_group_by_elements();
461              
462             return (
463 6         74 'GROUP BY '
464             . (
465             join ', ',
466 5         138 map { $_->sql_or_alias($dbh) } $self->_group_by()
467             )
468             );
469             }
470              
471             sub having_clause {
472 94     94 1 124 my $self = shift;
473 94         89 my $dbh = shift;
474              
475 94 100       2910 return unless $self->_has_having_elements();
476              
477             return (
478 23         64 'HAVING '
479             . (
480             join ' ',
481 17         510 map { $_->sql($dbh) } $self->_having()
482             )
483             );
484             }
485              
486             sub bind_params {
487 29     29 1 45 my $self = shift;
488              
489             return (
490             (
491 1         3 map { $_->bind_params() }
  16         424  
492 18         48 grep { $_->can('bind_params') }
493             $self->select_clause_elements()
494             ),
495              
496             (
497 18         66 map { $_->bind_params() }
498 18         510 grep { $_->can('bind_params') }
499 3         6 map { $self->_get_from($_) }
500             sort $self->_from_ids()
501             ),
502              
503             $self->_where_clause_bind_params(),
504              
505             (
506 3         11 map { $_->bind_params() }
507 29         1003 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.42
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