File Coverage

blib/lib/Fey/Role/SetOperation.pm
Criterion Covered Total %
statement 41 42 97.6
branch 4 4 100.0
condition 3 3 100.0
subroutine 21 22 95.4
pod 1 4 25.0
total 70 75 93.3


line stmt bran cond sub pod time code
1             package Fey::Role::SetOperation;
2              
3 27     27   14185 use strict;
  27         46  
  27         972  
4 27     27   135 use warnings;
  27         45  
  27         676  
5 27     27   113 use namespace::autoclean;
  27         43  
  27         157  
6              
7             our $VERSION = '0.42';
8              
9 27     27   2034 use Fey::Types qw( ArrayRef Bool SetOperationArg Str );
  27         46  
  27         193  
10              
11 27     27   276361 use MooseX::Role::Parameterized 0.04;
  27         717  
  27         202  
12 27     27   192265 use MooseX::Params::Validate 0.08 qw( pos_validated_list );
  27         707  
  27         164  
13              
14             parameter keyword => (
15             isa => Str,
16             required => 1,
17             );
18              
19             with 'Fey::Role::Comparable',
20             'Fey::Role::SQL::HasOrderByClause',
21             'Fey::Role::SQL::HasLimitClause',
22             'Fey::Role::SQL::ReturnsData';
23              
24             has 'is_all' => (
25             is => 'rw',
26             isa => Bool,
27             default => 0,
28             writer => '_set_is_all',
29             );
30              
31             has '_set_elements' => (
32             traits => ['Array'],
33             is => 'bare',
34             isa => ArrayRef [SetOperationArg],
35             default => sub { [] },
36             handles => {
37             _add_set_elements => 'push',
38             _set_element_count => 'count',
39             _set_elements => 'elements',
40             },
41             init_arg => undef,
42             );
43              
44             sub id {
45 3     3 0 9 return $_[0]->sql('Fey::FakeDBI');
46             }
47              
48             sub all {
49 3     3 1 2845 $_[0]->_set_is_all(1);
50 3         9 return $_[0];
51             }
52              
53             sub bind_params {
54 1     1 0 2 my $self = shift;
55 1         35 return map { $_->bind_params } $self->_set_elements();
  2         5  
56             }
57              
58             sub select_clause_elements {
59 0     0 0 0 return ( $_[0]->_set_elements() )[0]->select_clause_elements();
60             }
61              
62             role {
63             my $p = shift;
64             my %extra = @_;
65              
66             my $name = lc $p->keyword();
67              
68             method 'keyword_clause' => sub {
69 28     28   45 my $self = shift;
        28      
        28      
70              
71 28         63 my $sql = uc($name);
72 28 100       780 $sql .= ' ALL' if $self->is_all();
73 28         921 return $sql;
74             };
75              
76             my $clause_method = $name . '_clause';
77              
78             method 'sql' => sub {
79 28     28   123 my $self = shift;
        28      
        28      
80 28         36 my $dbh = shift;
81              
82             return (
83 28         96 join q{ },
84             $self->$clause_method($dbh),
85             $self->order_by_clause($dbh),
86             $self->limit_clause($dbh),
87             );
88             };
89              
90             method $name => sub {
91 37     37   11928 my $self = shift;
        37      
        37      
92              
93 37         54 my $count = @_;
94 37 100 100     647 $count = 2
95             if $count < 2 && $self->_set_element_count() < 2;
96              
97 37         156 my (@set) = pos_validated_list(
98             \@_,
99             ( ( { isa => SetOperationArg } ) x $count ),
100             MX_PARAMS_VALIDATE_NO_CACHE => 1,
101             );
102              
103 25         70139 $self->_add_set_elements(@set);
104              
105 25         92 return $self;
106             };
107              
108             method $clause_method => sub {
109 28     28   29 my $self = shift;
        28      
        28      
110 28         30 my $dbh = shift;
111              
112             return (
113 59         179 join q{ } . $self->keyword_clause($dbh) . q{ },
114 28         79 map { '(' . $_->sql($dbh) . ')' } $self->_set_elements()
115             );
116             };
117              
118             with 'Fey::Role::HasAliasName' => {
119             generated_alias_prefix => uc $name,
120             sql_needs_parens => 1,
121             };
122             };
123              
124             1;
125              
126             # ABSTRACT: A role for things that are a set operation
127              
128             __END__
129              
130             =pod
131              
132             =head1 NAME
133              
134             Fey::Role::SetOperation - A role for things that are a set operation
135              
136             =head1 VERSION
137              
138             version 0.42
139              
140             =head1 SYNOPSIS
141              
142             use Moose 0.90;
143              
144             with 'Fey::Role::SetOperation' => { keyword => $keyword };
145              
146             =head1 DESCRIPTION
147              
148             Classes which do this role represent a query which can include
149             multiple C<SELECT> queries or set operations.
150              
151             =head1 PARAMETERS
152              
153             =head2 keyword
154              
155             The SQL keyword for this set operation (i.e. C<UNION>, C<INTERSECT>,
156             C<EXCEPT>).
157              
158             =head1 METHODS
159              
160             This role provides the following methods, where C<$keyword> is the
161             C<keyword> parameter, above:
162              
163             =head2 $query->$keyword()
164              
165             $union->union($select1, $select2, $select3);
166              
167             $union->union($select, $except->except($select2, $select3));
168              
169             Adds C<SELECT> queries or set operations to the list of queries that this set operation
170             includes.
171              
172             A set operation must include at least two queries, so the first time
173             this is called, at least two arguments must be provided; subsequent
174             calls do not suffer this constraint.
175              
176             =head2 $query->all()
177              
178             Sets whether or not C<ALL> is included in the SQL for this set
179             operation (e.g. C<UNION ALL>).
180              
181             =head2 $query->is_all()
182              
183             Returns true if C<< $query->all() >> has previously been called.
184              
185             =head2 $query->keyword_clause()
186              
187             Returns the SQL keyword and possible C<ALL> for this set operation.
188              
189             =head2 $query->${keyword}_clause()
190              
191             print $query->union_clause();
192              
193             Returns each of the selects for this set operation, joined by the
194             C<keyword_clause>.
195              
196             =head1 ROLES
197              
198             This class includes C<Fey::Role::SQL::HasOrderByClause>,
199             C<Fey::Role::SQL::HasLimitClause>, and C<Fey::Role::SQL::HasAliasName>.
200              
201             =head1 BUGS
202              
203             See L<Fey> for details on how to report bugs.
204              
205             =head1 AUTHOR
206              
207             Dave Rolsky <autarch@urth.org>
208              
209             =head1 COPYRIGHT AND LICENSE
210              
211             This software is Copyright (c) 2011 - 2015 by Dave Rolsky.
212              
213             This is free software, licensed under:
214              
215             The Artistic License 2.0 (GPL Compatible)
216              
217             =cut